From 9748813eb10af64976ffad7f9ccff6dd991226be Mon Sep 17 00:00:00 2001 From: baldurk Date: Sun, 30 Nov 2014 16:05:01 +0000 Subject: [PATCH] Use serialised program initial states to translate uniform locations * If you're capturing and replaying on the same driver it's insanely unlikely that this translation will be anything other than the identity map, although it wouldn't be illegal to renumber locations. However this should allow moving captures between vendors/driver versions/platforms, which in the past wasn't possible because locations would change (quite validly) when the programs were recompiled. There might be other issues, but at least this one is fixed. --- renderdoc/driver/gl/gl_common.cpp | 11 +- renderdoc/driver/gl/gl_common.h | 2 +- renderdoc/driver/gl/gl_driver.h | 2 + renderdoc/driver/gl/gl_manager.cpp | 4 +- .../driver/gl/wrappers/gl_shader_funcs.cpp | 8 ++ .../driver/gl/wrappers/gl_uniform_funcs.cpp | 104 +++++++++++------- 6 files changed, 82 insertions(+), 49 deletions(-) diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index 042a37dbf..94345b73f 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -422,7 +422,7 @@ ResourceFormat MakeResourceFormat(WrappedOpenGL &gl, GLenum target, GLenum fmt) } template -static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint progSrc, GLuint progDst, bool writing) +static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint progSrc, GLuint progDst, map *locTranslate, bool writing) { const bool ReadSourceProgram = CopyUniforms || (SerialiseUniforms && writing); const bool WriteDestProgram = CopyUniforms || (SerialiseUniforms && !writing); @@ -520,7 +520,10 @@ static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint p GLint newloc = 0; if(WriteDestProgram) + { newloc = gl.glGetUniformLocation(progDst, name.c_str()); + if(locTranslate) (*locTranslate)[srcLocation] = newloc; + } if(CopyUniforms && newloc == -1) continue; @@ -807,14 +810,14 @@ void CopyProgramUniforms(const GLHookSet &gl, GLuint progSrc, GLuint progDst) { const bool CopyUniforms = true; const bool SerialiseUniforms = false; - ForAllProgramUniforms(gl, NULL, progSrc, progDst, false); + ForAllProgramUniforms(gl, NULL, progSrc, progDst, NULL, false); } -void SerialiseProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint prog, bool writing) +void SerialiseProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint prog, map *locTranslate, bool writing) { const bool CopyUniforms = false; const bool SerialiseUniforms = true; - ForAllProgramUniforms(gl, ser, prog, prog, writing); + ForAllProgramUniforms(gl, ser, prog, prog, locTranslate, writing); } template<> diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index 665ac6731..05a654005 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -112,7 +112,7 @@ void DoVendorChecks(const GLHookSet &gl); #include "core/core.h" void CopyProgramUniforms(const GLHookSet &gl, GLuint progSrc, GLuint progDst); -void SerialiseProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint prog, bool writing); +void SerialiseProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint prog, map *locTranslate, bool writing); enum GLChunkType { diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index a7b911dfc..2eb5ecc09 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -211,6 +211,8 @@ class WrappedOpenGL } vector shaders; + map locationTranslate; + GLuint colOutProg; bool linked; ResourceId stageShaders[6]; diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 327ee3b7f..bb1f44ea0 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -156,7 +156,7 @@ bool GLResourceManager::Prepare_InitialState(GLResource res) m_pSerialiser->Serialise("Id", Id); - SerialiseProgramUniforms(gl, m_pSerialiser, res.name, true); + SerialiseProgramUniforms(gl, m_pSerialiser, res.name, NULL, true); SetInitialChunk(Id, scope.Get()); } @@ -356,7 +356,7 @@ bool GLResourceManager::Serialise_InitialState(GLResource res) gl.glLinkProgram(initProg); - SerialiseProgramUniforms(gl, m_pSerialiser, initProg, false); + SerialiseProgramUniforms(gl, m_pSerialiser, initProg, &details.locationTranslate, false); SetInitialContents(Id, InitialContentData(ProgramRes(m_GL->GetCtx(), initProg), 0, NULL)); } diff --git a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp index 4770b601a..0e930946d 100644 --- a/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_shader_funcs.cpp @@ -376,6 +376,10 @@ GLuint WrappedOpenGL::glCreateShaderProgramv(GLenum type, GLsizei count, const G GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id); RDCASSERT(record); + // we always want to mark programs as dirty so we can serialise their + // locations as initial state (and form a remapping table) + GetResourceManager()->MarkDirtyResource(id); + record->AddChunk(chunk); } else @@ -426,6 +430,10 @@ GLuint WrappedOpenGL::glCreateProgram() GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id); RDCASSERT(record); + + // we always want to mark programs as dirty so we can serialise their + // locations as initial state (and form a remapping table) + GetResourceManager()->MarkDirtyResource(id); record->AddChunk(chunk); } diff --git a/renderdoc/driver/gl/wrappers/gl_uniform_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_uniform_funcs.cpp index 11850ab24..51e272a4f 100644 --- a/renderdoc/driver/gl/wrappers/gl_uniform_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_uniform_funcs.cpp @@ -76,29 +76,39 @@ bool WrappedOpenGL::Serialise_glProgramUniformVector(GLuint program, GLint locat else if(m_State <= EXECUTING) { value = m_pSerialiser->RawReadBytes(elemSize*elemsPerVec*Count); - + + ResourceId liveProgId = GetResourceManager()->GetLiveID(id); GLuint live = GetResourceManager()->GetLiveResource(id).name; + + map &translate = m_Programs[liveProgId].locationTranslate; + if(translate.find(Loc) != translate.end()) + Loc = translate[Loc]; + else + Loc = -1; - switch(Type) + if(Loc >= 0) { - case VEC1iv: m_Real.glProgramUniform1iv(live, Loc, Count, (const GLint *)value); break; - case VEC1uiv: m_Real.glProgramUniform1uiv(live, Loc, Count, (const GLuint *)value); break; - case VEC1fv: m_Real.glProgramUniform1fv(live, Loc, Count, (const GLfloat *)value); break; - case VEC1dv: m_Real.glProgramUniform1dv(live, Loc, Count, (const GLdouble *)value); break; - case VEC2iv: m_Real.glProgramUniform2iv(live, Loc, Count, (const GLint *)value); break; - case VEC2uiv: m_Real.glProgramUniform2uiv(live, Loc, Count, (const GLuint *)value); break; - case VEC2fv: m_Real.glProgramUniform2fv(live, Loc, Count, (const GLfloat *)value); break; - case VEC2dv: m_Real.glProgramUniform2dv(live, Loc, Count, (const GLdouble *)value); break; - case VEC3iv: m_Real.glProgramUniform3iv(live, Loc, Count, (const GLint *)value); break; - case VEC3uiv: m_Real.glProgramUniform3uiv(live, Loc, Count, (const GLuint *)value); break; - case VEC3fv: m_Real.glProgramUniform3fv(live, Loc, Count, (const GLfloat *)value); break; - case VEC3dv: m_Real.glProgramUniform3dv(live, Loc, Count, (const GLdouble *)value); break; - case VEC4iv: m_Real.glProgramUniform4iv(live, Loc, Count, (const GLint *)value); break; - case VEC4uiv: m_Real.glProgramUniform4uiv(live, Loc, Count, (const GLuint *)value); break; - case VEC4fv: m_Real.glProgramUniform4fv(live, Loc, Count, (const GLfloat *)value); break; - case VEC4dv: m_Real.glProgramUniform4dv(live, Loc, Count, (const GLdouble *)value); break; - default: - RDCERR("Unexpected uniform type to Serialise_glProgramUniformVector: %d", Type); + switch(Type) + { + case VEC1iv: m_Real.glProgramUniform1iv(live, Loc, Count, (const GLint *)value); break; + case VEC1uiv: m_Real.glProgramUniform1uiv(live, Loc, Count, (const GLuint *)value); break; + case VEC1fv: m_Real.glProgramUniform1fv(live, Loc, Count, (const GLfloat *)value); break; + case VEC1dv: m_Real.glProgramUniform1dv(live, Loc, Count, (const GLdouble *)value); break; + case VEC2iv: m_Real.glProgramUniform2iv(live, Loc, Count, (const GLint *)value); break; + case VEC2uiv: m_Real.glProgramUniform2uiv(live, Loc, Count, (const GLuint *)value); break; + case VEC2fv: m_Real.glProgramUniform2fv(live, Loc, Count, (const GLfloat *)value); break; + case VEC2dv: m_Real.glProgramUniform2dv(live, Loc, Count, (const GLdouble *)value); break; + case VEC3iv: m_Real.glProgramUniform3iv(live, Loc, Count, (const GLint *)value); break; + case VEC3uiv: m_Real.glProgramUniform3uiv(live, Loc, Count, (const GLuint *)value); break; + case VEC3fv: m_Real.glProgramUniform3fv(live, Loc, Count, (const GLfloat *)value); break; + case VEC3dv: m_Real.glProgramUniform3dv(live, Loc, Count, (const GLdouble *)value); break; + case VEC4iv: m_Real.glProgramUniform4iv(live, Loc, Count, (const GLint *)value); break; + case VEC4uiv: m_Real.glProgramUniform4uiv(live, Loc, Count, (const GLuint *)value); break; + case VEC4fv: m_Real.glProgramUniform4fv(live, Loc, Count, (const GLfloat *)value); break; + case VEC4dv: m_Real.glProgramUniform4dv(live, Loc, Count, (const GLdouble *)value); break; + default: + RDCERR("Unexpected uniform type to Serialise_glProgramUniformVector: %d", Type); + } } } @@ -206,31 +216,41 @@ bool WrappedOpenGL::Serialise_glProgramUniformMatrix(GLuint program, GLint locat else if(m_State <= EXECUTING) { value = m_pSerialiser->RawReadBytes(elemSize*elemsPerMat*Count); - + + ResourceId liveProgId = GetResourceManager()->GetLiveID(id); GLuint live = GetResourceManager()->GetLiveResource(id).name; + + map &translate = m_Programs[liveProgId].locationTranslate; + if(translate.find(Loc) != translate.end()) + Loc = translate[Loc]; + else + Loc = -1; - switch(Type) + if(Loc >= 0) { - case MAT2fv: m_Real.glProgramUniformMatrix2fv (live, Loc, Count, Transpose, (const GLfloat *)value); break; - case MAT2x3fv: m_Real.glProgramUniformMatrix2x3fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; - case MAT2x4fv: m_Real.glProgramUniformMatrix2x4fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; - case MAT3fv: m_Real.glProgramUniformMatrix3fv (live, Loc, Count, Transpose, (const GLfloat *)value); break; - case MAT3x2fv: m_Real.glProgramUniformMatrix3x2fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; - case MAT3x4fv: m_Real.glProgramUniformMatrix3x4fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; - case MAT4fv: m_Real.glProgramUniformMatrix4fv (live, Loc, Count, Transpose, (const GLfloat *)value); break; - case MAT4x2fv: m_Real.glProgramUniformMatrix4x2fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; - case MAT4x3fv: m_Real.glProgramUniformMatrix4x3fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; - case MAT2dv: m_Real.glProgramUniformMatrix2dv (live, Loc, Count, Transpose, (const GLdouble *)value); break; - case MAT2x3dv: m_Real.glProgramUniformMatrix2x3dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; - case MAT2x4dv: m_Real.glProgramUniformMatrix2x4dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; - case MAT3dv: m_Real.glProgramUniformMatrix3dv (live, Loc, Count, Transpose, (const GLdouble *)value); break; - case MAT3x2dv: m_Real.glProgramUniformMatrix3x2dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; - case MAT3x4dv: m_Real.glProgramUniformMatrix3x4dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; - case MAT4dv: m_Real.glProgramUniformMatrix4dv (live, Loc, Count, Transpose, (const GLdouble *)value); break; - case MAT4x2dv: m_Real.glProgramUniformMatrix4x2dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; - case MAT4x3dv: m_Real.glProgramUniformMatrix4x3dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; - default: - RDCERR("Unexpected uniform type to Serialise_glProgramUniformMatrix: %d", Type); + switch(Type) + { + case MAT2fv: m_Real.glProgramUniformMatrix2fv (live, Loc, Count, Transpose, (const GLfloat *)value); break; + case MAT2x3fv: m_Real.glProgramUniformMatrix2x3fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; + case MAT2x4fv: m_Real.glProgramUniformMatrix2x4fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; + case MAT3fv: m_Real.glProgramUniformMatrix3fv (live, Loc, Count, Transpose, (const GLfloat *)value); break; + case MAT3x2fv: m_Real.glProgramUniformMatrix3x2fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; + case MAT3x4fv: m_Real.glProgramUniformMatrix3x4fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; + case MAT4fv: m_Real.glProgramUniformMatrix4fv (live, Loc, Count, Transpose, (const GLfloat *)value); break; + case MAT4x2fv: m_Real.glProgramUniformMatrix4x2fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; + case MAT4x3fv: m_Real.glProgramUniformMatrix4x3fv(live, Loc, Count, Transpose, (const GLfloat *)value); break; + case MAT2dv: m_Real.glProgramUniformMatrix2dv (live, Loc, Count, Transpose, (const GLdouble *)value); break; + case MAT2x3dv: m_Real.glProgramUniformMatrix2x3dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; + case MAT2x4dv: m_Real.glProgramUniformMatrix2x4dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; + case MAT3dv: m_Real.glProgramUniformMatrix3dv (live, Loc, Count, Transpose, (const GLdouble *)value); break; + case MAT3x2dv: m_Real.glProgramUniformMatrix3x2dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; + case MAT3x4dv: m_Real.glProgramUniformMatrix3x4dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; + case MAT4dv: m_Real.glProgramUniformMatrix4dv (live, Loc, Count, Transpose, (const GLdouble *)value); break; + case MAT4x2dv: m_Real.glProgramUniformMatrix4x2dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; + case MAT4x3dv: m_Real.glProgramUniformMatrix4x3dv(live, Loc, Count, Transpose, (const GLdouble *)value); break; + default: + RDCERR("Unexpected uniform type to Serialise_glProgramUniformMatrix: %d", Type); + } } }