mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Feat] (ProgramState): Implement automatic GLSL uniform management.
- Add SPIRV-Cross/glslang integration for uniform reflection. - Auto-detect and assign locations for uniforms/samplers. - Support most types of uniform. - Implement glUniform* functions with type safety. - Add MG_Util::Program: - GLSL-SPIRV conversion - SPIRV uniform reflection - Program uniform dumping
This commit is contained in:
+6
-1
@@ -64,6 +64,7 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
|||||||
|
|
||||||
MG/MG_GL/State/Buffer/BufferState.cpp
|
MG/MG_GL/State/Buffer/BufferState.cpp
|
||||||
|
|
||||||
|
MG/MG_GL/State/Program/ShaderObject.cpp
|
||||||
MG/MG_GL/State/Program/ProgramState.cpp
|
MG/MG_GL/State/Program/ProgramState.cpp
|
||||||
|
|
||||||
# MG_GL/BackendLoader
|
# MG_GL/BackendLoader
|
||||||
@@ -72,6 +73,10 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
|||||||
# MG_UTIL/Debug
|
# MG_UTIL/Debug
|
||||||
MG/MG_UTIL/Debug/Debug.cpp
|
MG/MG_UTIL/Debug/Debug.cpp
|
||||||
|
|
||||||
|
# MG_UTIL/Program
|
||||||
|
MG/MG_UTIL/Program/DebugTool.cpp
|
||||||
|
MG/MG_UTIL/Program/GLSLTool.cpp
|
||||||
|
|
||||||
# MG_RHI/GLES
|
# MG_RHI/GLES
|
||||||
MG/MG_RHI/GLES/Test/TestDrawing.cpp
|
MG/MG_RHI/GLES/Test/TestDrawing.cpp
|
||||||
)
|
)
|
||||||
@@ -80,7 +85,7 @@ target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ./includes)
|
|||||||
|
|
||||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||||
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libglslang.a
|
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libglslang.a
|
||||||
#${CMAKE_SOURCE_DIR}/library/arm64-v8a/libspirv-cross-c-shared.so
|
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libspirv-cross-c-shared.so
|
||||||
#${CMAKE_SOURCE_DIR}/library/arm64-v8a/libshaderconv.so
|
#${CMAKE_SOURCE_DIR}/library/arm64-v8a/libshaderconv.so
|
||||||
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libGenericCodeGen.a
|
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libGenericCodeGen.a
|
||||||
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libglslang-default-resource-limits.a
|
${CMAKE_SOURCE_DIR}/library/arm64-v8a/libglslang-default-resource-limits.a
|
||||||
|
|||||||
@@ -47,6 +47,9 @@
|
|||||||
#ifndef MOBILEGL_BUFFERSTATE_H
|
#ifndef MOBILEGL_BUFFERSTATE_H
|
||||||
#include "MG_GL/State/Buffer/BufferState.h"
|
#include "MG_GL/State/Buffer/BufferState.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef MOBILEGL_SHADEROBJECT_H
|
||||||
|
#include "MG_GL/State/Program/ShaderObject.h"
|
||||||
|
#endif
|
||||||
#ifndef MOBILEGL_PROGRAMSTATE_H
|
#ifndef MOBILEGL_PROGRAMSTATE_H
|
||||||
#include "MG_GL/State/Program/ProgramState.h"
|
#include "MG_GL/State/Program/ProgramState.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -56,6 +59,12 @@
|
|||||||
#ifndef MOBILEGL_DEBUG_H
|
#ifndef MOBILEGL_DEBUG_H
|
||||||
#include "MG_UTIL/Debug/Debug.h"
|
#include "MG_UTIL/Debug/Debug.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef MOBILEGL_GLSLTOOL_H
|
||||||
|
#include "MG_UTIL/Program/GLSLTool.h"
|
||||||
|
#endif
|
||||||
|
#ifndef MOBILEGL_PROGRAM_DEBUGTOOL_H
|
||||||
|
#include "MG_UTIL/Program/DebugTool.h"
|
||||||
|
#endif
|
||||||
#ifndef MOBILEGL_GL_COMMON_H
|
#ifndef MOBILEGL_GL_COMMON_H
|
||||||
#include "MG_GL/Implementations/GL/Common/GL_Common.h"
|
#include "MG_GL/Implementations/GL/Common/GL_Common.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -87,6 +96,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ DECLARE_GL_FUNCTION_HEAD(void, ClearColor, GLfloat red, GLfloat green, GLfloat b
|
|||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearDepthf, GLfloat d) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearDepthf, d)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearDepthf, GLfloat d) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearDepthf, d)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearStencil, GLint s) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearStencil, s)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearStencil, GLint s) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearStencil, s)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ColorMask, red,green,blue,alpha)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, ColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ColorMask, red,green,blue,alpha)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompileShader, GLuint shader) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompileShader, shader)
|
DECLARE_GL_FUNCTION_HEAD(void, CompileShader, GLuint shader) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CompileShader, shader)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexImage2D, target,level,internalformat,width,height,border,imageSize,data)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexImage2D, target,level,internalformat,width,height,border,imageSize,data)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexSubImage2D, target,level,xoffset,yoffset,width,height,format,imageSize,data)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, CompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CompressedTexSubImage2D, target,level,xoffset,yoffset,width,height,format,imageSize,data)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTexImage2D, target,level,internalformat,x,y,width,height,border)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, CopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, CopyTexImage2D, target,level,internalformat,x,y,width,height,border)
|
||||||
@@ -143,25 +143,25 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameterfv, GLenum target, GLenum pname,
|
|||||||
DECLARE_GL_FUNCTION_HEAD(void, TexParameteri, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameteri, target,pname,param)
|
DECLARE_GL_FUNCTION_HEAD(void, TexParameteri, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameteri, target,pname,param)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameteriv, GLenum target, GLenum pname, const GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameteriv, target,pname,params)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameteriv, GLenum target, GLenum pname, const GLint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameteriv, target,pname,params)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, TexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexSubImage2D, target,level,xoffset,yoffset,width,height,format,type,pixels)
|
DECLARE_GL_FUNCTION_HEAD(void, TexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexSubImage2D, target,level,xoffset,yoffset,width,height,format,type,pixels)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1f, GLint location, GLfloat v0) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1f, location,v0)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform1f, GLint location, GLfloat v0) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1f, location,v0)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1fv, GLint location, GLsizei count, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1fv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform1fv, GLint location, GLsizei count, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1fv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1i, GLint location, GLint v0) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1i, location,v0)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform1i, GLint location, GLint v0) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1i, location,v0)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1iv, GLint location, GLsizei count, const GLint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1iv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform1iv, GLint location, GLsizei count, const GLint *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1iv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2f, GLint location, GLfloat v0, GLfloat v1) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2f, location,v0,v1)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform2f, GLint location, GLfloat v0, GLfloat v1) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2f, location,v0,v1)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2fv, GLint location, GLsizei count, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2fv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform2fv, GLint location, GLsizei count, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2fv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2i, GLint location, GLint v0, GLint v1) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2i, location,v0,v1)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform2i, GLint location, GLint v0, GLint v1) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2i, location,v0,v1)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2iv, GLint location, GLsizei count, const GLint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2iv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform2iv, GLint location, GLsizei count, const GLint *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2iv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3f, location,v0,v1,v2)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform3f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3f, location,v0,v1,v2)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3fv, GLint location, GLsizei count, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3fv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform3fv, GLint location, GLsizei count, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3fv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3i, GLint location, GLint v0, GLint v1, GLint v2) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3i, location,v0,v1,v2)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform3i, GLint location, GLint v0, GLint v1, GLint v2) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3i, location,v0,v1,v2)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3iv, GLint location, GLsizei count, const GLint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3iv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform3iv, GLint location, GLsizei count, const GLint *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3iv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4f, location,v0,v1,v2,v3)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform4f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4f, location,v0,v1,v2,v3)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4fv, GLint location, GLsizei count, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4fv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform4fv, GLint location, GLsizei count, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4fv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4i, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4i, location,v0,v1,v2,v3)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform4i, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4i, location,v0,v1,v2,v3)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4iv, GLint location, GLsizei count, const GLint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4iv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform4iv, GLint location, GLsizei count, const GLint *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4iv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix4fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_HEAD(void, UseProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UseProgram, program)
|
DECLARE_GL_FUNCTION_HEAD(void, UseProgram, GLuint program) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UseProgram, program)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ValidateProgram, GLuint program) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ValidateProgram, program)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, ValidateProgram, GLuint program) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ValidateProgram, program)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1f, GLuint index, GLfloat x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1f, index,x)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttrib1f, GLuint index, GLfloat x) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttrib1f, index,x)
|
||||||
@@ -191,12 +191,12 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetQueryObjectuiv, GLuint id, GLenum pname,
|
|||||||
DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target)
|
DECLARE_GL_FUNCTION_HEAD(GLboolean, UnmapBuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLboolean, UnmapBuffer, target)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void **params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferPointerv, target,pname,params)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetBufferPointerv, GLenum target, GLenum pname, void **params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetBufferPointerv, target,pname,params)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawBuffers, GLsizei n, const GLenum *bufs) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawBuffers, n,bufs)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, DrawBuffers, GLsizei n, const GLenum *bufs) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, DrawBuffers, n,bufs)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2x3fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x3fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3x2fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x2fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix2x4fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix2x4fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix4x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix4x2fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x2fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix3x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix3x4fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix3x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix3x4fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, UniformMatrix4x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, UniformMatrix4x3fv, location,count,transpose,value)
|
DECLARE_GL_FUNCTION_HEAD(void, UniformMatrix4x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, UniformMatrix4x3fv, location,count,transpose,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlitFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlitFramebuffer, srcX0,srcY0,srcX1,srcY1,dstX0,dstY0,dstX1,dstY1,mask,filter)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, BlitFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlitFramebuffer, srcX0,srcY0,srcX1,srcY1,dstX0,dstY0,dstX1,dstY1,mask,filter)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, RenderbufferStorageMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, RenderbufferStorageMultisample, target,samples,internalformat,width,height)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, RenderbufferStorageMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, RenderbufferStorageMultisample, target,samples,internalformat,width,height)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferTextureLayer, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferTextureLayer, target,attachment,texture,level,layer)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferTextureLayer, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferTextureLayer, target,attachment,texture,level,layer)
|
||||||
@@ -221,14 +221,14 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4iv, GLuint index, const GLint
|
|||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4uiv, GLuint index, const GLuint *v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4uiv, index,v)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, VertexAttribI4uiv, GLuint index, const GLuint *v) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, VertexAttribI4uiv, index,v)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetUniformuiv, GLuint program, GLint location, GLuint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetUniformuiv, program,location,params)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetUniformuiv, GLuint program, GLint location, GLuint *params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetUniformuiv, program,location,params)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(GLint, GetFragDataLocation, GLuint program, const GLchar *name) DECLARE_GL_FUNCTION_STUB_END(GLint, GetFragDataLocation, program,name)
|
DECLARE_GL_FUNCTION_STUB_HEAD(GLint, GetFragDataLocation, GLuint program, const GLchar *name) DECLARE_GL_FUNCTION_STUB_END(GLint, GetFragDataLocation, program,name)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1ui, GLint location, GLuint v0) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1ui, location,v0)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform1ui, GLint location, GLuint v0) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1ui, location,v0)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2ui, GLint location, GLuint v0, GLuint v1) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2ui, location,v0,v1)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform2ui, GLint location, GLuint v0, GLuint v1) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2ui, location,v0,v1)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3ui, GLint location, GLuint v0, GLuint v1, GLuint v2) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3ui, location,v0,v1,v2)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform3ui, GLint location, GLuint v0, GLuint v1, GLuint v2) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3ui, location,v0,v1,v2)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4ui, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4ui, location,v0,v1,v2,v3)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform4ui, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4ui, location,v0,v1,v2,v3)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform1uiv, GLint location, GLsizei count, const GLuint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform1uiv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform1uiv, GLint location, GLsizei count, const GLuint *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1uiv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform2uiv, GLint location, GLsizei count, const GLuint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform2uiv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform2uiv, GLint location, GLsizei count, const GLuint *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform2uiv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform3uiv, GLint location, GLsizei count, const GLuint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform3uiv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform3uiv, GLint location, GLsizei count, const GLuint *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform3uiv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, Uniform4uiv, GLint location, GLsizei count, const GLuint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Uniform4uiv, location,count,value)
|
DECLARE_GL_FUNCTION_HEAD(void, Uniform4uiv, GLint location, GLsizei count, const GLuint *value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform4uiv, location,count,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferiv, GLenum buffer, GLint drawbuffer, const GLint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearBufferiv, buffer,drawbuffer,value)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferiv, GLenum buffer, GLint drawbuffer, const GLint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearBufferiv, buffer,drawbuffer,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferuiv, GLenum buffer, GLint drawbuffer, const GLuint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearBufferuiv, buffer,drawbuffer,value)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferuiv, GLenum buffer, GLint drawbuffer, const GLuint *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearBufferuiv, buffer,drawbuffer,value)
|
||||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferfv, GLenum buffer, GLint drawbuffer, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearBufferfv, buffer,drawbuffer,value)
|
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearBufferfv, GLenum buffer, GLint drawbuffer, const GLfloat *value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearBufferfv, buffer,drawbuffer,value)
|
||||||
|
|||||||
@@ -130,4 +130,169 @@ namespace MG_GL::GL {
|
|||||||
MG_State::SetError(result);
|
MG_State::SetError(result);
|
||||||
MG_Util::Debug::LogE("Error getting shader param: %s", MG_Util::Debug::GLEnumToString(result));
|
MG_Util::Debug::LogE("Error getting shader param: %s", MG_Util::Debug::GLEnumToString(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Uniform1f(GLint location, GLfloat v0) {
|
||||||
|
MG_Util::Debug::LogD("glUniform1f, location: %d, v0: %f", location, v0);
|
||||||
|
MG_State::UpdateProgramUniformFloat1(location, v0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform2f(GLint location, GLfloat v0, GLfloat v1) {
|
||||||
|
MG_Util::Debug::LogD("glUniform2f, location: %d, v0: %f, v1: %f", location, v0, v1);
|
||||||
|
MG_State::UpdateProgramUniformFloat2(location, v0, v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
|
||||||
|
MG_Util::Debug::LogD("glUniform3f, location: %d, v0: %f, v1: %f, v2: %f", location, v0, v1, v2);
|
||||||
|
MG_State::UpdateProgramUniformFloat3(location, v0, v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
|
||||||
|
MG_Util::Debug::LogD("glUniform4f, location: %d, v0: %f, v1: %f, v2: %f, v3: %f", location, v0, v1, v2, v3);
|
||||||
|
MG_State::UpdateProgramUniformFloat4(location, v0, v1, v2, v3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform1fv(GLint location, GLsizei count, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform1fv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformFloatVector1(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform2fv(GLint location, GLsizei count, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform2fv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformFloatVector2(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform3fv(GLint location, GLsizei count, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform3fv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformFloatVector3(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform4fv(GLint location, GLsizei count, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform4fv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformFloatVector4(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform1i(GLint location, GLint v0) {
|
||||||
|
MG_Util::Debug::LogD("glUniform1i, location: %d, v0: %d", location, v0);
|
||||||
|
MG_State::UpdateProgramUniformInt1(location, v0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform2i(GLint location, GLint v0, GLint v1) {
|
||||||
|
MG_Util::Debug::LogD("glUniform2i, location: %d, v0: %d, v1: %d", location, v0, v1);
|
||||||
|
MG_State::UpdateProgramUniformInt2(location, v0, v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform3i(GLint location, GLint v0, GLint v1, GLint v2) {
|
||||||
|
MG_Util::Debug::LogD("glUniform3i, location: %d, v0: %d, v1: %d, v2: %d", location, v0, v1, v2);
|
||||||
|
MG_State::UpdateProgramUniformInt3(location, v0, v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
|
||||||
|
MG_Util::Debug::LogD("glUniform4i, location: %d, v0: %d, v1: %d, v2: %d, v3: %d", location, v0, v1, v2, v3);
|
||||||
|
MG_State::UpdateProgramUniformInt4(location, v0, v1, v2, v3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform1iv(GLint location, GLsizei count, const GLint* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform1iv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformIntVector1(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform2iv(GLint location, GLsizei count, const GLint* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform2iv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformIntVector2(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform3iv(GLint location, GLsizei count, const GLint* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform3iv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformIntVector3(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform4iv(GLint location, GLsizei count, const GLint* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform4iv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformIntVector4(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform1ui(GLint location, GLuint v0) {
|
||||||
|
MG_Util::Debug::LogD("glUniform1ui, location: %d, v0: %u", location, v0);
|
||||||
|
MG_State::UpdateProgramUniformUInt1(location, v0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform2ui(GLint location, GLuint v0, GLuint v1) {
|
||||||
|
MG_Util::Debug::LogD("glUniform2ui, location: %d, v0: %u, v1: %u", location, v0, v1);
|
||||||
|
MG_State::UpdateProgramUniformUInt2(location, v0, v1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) {
|
||||||
|
MG_Util::Debug::LogD("glUniform3ui, location: %d, v0: %u, v1: %u, v2: %u", location, v0, v1, v2);
|
||||||
|
MG_State::UpdateProgramUniformUInt3(location, v0, v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
|
||||||
|
MG_Util::Debug::LogD("glUniform4ui, location: %d, v0: %u, v1: %u, v2: %u, v3: %u", location, v0, v1, v2, v3);
|
||||||
|
MG_State::UpdateProgramUniformUInt4(location, v0, v1, v2, v3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform1uiv(GLint location, GLsizei count, const GLuint* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform1uiv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformUIntVector1(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform2uiv(GLint location, GLsizei count, const GLuint* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform2uiv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformUIntVector2(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform3uiv(GLint location, GLsizei count, const GLuint* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform3uiv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformUIntVector3(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Uniform4uiv(GLint location, GLsizei count, const GLuint* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniform4uiv, location: %d, count: %d", location, count);
|
||||||
|
MG_State::UpdateProgramUniformUIntVector4(location, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniformMatrix2fv, location: %d, count: %d, transpose: %d", location, count, transpose);
|
||||||
|
MG_State::UpdateProgramUniformMatrix2x2Vector(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniformMatrix3fv, location: %d, count: %d, transpose: %d", location, count, transpose);
|
||||||
|
MG_State::UpdateProgramUniformMatrix3x3Vector(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniformMatrix4fv, location: %d, count: %d, transpose: %d", location, count, transpose);
|
||||||
|
MG_State::UpdateProgramUniformMatrix4x4Vector(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniformMatrix2x3fv, location: %d, count: %d, transpose: %d", location, count, transpose);
|
||||||
|
MG_State::UpdateProgramUniformMatrix2x3Vector(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniformMatrix2x4fv, location: %d, count: %d, transpose: %d", location, count, transpose);
|
||||||
|
MG_State::UpdateProgramUniformMatrix2x4Vector(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniformMatrix3x2fv, location: %d, count: %d, transpose: %d", location, count, transpose);
|
||||||
|
MG_State::UpdateProgramUniformMatrix3x2Vector(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniformMatrix3x4fv, location: %d, count: %d, transpose: %d", location, count, transpose);
|
||||||
|
MG_State::UpdateProgramUniformMatrix3x4Vector(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniformMatrix4x2fv, location: %d, count: %d, transpose: %d", location, count, transpose);
|
||||||
|
MG_State::UpdateProgramUniformMatrix4x2Vector(location, count, transpose, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
|
MG_Util::Debug::LogD("glUniformMatrix4x3fv, location: %d, count: %d, transpose: %d", location, count, transpose);
|
||||||
|
MG_State::UpdateProgramUniformMatrix4x3Vector(location, count, transpose, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,39 @@ namespace MG_GL::GL {
|
|||||||
GLint GetUniformLocation(GLuint program, const GLchar* name);
|
GLint GetUniformLocation(GLuint program, const GLchar* name);
|
||||||
void GetProgramiv(GLuint program, GLenum pname, GLint* params);
|
void GetProgramiv(GLuint program, GLenum pname, GLint* params);
|
||||||
void GetShaderiv(GLuint shader, GLenum pname, GLint* params);
|
void GetShaderiv(GLuint shader, GLenum pname, GLint* params);
|
||||||
|
void Uniform1f(GLint location, GLfloat v0);
|
||||||
|
void Uniform2f(GLint location, GLfloat v0, GLfloat v1);
|
||||||
|
void Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
||||||
|
void Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||||
|
void Uniform1fv(GLint location, GLsizei count, const GLfloat* value);
|
||||||
|
void Uniform2fv(GLint location, GLsizei count, const GLfloat* value);
|
||||||
|
void Uniform3fv(GLint location, GLsizei count, const GLfloat* value);
|
||||||
|
void Uniform4fv(GLint location, GLsizei count, const GLfloat* value);
|
||||||
|
void Uniform1i(GLint location, GLint v0);
|
||||||
|
void Uniform2i(GLint location, GLint v0, GLint v1);
|
||||||
|
void Uniform3i(GLint location, GLint v0, GLint v1, GLint v2);
|
||||||
|
void Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
|
||||||
|
void Uniform1iv(GLint location, GLsizei count, const GLint* value);
|
||||||
|
void Uniform2iv(GLint location, GLsizei count, const GLint* value);
|
||||||
|
void Uniform3iv(GLint location, GLsizei count, const GLint* value);
|
||||||
|
void Uniform4iv(GLint location, GLsizei count, const GLint* value);
|
||||||
|
void Uniform1ui(GLint location, GLuint v0);
|
||||||
|
void Uniform2ui(GLint location, GLuint v0, GLuint v1);
|
||||||
|
void Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
|
||||||
|
void Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
|
||||||
|
void Uniform1uiv(GLint location, GLsizei count, const GLuint* value);
|
||||||
|
void Uniform2uiv(GLint location, GLsizei count, const GLuint* value);
|
||||||
|
void Uniform3uiv(GLint location, GLsizei count, const GLuint* value);
|
||||||
|
void Uniform4uiv(GLint location, GLsizei count, const GLuint* value);
|
||||||
|
void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
void UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
void UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
void UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
void UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
void UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
void UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //MOBILEGL_GL_PROGRAM_H
|
#endif //MOBILEGL_GL_PROGRAM_H
|
||||||
|
|||||||
@@ -241,6 +241,54 @@ namespace MG_State {
|
|||||||
return MG_State_T::programState->QueryShaderStateIntVector(shader, pname, params);
|
return MG_State_T::programState->QueryShaderStateIntVector(shader, pname, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define IMPLEMENT_UNIFORM_FUNCTIONS(type, suffix, vecType) \
|
||||||
|
void UpdateProgramUniform##suffix##1(GLint location, type v0) { \
|
||||||
|
MG_State_T::programState->UpdateUniform##suffix##1(location, v0); \
|
||||||
|
} \
|
||||||
|
void UpdateProgramUniform##suffix##2(GLint location, type v0, type v1) { \
|
||||||
|
MG_State_T::programState->UpdateUniform##suffix##2(location, v0, v1); \
|
||||||
|
} \
|
||||||
|
void UpdateProgramUniform##suffix##3(GLint location, type v0, type v1, type v2) { \
|
||||||
|
MG_State_T::programState->UpdateUniform##suffix##3(location, v0, v1, v2); \
|
||||||
|
} \
|
||||||
|
void UpdateProgramUniform##suffix##4(GLint location, type v0, type v1, type v2, type v3) { \
|
||||||
|
MG_State_T::programState->UpdateUniform##suffix##4(location, v0, v1, v2, v3); \
|
||||||
|
} \
|
||||||
|
void UpdateProgramUniform##suffix##Vector1(GLint location, GLsizei count, const type* value) { \
|
||||||
|
MG_State_T::programState->UpdateUniform##suffix##Vector1(location, count,value); \
|
||||||
|
} \
|
||||||
|
void UpdateProgramUniform##suffix##Vector2(GLint location, GLsizei count, const type* value) { \
|
||||||
|
MG_State_T::programState->UpdateUniform##suffix##Vector2(location, count, value); \
|
||||||
|
} \
|
||||||
|
void UpdateProgramUniform##suffix##Vector3(GLint location, GLsizei count, const type* value) { \
|
||||||
|
MG_State_T::programState->UpdateUniform##suffix##Vector3(location, count, value); \
|
||||||
|
} \
|
||||||
|
void UpdateProgramUniform##suffix##Vector4(GLint location, GLsizei count, const type* value) { \
|
||||||
|
MG_State_T::programState->UpdateUniform##suffix##Vector4(location, count, value); \
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_UNIFORM_FUNCTIONS(GLfloat, Float, GL_FLOAT_VEC4)
|
||||||
|
IMPLEMENT_UNIFORM_FUNCTIONS(GLint, Int, GL_INT_VEC4)
|
||||||
|
IMPLEMENT_UNIFORM_FUNCTIONS(GLuint, UInt, GL_UNSIGNED_INT_VEC4)
|
||||||
|
IMPLEMENT_UNIFORM_FUNCTIONS(GLboolean, Bool, GL_BOOL_VEC4)
|
||||||
|
#undef IMPLEMENT_UNIFORM_FUNCTIONS
|
||||||
|
|
||||||
|
#define IMPLEMENT_MATRIX_FUNCTIONS(suffix, matrixType) \
|
||||||
|
void UpdateProgramUniformMatrix##suffix##Vector(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { \
|
||||||
|
MG_State_T::programState->UpdateUniformMatrix##suffix##Vector(location, count, transpose, value); \
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(2x2, GL_FLOAT_MAT2)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(3x3, GL_FLOAT_MAT3)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(4x4, GL_FLOAT_MAT4)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(2x3, GL_FLOAT_MAT2x3)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(2x4, GL_FLOAT_MAT2x4)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(3x2, GL_FLOAT_MAT3x2)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(3x4, GL_FLOAT_MAT3x4)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(4x2, GL_FLOAT_MAT4x2)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(4x3, GL_FLOAT_MAT4x3)
|
||||||
|
#undef IMPLEMENT_MATRIX_FUNCTIONS
|
||||||
|
|
||||||
GLuint GetCurrentProgram() {
|
GLuint GetCurrentProgram() {
|
||||||
return MG_State_T::programState->GetCurrentProgram();
|
return MG_State_T::programState->GetCurrentProgram();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,38 @@ namespace MG_State {
|
|||||||
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name);
|
GLint QueryProgramUniformLocation(GLuint program, const GLchar* name);
|
||||||
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
|
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
|
||||||
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
|
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
|
||||||
|
template<typename T>
|
||||||
|
GLenum SetUniform(GLuint program, GLint location, GLsizei count, const T* value, GLenum type);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
GLenum SetUniformMatrix(GLuint program, GLint location, GLsizei count, GLboolean transpose, const T* value, GLenum matrixType);
|
||||||
|
|
||||||
|
#define DECLARE_UNIFORM_FUNCTIONS(type, suffix, vecType) \
|
||||||
|
void UpdateProgramUniform##suffix##1(GLint location, type v0); \
|
||||||
|
void UpdateProgramUniform##suffix##2(GLint location, type v0, type v1); \
|
||||||
|
void UpdateProgramUniform##suffix##3(GLint location, type v0, type v1, type v2); \
|
||||||
|
void UpdateProgramUniform##suffix##4(GLint location, type v0, type v1, type v2, type v3); \
|
||||||
|
void UpdateProgramUniform##suffix##Vector1(GLint location, GLsizei count, const type* value); \
|
||||||
|
void UpdateProgramUniform##suffix##Vector2(GLint location, GLsizei count, const type* value); \
|
||||||
|
void UpdateProgramUniform##suffix##Vector3(GLint location, GLsizei count, const type* value); \
|
||||||
|
void UpdateProgramUniform##suffix##Vector4(GLint location, GLsizei count, const type* value);
|
||||||
|
DECLARE_UNIFORM_FUNCTIONS(GLfloat, Float, GL_FLOAT)
|
||||||
|
DECLARE_UNIFORM_FUNCTIONS(GLint, Int, GL_INT)
|
||||||
|
DECLARE_UNIFORM_FUNCTIONS(GLuint, UInt, GL_UNSIGNED_INT)
|
||||||
|
DECLARE_UNIFORM_FUNCTIONS(GLboolean, Bool, GL_BOOL)
|
||||||
|
#undef DECLARE_UNIFORM_FUNCTIONS
|
||||||
|
#define DECLARE_MATRIX_FUNCTIONS(suffix, matrixType) \
|
||||||
|
void UpdateProgramUniformMatrix##suffix##Vector(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(2x2, GL_FLOAT_MAT2)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(3x3, GL_FLOAT_MAT3)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(4x4, GL_FLOAT_MAT4)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(2x3, GL_FLOAT_MAT2x3)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(2x4, GL_FLOAT_MAT2x4)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(3x2, GL_FLOAT_MAT3x2)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(3x4, GL_FLOAT_MAT3x4)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(4x2, GL_FLOAT_MAT4x2)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(4x3, GL_FLOAT_MAT4x3)
|
||||||
|
#undef DECLARE_MATRIX_FUNCTIONS
|
||||||
|
|
||||||
GLuint GetCurrentProgram();
|
GLuint GetCurrentProgram();
|
||||||
bool SetProgramStatus(GLuint program, GLboolean status);
|
bool SetProgramStatus(GLuint program, GLboolean status);
|
||||||
|
|||||||
@@ -1,258 +1,530 @@
|
|||||||
//
|
//
|
||||||
// Created by BZLZHH on 2025/5/1.
|
// Created by BZLZHH on 2025/5/1.
|
||||||
//
|
|
||||||
|
|
||||||
// TODO: Add more gl error check for buffer state manager.
|
// TODO: Add more gl error check for buffer state manager.
|
||||||
// TODO: Check if the state machine really meets up to OpenGL 3 standard.
|
// TODO: Check if the state machine really meets up to OpenGL 3 standard.
|
||||||
|
|
||||||
#include "ProgramState.h"
|
#include "ProgramState.h"
|
||||||
|
|
||||||
GLenum ProgramState::CreateShader(GLenum type, GLuint* shader) {
|
// Re-Include Includes.h, cuz of the absence of Program/DebugTool.h and Program/GLSLTool.cpp.
|
||||||
if (!shader) return GL_INVALID_VALUE;
|
#undef MOBILEGL_GLSLTOOL_H
|
||||||
if (type != GL_VERTEX_SHADER && type != GL_FRAGMENT_SHADER)
|
#undef MOBILEGL_PROGRAM_DEBUGTOOL_H
|
||||||
return GL_INVALID_ENUM;
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
GLuint id = freeShaderIds_.empty() ? ++lastShaderId_ : *freeShaderIds_.begin();
|
ProgramState::ProgramState() {
|
||||||
if (!freeShaderIds_.empty()) freeShaderIds_.erase(freeShaderIds_.begin());
|
glslang::InitializeProcess();
|
||||||
|
}
|
||||||
|
|
||||||
ShaderObject obj;
|
ProgramState::~ProgramState() {
|
||||||
obj.type = type;
|
glslang::FinalizeProcess();
|
||||||
obj.compiled = UncertainBool::False;
|
|
||||||
obj.markedForDeletion = false;
|
|
||||||
shaders_[id] = obj;
|
|
||||||
*shader = id;
|
|
||||||
return GL_NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::CreateProgram(GLuint* program) {
|
GLenum ProgramState::CreateProgram(GLuint* program) {
|
||||||
if (!program) return GL_INVALID_VALUE;
|
MG_Util::Debug::LogD("MG_State: Program: CreateProgram called, program ptr=%p", program);
|
||||||
|
if (!program) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: CreateProgram error: program pointer is null");
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
GLuint id = freeProgramIds_.empty() ? ++lastProgramId_ : *freeProgramIds_.begin();
|
GLuint id = freeProgramIds_.empty() ? ++lastProgramId_ : *freeProgramIds_.begin();
|
||||||
if (!freeProgramIds_.empty()) freeProgramIds_.erase(freeProgramIds_.begin());
|
if (!freeProgramIds_.empty())
|
||||||
|
freeProgramIds_.erase(freeProgramIds_.begin());
|
||||||
|
|
||||||
ProgramObject obj;
|
ProgramObject obj;
|
||||||
obj.linked = UncertainBool::False;
|
obj.linked = {UncertainBool::Unknown, UncertainBool::False};
|
||||||
|
obj.linkStatus = GL_FALSE;
|
||||||
obj.markedForDeletion = false;
|
obj.markedForDeletion = false;
|
||||||
programs_[id] = obj;
|
programs_[id] = obj;
|
||||||
*program = id;
|
*program = id;
|
||||||
return GL_NO_ERROR;
|
MG_Util::Debug::LogD("MG_State: Program: CreateProgram success, new id=%u", id);
|
||||||
}
|
|
||||||
|
|
||||||
GLenum ProgramState::DeleteShader(GLuint shader) {
|
|
||||||
if (!ValidateShader_(shader)) return GL_INVALID_VALUE;
|
|
||||||
|
|
||||||
if (shaders_[shader].markedForDeletion) return GL_NO_ERROR;
|
|
||||||
|
|
||||||
bool inUse = false;
|
|
||||||
for (auto& [progId, program] : programs_) {
|
|
||||||
auto it = std::find(program.attachedShaders.begin(),
|
|
||||||
program.attachedShaders.end(), shader);
|
|
||||||
if (it != program.attachedShaders.end()) {
|
|
||||||
inUse = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inUse) {
|
|
||||||
shaders_[shader].markedForDeletion = true;
|
|
||||||
} else {
|
|
||||||
shaders_.erase(shader);
|
|
||||||
freeShaderIds_.insert(shader);
|
|
||||||
}
|
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::DeleteProgram(GLuint program) {
|
GLenum ProgramState::DeleteProgram(GLuint program) {
|
||||||
if (!ValidateProgram_(program)) return GL_INVALID_VALUE;
|
MG_Util::Debug::LogD("MG_State: Program: DeleteProgram called, id=%u", program);
|
||||||
|
if (!ValidateProgram_(program)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: DeleteProgram error: invalid program id %u", program);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
programs_.erase(program);
|
programs_.erase(program);
|
||||||
freeProgramIds_.insert(program);
|
freeProgramIds_.insert(program);
|
||||||
if (currentProgram_ == program)
|
if (currentProgram_ == program)
|
||||||
currentProgram_ = 0;
|
currentProgram_ = 0;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: DeleteProgram success, id=%u", program);
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::LinkShaderToProgram(GLuint program, GLuint shader) {
|
GLenum ProgramState::LinkShaderToProgram(GLuint program, GLuint shader) {
|
||||||
if (!ValidateProgram_(program) || !ValidateShader_(shader))
|
MG_Util::Debug::LogD("MG_State: Program: LinkShaderToProgram called, program=%u, shader=%u",
|
||||||
|
program, shader);
|
||||||
|
if (!ValidateProgram_(program) || !ValidateShader_(shader)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: LinkShaderToProgram error: invalid ids program=%u shader=%u",
|
||||||
|
program, shader);
|
||||||
return GL_INVALID_VALUE;
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
auto& prog = programs_[program];
|
auto& prog = programs_[program];
|
||||||
if (std::find(prog.attachedShaders.begin(),
|
if (std::find(prog.attachedShaders.begin(),
|
||||||
prog.attachedShaders.end(), shader) != prog.attachedShaders.end())
|
prog.attachedShaders.end(), shader) != prog.attachedShaders.end()) {
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: LinkShaderToProgram warning: shader %u already attached to program %u",
|
||||||
|
shader, program);
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
prog.attachedShaders.push_back(shader);
|
prog.attachedShaders.push_back(shader);
|
||||||
return GL_NO_ERROR;
|
MG_Util::Debug::LogD("MG_State: Program: LinkShaderToProgram success: shader %u attached to program %u",
|
||||||
}
|
shader, program);
|
||||||
|
|
||||||
GLenum ProgramState::UploadShaderSource(GLuint shader, GLsizei count,
|
|
||||||
const GLchar** string, const GLint* length) {
|
|
||||||
if (!ValidateShader_(shader)) return GL_INVALID_VALUE;
|
|
||||||
if (count < 0) return GL_INVALID_VALUE;
|
|
||||||
|
|
||||||
std::string source;
|
|
||||||
for (GLsizei i = 0; i < count; ++i) {
|
|
||||||
const GLchar* str = string[i];
|
|
||||||
GLint len = (length && length[i] >= 0) ? length[i] : strlen(str);
|
|
||||||
source.append(str, len);
|
|
||||||
}
|
|
||||||
shaders_[shader].source = std::move(source);
|
|
||||||
return GL_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLenum ProgramState::BuildShaderStage(GLuint shader) {
|
|
||||||
if (!ValidateShader_(shader)) return GL_INVALID_VALUE;
|
|
||||||
|
|
||||||
auto& obj = shaders_[shader];
|
|
||||||
// TODO: Add glslang to convert it to SPIR-V first, and then check it in the actual backend.
|
|
||||||
obj.compiled = {UncertainBool::Unknown, UncertainBool::True};
|
|
||||||
obj.compileStatus = GL_TRUE;
|
|
||||||
obj.infoLog.clear();
|
|
||||||
|
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::FinalizeProgramPipeline(GLuint program) {
|
GLenum ProgramState::FinalizeProgramPipeline(GLuint program) {
|
||||||
if (!ValidateProgram_(program)) return GL_INVALID_VALUE;
|
MG_Util::Debug::LogD("MG_State: Program: FinalizeProgramPipeline called, id=%u", program);
|
||||||
|
if (!ValidateProgram_(program)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: FinalizeProgramPipeline error: invalid program id %u", program);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
auto& prog = programs_[program];
|
auto& prog = programs_[program];
|
||||||
|
|
||||||
for (GLuint shader : prog.attachedShaders) {
|
for (GLuint shader : prog.attachedShaders) {
|
||||||
if (!shaders_[shader].compiled.toBool())
|
if (!shaders_[shader].compiled.toBool()) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: FinalizeProgramPipeline error: shader %u not compiled", shader);
|
||||||
return GL_INVALID_OPERATION;
|
return GL_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Check the actual program linking status.
|
|
||||||
// We might consider using a program emulator (or real backend checking?) or something better in the future.
|
|
||||||
prog.linked = {UncertainBool::Unknown, UncertainBool::True};
|
|
||||||
prog.linkStatus = GL_TRUE;
|
|
||||||
prog.infoLog.clear();
|
prog.infoLog.clear();
|
||||||
|
|
||||||
|
for (GLuint shaderId : prog.attachedShaders) {
|
||||||
|
auto& shader = shaders_[shaderId];
|
||||||
|
if (!shader.compiled.toBool() || shader.compiledSpirv.empty()) {
|
||||||
|
prog.infoLog = "Program linking failed: \n" +
|
||||||
|
MG_Util::Program::GetShaderTypeName(shader.type) + " is not compiled.";
|
||||||
|
prog.linked = UncertainBool::False;
|
||||||
|
prog.linkStatus = GL_FALSE;
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: FinalizeProgramPipeline error: %s", prog.infoLog.c_str());
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<unsigned>> allSpirv =
|
||||||
|
MG_Util::Program::CompileMultipleShadersToSPIRV(*this, prog, prog.infoLog);
|
||||||
|
|
||||||
|
MG_Util::Program::ReflectSPIRVUniforms(allSpirv, prog, prog.infoLog);
|
||||||
|
if (!prog.infoLog.empty()) {
|
||||||
|
prog.linked = UncertainBool::False;
|
||||||
|
prog.linkStatus = GL_FALSE;
|
||||||
|
prog.infoLog = "Program linking failed: " + prog.infoLog;
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: FinalizeProgramPipeline error: %s", prog.infoLog.c_str());
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& [name, index] : prog.attribBindings) {
|
for (auto& [name, index] : prog.attribBindings) {
|
||||||
prog.attribLocations[name] = index;
|
prog.attribLocations[name] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prog.linked = {UncertainBool::Unknown, UncertainBool::True};
|
||||||
|
prog.linkStatus = GL_TRUE;
|
||||||
|
|
||||||
CleanupShaders_();
|
CleanupShaders_();
|
||||||
|
|
||||||
|
MG_Util::Program::DumpUniforms(*this, program);
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: FinalizeProgramPipeline success, id=%u", program);
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::ActivateRenderProgram(GLuint program) {
|
GLenum ProgramState::ActivateRenderProgram(GLuint program) {
|
||||||
if (program != 0 && !ValidateProgram_(program))
|
MG_Util::Debug::LogD("MG_State: Program: ActivateRenderProgram called, id=%u", program);
|
||||||
|
if (program != 0 && !ValidateProgram_(program)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: ActivateRenderProgram error: invalid program id %u", program);
|
||||||
return GL_INVALID_VALUE;
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MG_Util::Program::DumpCurrentUniforms(*this);
|
||||||
currentProgram_ = program;
|
currentProgram_ = program;
|
||||||
|
MG_Util::Program::DumpCurrentUniforms(*this);
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: ActivateRenderProgram success, current program=%u", currentProgram_);
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name) {
|
GLenum ProgramState::DefineProgramAttributeBinding(GLuint program, GLuint index, const GLchar* name) {
|
||||||
if (!ValidateProgram_(program)) return GL_INVALID_VALUE;
|
MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeBinding called, program=%u, index=%u, name=%s",
|
||||||
if (index >= GL_MAX_VERTEX_ATTRIBS) return GL_INVALID_VALUE;
|
program, index, name);
|
||||||
|
if (!ValidateProgram_(program)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeBinding error: invalid program id %u", program);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (index >= GL_MAX_VERTEX_ATTRIBS) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: DefineProgramAttributeBinding error: index %u out of range", index);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
programs_[program].attribBindings[name] = index;
|
programs_[program].attribBindings[name] = index;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: DefineProgramAttributeBinding success: %s -> %u", name, index);
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint ProgramState::QueryProgramAttributeBinding(GLuint program, const GLchar* name) {
|
GLint ProgramState::QueryProgramAttributeBinding(GLuint program, const GLchar* name) {
|
||||||
if (!ValidateProgram_(program)) return -1;
|
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeBinding called, program=%u, name=%s",
|
||||||
|
program, name);
|
||||||
auto& prog = programs_[program];
|
if (!ValidateProgram_(program)) {
|
||||||
if (prog.attribLocations.count(name))
|
MG_Util::Debug::LogE("MG_State: Program: QueryProgramAttributeBinding error: invalid program id %u", program);
|
||||||
return prog.attribLocations[name];
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint ProgramState::QueryProgramUniformLocation(GLuint program, const GLchar* name) {
|
|
||||||
if (!ValidateProgram_(program)) return -1;
|
|
||||||
|
|
||||||
auto& prog = programs_[program];
|
auto& prog = programs_[program];
|
||||||
if (prog.uniformLocations.count(name))
|
auto it = prog.attribLocations.find(name);
|
||||||
return prog.uniformLocations[name];
|
if (it != prog.attribLocations.end()) {
|
||||||
|
GLint loc = it->second;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: QueryProgramAttributeBinding success: %s -> %d", name, loc);
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: QueryProgramAttributeBinding warning: name '%s' not found", name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params) {
|
GLenum ProgramState::QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params) {
|
||||||
if (!ValidateProgram_(program)) return GL_INVALID_VALUE;
|
MG_Util::Debug::LogD("MG_State: Program: QueryProgramStateIntVector called, program=%u, pname=0x%X",
|
||||||
|
program, pname);
|
||||||
|
if (!ValidateProgram_(program)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: QueryProgramStateIntVector error: invalid program id %u", program);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
auto& prog = programs_[program];
|
auto& prog = programs_[program];
|
||||||
|
|
||||||
switch (pname) {
|
switch (pname) {
|
||||||
case GL_LINK_STATUS: *params = prog.linkStatus; break;
|
case GL_LINK_STATUS: *params = prog.linkStatus; break;
|
||||||
case GL_DELETE_STATUS: *params = prog.markedForDeletion; break;
|
case GL_DELETE_STATUS: *params = prog.markedForDeletion; break;
|
||||||
case GL_ATTACHED_SHADERS:*params = (GLint)prog.attachedShaders.size(); break;
|
case GL_ATTACHED_SHADERS:*params = (GLint)prog.attachedShaders.size(); break;
|
||||||
default: return GL_INVALID_ENUM;
|
default:
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: QueryProgramStateIntVector error: invalid pname 0x%X", pname);
|
||||||
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: QueryProgramStateIntVector success: value=%d", *params);
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum ProgramState::QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params) {
|
GLenum ProgramState::QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params) {
|
||||||
if (!ValidateShader_(shader)) return GL_INVALID_VALUE;
|
MG_Util::Debug::LogD("MG_State: Program: QueryShaderStateIntVector called, shader=%u, pname=0x%X",
|
||||||
|
shader, pname);
|
||||||
|
if (!ValidateShader_(shader)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: QueryShaderStateIntVector error: invalid shader id %u", shader);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
auto& obj = shaders_[shader];
|
auto& obj = shaders_[shader];
|
||||||
|
|
||||||
switch (pname) {
|
switch (pname) {
|
||||||
case GL_COMPILE_STATUS: *params = obj.compileStatus; break;
|
case GL_COMPILE_STATUS: *params = obj.compileStatus; break;
|
||||||
case GL_DELETE_STATUS: *params = obj.markedForDeletion; break;
|
case GL_DELETE_STATUS: *params = obj.markedForDeletion; break;
|
||||||
case GL_SHADER_TYPE: *params = obj.type; break;
|
case GL_SHADER_TYPE: *params = obj.type; break;
|
||||||
default: return GL_INVALID_ENUM;
|
default:
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: QueryShaderStateIntVector error: invalid pname 0x%X", pname);
|
||||||
|
return GL_INVALID_ENUM;
|
||||||
}
|
}
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: QueryShaderStateIntVector success: value=%d", *params);
|
||||||
return GL_NO_ERROR;
|
return GL_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgramState::SetProgramStatus(GLuint program, GLboolean status) {
|
template<typename T>
|
||||||
if (!ValidateProgram_(program)) return false;
|
GLenum ProgramState::SetUniform(GLuint program, GLint location, GLsizei count, const T* value, GLenum type) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: SetUniform called, program=%u, location=%d, count=%d, type=0x%X",
|
||||||
|
program, location, count, type);
|
||||||
|
if (!ValidateProgram_(program)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetUniform error: invalid program id %u", program);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (location < -1) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetUniform error: invalid location %d", location);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (count < 0) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetUniform error: invalid count %d", count);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (location == -1) {
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: SetUniform warning: location -1, no-op");
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramObject& prog = programs_[program];
|
||||||
|
std::string uniformName;
|
||||||
|
for (const auto& pair : prog.uniformLocations) {
|
||||||
|
if (pair.second == location) {
|
||||||
|
uniformName = pair.first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (uniformName.empty()) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetUniform error: no uniform at location %d in program %u",
|
||||||
|
location, program);
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniformValue& uniform = prog.uniformValues[uniformName];
|
||||||
|
uniform.setData(type, count, value);
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: SetUniform success: %s set", uniformName.c_str());
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
GLenum ProgramState::SetUniformMatrix(GLuint program, GLint location, GLsizei count, GLboolean transpose, const T* value, GLenum matrixType) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: SetUniformMatrix called, program=%u, location=%d, count=%d, matrixType=0x%X",
|
||||||
|
program, location, count, matrixType);
|
||||||
|
(void)transpose;
|
||||||
|
if (!ValidateProgram_(program)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetUniformMatrix error: invalid program id %u", program);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (location < -1) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetUniformMatrix error: invalid location %d", location);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (count < 0) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetUniformMatrix error: invalid count %d", count);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (location == -1) {
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: SetUniformMatrix warning: location -1, no-op");
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramObject& prog = programs_[program];
|
||||||
|
std::string uniformName;
|
||||||
|
for (const auto& pair : prog.uniformLocations) {
|
||||||
|
if (pair.second == location) {
|
||||||
|
uniformName = pair.first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (uniformName.empty()) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetUniformMatrix error: no uniform at location %d in program %u",
|
||||||
|
location, program);
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniformValue& uniform = prog.uniformValues[uniformName];
|
||||||
|
uniform.setData(matrixType, count * MG_Util::Program::GetMatrixElementCount(matrixType), value);
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: SetUniformMatrix success: %s set", uniformName.c_str());
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IMPLEMENT_UNIFORM_FUNCTIONS(type, suffix, vecType) \
|
||||||
|
void ProgramState::UpdateUniform##suffix##1(GLint location, type v0) { \
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "1 called, location=%d", location); \
|
||||||
|
SetUniform<type>(currentProgram_, location, 1, &v0, vecType); \
|
||||||
|
} \
|
||||||
|
void ProgramState::UpdateUniform##suffix##2(GLint location, type v0, type v1) { \
|
||||||
|
type values[2] = {v0, v1}; \
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "2 called, location=%d", location); \
|
||||||
|
SetUniform<type>(currentProgram_, location, 1, values, vecType); \
|
||||||
|
} \
|
||||||
|
void ProgramState::UpdateUniform##suffix##3(GLint location, type v0, type v1, type v2) { \
|
||||||
|
type values[3] = {v0, v1, v2}; \
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "3 called, location=%d", location); \
|
||||||
|
SetUniform<type>(currentProgram_, location, 1, values, vecType); \
|
||||||
|
} \
|
||||||
|
void ProgramState::UpdateUniform##suffix##4(GLint location, type v0, type v1, type v2, type v3) { \
|
||||||
|
type values[4] = {v0, v1, v2, v3}; \
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "4 called, location=%d", location); \
|
||||||
|
SetUniform<type>(currentProgram_, location, 1, values, vecType); \
|
||||||
|
} \
|
||||||
|
void ProgramState::UpdateUniform##suffix##Vector1(GLint location, GLsizei count, const type* value) { \
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "Vector1 called, location=%d, count=%d", location, count); \
|
||||||
|
SetUniform<type>(currentProgram_, location, count, value, vecType); \
|
||||||
|
} \
|
||||||
|
void ProgramState::UpdateUniform##suffix##Vector2(GLint location, GLsizei count, const type* value) { \
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "Vector2 called, location=%d, count=%d", location, count); \
|
||||||
|
SetUniform<type>(currentProgram_, location, count * 2, value, vecType); \
|
||||||
|
} \
|
||||||
|
void ProgramState::UpdateUniform##suffix##Vector3(GLint location, GLsizei count, const type* value) { \
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "Vector3 called, location=%d, count=%d", location, count); \
|
||||||
|
SetUniform<type>(currentProgram_, location, count * 3, value, vecType); \
|
||||||
|
} \
|
||||||
|
void ProgramState::UpdateUniform##suffix##Vector4(GLint location, GLsizei count, const type* value) { \
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UpdateUniform" #suffix "Vector4 called, location=%d, count=%d", location, count); \
|
||||||
|
SetUniform<type>(currentProgram_, location, count * 4, value, vecType); \
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_UNIFORM_FUNCTIONS(GLfloat, Float, GL_FLOAT_VEC4)
|
||||||
|
IMPLEMENT_UNIFORM_FUNCTIONS(GLint, Int, GL_INT_VEC4)
|
||||||
|
IMPLEMENT_UNIFORM_FUNCTIONS(GLuint, UInt, GL_UNSIGNED_INT_VEC4)
|
||||||
|
IMPLEMENT_UNIFORM_FUNCTIONS(GLboolean, Bool, GL_BOOL_VEC4)
|
||||||
|
#undef IMPLEMENT_UNIFORM_FUNCTIONS
|
||||||
|
|
||||||
|
#define IMPLEMENT_MATRIX_FUNCTIONS(suffix, matrixType) \
|
||||||
|
void ProgramState::UpdateUniformMatrix##suffix##Vector(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { \
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UpdateUniformMatrix" #suffix "Vector called, location=%d, count=%d", location, count); \
|
||||||
|
SetUniformMatrix<GLfloat>(currentProgram_, location, count, transpose, value, matrixType); \
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(2x2, GL_FLOAT_MAT2)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(3x3, GL_FLOAT_MAT3)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(4x4, GL_FLOAT_MAT4)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(2x3, GL_FLOAT_MAT2x3)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(2x4, GL_FLOAT_MAT2x4)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(3x2, GL_FLOAT_MAT3x2)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(3x4, GL_FLOAT_MAT3x4)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(4x2, GL_FLOAT_MAT4x2)
|
||||||
|
IMPLEMENT_MATRIX_FUNCTIONS(4x3, GL_FLOAT_MAT4x3)
|
||||||
|
#undef IMPLEMENT_MATRIX_FUNCTIONS
|
||||||
|
|
||||||
|
GLint ProgramState::QueryProgramUniformLocation(GLuint program, const GLchar* name) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: QueryProgramUniformLocation called, program=%u, name=%s", program, name);
|
||||||
|
if (!ValidateProgram_(program)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: QueryProgramUniformLocation error: invalid program id %u", program);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
auto& prog = programs_[program];
|
auto& prog = programs_[program];
|
||||||
if (prog.linked && status != GL_TRUE) {
|
auto it = prog.uniformLocations.find(name);
|
||||||
|
if (it != prog.uniformLocations.end()) {
|
||||||
|
GLint loc = it->second;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: QueryProgramUniformLocation success: %s -> %d", name, loc);
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: QueryProgramUniformLocation warning: name '%s' not found", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProgramState::SetProgramStatus(GLuint program, GLboolean status) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: SetProgramStatus called, program=%u, status=%d", program, status);
|
||||||
|
if (!ValidateProgram_(program)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetProgramStatus error: invalid program id %u", program);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (status == GL_TRUE)
|
auto& prog = programs_[program];
|
||||||
prog.linked = true;
|
if (prog.linked.getValue() != UncertainBool::Unknown) {
|
||||||
else
|
MG_Util::Debug::LogW("MG_State: Program: SetProgramStatus warning: link state already known");
|
||||||
prog.linked = false;
|
return false;
|
||||||
|
}
|
||||||
|
prog.linked = (status == GL_TRUE) ? UncertainBool::True : UncertainBool::False;
|
||||||
prog.linkStatus = status;
|
prog.linkStatus = status;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: SetProgramStatus success, status=%d", status);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgramState::SetShaderStatus(GLuint shader, GLboolean status) {
|
GLuint ProgramState::GetCurrentProgram() const {
|
||||||
if (!ValidateShader_(shader)) return false;
|
MG_Util::Debug::LogD("MG_State: Program: GetCurrentProgram called, returning %u", currentProgram_);
|
||||||
auto& obj = shaders_[shader];
|
return currentProgram_;
|
||||||
if (status == GL_TRUE)
|
|
||||||
obj.compiled = true;
|
|
||||||
else
|
|
||||||
obj.compiled = false;
|
|
||||||
obj.compileStatus = status;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgramState::ValidateShader_(GLuint shader) {
|
ShaderObject ProgramState::GetShaderObject(GLuint shader) const {
|
||||||
return shaders_.count(shader) && !shaders_[shader].markedForDeletion;
|
MG_Util::Debug::LogD("MG_State: Program: GetShaderObject called, shader=%u", shader);
|
||||||
|
auto it = shaders_.find(shader);
|
||||||
|
if (it == shaders_.end()) {
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: GetShaderObject warning: invalid shader id %u", shader);
|
||||||
|
return ShaderObject();
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: GetShaderObject success, returning object");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramObject ProgramState::GetProgramObject(GLuint program) const {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: GetProgramObject called, program=%u", program);
|
||||||
|
auto it = programs_.find(program);
|
||||||
|
if (it == programs_.end()) {
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: GetProgramObject warning: invalid program id %u", program);
|
||||||
|
return ProgramObject();
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: GetProgramObject success, returning object");
|
||||||
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProgramState::ValidateProgram_(GLuint program) {
|
bool ProgramState::ValidateProgram_(GLuint program) {
|
||||||
return programs_.count(program) && !programs_[program].markedForDeletion;
|
bool ok = programs_.count(program) && !programs_[program].markedForDeletion;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: ValidateProgram_ called, program=%u, result=%d", program, ok);
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgramState::CleanupShaders_() {
|
void ProgramState::CleanupShaders_() {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: CleanupShaders_ start");
|
||||||
auto it = shaders_.begin();
|
auto it = shaders_.begin();
|
||||||
while (it != shaders_.end()) {
|
while (it != shaders_.end()) {
|
||||||
if (it->second.markedForDeletion) {
|
if (it->second.markedForDeletion) {
|
||||||
bool inUse = false;
|
bool inUse = false;
|
||||||
for (auto& [progId, program] : programs_) {
|
for (auto& [progId, program] : programs_) {
|
||||||
if (std::find(program.attachedShaders.begin(),
|
if (std::find(program.attachedShaders.begin(),
|
||||||
program.attachedShaders.end(), it->first)
|
program.attachedShaders.end(), it->first) != program.attachedShaders.end()) {
|
||||||
!= program.attachedShaders.end()) {
|
|
||||||
inUse = true;
|
inUse = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!inUse) {
|
if (!inUse) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: CleanupShaders_ deleting shader %u", it->first);
|
||||||
freeShaderIds_.insert(it->first);
|
freeShaderIds_.insert(it->first);
|
||||||
it = shaders_.erase(it);
|
it = shaders_.erase(it);
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
} else {
|
MG_Util::Debug::LogD("MG_State: Program: CleanupShaders_ end");
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint ProgramState::GetCurrentProgram() const {
|
// UniformValue
|
||||||
return currentProgram_;
|
template<typename T>
|
||||||
|
void UniformValue::setData(GLenum uniformType, GLsizei numElements, const T* values) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UniformValue::setData called, type=0x%X, count=%d", uniformType, numElements);
|
||||||
|
type = uniformType;
|
||||||
|
count = numElements;
|
||||||
|
|
||||||
|
floatData.clear();
|
||||||
|
intData.clear();
|
||||||
|
uintData.clear();
|
||||||
|
boolData.clear();
|
||||||
|
|
||||||
|
for (GLsizei i = 0; i < numElements; ++i) {
|
||||||
|
switch (uniformType) {
|
||||||
|
case GL_FLOAT:
|
||||||
|
case GL_FLOAT_VEC2:
|
||||||
|
case GL_FLOAT_VEC3:
|
||||||
|
case GL_FLOAT_VEC4:
|
||||||
|
case GL_FLOAT_MAT2:
|
||||||
|
case GL_FLOAT_MAT3:
|
||||||
|
case GL_FLOAT_MAT4:
|
||||||
|
case GL_FLOAT_MAT2x3:
|
||||||
|
case GL_FLOAT_MAT2x4:
|
||||||
|
case GL_FLOAT_MAT3x2:
|
||||||
|
case GL_FLOAT_MAT3x4:
|
||||||
|
case GL_FLOAT_MAT4x2:
|
||||||
|
case GL_FLOAT_MAT4x3:
|
||||||
|
floatData.push_back(static_cast<GLfloat>(values[i]));
|
||||||
|
break;
|
||||||
|
case GL_INT:
|
||||||
|
case GL_INT_VEC2:
|
||||||
|
case GL_INT_VEC3:
|
||||||
|
case GL_INT_VEC4:
|
||||||
|
case GL_SAMPLER_1D:
|
||||||
|
case GL_SAMPLER_2D:
|
||||||
|
case GL_SAMPLER_3D:
|
||||||
|
case GL_SAMPLER_CUBE:
|
||||||
|
case GL_SAMPLER_1D_SHADOW:
|
||||||
|
case GL_SAMPLER_2D_SHADOW:
|
||||||
|
case GL_SAMPLER_CUBE_SHADOW:
|
||||||
|
case GL_SAMPLER_1D_ARRAY:
|
||||||
|
case GL_SAMPLER_2D_ARRAY:
|
||||||
|
case GL_SAMPLER_1D_ARRAY_SHADOW:
|
||||||
|
case GL_SAMPLER_2D_ARRAY_SHADOW:
|
||||||
|
case GL_SAMPLER_BUFFER:
|
||||||
|
case GL_SAMPLER_2D_MULTISAMPLE:
|
||||||
|
case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
|
||||||
|
intData.push_back(static_cast<GLint>(values[i]));
|
||||||
|
break;
|
||||||
|
case GL_UNSIGNED_INT:
|
||||||
|
case GL_UNSIGNED_INT_VEC2:
|
||||||
|
case GL_UNSIGNED_INT_VEC3:
|
||||||
|
case GL_UNSIGNED_INT_VEC4:
|
||||||
|
uintData.push_back(static_cast<GLuint>(values[i]));
|
||||||
|
break;
|
||||||
|
case GL_BOOL:
|
||||||
|
case GL_BOOL_VEC2:
|
||||||
|
case GL_BOOL_VEC3:
|
||||||
|
case GL_BOOL_VEC4:
|
||||||
|
boolData.push_back(values[i] ? GL_TRUE : GL_FALSE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: UniformValue::setData warning: unsupported type 0x%X", uniformType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UniformValue::setData end");
|
||||||
}
|
}
|
||||||
@@ -5,18 +5,35 @@
|
|||||||
#ifndef MOBILEGL_PROGRAMSTATE_H
|
#ifndef MOBILEGL_PROGRAMSTATE_H
|
||||||
#define MOBILEGL_PROGRAMSTATE_H
|
#define MOBILEGL_PROGRAMSTATE_H
|
||||||
#define MOBILEGL_GLSTATE_H
|
#define MOBILEGL_GLSTATE_H
|
||||||
|
#define MOBILEGL_PROGRAM_DEBUGTOOL_H
|
||||||
|
#define MOBILEGL_GLSLTOOL_H
|
||||||
|
|
||||||
#include "../../../Includes.h"
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
struct ShaderObject {
|
struct ShaderObject {
|
||||||
GLenum type;
|
GLenum type;
|
||||||
std::string source;
|
std::string source;
|
||||||
|
std::vector<unsigned int> compiledSpirv;
|
||||||
UncertainBool compiled;
|
UncertainBool compiled;
|
||||||
GLint compileStatus;
|
GLint compileStatus;
|
||||||
std::string infoLog;
|
std::string infoLog;
|
||||||
bool markedForDeletion;
|
bool markedForDeletion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UniformValue {
|
||||||
|
GLenum type;
|
||||||
|
std::vector<GLfloat> floatData;
|
||||||
|
std::vector<GLint> intData;
|
||||||
|
std::vector<GLuint> uintData;
|
||||||
|
std::vector<GLboolean> boolData;
|
||||||
|
GLsizei count;
|
||||||
|
|
||||||
|
UniformValue() : type(0), count(0) {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void setData(GLenum uniformType, GLsizei numElements, const T* values);
|
||||||
|
};
|
||||||
|
|
||||||
struct ProgramObject {
|
struct ProgramObject {
|
||||||
std::vector<GLuint> attachedShaders;
|
std::vector<GLuint> attachedShaders;
|
||||||
UncertainBool linked;
|
UncertainBool linked;
|
||||||
@@ -25,6 +42,7 @@ struct ProgramObject {
|
|||||||
std::unordered_map<std::string, GLint> attribBindings;
|
std::unordered_map<std::string, GLint> attribBindings;
|
||||||
std::unordered_map<std::string, GLint> attribLocations;
|
std::unordered_map<std::string, GLint> attribLocations;
|
||||||
std::unordered_map<std::string, GLint> uniformLocations;
|
std::unordered_map<std::string, GLint> uniformLocations;
|
||||||
|
std::unordered_map<std::string, UniformValue> uniformValues;
|
||||||
bool markedForDeletion;
|
bool markedForDeletion;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,6 +57,9 @@ private:
|
|||||||
GLuint currentProgram_ = 0;
|
GLuint currentProgram_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
ProgramState();
|
||||||
|
~ProgramState();
|
||||||
|
|
||||||
// Return: the validity of the operation, according to OpenGL 3 standard
|
// Return: the validity of the operation, according to OpenGL 3 standard
|
||||||
GLenum CreateShader(GLenum type, GLuint* shader);
|
GLenum CreateShader(GLenum type, GLuint* shader);
|
||||||
GLenum CreateProgram(GLuint* program);
|
GLenum CreateProgram(GLuint* program);
|
||||||
@@ -55,6 +76,41 @@ public:
|
|||||||
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
|
GLenum QueryProgramStateIntVector(GLuint program, GLenum pname, GLint* params);
|
||||||
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
|
GLenum QueryShaderStateIntVector(GLuint shader, GLenum pname, GLint* params);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
GLenum SetUniform(GLuint program, GLint location, GLsizei count, const T* value, GLenum type);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
GLenum SetUniformMatrix(GLuint program, GLint location, GLsizei count, GLboolean transpose, const T* value, GLenum matrixType);
|
||||||
|
|
||||||
|
#define DECLARE_UNIFORM_FUNCTIONS(type, suffix, vecType) \
|
||||||
|
void UpdateUniform##suffix##1(GLint location, type v0); \
|
||||||
|
void UpdateUniform##suffix##2(GLint location, type v0, type v1); \
|
||||||
|
void UpdateUniform##suffix##3(GLint location, type v0, type v1, type v2); \
|
||||||
|
void UpdateUniform##suffix##4(GLint location, type v0, type v1, type v2, type v3); \
|
||||||
|
void UpdateUniform##suffix##Vector1(GLint location, GLsizei count, const type* value); \
|
||||||
|
void UpdateUniform##suffix##Vector2(GLint location, GLsizei count, const type* value); \
|
||||||
|
void UpdateUniform##suffix##Vector3(GLint location, GLsizei count, const type* value); \
|
||||||
|
void UpdateUniform##suffix##Vector4(GLint location, GLsizei count, const type* value);
|
||||||
|
DECLARE_UNIFORM_FUNCTIONS(GLfloat, Float, GL_FLOAT)
|
||||||
|
DECLARE_UNIFORM_FUNCTIONS(GLint, Int, GL_INT)
|
||||||
|
DECLARE_UNIFORM_FUNCTIONS(GLuint, UInt, GL_UNSIGNED_INT)
|
||||||
|
DECLARE_UNIFORM_FUNCTIONS(GLboolean, Bool, GL_BOOL)
|
||||||
|
#undef DECLARE_UNIFORM_FUNCTIONS
|
||||||
|
#define DECLARE_MATRIX_FUNCTIONS(suffix, matrixType) \
|
||||||
|
void UpdateUniformMatrix##suffix##Vector(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(2x2, GL_FLOAT_MAT2)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(3x3, GL_FLOAT_MAT3)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(4x4, GL_FLOAT_MAT4)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(2x3, GL_FLOAT_MAT2x3)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(2x4, GL_FLOAT_MAT2x4)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(3x2, GL_FLOAT_MAT3x2)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(3x4, GL_FLOAT_MAT3x4)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(4x2, GL_FLOAT_MAT4x2)
|
||||||
|
DECLARE_MATRIX_FUNCTIONS(4x3, GL_FLOAT_MAT4x3)
|
||||||
|
#undef DECLARE_MATRIX_FUNCTIONS
|
||||||
|
|
||||||
|
ProgramObject GetProgramObject(GLuint program) const;
|
||||||
|
ShaderObject GetShaderObject(GLuint program) const;
|
||||||
GLuint GetCurrentProgram() const;
|
GLuint GetCurrentProgram() const;
|
||||||
bool SetProgramStatus(GLuint program, GLboolean status);
|
bool SetProgramStatus(GLuint program, GLboolean status);
|
||||||
bool SetShaderStatus(GLuint shader, GLboolean status);
|
bool SetShaderStatus(GLuint shader, GLboolean status);
|
||||||
@@ -63,6 +119,7 @@ private:
|
|||||||
bool ValidateShader_(GLuint shader);
|
bool ValidateShader_(GLuint shader);
|
||||||
bool ValidateProgram_(GLuint program);
|
bool ValidateProgram_(GLuint program);
|
||||||
void CleanupShaders_();
|
void CleanupShaders_();
|
||||||
|
GLint GetUniformLocation_(GLuint program, GLint location, const GLchar* name);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MOBILEGL_PROGRAMSTATE_H
|
#endif // MOBILEGL_PROGRAMSTATE_H
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
//
|
||||||
|
// Created by BZLZHH on 2025/5/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ShaderObject.h"
|
||||||
|
|
||||||
|
// Re-Include Includes.h, cuz of the absence of Program/DebugTool.h and Program/GLSLTool.cpp.
|
||||||
|
#undef MOBILEGL_GLSLTOOL_H
|
||||||
|
#undef MOBILEGL_PROGRAM_DEBUGTOOL_H
|
||||||
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
|
GLenum ProgramState::CreateShader(GLenum type, GLuint* shader) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: CreateShader called, type=0x%X, shader ptr=%p", type, shader);
|
||||||
|
if (!shader) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: CreateShader error: shader pointer is null");
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (type != GL_VERTEX_SHADER && type != GL_FRAGMENT_SHADER) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: CreateShader error: invalid shader type 0x%X", type);
|
||||||
|
return GL_INVALID_ENUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint id = freeShaderIds_.empty() ? ++lastShaderId_ : *freeShaderIds_.begin();
|
||||||
|
if (!freeShaderIds_.empty())
|
||||||
|
freeShaderIds_.erase(freeShaderIds_.begin());
|
||||||
|
|
||||||
|
ShaderObject obj;
|
||||||
|
obj.type = type;
|
||||||
|
obj.compiled = {UncertainBool::Unknown, UncertainBool::False};
|
||||||
|
obj.compiledSpirv = {};
|
||||||
|
obj.markedForDeletion = false;
|
||||||
|
obj.compileStatus = GL_FALSE;
|
||||||
|
shaders_[id] = obj;
|
||||||
|
*shader = id;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: CreateShader success, new shader id=%u", id);
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum ProgramState::DeleteShader(GLuint shader) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: DeleteShader called, shader id=%u", shader);
|
||||||
|
if (!ValidateShader_(shader)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: DeleteShader error: invalid shader id %u", shader);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (shaders_[shader].markedForDeletion) {
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: DeleteShader warning: shader %u already marked for deletion", shader);
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool inUse = false;
|
||||||
|
for (auto& [progId, program] : programs_) {
|
||||||
|
if (std::find(program.attachedShaders.begin(),
|
||||||
|
program.attachedShaders.end(), shader) != program.attachedShaders.end()) {
|
||||||
|
inUse = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inUse) {
|
||||||
|
shaders_[shader].markedForDeletion = true;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: DeleteShader info: shader %u marked for deferred deletion (in use)", shader);
|
||||||
|
} else {
|
||||||
|
shaders_.erase(shader);
|
||||||
|
freeShaderIds_.insert(shader);
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: DeleteShader success: shader %u deleted immediately", shader);
|
||||||
|
}
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum ProgramState::UploadShaderSource(GLuint shader, GLsizei count,
|
||||||
|
const GLchar** string, const GLint* length) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UploadShaderSource called, shader id=%u, count=%d", shader, count);
|
||||||
|
if (!ValidateShader_(shader)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: UploadShaderSource error: invalid shader id %u", shader);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
if (count < 0) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: UploadShaderSource error: negative count %d", count);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string source;
|
||||||
|
for (GLsizei i = 0; i < count; ++i) {
|
||||||
|
const GLchar* str = string[i];
|
||||||
|
GLint len = (length && length[i] >= 0) ? length[i] : strlen(str);
|
||||||
|
source.append(str, len);
|
||||||
|
}
|
||||||
|
shaders_[shader].source = std::move(source);
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: UploadShaderSource success: source uploaded (length=%zu)", shaders_[shader].source.size());
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum ProgramState::BuildShaderStage(GLuint shader) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: BuildShaderStage called, shader id=%u", shader);
|
||||||
|
if (!ValidateShader_(shader)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: BuildShaderStage error: invalid shader id %u", shader);
|
||||||
|
return GL_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
auto& obj = shaders_[shader];
|
||||||
|
|
||||||
|
std::string compilationLog;
|
||||||
|
auto spirv = MG_Util::Program::CompileGLSLToSPIRV(obj.type, obj.source, compilationLog);
|
||||||
|
if (spirv.empty()) {
|
||||||
|
obj.infoLog = "Shader compilation failed: " + compilationLog;
|
||||||
|
obj.compiled = UncertainBool::False;
|
||||||
|
obj.compileStatus = GL_FALSE;
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: BuildShaderStage error: %s", compilationLog.c_str());
|
||||||
|
return GL_INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
obj.compiledSpirv = spirv;
|
||||||
|
obj.compiled = {UncertainBool::Unknown, UncertainBool::True};
|
||||||
|
obj.compileStatus = GL_TRUE;
|
||||||
|
obj.infoLog.clear();
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: BuildShaderStage success: shader %u compiled to SPIR-V (size=%zu bytes)", shader, spirv.size() * sizeof(unsigned));
|
||||||
|
return GL_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProgramState::SetShaderStatus(GLuint shader, GLboolean status) {
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: SetShaderStatus called, shader id=%u, status=%d", shader, status);
|
||||||
|
if (!ValidateShader_(shader)) {
|
||||||
|
MG_Util::Debug::LogE("MG_State: Program: SetShaderStatus error: invalid shader id %u", shader);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto& obj = shaders_[shader];
|
||||||
|
if (obj.compiled.getValue() != UncertainBool::Unknown) {
|
||||||
|
MG_Util::Debug::LogW("MG_State: Program: SetShaderStatus warning: shader %u status already set", shader);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
obj.compiled = (status == GL_TRUE) ? UncertainBool::True : UncertainBool::False;
|
||||||
|
obj.compileStatus = status;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: SetShaderStatus success: shader %u status=%d", shader, status);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProgramState::ValidateShader_(GLuint shader) {
|
||||||
|
bool valid = shaders_.count(shader) && !shaders_[shader].markedForDeletion;
|
||||||
|
MG_Util::Debug::LogD("MG_State: Program: ValidateShader_ called, shader id=%u, result=%d", shader, valid);
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Created by BZLZHH on 2025/5/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MOBILEGL_SHADEROBJECT_H
|
||||||
|
#define MOBILEGL_SHADEROBJECT_H
|
||||||
|
|
||||||
|
#define MOBILEGL_GLSTATE_H
|
||||||
|
|
||||||
|
#include "../../../Includes.h"
|
||||||
|
|
||||||
|
#endif //MOBILEGL_SHADEROBJECT_H
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
//
|
||||||
|
// Created by BZLZHH on 2025/5/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "DebugTool.h"
|
||||||
|
|
||||||
|
namespace MG_Util::Program {
|
||||||
|
std::string GLTypeToString(GLenum type) {
|
||||||
|
switch(type) {
|
||||||
|
case GL_FLOAT: return "float";
|
||||||
|
case GL_FLOAT_VEC2: return "vec2";
|
||||||
|
case GL_FLOAT_VEC3: return "vec3";
|
||||||
|
case GL_FLOAT_VEC4: return "vec4";
|
||||||
|
case GL_INT: return "int";
|
||||||
|
case GL_INT_VEC2: return "ivec2";
|
||||||
|
case GL_INT_VEC3: return "ivec3";
|
||||||
|
case GL_INT_VEC4: return "ivec4";
|
||||||
|
case GL_UNSIGNED_INT: return "uint";
|
||||||
|
case GL_UNSIGNED_INT_VEC2: return "uvec2";
|
||||||
|
case GL_UNSIGNED_INT_VEC3: return "uvec3";
|
||||||
|
case GL_UNSIGNED_INT_VEC4: return "uvec4";
|
||||||
|
case GL_BOOL: return "bool";
|
||||||
|
case GL_BOOL_VEC2: return "bvec2";
|
||||||
|
case GL_BOOL_VEC3: return "bvec3";
|
||||||
|
case GL_BOOL_VEC4: return "bvec4";
|
||||||
|
case GL_FLOAT_MAT2: return "mat2";
|
||||||
|
case GL_FLOAT_MAT3: return "mat3";
|
||||||
|
case GL_FLOAT_MAT4: return "mat4";
|
||||||
|
case GL_FLOAT_MAT2x3: return "mat2x3";
|
||||||
|
case GL_FLOAT_MAT2x4: return "mat2x4";
|
||||||
|
case GL_FLOAT_MAT3x2: return "mat3x2";
|
||||||
|
case GL_FLOAT_MAT3x4: return "mat3x4";
|
||||||
|
case GL_FLOAT_MAT4x2: return "mat4x2";
|
||||||
|
case GL_FLOAT_MAT4x3: return "mat4x3";
|
||||||
|
case GL_SAMPLER_1D: return "sampler1D";
|
||||||
|
case GL_SAMPLER_2D: return "sampler2D";
|
||||||
|
case GL_SAMPLER_3D: return "sampler3D";
|
||||||
|
case GL_SAMPLER_CUBE: return "samplerCube";
|
||||||
|
case GL_SAMPLER_1D_SHADOW: return "sampler1DShadow";
|
||||||
|
case GL_SAMPLER_2D_SHADOW: return "sampler2DShadow";
|
||||||
|
case GL_SAMPLER_CUBE_SHADOW: return "samplerCubeShadow";
|
||||||
|
case GL_SAMPLER_1D_ARRAY: return "sampler1DArray";
|
||||||
|
case GL_SAMPLER_2D_ARRAY: return "sampler2DArray";
|
||||||
|
case GL_SAMPLER_1D_ARRAY_SHADOW: return "sampler1DArrayShadow";
|
||||||
|
case GL_SAMPLER_2D_ARRAY_SHADOW: return "sampler2DArrayShadow";
|
||||||
|
case GL_SAMPLER_BUFFER: return "samplerBuffer";
|
||||||
|
case GL_SAMPLER_2D_MULTISAMPLE: return "sampler2DMS";
|
||||||
|
case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: return "sampler2DMSArray";
|
||||||
|
default: return "UnknownType(0x" + std::to_string(type) + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FormatUniformValue(const UniformValue& value) {
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "[";
|
||||||
|
|
||||||
|
const size_t elemCount = std::min<size_t>(value.count, 16); // 限制最大显示元素
|
||||||
|
|
||||||
|
switch(value.type) {
|
||||||
|
case GL_FLOAT:
|
||||||
|
case GL_FLOAT_VEC2:
|
||||||
|
case GL_FLOAT_VEC3:
|
||||||
|
case GL_FLOAT_VEC4:
|
||||||
|
case GL_FLOAT_MAT2:
|
||||||
|
case GL_FLOAT_MAT3:
|
||||||
|
case GL_FLOAT_MAT4:
|
||||||
|
case GL_FLOAT_MAT2x3:
|
||||||
|
case GL_FLOAT_MAT2x4:
|
||||||
|
case GL_FLOAT_MAT3x2:
|
||||||
|
case GL_FLOAT_MAT3x4:
|
||||||
|
case GL_FLOAT_MAT4x2:
|
||||||
|
case GL_FLOAT_MAT4x3:
|
||||||
|
for(size_t i=0; i<elemCount; ++i) {
|
||||||
|
if (i > 0) ss << ", ";
|
||||||
|
ss << (i < value.floatData.size() ? value.floatData[i] : 0.0f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_INT:
|
||||||
|
case GL_INT_VEC2:
|
||||||
|
case GL_INT_VEC3:
|
||||||
|
case GL_INT_VEC4:
|
||||||
|
for(size_t i=0; i<elemCount; ++i) {
|
||||||
|
if (i > 0) ss << ", ";
|
||||||
|
ss << (i < value.intData.size() ? value.intData[i] : 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_UNSIGNED_INT:
|
||||||
|
case GL_UNSIGNED_INT_VEC2:
|
||||||
|
case GL_UNSIGNED_INT_VEC3:
|
||||||
|
case GL_UNSIGNED_INT_VEC4:
|
||||||
|
for(size_t i=0; i<elemCount; ++i) {
|
||||||
|
if (i > 0) ss << ", ";
|
||||||
|
ss << (i < value.uintData.size() ? value.uintData[i] : 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_BOOL:
|
||||||
|
case GL_BOOL_VEC2:
|
||||||
|
case GL_BOOL_VEC3:
|
||||||
|
case GL_BOOL_VEC4:
|
||||||
|
for(size_t i=0; i<elemCount; ++i) {
|
||||||
|
if (i > 0) ss << ", ";
|
||||||
|
ss << (i < value.boolData.size() ? (value.boolData[i] ? "true" : "false") : "false");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ss << "N/A";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.count > elemCount) ss << ", ...";
|
||||||
|
ss << "]";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpUniforms(const ProgramState& state, GLuint program) {
|
||||||
|
if (MG_Global::Common::LogLevel > MG_Constants::Common::LOG_LEVEL_DEBUG)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto prog = (ProgramObject)state.GetProgramObject(program);
|
||||||
|
if (!prog.linked.toBool()) {
|
||||||
|
MG_Util::Debug::LogE("Program %u not linked", program);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MG_Util::Debug::LogD("=== Dumping uniforms for program %u ===", program);
|
||||||
|
for(const auto& [name, loc] : prog.uniformLocations) {
|
||||||
|
const auto& value = prog.uniformValues.at(name);
|
||||||
|
MG_Util::Debug::LogD("Uniform: %-24s Location: %-4d Type: %-16s Count: %-3d Value: %s",
|
||||||
|
name.c_str(),
|
||||||
|
loc,
|
||||||
|
GLTypeToString(value.type).c_str(),
|
||||||
|
value.count,
|
||||||
|
FormatUniformValue(value).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpCurrentUniforms(const ProgramState& state) {
|
||||||
|
if (MG_Global::Common::LogLevel > MG_Constants::Common::LOG_LEVEL_DEBUG)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GLuint current = state.GetCurrentProgram();
|
||||||
|
if (current == 0) {
|
||||||
|
MG_Util::Debug::LogE("No active program");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DumpUniforms(state, current);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// Created by BZLZHH on 2025/5/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MOBILEGL_PROGRAM_DEBUGTOOL_H
|
||||||
|
#define MOBILEGL_PROGRAM_DEBUGTOOL_H
|
||||||
|
#include "../../Includes.h"
|
||||||
|
|
||||||
|
namespace MG_Util::Program {
|
||||||
|
std::string GLTypeToString(GLenum type);
|
||||||
|
std::string FormatUniformValue(const UniformValue& value);
|
||||||
|
void DumpUniforms(const ProgramState& state, GLuint program);
|
||||||
|
void DumpCurrentUniforms(const ProgramState& state);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MOBILEGL_PROGRAM_DEBUGTOOL_H
|
||||||
@@ -0,0 +1,405 @@
|
|||||||
|
//
|
||||||
|
// Created by BZLZHH on 2025/5/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "GLSLTool.h"
|
||||||
|
|
||||||
|
namespace MG_Util::Program {
|
||||||
|
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source, glslang::TShader *&shader) {
|
||||||
|
std::string infoLog;
|
||||||
|
using namespace glslang;
|
||||||
|
|
||||||
|
int glslVersion = QueryGLSLVersion(source);
|
||||||
|
EShLanguage language = GetEShLanguageByShaderType(shaderType);
|
||||||
|
if (language == EShLanguage::EShLangCount) {
|
||||||
|
infoLog += "Error: [Preprocess] Unsupported shader type: " +
|
||||||
|
std::to_string(shaderType);
|
||||||
|
TShader tmpShader(EShLanguage::EShLangVertex);
|
||||||
|
return infoLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader = new TShader(language);
|
||||||
|
const char *src = source.c_str();
|
||||||
|
shader->setStrings(&src, 1);
|
||||||
|
shader->setEnvInput(EShSourceGlsl, language, EShClientVulkan, glslVersion);
|
||||||
|
shader->setEnvClient(EShClientOpenGL, EShTargetOpenGL_450);
|
||||||
|
shader->setEnvTarget(EShTargetSpv, EShTargetSpv_1_6);
|
||||||
|
shader->setAutoMapLocations(true);
|
||||||
|
shader->setAutoMapBindings(true);
|
||||||
|
|
||||||
|
// Is InitResources() really correct?
|
||||||
|
TBuiltInResource resources = InitResources();
|
||||||
|
|
||||||
|
if (!shader->parse(&resources, glslVersion, true, EShMsgDefault)) {
|
||||||
|
infoLog += "Error: [glslang] Cannot compile the " + GetShaderTypeName(shaderType) + ":\n"
|
||||||
|
+ std::to_string(shader->getInfoLog());
|
||||||
|
return infoLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<unsigned>> CompileMultipleShadersToSPIRV(const ProgramState& state, ProgramObject& prog, std::string& infoLog) {
|
||||||
|
using namespace glslang;
|
||||||
|
|
||||||
|
std::vector<EShLanguage> usedShaderTypes;
|
||||||
|
TProgram program;
|
||||||
|
for (GLuint shaderId : prog.attachedShaders) {
|
||||||
|
auto shaderObject = state.GetShaderObject(shaderId);
|
||||||
|
EShLanguage shLanguage = GetEShLanguageByShaderType(shaderObject.type);
|
||||||
|
TShader* shader = nullptr;
|
||||||
|
std::string infoLogOfShader = CompileGLSLToTShader(shaderObject.type, shaderObject.source, shader);
|
||||||
|
if (!infoLogOfShader.empty()) {
|
||||||
|
infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderObject.type) +
|
||||||
|
" :\n" + infoLogOfShader;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
program.addShader(shader);
|
||||||
|
usedShaderTypes.push_back(shLanguage);
|
||||||
|
}
|
||||||
|
if (!program.link(EShMsgDefault)) {
|
||||||
|
infoLog = "Error: [glslang] Cannot link the program:\n" + std::to_string(program.getInfoLog());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
SpvOptions spvOptions;
|
||||||
|
spvOptions.disableOptimizer = false;
|
||||||
|
|
||||||
|
std::vector<std::vector<unsigned>> allSpirv;
|
||||||
|
for(auto type : usedShaderTypes) {
|
||||||
|
std::vector<unsigned> spirv;
|
||||||
|
GlslangToSpv(*program.getIntermediate(type), spirv, &spvOptions);
|
||||||
|
allSpirv.push_back(spirv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return allSpirv;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string &source, std::string &infoLog) {
|
||||||
|
using namespace glslang;
|
||||||
|
|
||||||
|
TShader* shader = nullptr;
|
||||||
|
std::string infoLogOfShader = CompileGLSLToTShader(shaderType, source, shader);
|
||||||
|
if (!infoLogOfShader.empty()) {
|
||||||
|
infoLog = "Error: [glslang] Cannot compile " + GetShaderTypeName(shaderType) + ":\n" + infoLogOfShader;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
TProgram program;
|
||||||
|
program.addShader(shader);
|
||||||
|
if (!program.link(EShMsgDefault)) {
|
||||||
|
infoLog = "Error: [glslang] Cannot link the program of the single shader:\n" + std::to_string(program.getInfoLog());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::vector<unsigned> spirv;
|
||||||
|
|
||||||
|
SpvOptions spvOptions;
|
||||||
|
spvOptions.disableOptimizer = false;
|
||||||
|
EShLanguage language = GetEShLanguageByShaderType(shaderType);
|
||||||
|
GlslangToSpv(*program.getIntermediate(language), spirv, &spvOptions);
|
||||||
|
|
||||||
|
return spirv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReflectSPIRVUniforms(const std::vector<std::vector<unsigned>>& allSpirv, ProgramObject& prog, std::string& infoLog) {
|
||||||
|
spvc_context context = nullptr;
|
||||||
|
|
||||||
|
if (spvc_context_create(&context) != SPVC_SUCCESS) {
|
||||||
|
infoLog = "Failed to create SPIRV-Cross context";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<GLint> used_locations;
|
||||||
|
GLint auto_location = 0;
|
||||||
|
for (auto spirv: allSpirv) {
|
||||||
|
spvc_parsed_ir ir = nullptr;
|
||||||
|
spvc_compiler compiler = nullptr;
|
||||||
|
spvc_resources resources = nullptr;
|
||||||
|
|
||||||
|
spvc_result result = spvc_context_parse_spirv(context, spirv.data(), spirv.size(), &ir);
|
||||||
|
if (result != SPVC_SUCCESS) {
|
||||||
|
infoLog = "SPIR-V parsing failed";
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = spvc_context_create_compiler(context, SPVC_BACKEND_GLSL, ir,
|
||||||
|
SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, &compiler);
|
||||||
|
if (result != SPVC_SUCCESS) {
|
||||||
|
infoLog = "Failed to create SPIRV-Cross compiler";
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = spvc_compiler_create_shader_resources(compiler, &resources);
|
||||||
|
if (result != SPVC_SUCCESS) {
|
||||||
|
infoLog = "Failed to get shader resources";
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const spvc_reflected_resource *uniform_buffers = nullptr;
|
||||||
|
const spvc_reflected_resource *uniform_vars = nullptr;
|
||||||
|
const spvc_reflected_resource *sampled_images = nullptr;
|
||||||
|
size_t uniform_buffer_count = 0;
|
||||||
|
size_t uniform_var_count = 0;
|
||||||
|
size_t sampled_image_count = 0;
|
||||||
|
|
||||||
|
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER,
|
||||||
|
&uniform_buffers, &uniform_buffer_count);
|
||||||
|
spvc_resources_get_resource_list_for_type(resources,
|
||||||
|
SPVC_RESOURCE_TYPE_GL_PLAIN_UNIFORM,
|
||||||
|
&uniform_vars, &uniform_var_count);
|
||||||
|
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_SAMPLED_IMAGE,
|
||||||
|
&sampled_images, &sampled_image_count);
|
||||||
|
|
||||||
|
std::vector<const spvc_reflected_resource *> all_resources;
|
||||||
|
for (size_t i = 0; i < uniform_buffer_count; ++i)
|
||||||
|
all_resources.push_back(&uniform_buffers[i]);
|
||||||
|
for (size_t i = 0; i < uniform_var_count; ++i)
|
||||||
|
all_resources.push_back(&uniform_vars[i]);
|
||||||
|
for (size_t i = 0; i < sampled_image_count; ++i)
|
||||||
|
all_resources.push_back(&sampled_images[i]);
|
||||||
|
|
||||||
|
for (const auto res_ptr: all_resources) {
|
||||||
|
const spvc_reflected_resource &res = *res_ptr;
|
||||||
|
const char *name = res.name;
|
||||||
|
if (name[0] == '_') continue;
|
||||||
|
|
||||||
|
unsigned spirv_location = spvc_compiler_get_decoration(compiler, res.id,
|
||||||
|
SpvDecorationLocation);
|
||||||
|
GLint final_location;
|
||||||
|
|
||||||
|
if (spirv_location > 0) {
|
||||||
|
if (used_locations.find(spirv_location) != used_locations.end()) {
|
||||||
|
infoLog += "\nLocation conflict for uniform: " + std::string(name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final_location = spirv_location;
|
||||||
|
} else {
|
||||||
|
while (used_locations.find(auto_location) != used_locations.end()) {
|
||||||
|
auto_location++;
|
||||||
|
}
|
||||||
|
final_location = auto_location;
|
||||||
|
}
|
||||||
|
|
||||||
|
used_locations.insert(final_location);
|
||||||
|
|
||||||
|
spvc_type_id type_id = res.type_id;
|
||||||
|
spvc_type type = spvc_compiler_get_type_handle(compiler, type_id);
|
||||||
|
spvc_basetype base_type = spvc_type_get_basetype(type);
|
||||||
|
GLenum gl_type = GL_NONE;
|
||||||
|
|
||||||
|
if (base_type == SPVC_BASETYPE_SAMPLED_IMAGE) {
|
||||||
|
SpvDim dim = spvc_type_get_image_dimension(type);
|
||||||
|
bool is_array = spvc_type_get_image_arrayed(type);
|
||||||
|
bool is_shadow = spvc_type_get_image_is_depth(type);
|
||||||
|
bool is_ms = spvc_type_get_image_multisampled(type);
|
||||||
|
|
||||||
|
switch (dim) {
|
||||||
|
case SpvDim1D:
|
||||||
|
gl_type = is_array ? GL_SAMPLER_1D_ARRAY : GL_SAMPLER_1D;
|
||||||
|
if (is_shadow)
|
||||||
|
gl_type = is_array ? GL_SAMPLER_1D_ARRAY_SHADOW
|
||||||
|
: GL_SAMPLER_1D_SHADOW;
|
||||||
|
break;
|
||||||
|
case SpvDim2D:
|
||||||
|
if (is_ms) {
|
||||||
|
gl_type = is_array ? GL_SAMPLER_2D_MULTISAMPLE_ARRAY
|
||||||
|
: GL_SAMPLER_2D_MULTISAMPLE;
|
||||||
|
} else {
|
||||||
|
gl_type = is_array ? GL_SAMPLER_2D_ARRAY : GL_SAMPLER_2D;
|
||||||
|
if (is_shadow)
|
||||||
|
gl_type = is_array ? GL_SAMPLER_2D_ARRAY_SHADOW
|
||||||
|
: GL_SAMPLER_2D_SHADOW;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SpvDim3D:
|
||||||
|
gl_type = GL_SAMPLER_3D;
|
||||||
|
break;
|
||||||
|
case SpvDimCube:
|
||||||
|
gl_type = is_array ? GL_SAMPLER_CUBE_MAP_ARRAY : GL_SAMPLER_CUBE;
|
||||||
|
if (is_shadow)
|
||||||
|
gl_type = is_array ? GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW
|
||||||
|
: GL_SAMPLER_CUBE_SHADOW;
|
||||||
|
break;
|
||||||
|
case SpvDimRect:
|
||||||
|
gl_type = is_shadow ? GL_SAMPLER_2D_RECT_SHADOW : GL_SAMPLER_2D_RECT;
|
||||||
|
break;
|
||||||
|
case SpvDimBuffer:
|
||||||
|
gl_type = GL_SAMPLER_BUFFER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gl_type = GL_SAMPLER_2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
spvc_basetype sampled_base = spvc_type_get_basetype(type);
|
||||||
|
if (sampled_base == SPVC_BASETYPE_INT32) {
|
||||||
|
switch (gl_type) {
|
||||||
|
case GL_SAMPLER_1D:
|
||||||
|
gl_type = GL_INT_SAMPLER_1D;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D:
|
||||||
|
gl_type = GL_INT_SAMPLER_2D;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_3D:
|
||||||
|
gl_type = GL_INT_SAMPLER_3D;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_CUBE:
|
||||||
|
gl_type = GL_INT_SAMPLER_CUBE;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_1D_ARRAY:
|
||||||
|
gl_type = GL_INT_SAMPLER_1D_ARRAY;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D_ARRAY:
|
||||||
|
gl_type = GL_INT_SAMPLER_2D_ARRAY;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_CUBE_MAP_ARRAY:
|
||||||
|
gl_type = GL_INT_SAMPLER_CUBE_MAP_ARRAY;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D_RECT:
|
||||||
|
gl_type = GL_INT_SAMPLER_2D_RECT;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_BUFFER:
|
||||||
|
gl_type = GL_INT_SAMPLER_BUFFER;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D_MULTISAMPLE:
|
||||||
|
gl_type = GL_INT_SAMPLER_2D_MULTISAMPLE;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
|
||||||
|
gl_type = GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (sampled_base == SPVC_BASETYPE_UINT32) {
|
||||||
|
switch (gl_type) {
|
||||||
|
case GL_SAMPLER_1D:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_1D;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_2D;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_3D:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_3D;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_CUBE:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_CUBE;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_1D_ARRAY:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_1D_ARRAY;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D_ARRAY:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_CUBE_MAP_ARRAY:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D_RECT:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_2D_RECT;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_BUFFER:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_BUFFER;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D_MULTISAMPLE:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE;
|
||||||
|
break;
|
||||||
|
case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
|
||||||
|
gl_type = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned vec_size = spvc_type_get_vector_size(type);
|
||||||
|
unsigned columns = spvc_type_get_columns(type);
|
||||||
|
|
||||||
|
switch (base_type) {
|
||||||
|
case SPVC_BASETYPE_FP32:
|
||||||
|
if (columns > 1) {
|
||||||
|
if (vec_size == 2 && columns == 2) gl_type = GL_FLOAT_MAT2;
|
||||||
|
else if (vec_size == 3 && columns == 3) gl_type = GL_FLOAT_MAT3;
|
||||||
|
else if (vec_size == 4 && columns == 4) gl_type = GL_FLOAT_MAT4;
|
||||||
|
else if (vec_size == 3 && columns == 2) gl_type = GL_FLOAT_MAT2x3;
|
||||||
|
else if (vec_size == 4 && columns == 2) gl_type = GL_FLOAT_MAT2x4;
|
||||||
|
else if (vec_size == 2 && columns == 3) gl_type = GL_FLOAT_MAT3x2;
|
||||||
|
else if (vec_size == 4 && columns == 3) gl_type = GL_FLOAT_MAT3x4;
|
||||||
|
else if (vec_size == 2 && columns == 4) gl_type = GL_FLOAT_MAT4x2;
|
||||||
|
else if (vec_size == 3 && columns == 4) gl_type = GL_FLOAT_MAT4x3;
|
||||||
|
} else {
|
||||||
|
switch (vec_size) {
|
||||||
|
case 1:
|
||||||
|
gl_type = GL_FLOAT;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gl_type = GL_FLOAT_VEC2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gl_type = GL_FLOAT_VEC3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
gl_type = GL_FLOAT_VEC4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPVC_BASETYPE_INT32:
|
||||||
|
switch (vec_size) {
|
||||||
|
case 1:
|
||||||
|
gl_type = GL_INT;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gl_type = GL_INT_VEC2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gl_type = GL_INT_VEC3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
gl_type = GL_INT_VEC4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPVC_BASETYPE_UINT32:
|
||||||
|
switch (vec_size) {
|
||||||
|
case 1:
|
||||||
|
gl_type = GL_UNSIGNED_INT;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gl_type = GL_UNSIGNED_INT_VEC2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gl_type = GL_UNSIGNED_INT_VEC3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
gl_type = GL_UNSIGNED_INT_VEC4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SPVC_BASETYPE_BOOLEAN:
|
||||||
|
switch (vec_size) {
|
||||||
|
case 1:
|
||||||
|
gl_type = GL_BOOL;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gl_type = GL_BOOL_VEC2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gl_type = GL_BOOL_VEC3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
gl_type = GL_BOOL_VEC4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prog.uniformLocations[name] = final_location;
|
||||||
|
UniformValue uniformValue;
|
||||||
|
uniformValue.type = gl_type;
|
||||||
|
uniformValue.count = spvc_type_get_array_dimension(type, 0) > 0 ?
|
||||||
|
spvc_type_get_array_dimension(type, 0) : 1;
|
||||||
|
prog.uniformValues[name] = uniformValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spvc_context_destroy(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
//
|
||||||
|
// Created by BZLZHH on 2025/5/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef MOBILEGL_GLSLTOOL_H
|
||||||
|
#define MOBILEGL_GLSLTOOL_H
|
||||||
|
|
||||||
|
#include "../../Includes.h"
|
||||||
|
|
||||||
|
namespace MG_Util::Program {
|
||||||
|
inline static TBuiltInResource InitResources()
|
||||||
|
{
|
||||||
|
TBuiltInResource Resources{};
|
||||||
|
Resources.maxLights = 32;
|
||||||
|
Resources.maxClipPlanes = 6;
|
||||||
|
Resources.maxTextureUnits = 32;
|
||||||
|
Resources.maxTextureCoords = 32;
|
||||||
|
Resources.maxVertexAttribs = 64;
|
||||||
|
Resources.maxVertexUniformComponents = 4096;
|
||||||
|
Resources.maxVaryingFloats = 64;
|
||||||
|
Resources.maxVertexTextureImageUnits = 32;
|
||||||
|
Resources.maxCombinedTextureImageUnits = 80;
|
||||||
|
Resources.maxTextureImageUnits = 32;
|
||||||
|
Resources.maxFragmentUniformComponents = 4096;
|
||||||
|
Resources.maxDrawBuffers = 32;
|
||||||
|
Resources.maxVertexUniformVectors = 128;
|
||||||
|
Resources.maxVaryingVectors = 8;
|
||||||
|
Resources.maxFragmentUniformVectors = 16;
|
||||||
|
Resources.maxVertexOutputVectors = 16;
|
||||||
|
Resources.maxFragmentInputVectors = 15;
|
||||||
|
Resources.minProgramTexelOffset = -8;
|
||||||
|
Resources.maxProgramTexelOffset = 7;
|
||||||
|
Resources.maxClipDistances = 8;
|
||||||
|
Resources.maxComputeWorkGroupCountX = 65535;
|
||||||
|
Resources.maxComputeWorkGroupCountY = 65535;
|
||||||
|
Resources.maxComputeWorkGroupCountZ = 65535;
|
||||||
|
Resources.maxComputeWorkGroupSizeX = 1024;
|
||||||
|
Resources.maxComputeWorkGroupSizeY = 1024;
|
||||||
|
Resources.maxComputeWorkGroupSizeZ = 64;
|
||||||
|
Resources.maxComputeUniformComponents = 1024;
|
||||||
|
Resources.maxComputeTextureImageUnits = 16;
|
||||||
|
Resources.maxComputeImageUniforms = 8;
|
||||||
|
Resources.maxComputeAtomicCounters = 8;
|
||||||
|
Resources.maxComputeAtomicCounterBuffers = 1;
|
||||||
|
Resources.maxVaryingComponents = 60;
|
||||||
|
Resources.maxVertexOutputComponents = 64;
|
||||||
|
Resources.maxGeometryInputComponents = 64;
|
||||||
|
Resources.maxGeometryOutputComponents = 128;
|
||||||
|
Resources.maxFragmentInputComponents = 128;
|
||||||
|
Resources.maxImageUnits = 8;
|
||||||
|
Resources.maxCombinedImageUnitsAndFragmentOutputs = 8;
|
||||||
|
Resources.maxCombinedShaderOutputResources = 8;
|
||||||
|
Resources.maxImageSamples = 0;
|
||||||
|
Resources.maxVertexImageUniforms = 0;
|
||||||
|
Resources.maxTessControlImageUniforms = 0;
|
||||||
|
Resources.maxTessEvaluationImageUniforms = 0;
|
||||||
|
Resources.maxGeometryImageUniforms = 0;
|
||||||
|
Resources.maxFragmentImageUniforms = 8;
|
||||||
|
Resources.maxCombinedImageUniforms = 8;
|
||||||
|
Resources.maxGeometryTextureImageUnits = 16;
|
||||||
|
Resources.maxGeometryOutputVertices = 256;
|
||||||
|
Resources.maxGeometryTotalOutputComponents = 1024;
|
||||||
|
Resources.maxGeometryUniformComponents = 1024;
|
||||||
|
Resources.maxGeometryVaryingComponents = 64;
|
||||||
|
Resources.maxTessControlInputComponents = 128;
|
||||||
|
Resources.maxTessControlOutputComponents = 128;
|
||||||
|
Resources.maxTessControlTextureImageUnits = 16;
|
||||||
|
Resources.maxTessControlUniformComponents = 1024;
|
||||||
|
Resources.maxTessControlTotalOutputComponents = 4096;
|
||||||
|
Resources.maxTessEvaluationInputComponents = 128;
|
||||||
|
Resources.maxTessEvaluationOutputComponents = 128;
|
||||||
|
Resources.maxTessEvaluationTextureImageUnits = 16;
|
||||||
|
Resources.maxTessEvaluationUniformComponents = 1024;
|
||||||
|
Resources.maxTessPatchComponents = 120;
|
||||||
|
Resources.maxPatchVertices = 32;
|
||||||
|
Resources.maxTessGenLevel = 64;
|
||||||
|
Resources.maxViewports = 16;
|
||||||
|
Resources.maxVertexAtomicCounters = 0;
|
||||||
|
Resources.maxTessControlAtomicCounters = 0;
|
||||||
|
Resources.maxTessEvaluationAtomicCounters = 0;
|
||||||
|
Resources.maxGeometryAtomicCounters = 0;
|
||||||
|
Resources.maxFragmentAtomicCounters = 8;
|
||||||
|
Resources.maxCombinedAtomicCounters = 8;
|
||||||
|
Resources.maxAtomicCounterBindings = 1;
|
||||||
|
Resources.maxVertexAtomicCounterBuffers = 0;
|
||||||
|
Resources.maxTessControlAtomicCounterBuffers = 0;
|
||||||
|
Resources.maxTessEvaluationAtomicCounterBuffers = 0;
|
||||||
|
Resources.maxGeometryAtomicCounterBuffers = 0;
|
||||||
|
Resources.maxFragmentAtomicCounterBuffers = 1;
|
||||||
|
Resources.maxCombinedAtomicCounterBuffers = 1;
|
||||||
|
Resources.maxAtomicCounterBufferSize = 16384;
|
||||||
|
Resources.maxTransformFeedbackBuffers = 4;
|
||||||
|
Resources.maxTransformFeedbackInterleavedComponents = 64;
|
||||||
|
Resources.maxCullDistances = 8;
|
||||||
|
Resources.maxCombinedClipAndCullDistances = 8;
|
||||||
|
Resources.maxSamples = 4;
|
||||||
|
Resources.maxMeshOutputVerticesNV = 256;
|
||||||
|
Resources.maxMeshOutputPrimitivesNV = 512;
|
||||||
|
Resources.maxMeshWorkGroupSizeX_NV = 32;
|
||||||
|
Resources.maxMeshWorkGroupSizeY_NV = 1;
|
||||||
|
Resources.maxMeshWorkGroupSizeZ_NV = 1;
|
||||||
|
Resources.maxTaskWorkGroupSizeX_NV = 32;
|
||||||
|
Resources.maxTaskWorkGroupSizeY_NV = 1;
|
||||||
|
Resources.maxTaskWorkGroupSizeZ_NV = 1;
|
||||||
|
Resources.maxMeshViewCountNV = 4;
|
||||||
|
|
||||||
|
Resources.limits.nonInductiveForLoops = true;
|
||||||
|
Resources.limits.whileLoops = true;
|
||||||
|
Resources.limits.doWhileLoops = true;
|
||||||
|
Resources.limits.generalUniformIndexing = true;
|
||||||
|
Resources.limits.generalAttributeMatrixVectorIndexing = true;
|
||||||
|
Resources.limits.generalVaryingIndexing = true;
|
||||||
|
Resources.limits.generalSamplerIndexing = true;
|
||||||
|
Resources.limits.generalVariableIndexing = true;
|
||||||
|
Resources.limits.generalConstantMatrixVectorIndexing = true;
|
||||||
|
|
||||||
|
return Resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int QueryGLSLVersion(const std::string& code) {
|
||||||
|
static std::regex version_pattern(R"(#version\s+(\d{3}))");
|
||||||
|
std::smatch match;
|
||||||
|
if (std::regex_search(code, match, version_pattern)) {
|
||||||
|
return std::stoi(match[1].str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GLsizei GetMatrixElementCount(GLenum matrixType) {
|
||||||
|
switch(matrixType) {
|
||||||
|
case GL_FLOAT_MAT2: return 4;
|
||||||
|
case GL_FLOAT_MAT3: return 9;
|
||||||
|
case GL_FLOAT_MAT4: return 16;
|
||||||
|
case GL_FLOAT_MAT2x3: return 6;
|
||||||
|
case GL_FLOAT_MAT2x4: return 8;
|
||||||
|
case GL_FLOAT_MAT3x2: return 6;
|
||||||
|
case GL_FLOAT_MAT3x4: return 12;
|
||||||
|
case GL_FLOAT_MAT4x2: return 8;
|
||||||
|
case GL_FLOAT_MAT4x3: return 12;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string GetShaderTypeName(GLenum shaderType) {
|
||||||
|
switch(shaderType) {
|
||||||
|
case GL_VERTEX_SHADER: return "Vertex Shader";
|
||||||
|
case GL_FRAGMENT_SHADER: return "Fragment Shader";
|
||||||
|
case GL_GEOMETRY_SHADER: return "Geometry Shader";
|
||||||
|
case GL_TESS_CONTROL_SHADER: return "Tessellation Control Shader";
|
||||||
|
case GL_TESS_EVALUATION_SHADER: return "Tessellation Evaluation Shader";
|
||||||
|
case GL_COMPUTE_SHADER: return "Compute Shader";
|
||||||
|
default: return "Unknown Shader Type (" + std::to_string(shaderType) + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EShLanguage GetEShLanguageByShaderType(GLenum shaderType) {
|
||||||
|
switch (shaderType) {
|
||||||
|
case GL_VERTEX_SHADER:
|
||||||
|
return EShLanguage::EShLangVertex;
|
||||||
|
case GL_FRAGMENT_SHADER:
|
||||||
|
return EShLanguage::EShLangFragment;
|
||||||
|
case GL_COMPUTE_SHADER:
|
||||||
|
return EShLanguage::EShLangCompute;
|
||||||
|
case GL_TESS_CONTROL_SHADER:
|
||||||
|
return EShLanguage::EShLangTessControl;
|
||||||
|
case GL_TESS_EVALUATION_SHADER:
|
||||||
|
return EShLanguage::EShLangTessEvaluation;
|
||||||
|
case GL_GEOMETRY_SHADER:
|
||||||
|
return EShLanguage::EShLangGeometry;
|
||||||
|
default:
|
||||||
|
return EShLanguage::EShLangCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned> CompileGLSLToSPIRV(GLenum shaderType, const std::string& source, std::string& infoLog);
|
||||||
|
std::string CompileGLSLToTShader(GLenum shaderType, const std::string& source, glslang::TShader *&shader);
|
||||||
|
std::vector<std::vector<unsigned>> CompileMultipleShadersToSPIRV(const ProgramState& state, ProgramObject& prog, std::string& infoLog);
|
||||||
|
void ReflectSPIRVUniforms(const std::vector<std::vector<unsigned>>& allSpirv, ProgramObject& prog, std::string& infoLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MOBILEGL_GLSLTOOL_H
|
||||||
Reference in New Issue
Block a user