Save off and store VAO initial frame state

This commit is contained in:
baldurk
2014-08-15 17:10:20 +01:00
parent c6f4536614
commit f3e9e3ffed
3 changed files with 181 additions and 7 deletions
+3 -1
View File
@@ -360,6 +360,8 @@ WrappedOpenGL::WrappedOpenGL(const wchar_t *logfile, const GLHookSet &funcs)
m_FakeBB_FBO = 0;
m_FakeBB_Color = 0;
m_FakeBB_DepthStencil = 0;
GetResourceManager()->SetSerialiser(m_State, m_pSerialiser);
RDCDEBUG("Debug Text enabled - for development! remove before release!");
m_pSerialiser->SetDebugText(true);
@@ -1401,7 +1403,7 @@ void WrappedOpenGL::ProcessChunk(uint64_t offset, GLChunkType context)
default:
// ignore system chunks
if((int)context == (int)INITIAL_CONTENTS)
RDCERR("Initial contents not implemented yet");
GetResourceManager()->Serialise_InitialState(GLResource(MakeNullResource));
else if((int)context < (int)FIRST_CHUNK_ID)
m_pSerialiser->SkipCurrentChunk();
else
+158
View File
@@ -26,6 +26,21 @@
#include "driver/gl/gl_manager.h"
#include "driver/gl/gl_driver.h"
struct VertexArrayInitialData
{
VertexArrayInitialData()
{
RDCEraseEl(*this);
}
uint32_t enabled;
uint32_t vbslot;
uint32_t offset;
GLenum type;
int32_t normalized;
uint32_t integer;
uint32_t size;
};
bool GLResourceManager::SerialisableResource(ResourceId id, GLResourceRecord *record)
{
if(id == m_GL->GetContextResourceID())
@@ -33,17 +48,160 @@ bool GLResourceManager::SerialisableResource(ResourceId id, GLResourceRecord *re
return true;
}
bool GLResourceManager::Need_InitialStateChunk(GLResource res)
{
return res.Namespace != eResBuffer;
}
bool GLResourceManager::Prepare_InitialState(GLResource res)
{
ResourceId Id = GetID(res);
if(res.Namespace == eResBuffer)
{
GLResourceRecord *record = GetResourceRecord(res);
// TODO copy this to an immutable buffer elsewhere and SetInitialContents() it.
// then only do the readback in Serialise_InitialState
GLint length;
m_GL->glGetNamedBufferParameterivEXT(res.name, eGL_BUFFER_SIZE, &length);
m_GL->glGetNamedBufferSubDataEXT(res.name, 0, length, record->GetDataPtr());
}
else if(res.Namespace == eResVertexArray)
{
GLuint VAO = 0;
m_GL->glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&VAO);
m_GL->glBindVertexArray(res.name);
VertexArrayInitialData *data = (VertexArrayInitialData *)new byte[sizeof(VertexArrayInitialData)*16];
for(GLuint i=0; i < 16; i++)
{
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_ENABLED, (GLint *)&data[i].enabled);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_BINDING, (GLint *)&data[i].vbslot);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_RELATIVE_OFFSET, (GLint*)&data[i].offset);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint *)&data[i].type);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_NORMALIZED, (GLint *)&data[i].normalized);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_INTEGER, (GLint *)&data[i].integer);
m_GL->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_SIZE, (GLint *)&data[i].size);
}
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, (byte *)data));
m_GL->glBindVertexArray(VAO);
}
else
{
RDCERR("Unexpected type of resource requiring initial state");
}
return true;
}
bool GLResourceManager::Force_InitialState(GLResource res)
{
// hack for now, these should be tracked through the normal dirty/ref tracking process.
if(res.Namespace == eResVertexArray) return true;
return false;
}
bool GLResourceManager::Serialise_InitialState(GLResource res)
{
ResourceId Id = ResourceId();
Serialiser *m_pSerialiser = NULL;
LogState m_State = READING;
if(m_State >= WRITING)
{
Id = GetID(res);
if(res.Namespace != eResBuffer)
m_pSerialiser->Serialise("Id", Id);
}
else
{
m_pSerialiser->Serialise("Id", Id);
}
if(m_State < WRITING)
{
if(HasLiveResource(Id))
res = GetLiveResource(Id);
else
res = GLResource(MakeNullResource);
}
if(res.Namespace == eResVertexArray)
{
VertexArrayInitialData data[16];
if(m_State >= WRITING)
{
VertexArrayInitialData *initialdata = (VertexArrayInitialData *)GetInitialContents(Id).blob;
memcpy(data, initialdata, sizeof(data));
}
for(GLuint i=0; i < 16; i++)
{
m_pSerialiser->Serialise("data[].enabled", data[i].enabled);
m_pSerialiser->Serialise("data[].vbslot", data[i].vbslot);
m_pSerialiser->Serialise("data[].offset", data[i].offset);
m_pSerialiser->Serialise("data[].type", data[i].type);
m_pSerialiser->Serialise("data[].normalized", data[i].normalized);
m_pSerialiser->Serialise("data[].integer", data[i].integer);
m_pSerialiser->Serialise("data[].size", data[i].size);
}
if(m_State < WRITING)
{
byte *blob = new byte[sizeof(data)];
memcpy(blob, data, sizeof(data));
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, blob));
}
}
else
{
RDCERR("Unexpected type of resource requiring initial state");
}
return true;
}
void GLResourceManager::Create_InitialState(ResourceId id, GLResource live, bool hasData)
{
RDCUNIMPLEMENTED("Expect all initial states to be created & not skipped, presently");
}
void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData initial)
{
if(live.Namespace == eResVertexArray)
{
GLuint VAO = 0;
m_GL->glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&VAO);
m_GL->glBindVertexArray(live.name);
VertexArrayInitialData *initialdata = (VertexArrayInitialData *)initial.blob;
for(GLuint i=0; i < 16; i++)
{
m_GL->glVertexAttribBinding(i, initialdata[i].vbslot);
if(initialdata[i].integer == 0)
m_GL->glVertexAttribFormat(i, initialdata[i].size, initialdata[i].type, (GLboolean)initialdata[i].normalized, initialdata[i].offset);
else
m_GL->glVertexAttribIFormat(i, initialdata[i].size, initialdata[i].type, initialdata[i].offset);
}
m_GL->glBindVertexArray(VAO);
}
else
{
RDCERR("Unexpected type of resource requiring initial state");
}
}
+20 -6
View File
@@ -34,7 +34,11 @@ class WrappedOpenGL;
class GLResourceManager : public ResourceManager<GLResource, GLResourceRecord>
{
public:
GLResourceManager(WrappedOpenGL *gl) : m_GL(gl), m_SyncName(1) {}
GLResourceManager(WrappedOpenGL *gl) : m_GL(gl), m_SyncName(1)
{
m_pSerialiser = NULL;
m_State = READING;
}
~GLResourceManager() {}
void Shutdown()
@@ -134,17 +138,24 @@ class GLResourceManager : public ResourceManager<GLResource, GLResourceRecord>
return m_SyncIDs[sync];
}
void SetSerialiser(LogState state, Serialiser *ser)
{
m_State = state;
m_pSerialiser = ser;
}
bool Serialise_InitialState(GLResource res);
private:
bool SerialisableResource(ResourceId id, GLResourceRecord *record);
bool ResourceTypeRelease(GLResource res) { return true; }
bool Force_InitialState(GLResource res) { return false; }
bool Need_InitialStateChunk(GLResource res) { return res.Namespace != eResBuffer; }
bool Force_InitialState(GLResource res);
bool Need_InitialStateChunk(GLResource res);
bool Prepare_InitialState(GLResource res);
bool Serialise_InitialState(GLResource res) { return true; }
void Create_InitialState(ResourceId id, GLResource live, bool hasData) { }
void Apply_InitialState(GLResource live, InitialContentData initial) { }
void Create_InitialState(ResourceId id, GLResource live, bool hasData);
void Apply_InitialState(GLResource live, InitialContentData initial);
map<GLResource, GLResourceRecord*> m_GLResourceRecords;
@@ -156,6 +167,9 @@ class GLResourceManager : public ResourceManager<GLResource, GLResourceRecord>
map<GLuint, GLsync> m_CurrentSyncs;
volatile int64_t m_SyncName;
Serialiser *m_pSerialiser;
LogState m_State;
WrappedOpenGL *m_GL;
};