mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-23 23:16:31 +00:00
Initial implementation of saving program uniforms at frame capture
* Previously we were saving every program uniform that got set, cumulatively. * Now, whenever a uniform is set that program is marked as dirty and we fetch out the uniform values at the start of the frame and serialise them out. * On replay, we create a dummy copy of the program to hold the initial uniform values, and copy them across to restore the frame-start values.
This commit is contained in:
@@ -280,6 +280,402 @@ ResourceFormat MakeResourceFormat(WrappedOpenGL &gl, GLenum target, GLenum fmt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<const bool CopyUniforms, const bool SerialiseUniforms>
|
||||
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<CopyUniforms, SerialiseUniforms>(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<CopyUniforms, SerialiseUniforms>(gl, ser, prog, prog, writing);
|
||||
}
|
||||
|
||||
template<>
|
||||
string ToStrHelper<false, WrappedOpenGL::UniformType>::Get(const WrappedOpenGL::UniformType &el)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<uint32_t> &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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user