diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp index 025edad4d..d1f9873b4 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp @@ -702,9 +702,9 @@ void D3D11PipelineStateViewer::addResourceRow(const D3D11ViewTag &view, .arg(buf->length / r.elementByteSize); } - if(r.bufferFlags & (D3DBufferViewFlags::Append | D3DBufferViewFlags::Counter)) + if(r.counterResourceId != ResourceId()) { - typeName += tr(" (Count: %1)").arg(r.bufferStructCount); + typeName += tr(" (%1: %2)").arg(ToQStr(r.counterResourceId)).arg(r.bufferStructCount); } // get the buffer type, whether it's just a basic type or a complex struct diff --git a/renderdoc/api/replay/d3d11_pipestate.h b/renderdoc/api/replay/d3d11_pipestate.h index 5019e1f70..403332aeb 100644 --- a/renderdoc/api/replay/d3d11_pipestate.h +++ b/renderdoc/api/replay/d3d11_pipestate.h @@ -179,11 +179,11 @@ struct View bool operator==(const View &o) const { return viewResourceId == o.viewResourceId && resourceResourceId == o.resourceResourceId && - type == o.type && viewFormat == o.viewFormat && structured == o.structured && - bufferStructCount == o.bufferStructCount && elementByteSize == o.elementByteSize && - firstElement == o.firstElement && numElements == o.numElements && - bufferFlags == o.bufferFlags && firstMip == o.firstMip && numMips == o.numMips && - numSlices == o.numSlices && firstSlice == o.firstSlice; + counterResourceId == o.counterResourceId && type == o.type && viewFormat == o.viewFormat && + structured == o.structured && bufferStructCount == o.bufferStructCount && + elementByteSize == o.elementByteSize && firstElement == o.firstElement && + numElements == o.numElements && bufferFlags == o.bufferFlags && firstMip == o.firstMip && + numMips == o.numMips && numSlices == o.numSlices && firstSlice == o.firstSlice; } bool operator<(const View &o) const { @@ -191,6 +191,8 @@ struct View return viewResourceId < o.viewResourceId; if(!(resourceResourceId == o.resourceResourceId)) return resourceResourceId < o.resourceResourceId; + if(!(counterResourceId == o.counterResourceId)) + return counterResourceId < o.counterResourceId; if(!(type == o.type)) return type < o.type; if(!(viewFormat == o.viewFormat)) @@ -223,6 +225,9 @@ struct View DOCUMENT("The :class:`ResourceId` of the underlying resource the view refers to."); ResourceId resourceResourceId; + DOCUMENT("The :class:`ResourceId` of the resource where the hidden buffer counter is stored."); + ResourceId counterResourceId; + DOCUMENT("The :class:`TextureType` of the view type."); TextureType type; diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index 1b8a3232c..ea06004f1 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -422,6 +422,14 @@ void D3D11DebugManager::RenderForPredicate() m_pImmediateContext->Draw(3, 0); } +ResourceId D3D11DebugManager::AddCounterUAVBuffer(ID3D11UnorderedAccessView *uav) +{ + ResourceId ret = ResourceIDGen::GetNewUniqueID(); + m_CounterBufferToUAV[ret] = uav; + m_UAVToCounterBuffer[uav] = ret; + return ret; +} + void D3D11Replay::GeneralMisc::Init(WrappedID3D11Device *device) { D3D11ShaderCache *shaderCache = device->GetShaderCache(); diff --git a/renderdoc/driver/d3d11/d3d11_debug.h b/renderdoc/driver/d3d11/d3d11_debug.h index 4a59af395..171030603 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.h +++ b/renderdoc/driver/d3d11/d3d11_debug.h @@ -104,6 +104,27 @@ public: void RenderForPredicate(); + ResourceId AddCounterUAVBuffer(ID3D11UnorderedAccessView *uav); + ResourceId GetCounterBufferID(ID3D11UnorderedAccessView *uav) + { + auto it = m_UAVToCounterBuffer.find(uav); + if(it != m_UAVToCounterBuffer.end()) + return it->second; + return ResourceId(); + } + ID3D11UnorderedAccessView *GetCounterBufferUAV(ResourceId id) + { + auto it = m_CounterBufferToUAV.find(id); + if(it != m_CounterBufferToUAV.end()) + return it->second; + return NULL; + } + void GetCounterBuffers(std::vector &ret) + { + for(auto pair : m_CounterBufferToUAV) + ret.push_back(pair.first); + } + uint32_t GetStructCount(ID3D11UnorderedAccessView *uav); void GetBufferData(ID3D11Buffer *buff, uint64_t offset, uint64_t length, bytebuf &retData); @@ -158,6 +179,9 @@ private: std::list m_ShaderItemCache; + std::map m_CounterBufferToUAV; + std::map m_UAVToCounterBuffer; + WrappedID3D11Device *m_pDevice = NULL; WrappedID3D11DeviceContext *m_pImmediateContext = NULL; diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index 74b90a33f..fb7b56f05 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -1243,6 +1243,32 @@ ReplayStatus WrappedID3D11Device::ReadLogInitialisation(RDCFile *rdc, bool store SetupDrawcallPointers(m_Drawcalls, GetFrameRecord().drawcallList); } + // propagate any UAV names onto counter buffers + { + std::vector counterBuffers; + GetDebugManager()->GetCounterBuffers(counterBuffers); + + for(ResourceId buffId : counterBuffers) + { + ID3D11UnorderedAccessView *uav = GetDebugManager()->GetCounterBufferUAV(buffId); + ResourceId uavId = GetResourceManager()->GetOriginalID(GetIDForResource(uav)); + + ResourceDescription &uavDesc = GetReplay()->GetResourceDesc(uavId); + ResourceDescription &bufDesc = GetReplay()->GetResourceDesc(buffId); + + if(uavDesc.autogeneratedName) + { + uint64_t num; + memcpy(&num, &uavId, sizeof(uint64_t)); + bufDesc.SetCustomName("UAV " + ToStr(num) + " counter"); + } + else + { + bufDesc.SetCustomName(uavDesc.name + " counter"); + } + } + } + #if ENABLED(RDOC_DEVEL) for(auto it = chunkInfos.begin(); it != chunkInfos.end(); ++it) { diff --git a/renderdoc/driver/d3d11/d3d11_device3_wrap.cpp b/renderdoc/driver/d3d11/d3d11_device3_wrap.cpp index a829087e2..10de7e18e 100644 --- a/renderdoc/driver/d3d11/d3d11_device3_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_device3_wrap.cpp @@ -24,6 +24,7 @@ #include "d3d11_device.h" #include "d3d11_context.h" +#include "d3d11_debug.h" #include "d3d11_resources.h" /////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -650,6 +651,19 @@ bool WrappedID3D11Device::Serialise_CreateUnorderedAccessView1( AddResource(pView, ResourceType::View, "Unordered Access View"); DerivedResource(pResource, pView); + + { + D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {}; + ret->GetDesc(&desc); + + if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER && + (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))) + { + ResourceId counterBuffer = GetDebugManager()->AddCounterUAVBuffer(ret); + AddResource(counterBuffer, ResourceType::Buffer, "UAV Counter"); + DerivedResource(ret, counterBuffer); + } + } } return true; diff --git a/renderdoc/driver/d3d11/d3d11_device_wrap.cpp b/renderdoc/driver/d3d11/d3d11_device_wrap.cpp index 112fe3c74..5575aa079 100644 --- a/renderdoc/driver/d3d11/d3d11_device_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_device_wrap.cpp @@ -969,6 +969,19 @@ bool WrappedID3D11Device::Serialise_CreateUnorderedAccessView( AddResource(pView, ResourceType::View, "Unordered Access View"); DerivedResource(pResource, pView); + + { + D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {}; + ret->GetDesc(&desc); + + if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER && + (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))) + { + ResourceId counterBuffer = GetDebugManager()->AddCounterUAVBuffer(ret); + AddResource(counterBuffer, ResourceType::Buffer, "UAV Counter"); + DerivedResource(ret, counterBuffer); + } + } } return true; diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 66caf69b2..ce634effd 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -613,6 +613,8 @@ std::vector D3D11Replay::GetBuffers() ret.push_back(it->first); } + GetDebugManager()->GetCounterBuffers(ret); + return ret; } @@ -621,6 +623,16 @@ BufferDescription D3D11Replay::GetBuffer(ResourceId id) BufferDescription ret = {}; ret.resourceId = ResourceId(); + if(GetDebugManager()->GetCounterBufferUAV(id)) + { + // no original ID for this one + ret.resourceId = id; + ret.length = 4; + ret.gpuAddress = 0; + ret.creationFlags = BufferCategory::ReadWrite; + return ret; + } + auto it = WrappedID3D11Buffer::m_BufferList.find(id); if(it == WrappedID3D11Buffer::m_BufferList.end()) @@ -952,10 +964,14 @@ void D3D11Replay::SavePipelineState(uint32_t eventId) view.elementByteSize = desc.Format == DXGI_FORMAT_UNKNOWN ? 1 : GetByteSize(1, 1, 1, desc.Format, 0); + view.counterResourceId = ResourceId(); + if(desc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER && (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))) { view.bufferStructCount = GetDebugManager()->GetStructCount(rs->CSUAVs[s]); + + view.counterResourceId = GetDebugManager()->GetCounterBufferID(rs->CSUAVs[s]); } view.resourceResourceId = rm->GetOriginalID(GetIDForResource(res)); @@ -1250,6 +1266,8 @@ void D3D11Replay::SavePipelineState(uint32_t eventId) (desc.Buffer.Flags & (D3D11_BUFFER_UAV_FLAG_APPEND | D3D11_BUFFER_UAV_FLAG_COUNTER))) { view.bufferStructCount = GetDebugManager()->GetStructCount(rs->OM.UAVs[s]); + + view.counterResourceId = GetDebugManager()->GetCounterBufferID(rs->OM.UAVs[s]); } view.resourceResourceId = rm->GetOriginalID(GetIDForResource(res)); @@ -1585,6 +1603,9 @@ std::vector D3D11Replay::GetPassEvents(uint32_t eventId) ResourceId D3D11Replay::GetLiveID(ResourceId id) { + ID3D11UnorderedAccessView *counterUAV = GetDebugManager()->GetCounterBufferUAV(id); + if(counterUAV) + return id; if(!m_pDevice->GetResourceManager()->HasLiveResource(id)) return ResourceId(); return m_pDevice->GetResourceManager()->GetLiveID(id); @@ -1911,6 +1932,20 @@ bool D3D11Replay::GetHistogram(ResourceId texid, const Subresource &sub, CompTyp void D3D11Replay::GetBufferData(ResourceId buff, uint64_t offset, uint64_t length, bytebuf &retData) { + ID3D11UnorderedAccessView *counterUAV = GetDebugManager()->GetCounterBufferUAV(buff); + if(counterUAV) + { + uint32_t count = GetDebugManager()->GetStructCount(counterUAV); + + // copy the uint first + retData.resize(4U); + memcpy(retData.data(), &count, retData.size()); + + // remove offset bytes, up to 4 + retData.erase(0, RDCMIN(4ULL, offset)); + return; + } + auto it = WrappedID3D11Buffer::m_BufferList.find(buff); if(it == WrappedID3D11Buffer::m_BufferList.end()) diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index e87015acc..6bdf0f951 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -1044,6 +1044,7 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::View &el) { SERIALISE_MEMBER(viewResourceId); SERIALISE_MEMBER(resourceResourceId); + SERIALISE_MEMBER(counterResourceId); SERIALISE_MEMBER(type); SERIALISE_MEMBER(viewFormat); @@ -1059,7 +1060,7 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::View &el) SERIALISE_MEMBER(firstSlice); SERIALISE_MEMBER(numSlices); - SIZE_CHECK(64); + SIZE_CHECK(72); } template @@ -1193,7 +1194,7 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::OutputMerger &el) SERIALISE_MEMBER(depthReadOnly); SERIALISE_MEMBER(stencilReadOnly); - SIZE_CHECK(272); + SIZE_CHECK(280); } template @@ -1225,7 +1226,7 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::State &el) SERIALISE_MEMBER(predication); - SIZE_CHECK(2072); + SIZE_CHECK(2080); } #pragma endregion D3D11 pipeline state