From f3e9e3ffed00b46d89c0069898e90047de74d799 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 15 Aug 2014 17:10:20 +0100 Subject: [PATCH] Save off and store VAO initial frame state --- renderdoc/driver/gl/gl_driver.cpp | 4 +- renderdoc/driver/gl/gl_manager.cpp | 158 +++++++++++++++++++++++++++++ renderdoc/driver/gl/gl_manager.h | 26 +++-- 3 files changed, 181 insertions(+), 7 deletions(-) diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 003b5d130..486cd0a6c 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -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 diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index cbbd25c21..ae2817770 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -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"); + } +} diff --git a/renderdoc/driver/gl/gl_manager.h b/renderdoc/driver/gl/gl_manager.h index f2272e5db..cd3d43d62 100644 --- a/renderdoc/driver/gl/gl_manager.h +++ b/renderdoc/driver/gl/gl_manager.h @@ -34,7 +34,11 @@ class WrappedOpenGL; class GLResourceManager : public ResourceManager { 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 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 m_GLResourceRecords; @@ -156,6 +167,9 @@ class GLResourceManager : public ResourceManager map m_CurrentSyncs; volatile int64_t m_SyncName; + Serialiser *m_pSerialiser; + LogState m_State; + WrappedOpenGL *m_GL; };