diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 39683de1..319f794c 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -44,7 +44,7 @@ jobs: - name: Build working-directory: ${{env.BENCH_ROOT}}/build-bench - run: cmake --build . --parallel 1 + run: cmake --build . --parallel 4 - name: Benchmark working-directory: ${{env.BENCH_ROOT}}/build-bench diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b279802b..353a3954 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,7 +44,7 @@ jobs: - name: Build working-directory: ${{env.TEST_ROOT}}/build-test - run: cmake --build . --parallel 1 + run: cmake --build . --parallel 4 - name: Test working-directory: ${{env.TEST_ROOT}}/build-test diff --git a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp index d65a1db5..aaf53306 100644 --- a/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp +++ b/MobileGL/MG_Impl/GLImpl/Program/GL_Program.cpp @@ -140,7 +140,23 @@ namespace MobileGL { } void GetAttachedShaders_State(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) { - THROW_UNIMPL_EXCEPTION; + if (maxCount < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeShared("MG_Impl/GLImpl", __func__, + "`maxCount` is less than 0.")); + return; + } + auto programObject = TryToGetProgramObject(program); + if (!programObject) + return; + const auto& s = programObject->GetAttachedShaders(); + GLsizei c = std::min((GLsizei)s.size(), maxCount); + if (count) + *count = c; + for (GLsizei i = 0; i < c; ++i) { + shaders[i] = s[i]->GetId(); + } } GLint GetAttribLocation_State(GLuint program, const GLchar* name) { @@ -164,7 +180,23 @@ namespace MobileGL { } void GetShaderSource_State(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* source) { - THROW_UNIMPL_EXCEPTION; + if (bufSize < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeShared("MG_Impl/GLImpl", __func__, + "`bufSize` is less than 0.")); + } + + auto shaderObject = TryToGetShaderObject(shader); + if (!shaderObject) + return; + + auto& src = shaderObject->GetShaderSource(); + auto sz = std::min(bufSize - 1, (GLsizei)src.length()); + if (length) + *length = sz; + memcpy(source, src.c_str(), sz); + source[sz] = '\0'; } GLint GetUniformLocation_State(GLuint program, const GLchar* name) { @@ -203,11 +235,36 @@ namespace MobileGL { } void ShaderSource_State(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) { - THROW_UNIMPL_EXCEPTION; + if (count < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeShared("MG_Impl/GLImpl", __func__, + "`count` is less than 0.")); + } + + auto shaderObject = TryToGetShaderObject(shader); + if (!shaderObject) + return; + + std::string src; + for (GLsizei i = 0; i < count; i++) { + src += + (length[i] <= 0) ? string[i] : std::string(string[i], length[i]); + } + shaderObject->SetShaderSource(Move(src)); } void UseProgram_State(GLuint program) { - THROW_UNIMPL_EXCEPTION; + if (program == 0) { + MG_State::pGLContext->UseProgram(0); + return; + } + + auto programObject = TryToGetProgramObject(program); + if (!programObject) + return; + MG_State::pGLContext->UseProgram(program); + } void Uniform1f_State(GLint location, GLfloat v0) { diff --git a/MobileGL/MG_State/GLState/Core.cpp b/MobileGL/MG_State/GLState/Core.cpp index 92c190ea..3f28f6f4 100644 --- a/MobileGL/MG_State/GLState/Core.cpp +++ b/MobileGL/MG_State/GLState/Core.cpp @@ -187,6 +187,10 @@ namespace MobileGL { SharedPtr GLContext::GetShaderObject(const Uint index) { return m_programState.GetShaderObject(index); } + + void GLContext::UseProgram(Uint program) { + return m_programState.UseProgram(program); + } } // namespace GLState GLState::GLContext* pGLContext; diff --git a/MobileGL/MG_State/GLState/Core.h b/MobileGL/MG_State/GLState/Core.h index b3bb10c6..e57d0785 100644 --- a/MobileGL/MG_State/GLState/Core.h +++ b/MobileGL/MG_State/GLState/Core.h @@ -63,6 +63,7 @@ namespace MobileGL { Bool ValidateShaderName(Uint index) const; SharedPtr GetProgramObject(Uint index); SharedPtr GetShaderObject(Uint index); + void UseProgram(Uint program); private: // Error ErrorState m_errorState; diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp index a82c57a9..db9bc49a 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp @@ -59,6 +59,10 @@ namespace MobileGL { void ProgramObject::MarkAsDeleted() { m_deleteStatus = true; } + + Vector>& ProgramObject::GetAttachedShaders() { + return m_shaders; + } } // namespace GLState } // namespace MG_State } // namespace MobileGL \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h index 1946707d..a4e5b1b5 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramObject.h @@ -7,12 +7,15 @@ namespace MobileGL { namespace GLState { class ProgramObject { public: + ProgramObject(const Uint id): m_id(id) {} bool ShaderIsAttached(SharedPtr shader); bool AttachShader(SharedPtr shader); SizeT DetachShader(SharedPtr shader); void Link(); void MarkAsDeleted(); + Vector>& GetAttachedShaders(); private: + const Uint m_id = 0; Vector> m_shaders; // basically this contains SPIR-V in binary format Vector> m_programBinary; diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramState.cpp b/MobileGL/MG_State/GLState/ProgramState/ProgramState.cpp index b90c276d..fb7f22eb 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramState.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramState.cpp @@ -33,11 +33,19 @@ namespace MobileGL { return CheckIndexAvail(program, m_programObjects) && m_programObjects[program] != nullptr; } + void ProgramState::UseProgram(Uint program) { + if (program == 0) + m_currentProgram.reset(); + + if (!CheckIndexAvail(program, m_programObjects)) return; + m_currentProgram = m_programObjects[program]; + } + Uint ProgramState::CreateShader(ShaderStage stage) { Uint shaderId = 0; m_shaderIndexGenerator.Generate(1, &shaderId); EnsureIndexAvail(shaderId, m_shaderObjects); - auto shaderObject = MakeShared(stage); + auto shaderObject = MakeShared(stage, shaderId); if (shaderObject == nullptr) return 0; m_shaderObjects[shaderId] = shaderObject; diff --git a/MobileGL/MG_State/GLState/ProgramState/ProgramState.h b/MobileGL/MG_State/GLState/ProgramState/ProgramState.h index 85a653a0..ff981cb1 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ProgramState.h +++ b/MobileGL/MG_State/GLState/ProgramState/ProgramState.h @@ -15,6 +15,8 @@ namespace MobileGL { void MarkProgramObjectForDeletion(Uint program); Bool ValidateProgramObject(Uint program) const; + void UseProgram(Uint program); + Uint CreateShader(ShaderStage stage); SharedPtr GetShaderObject(Uint shader); void MarkShaderObjectForDeletion(Uint shader); @@ -38,6 +40,8 @@ namespace MobileGL { IndexGenerator m_shaderIndexGenerator; Vector> m_shaderObjects; + + SharedPtr m_currentProgram; }; } // namespace GLState } // namespace MG_State diff --git a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp index fbbd93de..3345f025 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp +++ b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp @@ -8,6 +8,10 @@ namespace MobileGL { m_source = source; } + void ShaderObject::SetShaderSource(std::string &&source) { + m_source = Move(source); + } + void ShaderObject::Compile() { using namespace MG_Util::ShaderTranspiler; ShaderAttrib attrib{ diff --git a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h index c743a629..271c7939 100644 --- a/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h +++ b/MobileGL/MG_State/GLState/ProgramState/ShaderObject.h @@ -56,15 +56,18 @@ namespace MobileGL { class ShaderObject { public: - ShaderObject(const ShaderStage stage) : m_stage(stage) {} + ShaderObject(const ShaderStage stage, const Uint id) : m_stage(stage), m_id(id) {} void SetShaderSource(const std::string& source); + void SetShaderSource(std::string&& source); void Compile(); void MarkAsDeleted(); + Uint GetId() const { return m_id; } ShaderStage GetShaderStage() const { return m_stage; } const std::string& GetShaderSource() const { return m_source; } SharedPtr GetCompiledShader() const { return m_shader; } private: + const Uint m_id = 0; const ShaderStage m_stage; std::string m_source; SharedPtr m_shader;