Update GL initial state handling to new serialisation

This commit is contained in:
baldurk
2017-10-27 17:37:37 +01:00
parent 074ee8d8b8
commit 2322ffb3a6
6 changed files with 945 additions and 689 deletions
+147 -51
View File
@@ -1924,41 +1924,44 @@ bool CheckConstParam(bool t)
return t;
}
template <const bool CopyUniforms, const bool SerialiseUniforms>
static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint progSrc,
GLuint progDst, map<GLint, GLint> *locTranslate, bool writing)
template <const bool CopyUniforms, const bool SerialiseUniforms, typename SerialiserType>
static void ForAllProgramUniforms(SerialiserType *ser, CaptureState state, const GLHookSet &gl,
GLuint progSrc, GLuint progDst, map<GLint, GLint> *locTranslate)
{
const bool ReadSourceProgram = CopyUniforms || (SerialiseUniforms && writing);
const bool WriteDestProgram = CopyUniforms || (SerialiseUniforms && !writing);
const bool ReadSourceProgram = CopyUniforms || (SerialiseUniforms && ser && ser->IsWriting());
const bool WriteDestProgram = CopyUniforms || (SerialiseUniforms && ser && ser->IsReading());
RDCCOMPILE_ASSERT((CopyUniforms && !SerialiseUniforms) || (!CopyUniforms && SerialiseUniforms),
"Invalid call to ForAllProgramUniforms");
GLint numUniforms = 0;
GLint NumUniforms = 0;
if(CheckConstParam(ReadSourceProgram))
gl.glGetProgramInterfaceiv(progSrc, eGL_UNIFORM, eGL_ACTIVE_RESOURCES, &numUniforms);
gl.glGetProgramInterfaceiv(progSrc, eGL_UNIFORM, eGL_ACTIVE_RESOURCES, &NumUniforms);
if(CheckConstParam(SerialiseUniforms))
{
// get accurate count of uniforms not in UBOs
GLint numSerialisedUniforms = 0;
GLint numSerialised = 0;
for(GLint i = 0; writing && i < numUniforms; i++)
if(ser->IsWriting())
{
GLenum prop = eGL_BLOCK_INDEX;
GLint blockIdx;
gl.glGetProgramResourceiv(progSrc, eGL_UNIFORM, i, 1, &prop, 1, NULL, (GLint *)&blockIdx);
for(GLint i = 0; 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;
if(blockIdx >= 0)
continue;
numSerialisedUniforms++;
numSerialised++;
}
}
ser->Serialise("numUniforms", numSerialisedUniforms);
ser->Serialise("NumUniforms", numSerialised);
if(!writing)
numUniforms = numSerialisedUniforms;
if(ser->IsReading())
NumUniforms = numSerialised;
}
const size_t numProps = 5;
@@ -1966,7 +1969,7 @@ static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint p
eGL_BLOCK_INDEX, eGL_TYPE, eGL_NAME_LENGTH, eGL_ARRAY_SIZE, eGL_LOCATION,
};
for(GLint i = 0; i < numUniforms; i++)
for(GLint i = 0; i < NumUniforms; i++)
{
GLenum type = eGL_NONE;
int32_t arraySize = 0;
@@ -2015,7 +2018,7 @@ static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint p
ser->Serialise("isArray", isArray);
}
double dv[16];
double dv[16] = {};
float *fv = (float *)dv;
int32_t *iv = (int32_t *)dv;
uint32_t *uiv = (uint32_t *)dv;
@@ -2036,7 +2039,7 @@ static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint p
ser->Serialise("srcLocation", srcLocation);
GLint newloc = 0;
if(CheckConstParam(WriteDestProgram))
if(CheckConstParam(WriteDestProgram) && IsReplayMode(state))
{
newloc = gl.glGetUniformLocation(progDst, name.c_str());
if(locTranslate)
@@ -2169,9 +2172,9 @@ static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint p
}
if(CheckConstParam(SerialiseUniforms))
ser->SerialisePODArray<16>("data", dv);
ser->Serialise("data", dv);
if(CheckConstParam(WriteDestProgram))
if(CheckConstParam(WriteDestProgram) && IsReplayMode(state))
{
switch(type)
{
@@ -2348,7 +2351,7 @@ static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint p
ser->Serialise("name", name);
}
if(CheckConstParam(WriteDestProgram))
if(CheckConstParam(WriteDestProgram) && IsReplayMode(state))
{
GLuint idx = gl.glGetUniformBlockIndex(progDst, name.c_str());
if(idx != GL_INVALID_INDEX)
@@ -2386,7 +2389,7 @@ static void ForAllProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint p
ser->Serialise("name", name);
}
if(CheckConstParam(WriteDestProgram))
if(CheckConstParam(WriteDestProgram) && IsReplayMode(state))
{
GLuint idx = gl.glGetProgramResourceIndex(progDst, eGL_SHADER_STORAGE_BLOCK, name.c_str());
if(idx != GL_INVALID_INDEX)
@@ -2409,17 +2412,85 @@ void CopyProgramUniforms(const GLHookSet &gl, GLuint progSrc, GLuint progDst)
{
const bool CopyUniforms = true;
const bool SerialiseUniforms = false;
ForAllProgramUniforms<CopyUniforms, SerialiseUniforms>(gl, NULL, progSrc, progDst, NULL, false);
ForAllProgramUniforms<CopyUniforms, SerialiseUniforms, ReadSerialiser>(
NULL, CaptureState::ActiveReplaying, gl, progSrc, progDst, NULL);
}
void SerialiseProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint prog,
map<GLint, GLint> *locTranslate, bool writing)
uint32_t GetUniformsSerialiseSize(const GLHookSet &gl, GLuint prog)
{
// we do this by hand rather than adding another path to ForAllProgramUniforms, since we can just
// make a conservative estimate on uniform size.
uint32_t ret = 0;
GLint NumUniforms = 0;
gl.glGetProgramInterfaceiv(prog, eGL_UNIFORM, eGL_ACTIVE_RESOURCES, &NumUniforms);
// number of serialised uniforms
ret += 4;
// we figure out the number of serialised uniforms since it could be drastically lower than the
// number of uniforms (think shaders with lots of uniforms in UBOs).
// get accurate count of uniforms not in UBOs
GLint numSerialised = 0;
for(GLint i = 0; i < NumUniforms; i++)
{
GLenum props[2] = {
eGL_BLOCK_INDEX, eGL_ARRAY_SIZE,
};
GLint values[2] = {0, 0};
gl.glGetProgramResourceiv(prog, eGL_UNIFORM, i, 2, props, 2, NULL, values);
if(values[0] >= 0)
continue;
ret += 8 + sizeof(double) * 16 * RDCMAX(1, values[1]);
numSerialised++;
}
// estimate 256 bytes of data per serialised global uniform not in a UBO. This is variable based
// on type and name length
ret += 256 * numSerialised;
// number of UBOs.
ret += 4;
GLint numUBOs = 0;
gl.glGetProgramInterfaceiv(prog, eGL_UNIFORM_BLOCK, eGL_ACTIVE_RESOURCES, &numUBOs);
// name + binding per UBO
ret += 128 * numUBOs;
// number of SSBOs.
ret += 4;
GLint numSSBOs = 0;
gl.glGetProgramInterfaceiv(prog, eGL_SHADER_STORAGE_BLOCK, eGL_ACTIVE_RESOURCES, &numSSBOs);
// name + binding per SSBO
ret += 128 * numSSBOs;
return ret;
}
template <typename SerialiserType>
void SerialiseProgramUniforms(SerialiserType &ser, CaptureState state, const GLHookSet &gl,
GLuint prog, map<GLint, GLint> *locTranslate)
{
const bool CopyUniforms = false;
const bool SerialiseUniforms = true;
ForAllProgramUniforms<CopyUniforms, SerialiseUniforms>(gl, ser, prog, prog, locTranslate, writing);
ForAllProgramUniforms<CopyUniforms, SerialiseUniforms>(&ser, state, gl, prog, prog, locTranslate);
}
template void SerialiseProgramUniforms(ReadSerialiser &ser, CaptureState state, const GLHookSet &gl,
GLuint prog, map<GLint, GLint> *locTranslate);
template void SerialiseProgramUniforms(WriteSerialiser &ser, CaptureState state, const GLHookSet &gl,
GLuint prog, map<GLint, GLint> *locTranslate);
void CopyProgramAttribBindings(const GLHookSet &gl, GLuint progsrc, GLuint progdst,
ShaderReflection *refl)
{
@@ -2479,9 +2550,32 @@ void CopyProgramFragDataBindings(const GLHookSet &gl, GLuint progsrc, GLuint pro
}
}
void SerialiseProgramBindings(const GLHookSet &gl, Serialiser *ser, GLuint prog, bool writing)
uint32_t GetBindingsSerialiseSize(const GLHookSet &gl, GLuint prog)
{
char name[128] = {0};
uint32_t ret = 0;
for(int sigType = 0; sigType < 2; sigType++)
{
GLenum sigEnum = (sigType == 0 ? eGL_PROGRAM_INPUT : eGL_PROGRAM_OUTPUT);
int32_t NumAttributes = 0;
gl.glGetProgramInterfaceiv(prog, sigEnum, eGL_ACTIVE_RESOURCES, (GLint *)&NumAttributes);
// number
ret += 4;
// 128 character name and 4 byte location for each attribute
ret += 132 * NumAttributes;
}
return ret;
}
template <typename SerialiserType>
void SerialiseProgramBindings(SerialiserType &ser, CaptureState state, const GLHookSet &gl,
GLuint prog)
{
char Name[128] = {0};
for(int sigType = 0; sigType < 2; sigType++)
{
@@ -2489,58 +2583,56 @@ void SerialiseProgramBindings(const GLHookSet &gl, Serialiser *ser, GLuint prog,
uint64_t used = 0;
int32_t numAttrs = 0;
int32_t NumAttributes = 0;
if(writing)
gl.glGetProgramInterfaceiv(prog, sigEnum, eGL_ACTIVE_RESOURCES, (GLint *)&numAttrs);
if(ser.IsWriting())
gl.glGetProgramInterfaceiv(prog, sigEnum, eGL_ACTIVE_RESOURCES, (GLint *)&NumAttributes);
ser->Serialise("numAttrs", numAttrs);
SERIALISE_ELEMENT(NumAttributes);
for(GLint i = 0; i < numAttrs; i++)
for(GLint i = 0; i < NumAttributes; i++)
{
int32_t idx = -1;
int32_t Location = -1;
if(writing)
if(ser.IsWriting())
{
gl.glGetProgramResourceName(prog, sigEnum, i, 128, NULL, name);
gl.glGetProgramResourceName(prog, sigEnum, i, 128, NULL, Name);
if(sigType == 0)
idx = gl.glGetAttribLocation(prog, name);
Location = gl.glGetAttribLocation(prog, Name);
else
idx = gl.glGetFragDataLocation(prog, name);
Location = gl.glGetFragDataLocation(prog, Name);
}
string n = name;
SERIALISE_ELEMENT(Name);
SERIALISE_ELEMENT(Location);
ser->Serialise("name", n);
ser->Serialise("idx", idx);
if(!writing && idx >= 0)
if(ser.IsReading() && IsReplayMode(state) && Location >= 0)
{
uint64_t mask = 1ULL << idx;
uint64_t mask = 1ULL << Location;
if(used & mask)
{
RDCWARN("Multiple %s items bound to location %d, ignoring %s",
sigType == 0 ? "attrib" : "fragdata", idx, n.c_str());
sigType == 0 ? "attrib" : "fragdata", Location, Name);
continue;
}
used |= mask;
if(!strncmp("gl_", n.c_str(), 3))
if(!strncmp("gl_", Name, 3))
continue; // GL_INVALID_OPERATION if name starts with reserved gl_ prefix (for both
// glBindAttribLocation and glBindFragDataLocation)
if(sigType == 0)
{
gl.glBindAttribLocation(prog, (GLuint)idx, n.c_str());
gl.glBindAttribLocation(prog, (GLuint)Location, Name);
}
else
{
if(gl.glBindFragDataLocation)
{
gl.glBindFragDataLocation(prog, (GLuint)idx, n.c_str());
gl.glBindFragDataLocation(prog, (GLuint)Location, Name);
}
else
{
@@ -2554,6 +2646,10 @@ void SerialiseProgramBindings(const GLHookSet &gl, Serialiser *ser, GLuint prog,
}
}
template void SerialiseProgramBindings(ReadSerialiser &ser, CaptureState state, const GLHookSet &gl,
GLuint prog);
template void SerialiseProgramBindings(WriteSerialiser &ser, CaptureState state,
const GLHookSet &gl, GLuint prog);
#if ENABLED(ENABLE_UNIT_TESTS)
+8 -3
View File
@@ -509,13 +509,18 @@ void EmulateRequiredExtensions(GLHookSet *hooks);
struct ShaderReflection;
void CopyProgramUniforms(const GLHookSet &gl, GLuint progSrc, GLuint progDst);
void SerialiseProgramUniforms(const GLHookSet &gl, Serialiser *ser, GLuint prog,
map<GLint, GLint> *locTranslate, bool writing);
uint32_t GetUniformsSerialiseSize(const GLHookSet &gl, GLuint prog);
template <typename SerialiserType>
void SerialiseProgramUniforms(SerialiserType &ser, CaptureState state, const GLHookSet &gl,
GLuint prog, map<GLint, GLint> *locTranslate);
void CopyProgramAttribBindings(const GLHookSet &gl, GLuint progsrc, GLuint progdst,
ShaderReflection *refl);
void CopyProgramFragDataBindings(const GLHookSet &gl, GLuint progsrc, GLuint progdst,
ShaderReflection *refl);
void SerialiseProgramBindings(const GLHookSet &gl, Serialiser *ser, GLuint prog, bool writing);
uint32_t GetBindingsSerialiseSize(const GLHookSet &gl, GLuint prog);
template <typename SerialiserType>
void SerialiseProgramBindings(SerialiserType &ser, CaptureState state, const GLHookSet &gl,
GLuint prog);
struct DrawElementsIndirectCommand
{
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -113,4 +113,4 @@ bool GLResourceManager::SerialisableResource(ResourceId id, GLResourceRecord *re
if(id == m_GL->GetContextResourceID())
return false;
return true;
}
}
+10 -5
View File
@@ -33,10 +33,7 @@ class WrappedOpenGL;
class GLResourceManager : public ResourceManager<GLResource, GLResource, GLResourceRecord>
{
public:
GLResourceManager(LogState state, Serialiser *ser, WrappedOpenGL *gl)
: ResourceManager(state, ser), m_GL(gl), m_SyncName(1)
{
}
GLResourceManager(WrappedOpenGL *gl) : ResourceManager(), m_GL(gl), m_SyncName(1) {}
~GLResourceManager() {}
void Shutdown()
{
@@ -209,8 +206,14 @@ public:
void MarkVAOReferenced(GLResource res, FrameRefType ref, bool allowFake0 = false);
void MarkFBOReferenced(GLResource res, FrameRefType ref);
template <typename SerialiserType>
bool Serialise_InitialState(SerialiserType &ser, ResourceId resid, GLResource res);
bool Prepare_InitialState(GLResource res, byte *blob);
bool Serialise_InitialState(ResourceId resid, GLResource res);
bool Serialise_InitialState(WriteSerialiser &ser, ResourceId resid, GLResource res)
{
return Serialise_InitialState<WriteSerialiser>(ser, resid, res);
}
private:
bool SerialisableResource(ResourceId id, GLResourceRecord *record);
@@ -219,6 +222,7 @@ private:
bool Force_InitialState(GLResource res, bool prepare);
bool Need_InitialStateChunk(GLResource res);
bool Prepare_InitialState(GLResource res);
uint32_t GetSize_InitialState(ResourceId resid, GLResource res);
void CreateTextureImage(GLuint tex, GLenum internalFormat, GLenum textype, GLint dim, GLint width,
GLint height, GLint depth, GLint samples, int mips);
@@ -238,5 +242,6 @@ private:
map<ResourceId, std::string> m_Names;
volatile int64_t m_SyncName;
CaptureState m_State;
WrappedOpenGL *m_GL;
};
@@ -212,6 +212,9 @@
<ClCompile Include="precompiled.cpp">
<Filter>PCH</Filter>
</ClCompile>
<ClCompile Include="gl_initstate.cpp">
<Filter>Util</Filter>
</ClCompile>
<ClCompile Include="gl_hooks_vrapi.cpp">
<Filter>OS\EGL</Filter>
</ClCompile>