diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index 17929e51c..ff6c5ef2e 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -148,8 +148,10 @@ enum GLChunkType PROGRAMPARAMETER, BINDATTRIB_LOCATION, BINDFRAGDATA_LOCATION, + BINDFRAGDATA_LOCATION_INDEXED, UNIFORM_BLOCKBIND, STORAGE_BLOCKBIND, + UNIFORM_SUBROUTINE, PROGRAMUNIFORM_VECTOR, PROGRAMUNIFORM_MATRIX, LINKPROGRAM, diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index f07694b85..c41ab447b 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -93,8 +93,10 @@ const char *GLChunkNames[] = "glProgramParameter", "glBindAttribLocation", "glBindFragDataLocation", + "glBindFragDataLocationIndexed", "glUniformBlockBinding", "glShaderStorageBlockBinding", + "glUniformSubroutinesuiv", "glProgramUniformMatrix*", "glProgramUniformVector*", "glLinkProgram", @@ -1722,12 +1724,18 @@ void WrappedOpenGL::ProcessChunk(uint64_t offset, GLChunkType context) case BINDFRAGDATA_LOCATION: Serialise_glBindFragDataLocation(0, 0, NULL); break; + case BINDFRAGDATA_LOCATION_INDEXED: + Serialise_glBindFragDataLocationIndexed(0, 0, 0, NULL); + break; case UNIFORM_BLOCKBIND: Serialise_glUniformBlockBinding(0, 0, 0); break; case STORAGE_BLOCKBIND: Serialise_glShaderStorageBlockBinding(0, 0, 0); break; + case UNIFORM_SUBROUTINE: + Serialise_glUniformSubroutinesuiv(eGL_NONE, 0, NULL); + break; case PROGRAMUNIFORM_VECTOR: Serialise_glProgramUniformVector(0, eGL_NONE, 0, 0, UNIFORM_UNKNOWN); break; diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index f7fa95f30..5cd38dbb4 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -515,8 +515,10 @@ class WrappedOpenGL IMPLEMENT_FUNCTION_SERIALISED(void, glProgramParameteri(GLuint program, GLenum pname, GLint value)); IMPLEMENT_FUNCTION_SERIALISED(void, glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)); IMPLEMENT_FUNCTION_SERIALISED(void, glShaderStorageBlockBinding(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding)); + IMPLEMENT_FUNCTION_SERIALISED(void, glUniformSubroutinesuiv(GLenum shadertype, GLsizei count, const GLuint *indices)); IMPLEMENT_FUNCTION_SERIALISED(void, glBindAttribLocation(GLuint program, GLuint index, const GLchar *name)); IMPLEMENT_FUNCTION_SERIALISED(void, glBindFragDataLocation(GLuint program, GLuint color, const GLchar *name)); + IMPLEMENT_FUNCTION_SERIALISED(void, glBindFragDataLocationIndexed(GLuint program, GLuint colorNumber, GLuint index, const GLchar *name)); IMPLEMENT_FUNCTION_SERIALISED(void, glUseProgram(GLuint program)); IMPLEMENT_FUNCTION_SERIALISED(void, glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)); IMPLEMENT_FUNCTION_SERIALISED(void, glValidateProgram(GLuint program)); diff --git a/renderdoc/driver/gl/gl_hookset.h b/renderdoc/driver/gl/gl_hookset.h index dd0793b49..e3bd30fdd 100644 --- a/renderdoc/driver/gl/gl_hookset.h +++ b/renderdoc/driver/gl/gl_hookset.h @@ -424,6 +424,7 @@ struct GLHookSet PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor; PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation; PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation; + PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glBindFragDataLocationIndexed; PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray; PFNGLBINDVERTEXBUFFERPROC glBindVertexBuffer; @@ -476,6 +477,7 @@ struct GLHookSet PFNGLVIEWPORTARRAYVPROC glViewportArrayv; PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding; PFNGLSHADERSTORAGEBLOCKBINDINGPROC glShaderStorageBlockBinding; + PFNGLUNIFORMSUBROUTINESUIVPROC glUniformSubroutinesuiv; PFNGLUNIFORM1FPROC glUniform1f; PFNGLUNIFORM1IPROC glUniform1i; PFNGLUNIFORM1UIPROC glUniform1ui; diff --git a/renderdoc/driver/gl/gl_hookset_defs.h b/renderdoc/driver/gl/gl_hookset_defs.h index 45e30eb0d..482a2ae8c 100644 --- a/renderdoc/driver/gl/gl_hookset_defs.h +++ b/renderdoc/driver/gl/gl_hookset_defs.h @@ -454,6 +454,7 @@ HookExtension(PFNGLVERTEXATTRIBDIVISORPROC, glVertexAttribDivisor); \ HookExtension(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation); \ HookExtension(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation); \ + HookExtension(PFNGLBINDFRAGDATALOCATIONINDEXEDPROC, glBindFragDataLocationIndexed); \ HookExtension(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); \ HookExtension(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray); \ HookExtension(PFNGLBINDVERTEXBUFFERPROC, glBindVertexBuffer); \ @@ -508,6 +509,7 @@ HookExtension(PFNGLVIEWPORTARRAYVPROC, glViewportArrayv); \ HookExtension(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding); \ HookExtension(PFNGLSHADERSTORAGEBLOCKBINDINGPROC, glShaderStorageBlockBinding); \ + HookExtension(PFNGLUNIFORMSUBROUTINESUIVPROC, glUniformSubroutinesuiv); \ HookExtension(PFNGLUNIFORM1FPROC, glUniform1f); \ HookExtension(PFNGLUNIFORM1IPROC, glUniform1i); \ HookExtension(PFNGLUNIFORM1UIPROC, glUniform1ui); \ @@ -1134,6 +1136,7 @@ HookWrapper2(void, glVertexAttribDivisor, GLuint, index, GLuint, divisor); \ HookWrapper3(void, glBindAttribLocation, GLuint, program, GLuint, index, const GLchar *, name); \ HookWrapper3(void, glBindFragDataLocation, GLuint, program, GLuint, color, const GLchar *, name); \ + HookWrapper4(void, glBindFragDataLocationIndexed, GLuint, program, GLuint, colorNumber, GLuint, index, const GLchar *, name); \ HookWrapper1(void, glEnableVertexAttribArray, GLuint, index); \ HookWrapper1(void, glDisableVertexAttribArray, GLuint, index); \ HookWrapper4(void, glBindVertexBuffer, GLuint, bindingindex, GLuint, buffer, GLintptr, offset, GLsizei, stride); \ @@ -1186,6 +1189,7 @@ HookWrapper3(void, glViewportArrayv, GLuint, first, GLsizei, count, const GLfloat *, v); \ HookWrapper3(void, glUniformBlockBinding, GLuint, program, GLuint, uniformBlockIndex, GLuint, uniformBlockBinding); \ HookWrapper3(void, glShaderStorageBlockBinding, GLuint, program, GLuint, storageBlockIndex, GLuint, storageBlockBinding); \ + HookWrapper3(void, glUniformSubroutinesuiv, GLenum, shadertype, GLsizei, count, const GLuint *, indices); \ HookWrapper2(void, glUniform1f, GLint, location, GLfloat, v0); \ HookWrapper2(void, glUniform1i, GLint, location, GLint, v0); \ HookWrapper2(void, glUniform1ui, GLint, location, GLuint, v0); \ diff --git a/renderdoc/driver/gl/gl_renderstate.cpp b/renderdoc/driver/gl/gl_renderstate.cpp index 64b69cf35..90883795c 100644 --- a/renderdoc/driver/gl/gl_renderstate.cpp +++ b/renderdoc/driver/gl/gl_renderstate.cpp @@ -164,6 +164,24 @@ void GLRenderState::FetchState() m_Real->glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint *)&Program); m_Real->glGetIntegerv(eGL_PROGRAM_PIPELINE_BINDING, (GLint *)&Pipeline); + + GLenum shs[] = { + eGL_VERTEX_SHADER, + eGL_TESS_CONTROL_SHADER, + eGL_TESS_EVALUATION_SHADER, + eGL_GEOMETRY_SHADER, + eGL_FRAGMENT_SHADER, + eGL_COMPUTE_SHADER + }; + + RDCCOMPILE_ASSERT(ARRAY_COUNT(shs) == ARRAY_COUNT(Subroutines), "Subroutine array not the right size"); + for(size_t s=0; s < ARRAY_COUNT(shs); s++) + { + m_Real->glGetIntegerv(eGL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &Subroutines[s].numSubroutines); + + for(GLint i=0; i < Subroutines[s].numSubroutines; i++) + m_Real->glGetUniformSubroutineuiv(shs[s], i, &Subroutines[s].Values[s]); + } m_Real->glGetIntegerv(eGL_ARRAY_BUFFER_BINDING, (GLint*)&BufferBindings[eBufIdx_Array]); m_Real->glGetIntegerv(eGL_COPY_READ_BUFFER_BINDING, (GLint*)&BufferBindings[eBufIdx_Copy_Read]); @@ -376,6 +394,20 @@ void GLRenderState::ApplyState() m_Real->glUseProgram(Program); m_Real->glBindProgramPipeline(Pipeline); + + GLenum shs[] = { + eGL_VERTEX_SHADER, + eGL_TESS_CONTROL_SHADER, + eGL_TESS_EVALUATION_SHADER, + eGL_GEOMETRY_SHADER, + eGL_FRAGMENT_SHADER, + eGL_COMPUTE_SHADER + }; + + RDCCOMPILE_ASSERT(ARRAY_COUNT(shs) == ARRAY_COUNT(Subroutines), "Subroutine array not the right size"); + for(size_t s=0; s < ARRAY_COUNT(shs); s++) + if(Subroutines[s].numSubroutines > 0) + m_Real->glUniformSubroutinesuiv(shs[s], Subroutines[s].numSubroutines, Subroutines[s].Values); m_Real->glBindBuffer(eGL_ARRAY_BUFFER, BufferBindings[eBufIdx_Array]); m_Real->glBindBuffer(eGL_COPY_READ_BUFFER, BufferBindings[eBufIdx_Copy_Read]); @@ -529,17 +561,26 @@ void GLRenderState::Clear() RDCEraseEl(Tex2D); RDCEraseEl(Samplers); RDCEraseEl(ActiveTexture); + + RDCEraseEl(Program); + RDCEraseEl(Pipeline); + + RDCEraseEl(Subroutines); RDCEraseEl(VAO); RDCEraseEl(VertexBuffers); + RDCEraseEl(GenericVertexAttribs); + RDCEraseEl(PointFadeThresholdSize); RDCEraseEl(PointSpriteOrigin); RDCEraseEl(LineWidth); RDCEraseEl(PointSize); - RDCEraseEl(Program); - RDCEraseEl(Pipeline); + RDCEraseEl(PrimitiveRestartIndex); + RDCEraseEl(ClipOrigin); + RDCEraseEl(ClipDepth); + RDCEraseEl(ProvokingVertex); RDCEraseEl(BufferBindings); RDCEraseEl(AtomicCounter); @@ -571,6 +612,7 @@ void GLRenderState::Clear() RDCEraseEl(SampleMask); RDCEraseEl(SampleCoverage); RDCEraseEl(SampleCoverageInvert); + RDCEraseEl(MinSampleShading); RDCEraseEl(LogicOp); RDCEraseEl(ColorClearValue); @@ -656,6 +698,12 @@ void GLRenderState::Serialise(LogState state, void *ctx, WrappedOpenGL *gl) m_pSerialiser->Serialise("GL_PROGRAM_PIPELINE_BINDING", ID); if(state < WRITING && ID != ResourceId()) Pipeline = rm->GetLiveResource(ID).name; } + + for(size_t s=0; s < ARRAY_COUNT(Subroutines); s++) + { + m_pSerialiser->Serialise("GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS", Subroutines[s].numSubroutines); + m_pSerialiser->Serialise<128>("GL_SUBROUTINE_UNIFORMS", Subroutines[s].Values); + } { ResourceId ID = ResourceId(); diff --git a/renderdoc/driver/gl/gl_renderstate.h b/renderdoc/driver/gl/gl_renderstate.h index 438b11308..62eb94fe3 100644 --- a/renderdoc/driver/gl/gl_renderstate.h +++ b/renderdoc/driver/gl/gl_renderstate.h @@ -86,6 +86,12 @@ struct GLRenderState GLuint Program; GLuint Pipeline; + struct + { + GLint numSubroutines; + GLuint Values[128]; + } Subroutines[6]; + enum { eBufIdx_Array, diff --git a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp index b5b276c37..33ddd6ab8 100644 --- a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp @@ -609,6 +609,67 @@ void WrappedOpenGL::glBindFragDataLocation(GLuint program, GLuint color, const G } } +bool WrappedOpenGL::Serialise_glUniformSubroutinesuiv(GLenum shadertype, GLsizei count, const GLuint *indices) +{ + SERIALISE_ELEMENT(GLenum, sh, shadertype); + SERIALISE_ELEMENT(uint32_t, Count, count); + SERIALISE_ELEMENT_ARR(uint32_t, Idxs, indices, Count); + + if(m_State <= EXECUTING) + m_Real.glUniformSubroutinesuiv(sh, Count, Idxs); + + SAFE_DELETE_ARRAY(Idxs); + + return true; +} + +void WrappedOpenGL::glUniformSubroutinesuiv(GLenum shadertype, GLsizei count, const GLuint *indices) +{ + m_Real.glUniformSubroutinesuiv(shadertype, count, indices); + + if(m_State >= WRITING_CAPFRAME) + { + SCOPED_SERIALISE_CONTEXT(UNIFORM_SUBROUTINE); + Serialise_glUniformSubroutinesuiv(shadertype, count, indices); + + m_ContextRecord->AddChunk(scope.Get()); + } +} + +bool WrappedOpenGL::Serialise_glBindFragDataLocationIndexed(GLuint program, GLuint colorNumber, GLuint index, const GLchar *name_) +{ + SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ProgramRes(GetCtx(), program))); + SERIALISE_ELEMENT(uint32_t, colNum, colorNumber); + SERIALISE_ELEMENT(uint32_t, idx, index); + + string name = name_ ? name_ : ""; + m_pSerialiser->Serialise("Name", name); + + if(m_State == READING) + { + m_Real.glBindFragDataLocationIndexed(GetResourceManager()->GetLiveResource(id).name, colNum, idx, name.c_str()); + } + + return true; +} + +void WrappedOpenGL::glBindFragDataLocationIndexed(GLuint program, GLuint colorNumber, GLuint index, const GLchar *name) +{ + m_Real.glBindFragDataLocationIndexed(program, colorNumber, index, name); + + if(m_State >= WRITING) + { + GLResourceRecord *record = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), program)); + RDCASSERT(record); + { + SCOPED_SERIALISE_CONTEXT(BINDFRAGDATA_LOCATION_INDEXED); + Serialise_glBindFragDataLocationIndexed(program, colorNumber, index, name); + + record->AddChunk(scope.Get()); + } + } +} + bool WrappedOpenGL::Serialise_glProgramParameteri(GLuint program, GLenum pname, GLint value) { SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(ProgramRes(GetCtx(), program)));