From 4ecd4e4a07c45d824cc9ce6aaadac614455ce092 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 9 Aug 2025 13:08:26 +0800 Subject: [PATCH] [Feat] (MG_State/Program, MG_Impl/Program): skeleton and initial impl of program/shader state machine --- .../MG_Impl/GLImpl/Program/GL_Program.cpp | 260 ++++++++++++++++++ MobileGL/MG_Impl/GLImpl/Program/GL_Program.h | 51 ++++ .../GLState/ProgramState/ProgramObject.cpp | 51 ++++ .../GLState/ProgramState/ProgramObject.h | 23 ++ .../GLState/ProgramState/ProgramState.cpp | 27 ++ .../GLState/ProgramState/ProgramState.h | 30 ++ .../GLState/ProgramState/ShaderObject.cpp | 34 +++ .../GLState/ProgramState/ShaderObject.h | 52 ++++ MobileGL/MG_Test/Program/ShaderTest.cpp | 0 9 files changed, 528 insertions(+) create mode 100644 MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp create mode 100644 MobileGL/MG_Impl/GLImpl/Program/GL_Program.h create mode 100644 MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp create mode 100644 MobileGL/MG_State/GLState/ProgramState/ProgramObject.h create mode 100644 MobileGL/MG_State/GLState/ProgramState/ProgramState.cpp create mode 100644 MobileGL/MG_State/GLState/ProgramState/ProgramState.h create mode 100644 MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp create mode 100644 MobileGL/MG_State/GLState/ProgramState/ShaderObject.h create mode 100644 MobileGL/MG_Test/Program/ShaderTest.cpp diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp new file mode 100644 index 00000000..cb416259 --- /dev/null +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -0,0 +1,260 @@ +#include "../../../Includes.h" + +namespace MobileGL { + namespace MG_Impl::GLImpl { + void AttachShader_State(GLuint program, GLuint shader) { + THROW_UNIMPL_EXCEPTION + } + + void BindAttribLocation_State(GLuint program, GLuint index, const GLchar *name) { + THROW_UNIMPL_EXCEPTION + } + + void CompileShader_State(GLuint shader) { + THROW_UNIMPL_EXCEPTION + } + + GLuint CreateProgram_State(void) { + THROW_UNIMPL_EXCEPTION + } + + GLuint CreateShader_State(GLenum type) { + THROW_UNIMPL_EXCEPTION + } + + void DeleteProgram_State(GLuint program) { + THROW_UNIMPL_EXCEPTION + } + + void DeleteShader_State(GLuint shader) { + THROW_UNIMPL_EXCEPTION + } + + void DetachShader_State(GLuint program, GLuint shader) { + THROW_UNIMPL_EXCEPTION + } + + void GetActiveAttrib_State(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { + THROW_UNIMPL_EXCEPTION + } + + void GetActiveUniform_State(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { + THROW_UNIMPL_EXCEPTION + } + + void GetAttachedShaders_State(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders) { + THROW_UNIMPL_EXCEPTION + } + + GLint GetAttribLocation_State(GLuint program, const GLchar *name) { + THROW_UNIMPL_EXCEPTION + } + + void GetProgramiv_State(GLuint program, GLenum pname, GLint *params) { + THROW_UNIMPL_EXCEPTION + } + + void GetProgramInfoLog_State(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { + THROW_UNIMPL_EXCEPTION + } + + void GetShaderiv_State(GLuint shader, GLenum pname, GLint *params) { + THROW_UNIMPL_EXCEPTION + } + + void GetShaderInfoLog_State(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { + THROW_UNIMPL_EXCEPTION + } + + void GetShaderSource_State(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source) { + THROW_UNIMPL_EXCEPTION + } + + GLint GetUniformLocation_State(GLuint program, const GLchar *name) { + THROW_UNIMPL_EXCEPTION + } + + void GetUniformfv_State(GLuint program, GLint location, GLfloat *params) { + THROW_UNIMPL_EXCEPTION + } + + void GetUniformiv_State(GLuint program, GLint location, GLint *params) { + THROW_UNIMPL_EXCEPTION + } + + GLboolean IsProgram_State(GLuint program) { + THROW_UNIMPL_EXCEPTION + } + + GLboolean IsShader_State(GLuint shader) { + THROW_UNIMPL_EXCEPTION + } + + void LinkProgram_State(GLuint program) { + THROW_UNIMPL_EXCEPTION + } + + void ShaderSource_State(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) { + THROW_UNIMPL_EXCEPTION + } + + void UseProgram_State(GLuint program) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform1f_State(GLint location, GLfloat v0) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform2f_State(GLint location, GLfloat v0, GLfloat v1) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform3f_State(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform4f_State(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform1i_State(GLint location, GLint v0) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform2i_State(GLint location, GLint v0, GLint v1) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform3i_State(GLint location, GLint v0, GLint v1, GLint v2) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform4i_State(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform1fv_State(GLint location, GLsizei count, const GLfloat *value) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform2fv_State(GLint location, GLsizei count, const GLfloat *value) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform3fv_State(GLint location, GLsizei count, const GLfloat *value) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform4fv_State(GLint location, GLsizei count, const GLfloat *value) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform1iv_State(GLint location, GLsizei count, const GLint *value) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform2iv_State(GLint location, GLsizei count, const GLint *value) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform3iv_State(GLint location, GLsizei count, const GLint *value) { + THROW_UNIMPL_EXCEPTION + } + + void Uniform4iv_State(GLint location, GLsizei count, const GLint *value) { + THROW_UNIMPL_EXCEPTION + } + + void UniformMatrix2fv_State(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { + THROW_UNIMPL_EXCEPTION + } + + void UniformMatrix3fv_State(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { + THROW_UNIMPL_EXCEPTION + } + + void UniformMatrix4fv_State(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { + THROW_UNIMPL_EXCEPTION + } + + void ValidateProgram_State(GLuint program) { + THROW_UNIMPL_EXCEPTION + } + + + void AttachShader(GLuint program, GLuint shader) { AttachShader_State(program, shader); } + void BindAttribLocation(GLuint program, GLuint index, const GLchar *name) { + BindAttribLocation_State(program, index, name); + } + void CompileShader(GLuint shader) { CompileShader_State(shader); } + GLuint CreateProgram(void) { return CreateProgram_State(); } + GLuint CreateShader(GLenum type) { return CreateShader_State(type); } + void DeleteProgram(GLuint program) { DeleteProgram_State(program); } + void DeleteShader(GLuint shader) { DeleteShader_State(shader); } + void DetachShader(GLuint program, GLuint shader) { DetachShader_State(program, shader); } + void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { + GetActiveAttrib_State(program, index, bufSize, length, size, type, name); + } + void GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { + GetActiveUniform_State(program, index, bufSize, length, size, type, name); + } + void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders) { + GetAttachedShaders_State(program, maxCount, count, shaders); + } + GLint GetAttribLocation(GLuint program, const GLchar *name) { + GetAttribLocation_State(program, name); + } + void GetProgramiv(GLuint program, GLenum pname, GLint *params) { + GetProgramiv_State(program, pname, params); + } + void GetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { + GetProgramInfoLog_State(program, bufSize, length, infoLog); + } + void GetShaderiv(GLuint shader, GLenum pname, GLint *params) { + GetShaderiv_State(shader, pname, params); + } + void GetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { + GetShaderInfoLog_State(shader, bufSize, length, infoLog); + } + void GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source) { + GetShaderSource_State(shader, bufSize, length, source); + } + GLint GetUniformLocation(GLuint program, const GLchar *name) { + GetUniformLocation_State(program, name); + } + void GetUniformfv(GLuint program, GLint location, GLfloat *params) { + GetUniformfv_State(program, location, params); + } + void GetUniformiv(GLuint program, GLint location, GLint *params) { + GetUniformiv_State(program, location, params); + } + GLboolean IsProgram(GLuint program) { return IsProgram_State(program); } + GLboolean IsShader(GLuint shader) { return IsShader_State(shader); } + void LinkProgram(GLuint program) { LinkProgram_State(program); } + void ShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) { + ShaderSource_State(shader, count, string, length); + } + void UseProgram(GLuint program) { UseProgram_State(program); } + void Uniform1f(GLint location, GLfloat v0) { Uniform1f_State(location, v0); } + void Uniform2f(GLint location, GLfloat v0, GLfloat v1) { Uniform2f_State(location, v0, v1); } + void Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { Uniform3f_State(location, v0, v1, v2); } + void Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + void Uniform1i(GLint location, GLint v0) { Uniform1i_State(location, v0); } + void Uniform2i(GLint location, GLint v0, GLint v1) { Uniform2i_State(location, v0, v1); } + void Uniform3i(GLint location, GLint v0, GLint v1, GLint v2) { Uniform3i_State(location, v0, v1, v2); } + void Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) { Uniform4i_State(location, v0, v1, v2, v3); } + void Uniform1fv(GLint location, GLsizei count, const GLfloat *value) { Uniform1fv_State(location, count, value); } + void Uniform2fv(GLint location, GLsizei count, const GLfloat *value) { Uniform2fv_State(location, count, value); } + void Uniform3fv(GLint location, GLsizei count, const GLfloat *value) { Uniform3fv_State(location, count, value); } + void Uniform4fv(GLint location, GLsizei count, const GLfloat *value) { Uniform4fv_State(location, count, value); } + void Uniform1iv(GLint location, GLsizei count, const GLint *value) { Uniform1iv_State(location, count, value); } + void Uniform2iv(GLint location, GLsizei count, const GLint *value) { Uniform2iv_State(location, count, value); } + void Uniform3iv(GLint location, GLsizei count, const GLint *value) { Uniform3iv_State(location, count, value); } + void Uniform4iv(GLint location, GLsizei count, const GLint *value) { Uniform4iv_State(location, count, value); } + void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { UniformMatrix2fv_State(location, count, transpose, value); } + void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { UniformMatrix3fv_State(location, count, transpose, value); } + void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { UniformMatrix4fv_State(location, count, transpose, value); } + void ValidateProgram(GLuint program) { ValidateProgram_State(program); } + } +} \ No newline at end of file diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h new file mode 100644 index 00000000..b282d6a7 --- /dev/null +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.h @@ -0,0 +1,51 @@ +#pragma once + +namespace MobileGL { + namespace MG_Impl::GLImpl { + void AttachShader(GLuint program, GLuint shader); + void BindAttribLocation(GLuint program, GLuint index, const GLchar *name); + void CompileShader(GLuint shader); + GLuint CreateProgram(void); + GLuint CreateShader(GLenum type); + void DeleteProgram(GLuint program); + void DeleteShader(GLuint shader); + void DetachShader(GLuint program, GLuint shader); + void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); + void GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); + void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); + GLint GetAttribLocation(GLuint program, const GLchar *name); + void GetProgramiv(GLuint program, GLenum pname, GLint *params); + void GetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); + void GetShaderiv(GLuint shader, GLenum pname, GLint *params); + void GetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); + void GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); + GLint GetUniformLocation(GLuint program, const GLchar *name); + void GetUniformfv(GLuint program, GLint location, GLfloat *params); + void GetUniformiv(GLuint program, GLint location, GLint *params); + GLboolean IsProgram(GLuint program); + GLboolean IsShader(GLuint shader); + void LinkProgram(GLuint program); + void ShaderSource(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); + void UseProgram(GLuint program); + 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 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 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 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 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 ValidateProgram(GLuint program); + } +} diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp new file mode 100644 index 00000000..91d4fa41 --- /dev/null +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -0,0 +1,51 @@ +#include "../../../Includes.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + void ProgramObject::AttachShader(SharedPtr shader) { + m_shaders.emplace_back(shader); + } + + void ProgramObject::DetachShader(SharedPtr shader) { + auto count = std::erase_if(m_shaders, + [shader](const SharedPtr& s) { + return s.get() == shader.get(); + }); + + if (count == 0) { + // FIXME: handle error here + THROW_EXCEPTION("Program object does not have such shader object attached"); + } + } + + void ProgramObject::Link() { + Vector shaderTypes(m_shaders.size()); + Vector> shaders(m_shaders.size()); + for (SizeT i = 0; i < m_shaders.size(); i++) { + shaderTypes[i] = GetGLShaderTypeByMGLShaderStage(m_shaders[i]->m_stage); + shaders[i] = m_shaders[i]->m_shader; + } + + MG_Util::ShaderTranspiler::ProgramAttrib attrib { + .shaderTypes = Move(shaderTypes), + .shaders = Move(shaders), + }; + + auto result = MG_Util::ShaderTranspiler::ShaderCompiler::LinkProgram(attrib); + if (result) { + m_linkStatus = true; + m_programBinary = Move(result.value()); + } else { + m_linkStatus = false; + m_infoLog = result.error().log; + + const std::string e = + std::format("Shader link failed: \nerrc: {}\nmsg: {}\n", + result.error().errc, result.error().log); + THROW_EXCEPTION(e); + } + } + } + } +} \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h new file mode 100644 index 00000000..f028432c --- /dev/null +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -0,0 +1,23 @@ +#pragma once +#include "MG_Util/Types.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + class ProgramObject { + public: + void AttachShader(SharedPtr shader); + void DetachShader(SharedPtr shader); + void Link(); + private: + Vector> m_shaders; + // basically this contains SPIR-V in binary format + Vector> m_programBinary; + String m_infoLog; + bool m_deleteStatus = false; + bool m_linkStatus = true; + bool m_validateStatus = true; + }; + } + } +} diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramState.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramState.cpp new file mode 100644 index 00000000..591e6023 --- /dev/null +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramState.cpp @@ -0,0 +1,27 @@ +#include "../../../Includes.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + Uint ProgramState::CreateProgram() { + Uint programId = 0; + m_indexGenerator.Generate(1, &programId); + EnsureIndexAvail(programId); + m_programObjects[programId] = MakeShared(); + return programId; + } + + SharedPtr ProgramState::GetProgramObject(Uint id) { + if (!CheckIndexAvail(id)) + return nullptr; // FIXME: add error reporting here + return m_programObjects[id]; + } + + void ProgramState::DeleteProgram(Uint id) { + if (!CheckIndexAvail(id)) + return; // FIXME: add error reporting here + m_programObjects[id].reset(); + } + } + } +} \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramState.h b/MobileGL/MG_State/GLState/ProgramState/ProgramState.h new file mode 100644 index 00000000..82a2876b --- /dev/null +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramState.h @@ -0,0 +1,30 @@ +#pragma once + +namespace MobileGL { + namespace MG_State { + namespace GLState { + class ProgramState { + public: + // This function WILL actually create the program object. + // To retrieve created program object, use GetProgramObject() + Uint CreateProgram(); + SharedPtr GetProgramObject(Uint id); + void DeleteProgram(Uint program); + private: + bool CheckIndexAvail(SizeT idx) { + return idx < m_programObjects.size(); + } + + void EnsureIndexAvail(SizeT idx) { + if (CheckIndexAvail(idx)) return; + + m_programObjects.reserve(std::bit_ceil(idx)); + m_programObjects.resize(idx + 1); + } + + IndexGenerator m_indexGenerator; + Vector> m_programObjects; + }; + } + } +} \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp new file mode 100644 index 00000000..631bb263 --- /dev/null +++ b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp @@ -0,0 +1,34 @@ +#include "../../../Includes.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + void ShaderObject::SetShaderSource(const std::string& source) { + m_source = source; + } + + void ShaderObject::Compile() { + using namespace MG_Util::ShaderTranspiler; + ShaderAttrib attrib { + .sourceStr = m_source, + .shaderType = GetGLShaderTypeByMGLShaderStage(m_stage), + .flags = 0 + }; + + auto result = ShaderCompiler::CompileShader(attrib); + if (result) { + m_compileStatus = true; + m_shader = result.value(); + } else { + m_compileStatus = false; + m_infoLog = result.error().log; + + const std::string e = + std::format("Shader compilation failed: \nerrc: {}\nmsg: {}\n", + result.error().errc, result.error().log); + THROW_EXCEPTION(e); + } + } + } + } +} \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h new file mode 100644 index 00000000..48ab4b14 --- /dev/null +++ b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h @@ -0,0 +1,52 @@ +#pragma once +#include "MG_Util/Types.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + enum class ShaderStage { + Vertex, + TessControl, + TessEval, + Geometry, + Fragment, + Compute + }; + + inline static GLenum GetGLShaderTypeByMGLShaderStage(ShaderStage stage) { + switch (stage) { + case ShaderStage::Vertex: + return GL_VERTEX_SHADER; + case ShaderStage::TessControl: + return GL_TESS_CONTROL_SHADER; + case ShaderStage::TessEval: + return GL_TESS_EVALUATION_SHADER; + case ShaderStage::Geometry: + return GL_GEOMETRY_SHADER; + case ShaderStage::Fragment: + return GL_FRAGMENT_SHADER; + case ShaderStage::Compute: + return GL_COMPUTE_SHADER; + default: + assert(false); + return 0; + } + } + + class ShaderObject { + public: + ShaderObject(const ShaderStage stage): m_stage(stage) {} + void SetShaderSource(const std::string& source); + void Compile(); + + const ShaderStage m_stage; + std::string m_source; + SharedPtr m_shader; + std::string m_infoLog; + + bool m_deleteStatus = false; + bool m_compileStatus = false; + }; + } + } +} diff --git a/MobileGL/MG_Test/Program/ShaderTest.cpp b/MobileGL/MG_Test/Program/ShaderTest.cpp new file mode 100644 index 00000000..e69de29b