diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 7be3fd09c2..cb5d63d847 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -56,6 +56,8 @@ void GLQueueRunner::CreateDeviceObjects() { populate(GL_EXTENSIONS); } CHECK_GL_ERROR_IF_DEBUG(); + + useDebugGroups_ = !gl_extensions.IsGLES && gl_extensions.VersionGEThan(4, 3); } void GLQueueRunner::DestroyDeviceObjects() { @@ -132,6 +134,11 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps, bool ski return; } +#if !defined(USING_GLES2) + if (useDebugGroups_) + glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 1, -1, "InitSteps"); +#endif + CHECK_GL_ERROR_IF_DEBUG(); glActiveTexture(GL_TEXTURE0); GLuint boundTexture = (GLuint)-1; @@ -379,6 +386,14 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps, bool ski WARN_LOG(G3D, "Got an error after init: %08x (%s)", err, GLEnumToString(err).c_str()); } } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + +#if !defined(USING_GLES2) + if (useDebugGroups_) + glPopDebugGroup(); +#endif } void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { @@ -582,12 +597,32 @@ void GLQueueRunner::RunSteps(const std::vector &steps, bool skipGLCal return; } + size_t totalRenderCount = 0; + for (auto &step : steps) { + if (step->stepType == GLRStepType::RENDER) { + // Skip empty render steps. + if (step->commands.empty()) { + step->stepType = GLRStepType::RENDER_SKIP; + continue; + } + totalRenderCount++; + } + } + CHECK_GL_ERROR_IF_DEBUG(); + size_t renderCount = 0; for (size_t i = 0; i < steps.size(); i++) { const GLRStep &step = *steps[i]; + +#if !defined(USING_GLES2) + if (useDebugGroups_) + glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, (GLuint)i + 10000, -1, step.tag); +#endif + switch (step.stepType) { case GLRStepType::RENDER: - PerformRenderPass(step); + renderCount++; + PerformRenderPass(step, renderCount == 1, renderCount == totalRenderCount); break; case GLRStepType::COPY: PerformCopy(step); @@ -601,10 +636,18 @@ void GLQueueRunner::RunSteps(const std::vector &steps, bool skipGLCal case GLRStepType::READBACK_IMAGE: PerformReadbackImage(step); break; + case GLRStepType::RENDER_SKIP: + break; default: Crash(); break; } + +#if !defined(USING_GLES2) + if (useDebugGroups_) + glPopDebugGroup(); +#endif + delete steps[i]; } CHECK_GL_ERROR_IF_DEBUG(); @@ -644,27 +687,24 @@ void GLQueueRunner::PerformBlit(const GLRStep &step) { } } -void GLQueueRunner::PerformRenderPass(const GLRStep &step) { +void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last) { CHECK_GL_ERROR_IF_DEBUG(); - // Don't execute empty renderpasses. - if (step.commands.empty()) { - // Nothing to do. - return; - } PerformBindFramebufferAsRenderTarget(step); - glDisable(GL_DEPTH_TEST); - glDisable(GL_STENCIL_TEST); - glDisable(GL_BLEND); - glDisable(GL_CULL_FACE); - glDisable(GL_DITHER); - glEnable(GL_SCISSOR_TEST); + if (first) { + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_DITHER); + glEnable(GL_SCISSOR_TEST); #ifndef USING_GLES2 - if (!gl_extensions.IsGLES) { - glDisable(GL_COLOR_LOGIC_OP); - } + if (!gl_extensions.IsGLES) { + glDisable(GL_COLOR_LOGIC_OP); + } #endif + } /* #ifndef USING_GLES2 @@ -678,21 +718,22 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { #endif */ - if (gl_extensions.ARB_vertex_array_object) { + if (first && gl_extensions.ARB_vertex_array_object) { glBindVertexArray(globalVAO_); } GLRProgram *curProgram = nullptr; int activeSlot = 0; - glActiveTexture(GL_TEXTURE0 + activeSlot); + if (first) + glActiveTexture(GL_TEXTURE0 + activeSlot); // State filtering tracking. int attrMask = 0; int colorMask = -1; int depthMask = -1; int depthFunc = -1; - GLuint curArrayBuffer = (GLuint)-1; - GLuint curElemArrayBuffer = (GLuint)-1; + GLuint curArrayBuffer = (GLuint)0; + GLuint curElemArrayBuffer = (GLuint)0; bool depthEnabled = false; bool stencilEnabled = false; bool blendEnabled = false; @@ -929,9 +970,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::UNIFORMMATRIX: { assert(curProgram); - int loc = c.uniform4.loc ? *c.uniform4.loc : -1; - if (c.uniform4.name) { - loc = curProgram->GetUniformLoc(c.uniform4.name); + int loc = c.uniformMatrix4.loc ? *c.uniformMatrix4.loc : -1; + if (c.uniformMatrix4.name) { + loc = curProgram->GetUniformLoc(c.uniformMatrix4.name); } if (loc >= 0) { glUniformMatrix4fv(loc, 1, false, c.uniformMatrix4.m); @@ -1179,22 +1220,30 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { CHECK_GL_ERROR_IF_DEBUG(); // Wipe out the current state. - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - if (gl_extensions.ARB_vertex_array_object) { + if (curArrayBuffer != 0) + glBindBuffer(GL_ARRAY_BUFFER, 0); + if (curElemArrayBuffer != 0) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + if (last && gl_extensions.ARB_vertex_array_object) { glBindVertexArray(0); } - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_STENCIL_TEST); - glDisable(GL_BLEND); - glDisable(GL_CULL_FACE); + if (last) + glDisable(GL_SCISSOR_TEST); + if (depthEnabled) + glDisable(GL_DEPTH_TEST); + if (stencilEnabled) + glDisable(GL_STENCIL_TEST); + if (blendEnabled) + glDisable(GL_BLEND); + if (cullEnabled) + glDisable(GL_CULL_FACE); #ifndef USING_GLES2 - if (!gl_extensions.IsGLES) { + if (!gl_extensions.IsGLES && logicEnabled) { glDisable(GL_COLOR_LOGIC_OP); } #endif - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if ((colorMask & 15) != 15) + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 06ba82af31..d62c61e4ba 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -276,6 +276,7 @@ enum class GLRStepType : uint8_t { BLIT, READBACK, READBACK_IMAGE, + RENDER_SKIP, }; enum class GLRRenderPassAction { @@ -372,7 +373,7 @@ private: void InitCreateFramebuffer(const GLRInitStep &step); void PerformBindFramebufferAsRenderTarget(const GLRStep &pass); - void PerformRenderPass(const GLRStep &pass); + void PerformRenderPass(const GLRStep &pass, bool first, bool last); void PerformCopy(const GLRStep &pass); void PerformBlit(const GLRStep &pass); void PerformReadback(const GLRStep &pass); @@ -420,4 +421,5 @@ private: std::unordered_map glStrings_; bool sawOutOfMemory_ = false; + bool useDebugGroups_ = false; };