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.
This commit is contained in:
baldurk
2017-07-06 11:54:06 +01:00
parent 750bea339f
commit 3a47aa7840
+61 -53
View File
@@ -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)
{