From 3a47aa7840420a7c463666193a05393bd5bf4bde Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 6 Jul 2017 11:54:06 +0100 Subject: [PATCH] Support captures where programs are created mid-frame. Refs #684 * This is far more likely when you start capturing at the start of the program, but it can happen any other time if you get unlucky. * Normally we expect the preparation of initial states for programs to get all the data ready, but if the program is created during the frame capture then that's after preparation, so we need to instead fetch and serialise the data at the end of the frame while serialising initial contents. --- renderdoc/driver/gl/gl_manager.cpp | 114 +++++++++++++++-------------- 1 file changed, 61 insertions(+), 53 deletions(-) diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 1c00422a0..67dd93e2a 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -1035,72 +1035,80 @@ bool GLResourceManager::Serialise_InitialState(ResourceId resid, GLResource res) } 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++) + // most of the time Prepare_InitialState sets the serialise chunk directly on write, but if a + // program is newly created within a frame we won't have prepared its initial contents, so we + // need to be ready to write it out here. + if(m_State >= WRITING) { - const auto &shadDetails = m_GL->m_Shaders[details.shaders[i]]; + SerialiseProgramBindings(gl, m_pSerialiser, res.name, true); - GLuint shad = gl.glCreateShader(shadDetails.type); - - char **srcs = new char *[shadDetails.sources.size()]; - for(size_t s = 0; s < shadDetails.sources.size(); s++) - srcs[s] = (char *)shadDetails.sources[s].c_str(); - gl.glShaderSource(shad, (GLsizei)shadDetails.sources.size(), srcs, NULL); - - SAFE_DELETE_ARRAY(srcs); - gl.glCompileShader(shad); - gl.glAttachShader(initProg, shad); - gl.glDeleteShader(shad); + SerialiseProgramUniforms(gl, m_pSerialiser, res.name, NULL, true); } - - gl.glLinkProgram(initProg); - - GLint status = 0; - gl.glGetProgramiv(initProg, eGL_LINK_STATUS, &status); - - // if it failed to link, try again as a separable program. - // we can't do this by default because of the silly rules meaning - // shaders need fixup to be separable-compatible. - if(status == 0) + else { - gl.glProgramParameteri(initProg, eGL_PROGRAM_SEPARABLE, 1); + 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); + + char **srcs = new char *[shadDetails.sources.size()]; + for(size_t s = 0; s < shadDetails.sources.size(); s++) + srcs[s] = (char *)shadDetails.sources[s].c_str(); + gl.glShaderSource(shad, (GLsizei)shadDetails.sources.size(), srcs, NULL); + + SAFE_DELETE_ARRAY(srcs); + gl.glCompileShader(shad); + gl.glAttachShader(initProg, shad); + gl.glDeleteShader(shad); + } + gl.glLinkProgram(initProg); + GLint status = 0; gl.glGetProgramiv(initProg, eGL_LINK_STATUS, &status); - } - if(status == 0) - { - if(details.shaders.size() == 0) + // if it failed to link, try again as a separable program. + // we can't do this by default because of the silly rules meaning + // shaders need fixup to be separable-compatible. + if(status == 0) { - RDCWARN("No shaders attached to program"); + gl.glProgramParameteri(initProg, eGL_PROGRAM_SEPARABLE, 1); + gl.glLinkProgram(initProg); + + gl.glGetProgramiv(initProg, eGL_LINK_STATUS, &status); } - else + + if(status == 0) { - char buffer[1025] = {0}; - gl.glGetProgramInfoLog(initProg, 1024, NULL, buffer); - RDCERR("Link error: %s", buffer); + if(details.shaders.size() == 0) + { + RDCWARN("No shaders attached to program"); + } + else + { + char buffer[1025] = {0}; + gl.glGetProgramInfoLog(initProg, 1024, NULL, buffer); + RDCERR("Link error: %s", buffer); + } } + + if(m_GL->GetLogVersion() >= 0x0000014) + { + SerialiseProgramBindings(gl, m_pSerialiser, initProg, false); + + // re-link the program to set the new attrib bindings + gl.glLinkProgram(initProg); + } + + SerialiseProgramUniforms(gl, m_pSerialiser, initProg, &details.locationTranslate, false); + + SetInitialContents(Id, InitialContentData(ProgramRes(m_GL->GetCtx(), initProg), 0, NULL)); } - - if(m_GL->GetLogVersion() >= 0x0000014) - { - SerialiseProgramBindings(gl, m_pSerialiser, initProg, false); - - // re-link the program to set the new attrib bindings - gl.glLinkProgram(initProg); - } - - SerialiseProgramUniforms(gl, m_pSerialiser, initProg, &details.locationTranslate, false); - - SetInitialContents(Id, InitialContentData(ProgramRes(m_GL->GetCtx(), initProg), 0, NULL)); } else if(res.Namespace == eResTexture) {