From cf74b676600cac130d2a121c3713dbcf198382f8 Mon Sep 17 00:00:00 2001 From: Benson Joeris Date: Fri, 1 Feb 2019 10:28:04 -0500 Subject: [PATCH] Refactor `FrameRefType` and add `Clear` reference type This change simplifies the `FrameRefType` enum by removing the separate states and transitions, and replacing them with a smaller set of reference types, together with functions that compose those reference types. This change also introduces a `Clear` reference type, which is used to represent an access to the resource that completely overwrites the previous contents; this is in contrast with a `Write` access that may leave some of the previous contents untouched. --- renderdoc/core/resource_manager.cpp | 121 +++++++++++++------ renderdoc/core/resource_manager.h | 88 +++++++++++--- renderdoc/driver/d3d11/d3d11_renderstate.cpp | 52 ++++---- renderdoc/driver/gl/gl_manager.cpp | 4 +- renderdoc/driver/gl/gl_renderstate.cpp | 52 ++++---- renderdoc/driver/vulkan/vk_resources.h | 11 +- 6 files changed, 216 insertions(+), 112 deletions(-) diff --git a/renderdoc/core/resource_manager.cpp b/renderdoc/core/resource_manager.cpp index f3e597225..3778f6822 100644 --- a/renderdoc/core/resource_manager.cpp +++ b/renderdoc/core/resource_manager.cpp @@ -25,6 +25,8 @@ #include "resource_manager.h" +#include + namespace ResourceIDGen { static volatile int64_t globalIDCounter = 1; @@ -51,44 +53,96 @@ void SetReplayResourceIDs() INSTANTIATE_SERIALISE_TYPE(ResourceManagerInternal::WrittenRecord); +FrameRefType ComposeFrameRefs(FrameRefType first, FrameRefType second) +{ + RDCASSERT(eFrameRef_Minimum <= first && first <= eFrameRef_Maximum); + RDCASSERT(eFrameRef_Minimum <= second && second <= eFrameRef_Maximum); + + switch(first) + { + case eFrameRef_None: + case eFrameRef_Write: + if(second == eFrameRef_None) + // A `None` reference after any other reference type does not change + // the first reference type + return first; + else + // A `None` or `Write` reference before any non-`None` reference type + // does not change the reference type. + return second; + + case eFrameRef_Read: + switch(second) + { + case eFrameRef_None: + case eFrameRef_Read: + // Only referenced as `Read` (and possibly `None`) + return eFrameRef_Read; + + case eFrameRef_Write: + case eFrameRef_Clear: + case eFrameRef_ReadBeforeWrite: + // First read, and then written + return eFrameRef_ReadBeforeWrite; + + default: RDCERR("Unknown FrameRefType: %d", second); return eFrameRef_Maximum; + } + + case eFrameRef_Clear: + case eFrameRef_ReadBeforeWrite: + // These reference types are both locked in, and cannot be affected by + // later references. + return first; + + default: RDCERR("Unknown FrameRefType: %d", first); return eFrameRef_Maximum; + } +} + +FrameRefType ComposeFrameRefsUnordered(FrameRefType first, FrameRefType second) +{ + RDCASSERT(eFrameRef_Minimum <= first && first <= eFrameRef_Maximum); + RDCASSERT(eFrameRef_Minimum <= second && second <= eFrameRef_Maximum); + + // The order of the reference types is irrelevant, so put them in a + // consistent order (`first >= second`) to reduce the number of cases to + // consider. + if(first < second) + std::swap(first, second); + + if(first == eFrameRef_Read && (second == eFrameRef_Write || second == eFrameRef_Clear)) + // The resource is referenced both read and write/clear; + // We don't know whether the read or write/clear occurs first; + // if the write happens first, the final state would be Read or Clear; + // if the read happens first, the final state would be ReadBeforeWrite. + // We conservatively return ReadBeforeWrite, because this will force the + // resource to be reset before each frame when replaying. + return eFrameRef_ReadBeforeWrite; + + // In all other cases, we just return the more conservative reference type-- + // i.e. the reference type with the strongest (re)initialization + // requirements for replay. Because larger values in the `FrameRefType` have + // stronger (re)initialization requirements, this is simply the maximum + // reference type; note that `first >= second` by the earlier swap. + return first; +} + +bool IsDirtyFrameRef(FrameRefType refType) +{ + return (refType != eFrameRef_None && refType != eFrameRef_Read); +} + bool MarkReferenced(std::map &refs, ResourceId id, FrameRefType refType) { - if(refs.find(id) == refs.end()) + auto refit = refs.find(id); + if(refit == refs.end()) { - if(refType == eFrameRef_Read) - refs[id] = eFrameRef_ReadOnly; - else if(refType == eFrameRef_Write) - refs[id] = eFrameRef_ReadAndWrite; - else // unknown or existing state - refs[id] = refType; - + refs[id] = refType; return true; } else { - if(refType == eFrameRef_Unknown) - { - // nothing - } - else if(refType == eFrameRef_ReadBeforeWrite) - { - // special case, explicitly set to ReadBeforeWrite for when - // we know that this use will likely be a partial-write - refs[id] = eFrameRef_ReadBeforeWrite; - } - else if(refs[id] == eFrameRef_Unknown) - { - if(refType == eFrameRef_Read || refType == eFrameRef_ReadOnly) - refs[id] = eFrameRef_ReadOnly; - else - refs[id] = eFrameRef_ReadAndWrite; - } - else if(refs[id] == eFrameRef_ReadOnly && refType == eFrameRef_Write) - { - refs[id] = eFrameRef_ReadBeforeWrite; - } + refit->second = ComposeFrameRefs(refit->second, refType); } - return false; } @@ -121,14 +175,9 @@ void ResourceRecord::Delete(ResourceRecordHandler *mgr) DataPtr = NULL; for(auto it = m_FrameRefs.begin(); it != m_FrameRefs.end(); ++it) - { - if(it->second == eFrameRef_Write || it->second == eFrameRef_ReadAndWrite || - it->second == eFrameRef_ReadBeforeWrite) - { + if(IsDirtyFrameRef(it->second)) // lost a write to this resource, must mark it as gpu dirty. mgr->MarkPendingDirty(it->first); - } - } DeleteChunks(); diff --git a/renderdoc/core/resource_manager.h b/renderdoc/core/resource_manager.h index e92cfdc9a..25d7e161f 100644 --- a/renderdoc/core/resource_manager.h +++ b/renderdoc/core/resource_manager.h @@ -36,23 +36,84 @@ using std::set; using std::map; -// in what way (read, write, etc) was a resource referenced in a frame - -// used to determine if initial contents are needed and to what degree +// In what way (read, write, etc) was a resource referenced in a frame - +// used to determine if initial contents are needed and to what degree. +// These values are used both as states (representing the cumulative previous +// accesses to the resource), and state transitions (access by a single +// command, modifying the state). This state machine is illustrated below, +// with states represented in caps, and transitions in lower case. +// +// +------------ NONE -------------+ +// | | | +// read write clear +// | | | +// V V V +// READ <--read-- WRITE --clear--> CLEAR +// | +// write/clear +// | +// V +// READBEFOREWRITE +// +// Note: +// * All resources begin implicitly in the None state. +// * The state transitions for ReadBeforeWrite are simply the composition of +// the transition for read, followed by the transition for write (e.g. +// ReadBeforeWrite moves from NONE state to READBEFOREWRITE state). +// * All other transitions (excluding ReadBeforeWrite) that are not explicitly +// shown leave the state unchanged (e.g. a read in the CLEAR state remains +// in the CLEAR state). +// +// The enum values are ordered so that larger values correspond to greater +// requirements for (re)initialization of the resource during replay. enum FrameRefType { - eFrameRef_Unknown, // for the initial start of frame pipeline state - can't be marked as - // written/read yet until first action. + // Initial state, no reads or writes + eFrameRef_None = 0, - // Inputs - eFrameRef_Read, - eFrameRef_Write, + // Write to some unknown subset of resource. + // As a state, this represents that unlike clear, some part of the + // initial contents might still be visible to later reads. + eFrameRef_Write = 1, - // States - eFrameRef_ReadOnly, - eFrameRef_ReadAndWrite, - eFrameRef_ReadBeforeWrite, + // Clear the entire resource. + // As a state, this represents that no later reads will even be able to see + // the initial contents, and therefore, the initial contents need not be + // restored for replay. + eFrameRef_Clear = 2, + + // Read from the resource; + // As a state, this represents a read that could have seen the resource's + // initial contents, but the value seen by the read has not been overwritten; + // therefore, the initial contents needs to be restored before the first time + // we replay, but doesn't need to be reset between subsequent replays. + eFrameRef_Read = 3, + + // Read followed by a write; + // As a state, this represents a read that could have seen the resource + // initial contents, followed by a write that could have modified that + // initial contents; therefore, the initial contents will need to be reset + // before each time we replay the frame. + eFrameRef_ReadBeforeWrite = 4, }; +const FrameRefType eFrameRef_Minimum = eFrameRef_None; +const FrameRefType eFrameRef_Maximum = eFrameRef_ReadBeforeWrite; + +// Compose frame refs that occur in a known order. +// This can be thought of as a state (`first`) and a transition from that state +// (`second`), returning the new state (see the state diagram for +// `FrameRefType` above) +FrameRefType ComposeFrameRefs(FrameRefType first, FrameRefType second); + +// Compose frame refs when the order is unknown. +// This is conservative, in that, if there is both a Read and a Write/Clear, it +// assumes the Read occurs before the Write/Clear, forcing that resource to be +// reset for replay. +FrameRefType ComposeFrameRefsUnordered(FrameRefType first, FrameRefType second); + +bool IsDirtyFrameRef(FrameRefType refType); + // handle marking a resource referenced for read or write and storing RAW access etc. bool MarkReferenced(std::map &refs, ResourceId id, FrameRefType refType); @@ -685,8 +746,7 @@ void ResourceManager::Serialise_InitialContentsNeeded(WriteSerial for(auto it = m_FrameReferencedResources.begin(); it != m_FrameReferencedResources.end(); ++it) { RecordType *record = GetResourceRecord(it->first); - - if(it->second != eFrameRef_ReadOnly && it->second != eFrameRef_Unknown) + if(IsDirtyFrameRef(it->second)) { WrittenRecord wr = {it->first, record ? record->DataInSerialiser : true}; @@ -698,7 +758,7 @@ void ResourceManager::Serialise_InitialContentsNeeded(WriteSerial { ResourceId id = *it; auto ref = m_FrameReferencedResources.find(id); - if(ref == m_FrameReferencedResources.end() || ref->second == eFrameRef_ReadOnly) + if(ref == m_FrameReferencedResources.end() || !IsDirtyFrameRef(ref->second)) { WrittenRecord wr = {id, true}; diff --git a/renderdoc/driver/d3d11/d3d11_renderstate.cpp b/renderdoc/driver/d3d11/d3d11_renderstate.cpp index b796ffabe..edf6218fb 100644 --- a/renderdoc/driver/d3d11/d3d11_renderstate.cpp +++ b/renderdoc/driver/d3d11/d3d11_renderstate.cpp @@ -165,15 +165,14 @@ void D3D11RenderState::ReleaseRefs() void D3D11RenderState::MarkReferenced(WrappedID3D11DeviceContext *ctx, bool initial) const { - ctx->MarkResourceReferenced(GetIDForResource(IA.Layout), - initial ? eFrameRef_Unknown : eFrameRef_Read); + ctx->MarkResourceReferenced(GetIDForResource(IA.Layout), initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetIDForResource(IA.IndexBuffer), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); for(UINT i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) ctx->MarkResourceReferenced(GetIDForResource(IA.VBs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); const Shader *stages[] = {&VS, &HS, &DS, &GS, &PS, &CS}; for(int s = 0; s < 6; s++) @@ -181,24 +180,24 @@ void D3D11RenderState::MarkReferenced(WrappedID3D11DeviceContext *ctx, bool init const Shader *sh = stages[s]; ctx->MarkResourceReferenced(GetIDForResource(sh->Object), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); for(UINT i = 0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) ctx->MarkResourceReferenced(GetIDForResource(sh->ConstantBuffers[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); for(UINT i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; i++) ctx->MarkResourceReferenced(GetIDForResource(sh->Samplers[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); for(UINT i = 0; i < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++) { if(sh->SRVs[i]) { ctx->MarkResourceReferenced(GetIDForResource(sh->SRVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetViewResourceResID(sh->SRVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); } } @@ -211,37 +210,36 @@ void D3D11RenderState::MarkReferenced(WrappedID3D11DeviceContext *ctx, bool init { // UAVs we always assume to be partial updates ctx->MarkResourceReferenced(GetIDForResource(CSUAVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetIDForResource(CSUAVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Write); + initial ? eFrameRef_None : eFrameRef_Write); ctx->MarkResourceReferenced(GetViewResourceResID(CSUAVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetViewResourceResID(CSUAVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Write); + initial ? eFrameRef_None : eFrameRef_Write); } } for(UINT i = 0; i < D3D11_SO_BUFFER_SLOT_COUNT; i++) ctx->MarkResourceReferenced(GetIDForResource(SO.Buffers[i]), - initial ? eFrameRef_Unknown : eFrameRef_Write); + initial ? eFrameRef_None : eFrameRef_Write); - ctx->MarkResourceReferenced(GetIDForResource(RS.State), - initial ? eFrameRef_Unknown : eFrameRef_Read); + ctx->MarkResourceReferenced(GetIDForResource(RS.State), initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetIDForResource(OM.BlendState), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetIDForResource(OM.DepthStencilState), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); for(UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { if(OM.RenderTargets[i]) { ctx->MarkResourceReferenced(GetIDForResource(OM.RenderTargets[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetViewResourceResID(OM.RenderTargets[i]), - initial ? eFrameRef_Unknown : eFrameRef_Write); + initial ? eFrameRef_None : eFrameRef_Write); } } @@ -251,28 +249,28 @@ void D3D11RenderState::MarkReferenced(WrappedID3D11DeviceContext *ctx, bool init { // UAVs we always assume to be partial updates ctx->MarkResourceReferenced(GetIDForResource(OM.UAVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetIDForResource(OM.UAVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Write); + initial ? eFrameRef_None : eFrameRef_Write); ctx->MarkResourceReferenced(GetViewResourceResID(OM.UAVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetViewResourceResID(OM.UAVs[i]), - initial ? eFrameRef_Unknown : eFrameRef_Write); + initial ? eFrameRef_None : eFrameRef_Write); } } if(OM.DepthView) { ctx->MarkResourceReferenced(GetIDForResource(OM.DepthView), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); ctx->MarkResourceReferenced(GetViewResourceResID(OM.DepthView), - initial ? eFrameRef_Unknown : eFrameRef_Write); + initial ? eFrameRef_None : eFrameRef_Write); } if(Predicate) { ctx->MarkResourceReferenced(GetIDForResource(Predicate), - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); } } diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 04dc063e6..793e53e0e 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -39,7 +39,7 @@ void GLResourceManager::MarkVAOReferenced(GLResource res, FrameRefType ref, bool { ContextPair &ctx = m_Driver->GetCtx(); - MarkResourceFrameReferenced(res, ref == eFrameRef_Unknown ? eFrameRef_Unknown : eFrameRef_Read); + MarkResourceFrameReferenced(res, ref == eFrameRef_None ? eFrameRef_None : eFrameRef_Read); GLint numVBufferBindings = GetNumVertexBuffers(); @@ -61,7 +61,7 @@ void GLResourceManager::MarkFBOReferenced(GLResource res, FrameRefType ref) if(res.name == 0) return; - MarkResourceFrameReferenced(res, ref == eFrameRef_Unknown ? eFrameRef_Unknown : eFrameRef_Read); + MarkResourceFrameReferenced(res, ref == eFrameRef_None ? eFrameRef_None : eFrameRef_Read); ContextPair &ctx = m_Driver->GetCtx(); diff --git a/renderdoc/driver/gl/gl_renderstate.cpp b/renderdoc/driver/gl/gl_renderstate.cpp index df43fb29f..7733e8fe8 100644 --- a/renderdoc/driver/gl/gl_renderstate.cpp +++ b/renderdoc/driver/gl/gl_renderstate.cpp @@ -457,68 +457,66 @@ void GLRenderState::MarkReferenced(WrappedOpenGL *driver, bool initial) const for(GLuint i = 0; i < (GLuint)ARRAY_COUNT(Tex2D); i++) { - manager->MarkResourceFrameReferenced(Tex1D[i], initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(Tex2D[i], initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(Tex3D[i], initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(Tex1DArray[i], initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(Tex2DArray[i], initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(TexCubeArray[i], - initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(TexRect[i], initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(TexBuffer[i], initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(TexCube[i], initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(Tex2DMS[i], initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(Tex2DMSArray[i], - initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(Samplers[i], initial ? eFrameRef_Unknown : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Tex1D[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Tex2D[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Tex3D[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Tex1DArray[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Tex2DArray[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(TexCubeArray[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(TexRect[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(TexBuffer[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(TexCube[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Tex2DMS[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Tex2DMSArray[i], initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Samplers[i], initial ? eFrameRef_None : eFrameRef_Read); } for(GLuint i = 0; i < (GLuint)ARRAY_COUNT(Images); i++) { manager->MarkResourceFrameReferenced(Images[i].res, - initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite); + initial ? eFrameRef_None : eFrameRef_ReadBeforeWrite); driver->AddMissingTrack(manager->GetID(Images[i].res)); } - manager->MarkVAOReferenced(VAO, initial ? eFrameRef_Unknown : eFrameRef_Read, true); + manager->MarkVAOReferenced(VAO, initial ? eFrameRef_None : eFrameRef_Read, true); - manager->MarkResourceFrameReferenced(FeedbackObj, initial ? eFrameRef_Unknown : eFrameRef_Read); + manager->MarkResourceFrameReferenced(FeedbackObj, initial ? eFrameRef_None : eFrameRef_Read); - manager->MarkResourceFrameReferenced(Program, initial ? eFrameRef_Unknown : eFrameRef_Read); - manager->MarkResourceFrameReferenced(Pipeline, initial ? eFrameRef_Unknown : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Program, initial ? eFrameRef_None : eFrameRef_Read); + manager->MarkResourceFrameReferenced(Pipeline, initial ? eFrameRef_None : eFrameRef_Read); // the pipeline correctly has program parents, but we must also mark the programs as frame // referenced so that their // initial contents will be serialised. GLResourceRecord *record = manager->GetResourceRecord(Pipeline); if(record) - record->MarkParentsReferenced(manager, initial ? eFrameRef_Unknown : eFrameRef_Read); + record->MarkParentsReferenced(manager, initial ? eFrameRef_None : eFrameRef_Read); for(size_t i = 0; i < ARRAY_COUNT(BufferBindings); i++) manager->MarkResourceFrameReferenced(BufferBindings[i], - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); for(size_t i = 0; i < ARRAY_COUNT(AtomicCounter); i++) manager->MarkResourceFrameReferenced(AtomicCounter[i].res, - initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite); + initial ? eFrameRef_None : eFrameRef_ReadBeforeWrite); for(size_t i = 0; i < ARRAY_COUNT(ShaderStorage); i++) manager->MarkResourceFrameReferenced(ShaderStorage[i].res, - initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite); + initial ? eFrameRef_None : eFrameRef_ReadBeforeWrite); for(size_t i = 0; i < ARRAY_COUNT(TransformFeedback); i++) manager->MarkResourceFrameReferenced(TransformFeedback[i].res, - initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite); + initial ? eFrameRef_None : eFrameRef_ReadBeforeWrite); for(size_t i = 0; i < ARRAY_COUNT(UniformBinding); i++) manager->MarkResourceFrameReferenced(UniformBinding[i].res, - initial ? eFrameRef_Unknown : eFrameRef_Read); + initial ? eFrameRef_None : eFrameRef_Read); - manager->MarkFBOReferenced(DrawFBO, initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite); + manager->MarkFBOReferenced(DrawFBO, initial ? eFrameRef_None : eFrameRef_ReadBeforeWrite); // if same FBO is bound to both targets, treat it as draw only if(ReadFBO != DrawFBO) - manager->MarkFBOReferenced(ReadFBO, initial ? eFrameRef_Unknown : eFrameRef_Read); + manager->MarkFBOReferenced(ReadFBO, initial ? eFrameRef_None : eFrameRef_Read); } void GLRenderState::MarkDirty(WrappedOpenGL *driver) diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index 7d4699336..ce6fe0220 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -1039,17 +1039,16 @@ public: RDCERR("Unexpected NULL resource ID being added as a bind frame ref"); return; } - - if((descInfo->bindFrameRefs[id].first & ~DescriptorSetData::SPARSE_REF_BIT) == 0) + auto it = descInfo->bindFrameRefs.find(id); + if((it->second.first & ~DescriptorSetData::SPARSE_REF_BIT) == 0) { - descInfo->bindFrameRefs[id] = - std::make_pair(1 | (hasSparse ? DescriptorSetData::SPARSE_REF_BIT : 0), ref); + it->second = std::make_pair(1 | (hasSparse ? DescriptorSetData::SPARSE_REF_BIT : 0), ref); } else { // be conservative - mark refs as read before write if we see a write and a read ref on it - if(ref == eFrameRef_Write && descInfo->bindFrameRefs[id].second == eFrameRef_Read) - descInfo->bindFrameRefs[id].second = eFrameRef_ReadBeforeWrite; + descInfo->bindFrameRefs[id].second = + ComposeFrameRefsUnordered(descInfo->bindFrameRefs[id].second, ref); descInfo->bindFrameRefs[id].first++; } }