diff --git a/renderdoc/driver/gl/gl_common.cpp b/renderdoc/driver/gl/gl_common.cpp index a0debb10e..5705c3e16 100644 --- a/renderdoc/driver/gl/gl_common.cpp +++ b/renderdoc/driver/gl/gl_common.cpp @@ -280,6 +280,402 @@ ResourceFormat MakeResourceFormat(WrappedOpenGL &gl, GLenum target, GLenum fmt) return ret; } +template +static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint progSrc, GLuint progDst, bool writing) +{ + const bool ReadSourceProgram = CopyUniforms || (SerialiseUniforms && writing); + const bool WriteDestProgram = CopyUniforms || (SerialiseUniforms && !writing); + + RDCCOMPILE_ASSERT( (CopyUniforms && !SerialiseUniforms) || (!CopyUniforms && SerialiseUniforms), "Invalid call to ForAllProgramUniforms"); + + GLint numUniforms = 0; + if(ReadSourceProgram) + gl.glGetProgramInterfaceiv(progSrc, eGL_UNIFORM, eGL_ACTIVE_RESOURCES, &numUniforms); + + if(SerialiseUniforms) + { + // get accurate count of uniforms not in UBOs + GLint numSerialisedUniforms = 0; + + for(GLint i=0; writing && i < numUniforms; i++) + { + GLenum prop = eGL_BLOCK_INDEX; + GLint blockIdx; + gl.glGetProgramResourceiv(progSrc, eGL_UNIFORM, i, 1, &prop, 1, NULL, (GLint *)&blockIdx); + + if(blockIdx >= 0) continue; + + numSerialisedUniforms++; + } + + ser->Serialise("numUniforms", numSerialisedUniforms); + + if(!writing) + numUniforms = numSerialisedUniforms; + } + + const size_t numProps = 5; + GLenum resProps[numProps] = { eGL_BLOCK_INDEX, eGL_TYPE, eGL_NAME_LENGTH, eGL_ARRAY_SIZE, eGL_LOCATION, }; + + for(GLint i=0; i < numUniforms; i++) + { + GLenum type = eGL_NONE; + int32_t arraySize = 0; + int32_t srcLocation = 0; + string basename; + bool isArray = false; + + if(ReadSourceProgram) + { + GLint values[numProps]; + gl.glGetProgramResourceiv(progSrc, eGL_UNIFORM, i, numProps, resProps, numProps, NULL, values); + + // we don't need to consider uniforms within UBOs + if(values[0] >= 0) continue; + + type = (GLenum)values[1]; + arraySize = values[3]; + srcLocation = values[4]; + + char n[1024] = {0}; + gl.glGetProgramResourceName(progSrc, eGL_UNIFORM, i, values[2], NULL, n); + basename = n; + + if(arraySize > 1) + { + isArray = true; + + size_t len = strlen(n); + + if(n[len-3] == '[' && n[len-2] == '0' && n[len-1] == ']') + n[len-3] = 0; + } + else + { + arraySize = 1; + } + } + + if(SerialiseUniforms) + { + ser->Serialise("type", type); + ser->Serialise("arraySize", arraySize); + ser->Serialise("srcLocation", srcLocation); + ser->Serialise("basename", basename); + ser->Serialise("isArray", isArray); + } + + double dv[16]; + float *fv = (float *)dv; + int32_t *iv = (int32_t *)dv; + uint32_t *uiv = (uint32_t *)dv; + + for(GLint arr=0; arr < arraySize; arr++) + { + string name = basename; + + if(isArray) + name += StringFormat::Fmt("[%d]", arr); + + GLint newloc = 0; + if(WriteDestProgram) + newloc = gl.glGetUniformLocation(progDst, name.c_str()); + + if(CopyUniforms && newloc == -1) + continue; + + if(ReadSourceProgram) + { + switch(type) + { + case eGL_FLOAT_MAT4: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_MAT4x3: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_MAT4x2: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_MAT3: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_MAT3x4: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_MAT3x2: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_MAT2: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_MAT2x4: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_MAT2x3: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_DOUBLE_MAT4: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_MAT4x3: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_MAT4x2: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_MAT3: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_MAT3x4: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_MAT3x2: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_MAT2: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_MAT2x4: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_MAT2x3: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_FLOAT: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_VEC2: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_VEC3: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_FLOAT_VEC4: gl.glGetUniformfv(progSrc, srcLocation, fv); break; + case eGL_DOUBLE: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_VEC2: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_VEC3: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + case eGL_DOUBLE_VEC4: gl.glGetUniformdv(progSrc, srcLocation, dv); break; + + // treat all samplers as just an int (since they just store their binding value) + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_1D_ARRAY: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_1D_ARRAY_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_BUFFER: + case GL_SAMPLER_2D_RECT: + case GL_SAMPLER_2D_RECT_SHADOW: + case GL_INT_SAMPLER_1D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_1D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D_RECT: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D_RECT: + case GL_IMAGE_1D: + case GL_IMAGE_2D: + case GL_IMAGE_3D: + case GL_IMAGE_2D_RECT: + case GL_IMAGE_CUBE: + case GL_IMAGE_BUFFER: + case GL_IMAGE_1D_ARRAY: + case GL_IMAGE_2D_ARRAY: + case GL_IMAGE_2D_MULTISAMPLE: + case GL_IMAGE_2D_MULTISAMPLE_ARRAY: + case GL_INT_IMAGE_1D: + case GL_INT_IMAGE_2D: + case GL_INT_IMAGE_3D: + case GL_INT_IMAGE_2D_RECT: + case GL_INT_IMAGE_CUBE: + case GL_INT_IMAGE_BUFFER: + case GL_INT_IMAGE_1D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_MULTISAMPLE: + case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_IMAGE_1D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_2D_RECT: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_1D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY: + case eGL_INT: gl.glGetUniformiv(progSrc, srcLocation, iv); break; + case eGL_INT_VEC2: gl.glGetUniformiv(progSrc, srcLocation, iv); break; + case eGL_INT_VEC3: gl.glGetUniformiv(progSrc, srcLocation, iv); break; + case eGL_INT_VEC4: gl.glGetUniformiv(progSrc, srcLocation, iv); break; + case eGL_UNSIGNED_INT: + case eGL_BOOL: gl.glGetUniformuiv(progSrc, srcLocation, uiv); break; + case eGL_UNSIGNED_INT_VEC2: + case eGL_BOOL_VEC2: gl.glGetUniformuiv(progSrc, srcLocation, uiv); break; + case eGL_UNSIGNED_INT_VEC3: + case eGL_BOOL_VEC3: gl.glGetUniformuiv(progSrc, srcLocation, uiv); break; + case eGL_UNSIGNED_INT_VEC4: + case eGL_BOOL_VEC4: gl.glGetUniformuiv(progSrc, srcLocation, uiv); break; + default: + RDCERR("Unhandled uniform type '%hs'", ToStr::Get(type).c_str()); + } + } + + if(SerialiseUniforms) + ser->Serialise<16>("data", dv); + + if(WriteDestProgram) + { + switch(type) + { + case eGL_FLOAT_MAT4: gl.glProgramUniformMatrix4fv(progDst, newloc, 1, false, fv); break; + case eGL_FLOAT_MAT4x3: gl.glProgramUniformMatrix4x3fv(progDst, newloc, 1, false, fv); break; + case eGL_FLOAT_MAT4x2: gl.glProgramUniformMatrix4x2fv(progDst, newloc, 1, false, fv); break; + case eGL_FLOAT_MAT3: gl.glProgramUniformMatrix3fv(progDst, newloc, 1, false, fv); break; + case eGL_FLOAT_MAT3x4: gl.glProgramUniformMatrix3x4fv(progDst, newloc, 1, false, fv); break; + case eGL_FLOAT_MAT3x2: gl.glProgramUniformMatrix3x2fv(progDst, newloc, 1, false, fv); break; + case eGL_FLOAT_MAT2: gl.glProgramUniformMatrix2fv(progDst, newloc, 1, false, fv); break; + case eGL_FLOAT_MAT2x4: gl.glProgramUniformMatrix2x4fv(progDst, newloc, 1, false, fv); break; + case eGL_FLOAT_MAT2x3: gl.glProgramUniformMatrix2x3fv(progDst, newloc, 1, false, fv); break; + case eGL_DOUBLE_MAT4: gl.glProgramUniformMatrix4dv(progDst, newloc, 1, false, dv); break; + case eGL_DOUBLE_MAT4x3: gl.glProgramUniformMatrix4x3dv(progDst, newloc, 1, false, dv); break; + case eGL_DOUBLE_MAT4x2: gl.glProgramUniformMatrix4x2dv(progDst, newloc, 1, false, dv); break; + case eGL_DOUBLE_MAT3: gl.glProgramUniformMatrix3dv(progDst, newloc, 1, false, dv); break; + case eGL_DOUBLE_MAT3x4: gl.glProgramUniformMatrix3x4dv(progDst, newloc, 1, false, dv); break; + case eGL_DOUBLE_MAT3x2: gl.glProgramUniformMatrix3x2dv(progDst, newloc, 1, false, dv); break; + case eGL_DOUBLE_MAT2: gl.glProgramUniformMatrix2dv(progDst, newloc, 1, false, dv); break; + case eGL_DOUBLE_MAT2x4: gl.glProgramUniformMatrix2x4dv(progDst, newloc, 1, false, dv); break; + case eGL_DOUBLE_MAT2x3: gl.glProgramUniformMatrix2x3dv(progDst, newloc, 1, false, dv); break; + case eGL_FLOAT: gl.glProgramUniform1fv(progDst, newloc, 1, fv); break; + case eGL_FLOAT_VEC2: gl.glProgramUniform2fv(progDst, newloc, 1, fv); break; + case eGL_FLOAT_VEC3: gl.glProgramUniform3fv(progDst, newloc, 1, fv); break; + case eGL_FLOAT_VEC4: gl.glProgramUniform4fv(progDst, newloc, 1, fv); break; + case eGL_DOUBLE: gl.glProgramUniform1dv(progDst, newloc, 1, dv); break; + case eGL_DOUBLE_VEC2: gl.glProgramUniform2dv(progDst, newloc, 1, dv); break; + case eGL_DOUBLE_VEC3: gl.glProgramUniform3dv(progDst, newloc, 1, dv); break; + case eGL_DOUBLE_VEC4: gl.glProgramUniform4dv(progDst, newloc, 1, dv); break; + + // treat all samplers as just an int (since they just store their binding value) + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_1D_ARRAY: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_1D_ARRAY_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_BUFFER: + case GL_SAMPLER_2D_RECT: + case GL_SAMPLER_2D_RECT_SHADOW: + case GL_INT_SAMPLER_1D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_1D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_INT_SAMPLER_2D_RECT: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_2D_RECT: + case GL_IMAGE_1D: + case GL_IMAGE_2D: + case GL_IMAGE_3D: + case GL_IMAGE_2D_RECT: + case GL_IMAGE_CUBE: + case GL_IMAGE_BUFFER: + case GL_IMAGE_1D_ARRAY: + case GL_IMAGE_2D_ARRAY: + case GL_IMAGE_2D_MULTISAMPLE: + case GL_IMAGE_2D_MULTISAMPLE_ARRAY: + case GL_INT_IMAGE_1D: + case GL_INT_IMAGE_2D: + case GL_INT_IMAGE_3D: + case GL_INT_IMAGE_2D_RECT: + case GL_INT_IMAGE_CUBE: + case GL_INT_IMAGE_BUFFER: + case GL_INT_IMAGE_1D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_2D_MULTISAMPLE: + case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_IMAGE_1D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_2D_RECT: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_1D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY: + case eGL_INT: gl.glProgramUniform1iv(progDst, newloc, 1, iv); break; + case eGL_INT_VEC2: gl.glProgramUniform2iv(progDst, newloc, 1, iv); break; + case eGL_INT_VEC3: gl.glProgramUniform3iv(progDst, newloc, 1, iv); break; + case eGL_INT_VEC4: gl.glProgramUniform4iv(progDst, newloc, 1, iv); break; + case eGL_UNSIGNED_INT: + case eGL_BOOL: gl.glProgramUniform1uiv(progDst, newloc, 1, uiv); break; + case eGL_UNSIGNED_INT_VEC2: + case eGL_BOOL_VEC2: gl.glProgramUniform2uiv(progDst, newloc, 1, uiv); break; + case eGL_UNSIGNED_INT_VEC3: + case eGL_BOOL_VEC3: gl.glProgramUniform3uiv(progDst, newloc, 1, uiv); break; + case eGL_UNSIGNED_INT_VEC4: + case eGL_BOOL_VEC4: gl.glProgramUniform4uiv(progDst, newloc, 1, uiv); break; + default: + RDCERR("Unhandled uniform type '%hs'", ToStr::Get(type).c_str()); + } + } + } + } + + GLint numUBOs = 0; + if(ReadSourceProgram) + gl.glGetProgramInterfaceiv(progSrc, eGL_UNIFORM_BLOCK, eGL_ACTIVE_RESOURCES, &numUBOs); + + if(SerialiseUniforms) + ser->Serialise("numUBOs", numUBOs); + + for(GLint i=0; i < numUBOs; i++) + { + GLenum prop = eGL_BUFFER_BINDING; + uint32_t bind = 0; + if(ReadSourceProgram) + gl.glGetProgramResourceiv(progSrc, eGL_UNIFORM_BLOCK, i, 1, &prop, 1, NULL, (GLint *)&bind); + + if(SerialiseUniforms) + ser->Serialise("bind", bind); + + if(WriteDestProgram) + gl.glUniformBlockBinding(progDst, i, bind); + } + + GLint numSSBOs = 0; + if(ReadSourceProgram) + gl.glGetProgramInterfaceiv(progSrc, eGL_SHADER_STORAGE_BLOCK, eGL_ACTIVE_RESOURCES, &numSSBOs); + + if(SerialiseUniforms) + ser->Serialise("numSSBOs", numSSBOs); + + for(GLint i=0; i < numSSBOs; i++) + { + GLenum prop = eGL_BUFFER_BINDING; + uint32_t bind = 0; + if(ReadSourceProgram) + gl.glGetProgramResourceiv(progSrc, eGL_SHADER_STORAGE_BLOCK, i, 1, &prop, 1, NULL, (GLint *)&bind); + + if(SerialiseUniforms) + ser->Serialise("bind", bind); + + if(WriteDestProgram) + gl.glShaderStorageBlockBinding(progDst, i, bind); + } +} + +void CopyProgramUniforms(const GLHookSet &gl, GLuint progSrc, GLuint progDst) +{ + const bool CopyUniforms = true; + const bool SerialiseUniforms = false; + ForAllProgramUniforms(gl, NULL, progSrc, progDst, false); +} + +void SerialiseProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint prog, bool writing) +{ + const bool CopyUniforms = false; + const bool SerialiseUniforms = true; + ForAllProgramUniforms(gl, ser, prog, prog, writing); +} + template<> string ToStrHelper::Get(const WrappedOpenGL::UniformType &el) { diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index ea09662ec..a57c27563 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -70,6 +70,7 @@ struct GLWindowingData #define IMPLEMENT_FUNCTION_SERIALISED(ret, func) ret func; bool CONCAT(Serialise_, func); class WrappedOpenGL; +struct GLHookSet; size_t BufferIdx(GLenum buf); GLenum BufferEnum(size_t idx); @@ -84,6 +85,9 @@ GLenum MakeGLFormat(WrappedOpenGL &gl, GLenum target, ResourceFormat fmt); #include "serialise/serialiser.h" #include "core/core.h" +void CopyProgramUniforms(const GLHookSet &gl, GLuint progSrc, GLuint progDst); +void SerialiseProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint prog, bool writing); + enum GLChunkType { DEVICE_INIT = FIRST_CHUNK_ID, diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index 100fa9d4d..bbdc3beee 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -819,96 +819,6 @@ void GLReplay::RenderHighlightBox(float w, float h, float scale) gl.glDrawArrays(eGL_LINE_LOOP, 0, 4); } -void GLReplay::CopyProgramUniforms(WrappedOpenGL &gl, GLuint progSrc, GLuint progDst) -{ - // copy across uniforms - GLint numUniforms = 0; - gl.glGetProgramiv(progSrc, eGL_ACTIVE_UNIFORMS, &numUniforms); - - for(GLint i=0; i < numUniforms; i++) - { - char uniName[1024] = {}; - GLint uniSize = 0; - GLenum uniType = eGL_NONE; - gl.glGetActiveUniform(progSrc, i, 1024, NULL, &uniSize, &uniType, uniName); - - double dv[16]; - float *fv = (float *)dv; - int32_t *iv = (int32_t *)dv; - uint32_t *uv = (uint32_t *)dv; - - bool isArray = false; - - if(uniSize > 1) - { - isArray = true; - - size_t len = strlen(uniName); - - if(uniName[len-3] == '[' && uniName[len-2] == '0' && uniName[len-1] == ']') - uniName[len-3] = 0; - } - else - { - uniSize = 1; - } - - for(GLint arr=0; arr < uniSize; arr++) - { - string name = uniName; - - if(isArray) - name += StringFormat::Fmt("[%d]", arr); - - GLint origloc = gl.glGetUniformLocation(progSrc, name.c_str()); - GLint newloc = gl.glGetUniformLocation(progDst, name.c_str()); - - if(origloc != -1 && newloc != -1) - { - if(uniType == eGL_FLOAT_MAT4) - { - gl.glGetUniformfv(progSrc, origloc, fv); - gl.glProgramUniformMatrix4fv(progDst, newloc, 1, false, fv); - } - else if(uniType == eGL_FLOAT) - { - gl.glGetUniformfv(progSrc, origloc, fv); - gl.glProgramUniform1fv(progDst, newloc, 1, fv); - } - else if(uniType == eGL_FLOAT_VEC2) - { - gl.glGetUniformfv(progSrc, origloc, fv); - gl.glProgramUniform2fv(progDst, newloc, 1, fv); - } - else if(uniType == eGL_FLOAT_VEC3) - { - gl.glGetUniformfv(progSrc, origloc, fv); - gl.glProgramUniform3fv(progDst, newloc, 1, fv); - } - else if(uniType == eGL_FLOAT_VEC4) - { - gl.glGetUniformfv(progSrc, origloc, fv); - gl.glProgramUniform4fv(progDst, newloc, 1, fv); - } - else if(uniType == eGL_INT) - { - gl.glGetUniformiv(progSrc, origloc, iv); - gl.glProgramUniform1iv(progDst, newloc, 1, iv); - } - else if(uniType == eGL_UNSIGNED_INT) - { - gl.glGetUniformuiv(progSrc, origloc, uv); - gl.glProgramUniform1uiv(progDst, newloc, 1, uv); - } - else - { - RDCERR("Uniform type '%hs' not being copied to new program", ToStr::Get(uniType).c_str()); - } - } - } - } -} - ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector &passEvents) { WrappedOpenGL &gl = *m_pDriver; @@ -1003,7 +913,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl { gl.glUseProgram(progDetails.colOutProg); - CopyProgramUniforms(gl, curProg, progDetails.colOutProg); + CopyProgramUniforms(gl.m_Real, curProg, progDetails.colOutProg); float black[] = { 0.0f, 0.0f, 0.0f, 0.5f }; gl.glClearBufferfv(eGL_COLOR, 0, black); @@ -1020,7 +930,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl { gl.glUseProgram(progDetails.colOutProg); - CopyProgramUniforms(gl, curProg, progDetails.colOutProg); + CopyProgramUniforms(gl.m_Real, curProg, progDetails.colOutProg); float black[] = { 0.0f, 0.0f, 0.0f, 0.0f }; gl.glClearBufferfv(eGL_COLOR, 0, black); @@ -1156,7 +1066,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, TextureDisplayOverlay overl { gl.glUseProgram(progDetails.colOutProg); - CopyProgramUniforms(gl, curProg, progDetails.colOutProg); + CopyProgramUniforms(gl.m_Real, curProg, progDetails.colOutProg); float wireCol[] = { 200.0f/255.0f, 255.0f/255.0f, 0.0f/255.0f, 0.0f }; gl.glClearBufferfv(eGL_COLOR, 0, wireCol); diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 4ffb4c53f..5d3345500 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -71,6 +71,16 @@ bool GLResourceManager::Prepare_InitialState(GLResource res) gl.glGetNamedBufferSubDataEXT(res.name, 0, length, record->GetDataPtr()); } + else if(res.Namespace == eResProgram) + { + ScopedContext scope(m_pSerialiser, NULL, "Initial Contents", "Initial Contents", INITIAL_CONTENTS, false); + + m_pSerialiser->Serialise("Id", Id); + + SerialiseProgramUniforms(gl, m_pSerialiser, res.name, true); + + SetInitialChunk(Id, scope.Get()); + } else if(res.Namespace == eResTexture) { WrappedOpenGL::TextureData &details = m_GL->m_Textures[Id]; @@ -208,6 +218,37 @@ bool GLResourceManager::Serialise_InitialState(GLResource res) { // Nothing to serialize } + else if(res.Namespace == eResProgram) + { + // Prepare_InitialState sets the serialise chunk directly on write, + // so we should never come in here except for when reading + RDCASSERT(m_State < WRITING); + + WrappedOpenGL::ProgramData &details = m_GL->m_Programs[GetLiveID(Id)]; + + GLuint initProg = gl.glCreateProgram(); + + for(size_t i=0; i < details.shaders.size(); i++) + { + const auto &shadDetails = m_GL->m_Shaders[details.shaders[i]]; + + GLuint shad = gl.glCreateShader(shadDetails.type); + for(size_t s=0; s < shadDetails.sources.size(); s++) + { + const char *src = shadDetails.sources[s].c_str(); + gl.glShaderSource(shad, 1, &src, NULL); + } + gl.glCompileShader(shad); + gl.glAttachShader(initProg, shad); + gl.glDeleteShader(shad); + } + + gl.glLinkProgram(initProg); + + SerialiseProgramUniforms(gl, m_pSerialiser, initProg, false); + + SetInitialContents(Id, InitialContentData(ProgramRes(m_GL->GetCtx(), initProg), 0, NULL)); + } else if(res.Namespace == eResTexture) { if(m_State >= WRITING) @@ -627,6 +668,10 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i gl.glCopyImageSubData(tex, details.curType, i, 0, 0, 0, live.name, details.curType, i, 0, 0, 0, w, h, d); } } + else if(live.Namespace == eResProgram) + { + CopyProgramUniforms(gl, initial.resource.name, live.name); + } else if(live.Namespace == eResVertexArray) { GLuint VAO = 0; diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 444b2edf5..b35c3dc79 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -137,8 +137,6 @@ class GLReplay : public IReplayDriver void GetMapping(WrappedOpenGL &gl, GLuint curProg, int shadIdx, ShaderReflection *refl, ShaderBindpointMapping &mapping); - void CopyProgramUniforms(WrappedOpenGL &gl, GLuint progSrc, GLuint progDst); - struct OutputWindow : public GLWindowingData { struct diff --git a/renderdoc/driver/gl/wrappers/gl_uniform_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_uniform_funcs.cpp index 4c89a3e55..1cd7b6db8 100644 --- a/renderdoc/driver/gl/wrappers/gl_uniform_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_uniform_funcs.cpp @@ -258,22 +258,16 @@ void WrappedOpenGL::CONCAT(CONCAT(FUNCNAME, count), suffix)(FUNCPARAMS, __VA_ARG { \ m_Real.CONCAT(CONCAT(FUNCNAME, count), suffix)(FUNCARGPASS, ARRAYLIST); \ \ - if(m_State >= WRITING) \ + if(m_State == WRITING_CAPFRAME) \ { \ - GLResourceRecord *record = m_ContextRecord; \ -\ - /* TODO grab this at capture time as initial state for program resources */ \ - if(m_State == WRITING_IDLE) \ - record = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), PROGRAM)); \ -\ - if(record) \ - { \ - SCOPED_SERIALISE_CONTEXT(PROGRAMUNIFORM_VECTOR); \ - const paramtype vals[] = { ARRAYLIST }; \ - Serialise_glProgramUniformVector(PROGRAM, location, 1, vals, CONCAT(CONCAT(VEC, count), CONCAT(suffix, v))); \ -\ - record->AddChunk(scope.Get()); \ - } \ + SCOPED_SERIALISE_CONTEXT(PROGRAMUNIFORM_VECTOR); \ + const paramtype vals[] = { ARRAYLIST }; \ + Serialise_glProgramUniformVector(PROGRAM, location, 1, vals, CONCAT(CONCAT(VEC, count), CONCAT(suffix, v))); \ + m_ContextRecord->AddChunk(scope.Get()); \ + } \ + else if(m_State == WRITING_IDLE) \ + { \ + GetResourceManager()->MarkDirtyResource(ProgramRes(GetCtx(), PROGRAM)); \ } \ } @@ -362,21 +356,15 @@ void WrappedOpenGL::CONCAT(CONCAT(FUNCNAME, unicount), CONCAT(suffix, v))(FUNCPA { \ m_Real.CONCAT(CONCAT(FUNCNAME, unicount), CONCAT(suffix, v))(FUNCARGPASS, count, value); \ \ - if(m_State >= WRITING) \ + if(m_State == WRITING_CAPFRAME) \ { \ - GLResourceRecord *record = m_ContextRecord; \ -\ - /* TODO grab this at capture time as initial state for program resources */ \ - if(m_State == WRITING_IDLE) \ - record = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), PROGRAM)); \ -\ - if(record) \ - { \ - SCOPED_SERIALISE_CONTEXT(PROGRAMUNIFORM_VECTOR); \ - Serialise_glProgramUniformVector(PROGRAM, location, count, value, CONCAT(CONCAT(VEC, unicount), CONCAT(suffix, v))); \ -\ - record->AddChunk(scope.Get()); \ - } \ + SCOPED_SERIALISE_CONTEXT(PROGRAMUNIFORM_VECTOR); \ + Serialise_glProgramUniformVector(PROGRAM, location, count, value, CONCAT(CONCAT(VEC, unicount), CONCAT(suffix, v))); \ + m_ContextRecord->AddChunk(scope.Get()); \ + } \ + else if(m_State == WRITING_IDLE) \ + { \ + GetResourceManager()->MarkDirtyResource(ProgramRes(GetCtx(), PROGRAM)); \ } \ } @@ -444,21 +432,15 @@ void WrappedOpenGL::CONCAT(CONCAT(FUNCNAME, dim), suffix)(FUNCPARAMS, GLsizei co { \ m_Real.CONCAT(CONCAT(FUNCNAME, dim), suffix)(FUNCARGPASS, count, transpose, value); \ \ - if(m_State >= WRITING) \ + if(m_State == WRITING_CAPFRAME) \ { \ - GLResourceRecord *record = m_ContextRecord; \ -\ - /* TODO grab this at capture time as initial state for program resources */ \ - if(m_State == WRITING_IDLE) \ - record = GetResourceManager()->GetResourceRecord(ProgramRes(GetCtx(), PROGRAM)); \ -\ - if(record) \ - { \ - SCOPED_SERIALISE_CONTEXT(PROGRAMUNIFORM_MATRIX); \ - Serialise_glProgramUniformMatrix(PROGRAM, location, count, transpose, value, CONCAT(CONCAT(MAT, dim), suffix)); \ -\ - record->AddChunk(scope.Get()); \ - } \ + SCOPED_SERIALISE_CONTEXT(PROGRAMUNIFORM_MATRIX); \ + Serialise_glProgramUniformMatrix(PROGRAM, location, count, transpose, value, CONCAT(CONCAT(MAT, dim), suffix)); \ + m_ContextRecord->AddChunk(scope.Get()); \ + } \ + else if(m_State == WRITING_IDLE) \ + { \ + GetResourceManager()->MarkDirtyResource(ProgramRes(GetCtx(), PROGRAM)); \ } \ }