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:
baldurk
2014-11-11 22:54:57 +00:00
parent c9e74c7a56
commit b7912647cf
6 changed files with 473 additions and 138 deletions
+396
View File
@@ -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)
{
+4
View File
@@ -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,
+3 -93
View File
@@ -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);
+45
View File
@@ -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;
-2
View File
@@ -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)); \
} \
}