From 4ccfe298f3405397c7aa7a88ed7ae217ebbbf229 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 28 Sep 2016 15:09:02 +0200 Subject: [PATCH] Force initial states for 'viewed' resources in GL * If a buffer is used as a texbuffer, or a texture as a view, then any time the underlying data is dirty and needs to be saved as initial contents but the data object is never referenced directly (only the view), we need to force the underlying data object to have initial contents. --- renderdoc/core/resource_manager.h | 6 ++-- renderdoc/driver/d3d11/d3d11_manager.cpp | 2 +- renderdoc/driver/d3d11/d3d11_manager.h | 2 +- renderdoc/driver/d3d12/d3d12_manager.cpp | 2 +- renderdoc/driver/d3d12/d3d12_manager.h | 2 +- renderdoc/driver/gl/gl_manager.cpp | 35 ++++++++++++++++++- renderdoc/driver/gl/gl_manager.h | 2 +- renderdoc/driver/gl/gl_resources.h | 7 ++++ .../driver/gl/wrappers/gl_texture_funcs.cpp | 13 +++++++ renderdoc/driver/vulkan/vk_manager.cpp | 2 +- renderdoc/driver/vulkan/vk_manager.h | 2 +- 11 files changed, 64 insertions(+), 11 deletions(-) diff --git a/renderdoc/core/resource_manager.h b/renderdoc/core/resource_manager.h index 4d4087ba5..3a03fdd9d 100644 --- a/renderdoc/core/resource_manager.h +++ b/renderdoc/core/resource_manager.h @@ -427,7 +427,7 @@ protected: virtual bool ResourceTypeRelease(WrappedResourceType res) = 0; - virtual bool Force_InitialState(WrappedResourceType res) = 0; + virtual bool Force_InitialState(WrappedResourceType res, bool prepare) = 0; virtual bool AllowDeletedResource_InitialState() { return false; } virtual bool Need_InitialStateChunk(WrappedResourceType res) = 0; virtual bool Prepare_InitialState(WrappedResourceType res) = 0; @@ -943,7 +943,7 @@ void ResourceManager::Prepare if(it->second == (WrappedResourceType)RecordType::NullResource) continue; - if(Force_InitialState(it->second)) + if(Force_InitialState(it->second, true)) { prepared++; Prepare_InitialState(it->second); @@ -1049,7 +1049,7 @@ void ResourceManager::InsertI if(it->second == (WrappedResourceType)RecordType::NullResource) continue; - if(Force_InitialState(it->second)) + if(Force_InitialState(it->second, false)) { dirty++; diff --git a/renderdoc/driver/d3d11/d3d11_manager.cpp b/renderdoc/driver/d3d11/d3d11_manager.cpp index 5051f9180..e19b2a6e2 100644 --- a/renderdoc/driver/d3d11/d3d11_manager.cpp +++ b/renderdoc/driver/d3d11/d3d11_manager.cpp @@ -89,7 +89,7 @@ bool D3D11ResourceManager::ResourceTypeRelease(ID3D11DeviceChild *res) return true; } -bool D3D11ResourceManager::Force_InitialState(ID3D11DeviceChild *res) +bool D3D11ResourceManager::Force_InitialState(ID3D11DeviceChild *res, bool prepare) { return IdentifyTypeByPtr(res) == Resource_UnorderedAccessView; } diff --git a/renderdoc/driver/d3d11/d3d11_manager.h b/renderdoc/driver/d3d11/d3d11_manager.h index 25d1bbf82..f45486e64 100644 --- a/renderdoc/driver/d3d11/d3d11_manager.h +++ b/renderdoc/driver/d3d11/d3d11_manager.h @@ -187,7 +187,7 @@ private: bool ResourceTypeRelease(ID3D11DeviceChild *res); - bool Force_InitialState(ID3D11DeviceChild *res); + bool Force_InitialState(ID3D11DeviceChild *res, bool prepare); bool Need_InitialStateChunk(ID3D11DeviceChild *res); bool Prepare_InitialState(ID3D11DeviceChild *res); bool Serialise_InitialState(ResourceId resid, ID3D11DeviceChild *res); diff --git a/renderdoc/driver/d3d12/d3d12_manager.cpp b/renderdoc/driver/d3d12/d3d12_manager.cpp index 954b1c1f7..8089be1a8 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.cpp +++ b/renderdoc/driver/d3d12/d3d12_manager.cpp @@ -431,7 +431,7 @@ bool D3D12ResourceManager::ResourceTypeRelease(ID3D12DeviceChild *res) return true; } -bool D3D12ResourceManager::Force_InitialState(ID3D12DeviceChild *res) +bool D3D12ResourceManager::Force_InitialState(ID3D12DeviceChild *res, bool prepare) { return false; } diff --git a/renderdoc/driver/d3d12/d3d12_manager.h b/renderdoc/driver/d3d12/d3d12_manager.h index 7c581a788..7933acce6 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.h +++ b/renderdoc/driver/d3d12/d3d12_manager.h @@ -323,7 +323,7 @@ private: bool ResourceTypeRelease(ID3D12DeviceChild *res); - bool Force_InitialState(ID3D12DeviceChild *res); + bool Force_InitialState(ID3D12DeviceChild *res, bool prepare); bool Need_InitialStateChunk(ID3D12DeviceChild *res); bool Prepare_InitialState(ID3D12DeviceChild *res); void Create_InitialState(ResourceId id, ID3D12DeviceChild *live, bool hasData); diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 19bfc4d7e..5a0256ee1 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -888,8 +888,41 @@ void GLResourceManager::PrepareTextureInitialContents(ResourceId liveid, Resourc } } -bool GLResourceManager::Force_InitialState(GLResource res) +bool GLResourceManager::Force_InitialState(GLResource res, bool prepare) { + if(res.Namespace != eResBuffer && res.Namespace != eResTexture) + return false; + + // don't need to force anything if we're already including all resources + if(RenderDoc::Inst().GetCaptureOptions().RefAllResources) + return false; + + GLResourceRecord *record = GetResourceRecord(res); + + // if we have some viewers, check to see if they were referenced but we weren't, and force our own + // initial state inclusion. + if(record && !record->viewTextures.empty()) + { + // need to prepare all such resources, just in case for the worst case. + if(prepare) + return true; + + // if this data resource was referenced already, just skip + if(m_FrameReferencedResources.find(record->GetResourceID()) != m_FrameReferencedResources.end()) + return false; + + // see if any of our viewers were referenced + for(auto it = record->viewTextures.begin(); it != record->viewTextures.end(); ++it) + { + // if so, return true to force our inclusion, for the benefit of the view + if(m_FrameReferencedResources.find(*it) != m_FrameReferencedResources.end()) + { + RDCDEBUG("Forcing inclusion of %llu for %llu", record->GetResourceID(), *it); + return true; + } + } + } + return false; } diff --git a/renderdoc/driver/gl/gl_manager.h b/renderdoc/driver/gl/gl_manager.h index a23d76dc8..e898b0397 100644 --- a/renderdoc/driver/gl/gl_manager.h +++ b/renderdoc/driver/gl/gl_manager.h @@ -212,7 +212,7 @@ private: bool SerialisableResource(ResourceId id, GLResourceRecord *record); bool ResourceTypeRelease(GLResource res) { return true; } - bool Force_InitialState(GLResource res); + bool Force_InitialState(GLResource res, bool prepare); bool Need_InitialStateChunk(GLResource res); bool Prepare_InitialState(GLResource res); diff --git a/renderdoc/driver/gl/gl_resources.h b/renderdoc/driver/gl/gl_resources.h index b64b1f6a8..e236ed9ad 100644 --- a/renderdoc/driver/gl/gl_resources.h +++ b/renderdoc/driver/gl/gl_resources.h @@ -258,6 +258,13 @@ struct GLResourceRecord : public ResourceRecord GLenum datatype; GLenum usage; + // for texture buffers and texture views, this points from the data texture (or buffer) + // to the view texture. When preparing resource initial states, we force initial states + // for anything that is viewed if the viewer is frame referenced. Otherwise we might + // lose the underlying data for the view. + // Since it's 1-to-many, we keep a set here. + set viewTextures; + GLResource Resource; void AllocShadowStorage(size_t size) diff --git a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp index 5dfeaa2ee..93cbc0d11 100644 --- a/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_texture_funcs.cpp @@ -671,6 +671,7 @@ void WrappedOpenGL::glTextureView(GLuint texture, GLenum target, GLuint origtext record->AddChunk(scope.Get()); record->AddParent(origrecord); + origrecord->viewTextures.insert(record->GetResourceID()); // illegal to re-type textures record->VerifyDataType(target); @@ -5483,7 +5484,10 @@ void WrappedOpenGL::Common_glTextureBufferRangeEXT(ResourceId texId, GLenum targ GLResourceRecord *bufRecord = GetResourceManager()->GetResourceRecord(bufid); if(bufRecord) + { record->AddParent(bufRecord); + bufRecord->viewTextures.insert(record->GetResourceID()); + } } return; @@ -5512,7 +5516,10 @@ void WrappedOpenGL::Common_glTextureBufferRangeEXT(ResourceId texId, GLenum targ GLResourceRecord *bufRecord = GetResourceManager()->GetResourceRecord(bufid); if(bufRecord) + { record->AddParent(bufRecord); + bufRecord->viewTextures.insert(record->GetResourceID()); + } } } @@ -5643,7 +5650,10 @@ void WrappedOpenGL::Common_glTextureBufferEXT(ResourceId texId, GLenum target, GLResourceRecord *bufRecord = GetResourceManager()->GetResourceRecord(bufid); if(bufRecord) + { record->AddParent(bufRecord); + bufRecord->viewTextures.insert(record->GetResourceID()); + } } return; @@ -5673,7 +5683,10 @@ void WrappedOpenGL::Common_glTextureBufferEXT(ResourceId texId, GLenum target, GLResourceRecord *bufRecord = GetResourceManager()->GetResourceRecord(bufid); if(bufRecord) + { record->AddParent(bufRecord); + bufRecord->viewTextures.insert(record->GetResourceID()); + } } } diff --git a/renderdoc/driver/vulkan/vk_manager.cpp b/renderdoc/driver/vulkan/vk_manager.cpp index c23af01b5..834c40ea2 100644 --- a/renderdoc/driver/vulkan/vk_manager.cpp +++ b/renderdoc/driver/vulkan/vk_manager.cpp @@ -527,7 +527,7 @@ void VulkanResourceManager::ApplyBarriers(vector