From 8397aa1f28ad0fc8cdcabf8e436f7388eab5bd51 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 3 Dec 2014 13:57:03 +0000 Subject: [PATCH] Handle glBufferData being used to rename/orphan to a new size --- renderdoc/core/resource_manager.cpp | 4 +- renderdoc/core/resource_manager.h | 9 +++ .../driver/gl/wrappers/gl_buffer_funcs.cpp | 61 ++++++++++++++++++- 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/renderdoc/core/resource_manager.cpp b/renderdoc/core/resource_manager.cpp index 9b97d1cd6..b7f2f21f3 100644 --- a/renderdoc/core/resource_manager.cpp +++ b/renderdoc/core/resource_manager.cpp @@ -62,9 +62,7 @@ void ResourceRecord::Delete(ResourceRecordHandler *mgr) } } - for(auto it=m_Chunks.begin(); it != m_Chunks.end(); ++it) - SAFE_DELETE(it->second); - m_Chunks.clear(); + DeleteChunks(); for(int i=0; i < NumSubResources; i++) { diff --git a/renderdoc/core/resource_manager.h b/renderdoc/core/resource_manager.h index f70ecfbbe..c82dae48c 100644 --- a/renderdoc/core/resource_manager.h +++ b/renderdoc/core/resource_manager.h @@ -192,6 +192,15 @@ struct ResourceRecord UnlockChunks(); } + void DeleteChunks() + { + LockChunks(); + for(auto it=m_Chunks.begin(); it != m_Chunks.end(); ++it) + SAFE_DELETE(it->second); + m_Chunks.clear(); + UnlockChunks(); + } + Chunk *GetLastChunk() const { RDCASSERT(HasChunks()); diff --git a/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp index a508443a8..535f2c67e 100644 --- a/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_buffer_funcs.cpp @@ -348,6 +348,34 @@ void WrappedOpenGL::glNamedBufferDataEXT(GLuint buffer, GLsizeiptr size, const v memset(record->GetDataPtr(), 0xbe, (size_t)size); return; } + + // if we're recreating the buffer, clear the record and add new chunks. Normally + // we would just mark this record as dirty and pick it up on the capture frame as initial + // data, but we don't support (if it's even possible) querying out size etc. + // we need to add only the chunks required - glGenBuffers, glBindBuffer to current target, + // and this buffer storage. All other chunks have no effect + if(m_State == WRITING_IDLE && record->GetDataPtr() != NULL || size != record->Length) + { + record->DeleteChunks(); + + // add glGenBuffers chunk + { + SCOPED_SERIALISE_CONTEXT(GEN_BUFFER); + Serialise_glGenBuffers(1, &buffer); + + record->AddChunk(scope.Get()); + } + + // add glBindBuffer chunk + { + SCOPED_SERIALISE_CONTEXT(GEN_BUFFER); + Serialise_glBindBuffer(record->datatype, buffer); + + record->AddChunk(scope.Get()); + } + + // we're about to add the buffer data chunk + } SCOPED_SERIALISE_CONTEXT(BUFFERDATA); Serialise_glNamedBufferDataEXT(buffer, size, data, usage); @@ -389,9 +417,38 @@ void WrappedOpenGL::glBufferData(GLenum target, GLsizeiptr size, const void *dat return; } + GLuint buffer = GetResourceManager()->GetCurrentResource(record->GetResourceID()).name; + + // if we're recreating the buffer, clear the record and add new chunks. Normally + // we would just mark this record as dirty and pick it up on the capture frame as initial + // data, but we don't support (if it's even possible) querying out size etc. + // we need to add only the chunks required - glGenBuffers, glBindBuffer to current target, + // and this buffer storage. All other chunks have no effect + if(m_State == WRITING_IDLE && record->GetDataPtr() != NULL || size != record->Length) + { + record->DeleteChunks(); + + // add glGenBuffers chunk + { + SCOPED_SERIALISE_CONTEXT(GEN_BUFFER); + Serialise_glGenBuffers(1, &buffer); + + record->AddChunk(scope.Get()); + } + + // add glBindBuffer chunk + { + SCOPED_SERIALISE_CONTEXT(GEN_BUFFER); + Serialise_glBindBuffer(record->datatype, buffer); + + record->AddChunk(scope.Get()); + } + + // we're about to add the buffer data chunk + } + SCOPED_SERIALISE_CONTEXT(BUFFERDATA); - Serialise_glNamedBufferDataEXT(GetResourceManager()->GetCurrentResource(record->GetResourceID()).name, - size, data, usage); + Serialise_glNamedBufferDataEXT(buffer, size, data, usage); Chunk *chunk = scope.Get();