diff --git a/renderdoc/api/replay/data_types.h b/renderdoc/api/replay/data_types.h index 7c42ea5bf..35bd051e1 100644 --- a/renderdoc/api/replay/data_types.h +++ b/renderdoc/api/replay/data_types.h @@ -229,6 +229,48 @@ struct FetchFrameLayoutBindStats uint32_t nulls; }; +struct FetchFrameShaderStats +{ + uint32_t calls; + uint32_t sets; + uint32_t nulls; + uint32_t redundants; +}; + +struct FetchFrameBlendStats +{ + uint32_t calls; + uint32_t sets; + uint32_t nulls; + uint32_t redundants; +}; + +struct FetchFrameDepthStencilStats +{ + uint32_t calls; + uint32_t sets; + uint32_t nulls; + uint32_t redundants; +}; + +struct FetchFrameRasterizationStats +{ + uint32_t calls; + uint32_t sets; + uint32_t nulls; + uint32_t redundants; + rdctype::array viewports; + rdctype::array rects; +}; + +struct FetchFrameOutputStats +{ + uint32_t calls; + uint32_t sets; + uint32_t nulls; + rdctype::array bindslots; +}; + struct FetchFrameStatistics { uint32_t recorded; @@ -241,6 +283,11 @@ struct FetchFrameStatistics FetchFrameIndexBindStats indices; FetchFrameVertexBindStats vertices; FetchFrameLayoutBindStats layouts; + FetchFrameShaderStats shaders[eShaderStage_Count]; + FetchFrameBlendStats blends; + FetchFrameDepthStencilStats depths; + FetchFrameRasterizationStats rasters; + FetchFrameOutputStats outputs; }; struct FetchFrameInfo diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 8b8b01164..9c87abb1f 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -1150,6 +1150,63 @@ void Serialiser::Serialise(const char *name, FetchFrameLayoutBindStats &el) SIZE_CHECK(FetchFrameLayoutBindStats, 12); } +template<> +void Serialiser::Serialise(const char *name, FetchFrameShaderStats &el) +{ + Serialise("", el.calls); + Serialise("", el.sets); + Serialise("", el.nulls); + Serialise("", el.redundants); + + SIZE_CHECK(FetchFrameShaderStats, 16); +} + +template<> +void Serialiser::Serialise(const char *name, FetchFrameBlendStats &el) +{ + Serialise("", el.calls); + Serialise("", el.sets); + Serialise("", el.nulls); + Serialise("", el.redundants); + + SIZE_CHECK(FetchFrameBlendStats, 16); +} + +template<> +void Serialiser::Serialise(const char *name, FetchFrameDepthStencilStats &el) +{ + Serialise("", el.calls); + Serialise("", el.sets); + Serialise("", el.nulls); + Serialise("", el.redundants); + + SIZE_CHECK(FetchFrameDepthStencilStats, 16); +} + +template<> +void Serialiser::Serialise(const char *name, FetchFrameRasterizationStats &el) +{ + Serialise("", el.calls); + Serialise("", el.sets); + Serialise("", el.nulls); + Serialise("", el.redundants); + Serialise("", el.viewports); + Serialise("", el.rects); + + SIZE_CHECK(FetchFrameRasterizationStats, 48); +} + +template<> +void Serialiser::Serialise(const char *name, FetchFrameOutputStats &el) +{ + Serialise("", el.calls); + Serialise("", el.sets); + Serialise("", el.nulls); + Serialise("", el.bindslots); + + SIZE_CHECK(FetchFrameOutputStats, 32); +} + template<> void Serialiser::Serialise(const char *name, FetchFrameStatistics &el) { @@ -1170,8 +1227,14 @@ void Serialiser::Serialise(const char *name, FetchFrameStatistics &el) Serialise("", el.indices); Serialise("", el.vertices); Serialise("", el.layouts); + FetchFrameShaderStats* shaders = el.shaders; + SerialiseComplexArray("", shaders); + Serialise("", el.blends); + Serialise("", el.depths); + Serialise("", el.rasters); + Serialise("", el.outputs); - SIZE_CHECK(FetchFrameStatistics, 928); + SIZE_CHECK(FetchFrameStatistics, 1136); } template<> @@ -1188,7 +1251,7 @@ void Serialiser::Serialise(const char *name, FetchFrameInfo &el) Serialise("", el.stats); Serialise("", el.debugMessages); - SIZE_CHECK(FetchFrameInfo, 1000); + SIZE_CHECK(FetchFrameInfo, 1208); } template<> @@ -1197,7 +1260,7 @@ void Serialiser::Serialise(const char *name, FetchFrameRecord &el) Serialise("", el.frameInfo); Serialise("", el.drawcallList); - SIZE_CHECK(FetchFrameRecord, 1016); + SIZE_CHECK(FetchFrameRecord, 1224); } template<> diff --git a/renderdoc/driver/d3d11/d3d11_context.cpp b/renderdoc/driver/d3d11/d3d11_context.cpp index d68e86897..4868aacd0 100644 --- a/renderdoc/driver/d3d11/d3d11_context.cpp +++ b/renderdoc/driver/d3d11/d3d11_context.cpp @@ -1390,8 +1390,7 @@ HRESULT STDMETHODCALLTYPE WrappedID3D11DeviceContext::QueryInterface( REFIID rii void WrappedID3D11DeviceContext::RecordIndexBindStats(ID3D11Buffer* Buffer) { - FetchFrameRecord& record = m_pDevice->GetFrameRecord(); - FetchFrameStatistics& stats = record.frameInfo.stats; + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); FetchFrameIndexBindStats& indices = stats.indices; indices.calls += 1; indices.sets += (Buffer != NULL); @@ -1400,8 +1399,7 @@ void WrappedID3D11DeviceContext::RecordIndexBindStats(ID3D11Buffer* Buffer) void WrappedID3D11DeviceContext::RecordVertexBindStats(UINT NumBuffers, ID3D11Buffer* Buffers[]) { - FetchFrameRecord& record = m_pDevice->GetFrameRecord(); - FetchFrameStatistics& stats = record.frameInfo.stats; + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); FetchFrameVertexBindStats& vertices = stats.vertices; vertices.calls += 1; RDCASSERT(NumBuffers < vertices.bindslots.size()); @@ -1418,8 +1416,7 @@ void WrappedID3D11DeviceContext::RecordVertexBindStats(UINT NumBuffers, ID3D11Bu void WrappedID3D11DeviceContext::RecordLayoutBindStats(ID3D11InputLayout* Layout) { - FetchFrameRecord& record = m_pDevice->GetFrameRecord(); - FetchFrameStatistics& stats = record.frameInfo.stats; + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); FetchFrameLayoutBindStats& layouts = stats.layouts; layouts.calls += 1; layouts.sets += (Layout != NULL); @@ -1428,8 +1425,7 @@ void WrappedID3D11DeviceContext::RecordLayoutBindStats(ID3D11InputLayout* Layout void WrappedID3D11DeviceContext::RecordConstantStats(ShaderStageType stage, UINT NumBuffers, ID3D11Buffer* Buffers[]) { - FetchFrameRecord& record = m_pDevice->GetFrameRecord(); - FetchFrameStatistics& stats = record.frameInfo.stats; + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); RDCASSERT(stage < ARRAY_COUNT( stats.constants)); FetchFrameConstantBindStats& constants = stats.constants[stage]; constants.calls += 1; @@ -1458,8 +1454,7 @@ void WrappedID3D11DeviceContext::RecordConstantStats(ShaderStageType stage, UINT void WrappedID3D11DeviceContext::RecordResourceStats(ShaderStageType stage, UINT NumResources, ID3D11ShaderResourceView* Resources[]) { - FetchFrameRecord& record = m_pDevice->GetFrameRecord(); - FetchFrameStatistics& stats = record.frameInfo.stats; + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); RDCASSERT(stage < ARRAY_COUNT(stats.resources)); FetchFrameResourceBindStats& resources = stats.resources[stage]; resources.calls += 1; @@ -1506,8 +1501,7 @@ void WrappedID3D11DeviceContext::RecordResourceStats(ShaderStageType stage, UINT void WrappedID3D11DeviceContext::RecordSamplerStats(ShaderStageType stage, UINT NumSamplers, ID3D11SamplerState* Samplers[]) { - FetchFrameRecord& record = m_pDevice->GetFrameRecord(); - FetchFrameStatistics& stats = record.frameInfo.stats; + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); RDCASSERT(stage < ARRAY_COUNT(stats.samplers)); FetchFrameSamplerBindStats& samplers = stats.samplers[stage]; samplers.calls += 1; @@ -1525,8 +1519,7 @@ void WrappedID3D11DeviceContext::RecordSamplerStats(ShaderStageType stage, UINT void WrappedID3D11DeviceContext::RecordUpdateStats(ID3D11Resource* res, uint32_t Size, bool Server) { - FetchFrameRecord& record = m_pDevice->GetFrameRecord(); - FetchFrameStatistics& stats = record.frameInfo.stats; + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); FetchFrameUpdateStats& updates = stats.updates; if (res == NULL) @@ -1560,8 +1553,7 @@ void WrappedID3D11DeviceContext::RecordUpdateStats(ID3D11Resource* res, uint32_t void WrappedID3D11DeviceContext::RecordDrawStats(bool instanced, bool indirect, UINT InstanceCount) { - FetchFrameRecord& record = m_pDevice->GetFrameRecord(); - FetchFrameStatistics& stats = record.frameInfo.stats; + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); FetchFrameDrawStats& draws = stats.draws; draws.calls += 1; @@ -1578,12 +1570,129 @@ void WrappedID3D11DeviceContext::RecordDrawStats(bool instanced, bool indirect, void WrappedID3D11DeviceContext::RecordDispatchStats(bool indirect) { - FetchFrameRecord& record = m_pDevice->GetFrameRecord(); - FetchFrameStatistics& stats = record.frameInfo.stats; + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); FetchFrameDispatchStats& dispatches = stats.dispatches; dispatches.calls += 1; dispatches.indirect += (uint32_t)indirect; } +void WrappedID3D11DeviceContext::RecordShaderStats(ShaderStageType stage, ID3D11DeviceChild* Current, ID3D11DeviceChild* Shader) +{ + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); + RDCASSERT(stage <= ARRAY_COUNT(stats.shaders)); + FetchFrameShaderStats& shaders = stats.shaders[stage]; + + shaders.calls += 1; + shaders.sets += (Shader != NULL); + shaders.nulls += (Shader == NULL); + shaders.redundants += (Current == Shader); +} + +void WrappedID3D11DeviceContext::RecordBlendStats(ID3D11BlendState* Blend, FLOAT BlendFactor[4], UINT SampleMask) +{ + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); + FetchFrameBlendStats& blends = stats.blends; + + blends.calls += 1; + blends.sets += (Blend != NULL); + blends.nulls += (Blend == NULL); + const D3D11RenderState::outmerger* Current = &m_CurrentPipelineState->OM; + bool same = (Current->BlendState == Blend) && (memcmp(Current->BlendFactor, BlendFactor, sizeof(BlendFactor)) == 0) && (Current->SampleMask == SampleMask); + blends.redundants += (uint32_t)same; +} + +void WrappedID3D11DeviceContext::RecordDepthStencilStats(ID3D11DepthStencilState* DepthStencil, UINT StencilRef) +{ + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); + FetchFrameDepthStencilStats& depths = stats.depths; + + depths.calls += 1; + depths.sets += (DepthStencil != NULL); + depths.nulls += (DepthStencil == NULL); + const D3D11RenderState::outmerger* Current = &m_CurrentPipelineState->OM; + bool same = (Current->DepthStencilState == DepthStencil) && (Current->StencRef == StencilRef); + depths.redundants += (uint32_t)same; +} + +void WrappedID3D11DeviceContext::RecordRasterizationStats(ID3D11RasterizerState* Rasterizer) +{ + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); + FetchFrameRasterizationStats& rasters = stats.rasters; + + rasters.calls += 1; + rasters.sets += (Rasterizer != NULL); + rasters.nulls += (Rasterizer == NULL); + const D3D11RenderState::rasterizer* Current = &m_CurrentPipelineState->RS; + bool same = (Current->State == Rasterizer); + rasters.redundants += (uint32_t)same; +} + +void WrappedID3D11DeviceContext::RecordViewportStats(UINT NumViewports, const D3D11_VIEWPORT *viewports) +{ + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); + FetchFrameRasterizationStats& rasters = stats.rasters; + + rasters.calls += 1; + rasters.sets += 1; + // #mivance fairly sure setting 0 viewports/null viewports is illegal? + const D3D11RenderState::rasterizer* Current = &m_CurrentPipelineState->RS; + bool same = (Current->NumViews == NumViewports); + for (UINT index = 0; index < NumViewports; index++) + { + same = (same && (Current->Viewports[index] == viewports[index])); + } + rasters.redundants += (uint32_t)same; + RDCASSERT(NumViewports < rasters.viewports.size()); + rasters.viewports[NumViewports] += 1; +} + +void WrappedID3D11DeviceContext::RecordScissorStats(UINT NumRects, const D3D11_RECT *rects) +{ + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); + FetchFrameRasterizationStats& rasters = stats.rasters; + + rasters.calls += 1; + rasters.sets += 1; + // #mivance see above + const D3D11RenderState::rasterizer* Current = &m_CurrentPipelineState->RS; + bool same = (Current->NumScissors == NumRects); + for (UINT index = 0; index < NumRects; index++) + { + same = (same && (Current->Scissors[index] == rects[index])); + } + rasters.redundants += (uint32_t)same; + RDCASSERT(NumRects < rasters.rects.size()); + rasters.rects[NumRects] += 1; +} + +void WrappedID3D11DeviceContext::RecordOutputMergerStats(UINT NumRTVs, ID3D11RenderTargetView* RTVs[], ID3D11DepthStencilView* DSV, UINT UAVStartSlot, UINT NumUAVs, ID3D11UnorderedAccessView* UAVs[]) +{ + FetchFrameStatistics& stats = m_pDevice->GetFrameStats(); + FetchFrameOutputStats& outputs = stats.outputs; + + outputs.calls += 1; + // #mivance is an elaborate redundancy here even useful? + //const D3D11RenderState::outmerger* Current = &m_CurrentPipelineState->OM; + + for (UINT index = 0; index < NumRTVs; index++ ) + { + outputs.sets += (RTVs[index] != NULL); + outputs.nulls += (RTVs[index] == NULL); + } + + outputs.sets += (DSV != NULL); + outputs.nulls += (DSV == NULL); + + for (UINT index = 0; index < NumUAVs; index++ ) + { + outputs.sets += (UAVs[index] != NULL); + outputs.nulls += (UAVs[index] == NULL); + } + + UINT NumSlots = NumRTVs + NumUAVs; + RDCASSERT(NumSlots < outputs.bindslots.size()); + outputs.bindslots[NumSlots] += 1; +} + #pragma endregion diff --git a/renderdoc/driver/d3d11/d3d11_context.h b/renderdoc/driver/d3d11/d3d11_context.h index f419d41d2..720e2423d 100644 --- a/renderdoc/driver/d3d11/d3d11_context.h +++ b/renderdoc/driver/d3d11/d3d11_context.h @@ -253,6 +253,13 @@ private: void RecordUpdateStats(ID3D11Resource* res, uint32_t Size, bool Server); void RecordDrawStats(bool instanced, bool indirect, UINT InstanceCount); void RecordDispatchStats(bool indirect); + void RecordShaderStats(ShaderStageType stage, ID3D11DeviceChild* Current, ID3D11DeviceChild* Shader); + void RecordBlendStats(ID3D11BlendState* Blend, FLOAT BlendFactor[4], UINT SampleMask); + void RecordDepthStencilStats(ID3D11DepthStencilState* DepthStencil, UINT StencilRef); + void RecordRasterizationStats(ID3D11RasterizerState* Rasterizer); + void RecordViewportStats(UINT NumViewports, const D3D11_VIEWPORT *viewports); + void RecordScissorStats(UINT NumRects, const D3D11_RECT *rects); + void RecordOutputMergerStats(UINT NumRTVs, ID3D11RenderTargetView* RTVs[], ID3D11DepthStencilView* DSV, UINT UAVStartSlot, UINT NumUAVs, ID3D11UnorderedAccessView* UAVs[]); //////////////////////////////////////////////////////////////// // implement InterceptorSystem privately, since it is not thread safe (like all other context functions) diff --git a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp index ec50000bd..3699307e9 100644 --- a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp @@ -834,6 +834,10 @@ bool WrappedID3D11DeviceContext::Serialise_VSSetShader(ID3D11VertexShader *pShad ID3D11DeviceChild *pSH = NULL; if(m_pDevice->GetResourceManager()->HasLiveResource(Shader)) pSH = (ID3D11DeviceChild *)m_pDevice->GetResourceManager()->GetLiveResource(Shader); + + if(m_State == READING) + RecordShaderStats(eShaderStage_Vertex, m_CurrentPipelineState->VS.Shader, pSH); + m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->VS.Shader, pSH); m_pRealContext->VSSetShader(UNWRAP(WrappedID3D11Shader, pSH), Instances, NumClassInstances); VerifyState(); @@ -1205,6 +1209,10 @@ bool WrappedID3D11DeviceContext::Serialise_HSSetShader(ID3D11HullShader *pShader ID3D11DeviceChild *pSH = NULL; if(m_pDevice->GetResourceManager()->HasLiveResource(Shader)) pSH = (ID3D11DeviceChild *)m_pDevice->GetResourceManager()->GetLiveResource(Shader); + + if(m_State == READING) + RecordShaderStats(eShaderStage_Hull, m_CurrentPipelineState->HS.Shader, pSH); + m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->HS.Shader, pSH); m_pRealContext->HSSetShader(UNWRAP(WrappedID3D11Shader, pSH), Instances, NumClassInstances); VerifyState(); @@ -1575,6 +1583,10 @@ bool WrappedID3D11DeviceContext::Serialise_DSSetShader(ID3D11DomainShader *pShad ID3D11DeviceChild *pSH = NULL; if(m_pDevice->GetResourceManager()->HasLiveResource(Shader)) pSH = (ID3D11DeviceChild *)m_pDevice->GetResourceManager()->GetLiveResource(Shader); + + if(m_State == READING) + RecordShaderStats(eShaderStage_Domain, m_CurrentPipelineState->DS.Shader, pSH); + m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->DS.Shader, pSH); m_pRealContext->DSSetShader(UNWRAP(WrappedID3D11Shader, pSH), Instances, NumClassInstances); VerifyState(); @@ -1945,6 +1957,10 @@ bool WrappedID3D11DeviceContext::Serialise_GSSetShader(ID3D11GeometryShader *pSh ID3D11DeviceChild *pSH = NULL; if(m_pDevice->GetResourceManager()->HasLiveResource(Shader)) pSH = (ID3D11DeviceChild *)m_pDevice->GetResourceManager()->GetLiveResource(Shader); + + if(m_State == READING) + RecordShaderStats(eShaderStage_Geometry, m_CurrentPipelineState->GS.Shader, pSH); + m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->GS.Shader, pSH); m_pRealContext->GSSetShader(UNWRAP(WrappedID3D11Shader, pSH), Instances, NumClassInstances); VerifyState(); @@ -2268,6 +2284,9 @@ bool WrappedID3D11DeviceContext::Serialise_RSSetViewports(UINT NumViewports_, co if(m_State <= EXECUTING) { + if(m_State == READING) + RecordViewportStats(NumViewports, views); + m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.Viewports, views, 0, NumViewports); m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.NumViews, NumViewports); m_pRealContext->RSSetViewports(NumViewports, views); @@ -2305,6 +2324,9 @@ bool WrappedID3D11DeviceContext::Serialise_RSSetScissorRects(UINT NumRects_, con if(m_State <= EXECUTING) { + if(m_State == READING) + RecordScissorStats(NumRects, Rects); + m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.Scissors, Rects, 0, NumRects); m_CurrentPipelineState->Change(m_CurrentPipelineState->RS.NumScissors, NumRects); RSSetScissorRects(NumRects, Rects); @@ -2347,6 +2369,9 @@ bool WrappedID3D11DeviceContext::Serialise_RSSetState(ID3D11RasterizerState *pRa if(m_pDevice->GetResourceManager()->HasLiveResource(id)) live = m_pDevice->GetResourceManager()->GetLiveResource(id); + if(m_State == READING) + RecordRasterizationStats((ID3D11RasterizerState*)live); + if(WrappedID3D11RasterizerState1::IsAlloc(live)) { ID3D11RasterizerState1 *state = (ID3D11RasterizerState1 *)live; @@ -2713,6 +2738,10 @@ bool WrappedID3D11DeviceContext::Serialise_PSSetShader(ID3D11PixelShader *pShade ID3D11DeviceChild *pSH = NULL; if(m_pDevice->GetResourceManager()->HasLiveResource(Shader)) pSH = (ID3D11DeviceChild *)m_pDevice->GetResourceManager()->GetLiveResource(Shader); + + if(m_State == READING) + RecordShaderStats(eShaderStage_Pixel, m_CurrentPipelineState->PS.Shader, pSH); + m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->PS.Shader, pSH); m_pRealContext->PSSetShader(UNWRAP(WrappedID3D11Shader, pSH), Instances, NumClassInstances); VerifyState(); @@ -2941,6 +2970,9 @@ bool WrappedID3D11DeviceContext::Serialise_OMSetRenderTargets(UINT NumViews_, ID for(UINT i=0; i < NumViews; i++) RenderTargetViews[i] = UNWRAP(WrappedID3D11RenderTargetView, RenderTargetViews[i]); + if(m_State == READING) + RecordOutputMergerStats(NumViews, RenderTargetViews, pDepthStencilView, 0, 0, NULL); + m_pRealContext->OMSetRenderTargets(NumViews, RenderTargetViews, UNWRAP(WrappedID3D11DepthStencilView, pDepthStencilView)); VerifyState(); @@ -3124,6 +3156,9 @@ bool WrappedID3D11DeviceContext::Serialise_OMSetRenderTargetsAndUnorderedAccessV else pDepthStencilView = NULL; + if(m_State == READING) + RecordOutputMergerStats(NumRTVs, RenderTargetViews, pDepthStencilView, UAVStartSlot, NumUAVs, UnorderedAccessViews); + m_pRealContext->OMSetRenderTargetsAndUnorderedAccessViews(NumRTVs, RenderTargetViews, pDepthStencilView, UAVStartSlot, NumUAVs, UnorderedAccessViews, UAVInitialCounts); @@ -3299,6 +3334,9 @@ bool WrappedID3D11DeviceContext::Serialise_OMSetBlendState(ID3D11BlendState *pBl if(m_pDevice->GetResourceManager()->HasLiveResource(State)) live = m_pDevice->GetResourceManager()->GetLiveResource(State); + if(m_State == READING) + RecordBlendStats((ID3D11BlendState*)live, BlendFactor, SampleMask); + if(WrappedID3D11BlendState1::IsAlloc(live)) { ID3D11BlendState1 *state = (ID3D11BlendState1 *)live; @@ -3361,6 +3399,10 @@ bool WrappedID3D11DeviceContext::Serialise_OMSetDepthStencilState(ID3D11DepthSte pDepthStencilState = NULL; if(m_pDevice->GetResourceManager()->HasLiveResource(State)) pDepthStencilState = (ID3D11DepthStencilState *)m_pDevice->GetResourceManager()->GetLiveResource(State); + + if(m_State == READING) + RecordDepthStencilStats(pDepthStencilState, StencilRef); + m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->OM.DepthStencilState, pDepthStencilState); m_CurrentPipelineState->Change(m_CurrentPipelineState->OM.StencRef, StencilRef&0xff); m_pRealContext->OMSetDepthStencilState(UNWRAP(WrappedID3D11DepthStencilState, pDepthStencilState), StencilRef); @@ -4208,6 +4250,9 @@ bool WrappedID3D11DeviceContext::Serialise_CSSetShaderResources(UINT StartSlot_, for(UINT i=0; i < NumViews; i++) Views[i] = UNWRAP(WrappedID3D11ShaderResourceView, Views[i]); + if(m_State == READING) + RecordResourceStats(eShaderStage_Compute, NumViews, Views); + m_pRealContext->CSSetShaderResources(StartSlot, NumViews, Views); VerifyState(); } @@ -4279,6 +4324,10 @@ bool WrappedID3D11DeviceContext::Serialise_CSSetUnorderedAccessViews(UINT StartS for(UINT i=0; i < NumUAVs; i++) UAVs[i] = UNWRAP(WrappedID3D11UnorderedAccessView, UAVs[i]); + // #mivance this isn't strictly correct... + if(m_State == READING) + RecordOutputMergerStats(0, NULL, NULL, StartSlot, NumUAVs, UAVs); + m_pRealContext->CSSetUnorderedAccessViews(StartSlot, NumUAVs, UAVs, UAVInitialCounts); VerifyState(); } @@ -4413,6 +4462,10 @@ bool WrappedID3D11DeviceContext::Serialise_CSSetShader(ID3D11ComputeShader *pSha ID3D11DeviceChild *pSH = NULL; if(m_pDevice->GetResourceManager()->HasLiveResource(Shader)) pSH = (ID3D11DeviceChild *)m_pDevice->GetResourceManager()->GetLiveResource(Shader); + + if(m_State == READING) + RecordShaderStats(eShaderStage_Compute, m_CurrentPipelineState->CS.Shader, pSH); + m_CurrentPipelineState->ChangeRefRead(m_CurrentPipelineState->CS.Shader, pSH); m_pRealContext->CSSetShader(UNWRAP(WrappedID3D11Shader, pSH), Instances, NumClassInstances); VerifyState(); diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index 93a34cb73..0f0f51b95 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -1028,6 +1028,11 @@ void WrappedID3D11Device::Serialise_CaptureScope(uint64_t offset) create_array(stats.vertices.bindslots, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT + 1); + create_array(stats.rasters.viewports, D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX + 1); + create_array(stats.rasters.rects, D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX + 1); + + create_array(stats.outputs.bindslots, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT + D3D11_1_UAV_SLOT_COUNT + 1); + GetResourceManager()->CreateInitialContents(); } } diff --git a/renderdoc/driver/d3d11/d3d11_device.h b/renderdoc/driver/d3d11/d3d11_device.h index 0216c9e77..1469e584c 100644 --- a/renderdoc/driver/d3d11/d3d11_device.h +++ b/renderdoc/driver/d3d11/d3d11_device.h @@ -295,6 +295,7 @@ public: ResourceId GetResourceID() { return m_ResourceID; } FetchFrameRecord &GetFrameRecord() { return m_FrameRecord; } + FetchFrameStatistics &GetFrameStats() { return m_FrameRecord.frameInfo.stats; } const FetchDrawcall *GetDrawcall(uint32_t eventID); diff --git a/renderdocui/Interop/FetchInfo.cs b/renderdocui/Interop/FetchInfo.cs index df5ea6bda..63a9f2784 100644 --- a/renderdocui/Interop/FetchInfo.cs +++ b/renderdocui/Interop/FetchInfo.cs @@ -365,6 +365,56 @@ namespace renderdoc public UInt32 nulls; }; + [StructLayout(LayoutKind.Sequential)] + public class FetchFrameShaderStats + { + public UInt32 calls; + public UInt32 sets; + public UInt32 nulls; + public UInt32 redundants; + }; + + [StructLayout(LayoutKind.Sequential)] + public class FetchFrameBlendStats + { + public UInt32 calls; + public UInt32 sets; + public UInt32 nulls; + public UInt32 redundants; + }; + + [StructLayout(LayoutKind.Sequential)] + public class FetchFrameDepthStencilStats + { + public UInt32 calls; + public UInt32 sets; + public UInt32 nulls; + public UInt32 redundants; + }; + + [StructLayout(LayoutKind.Sequential)] + public class FetchFrameRasterizationStats + { + public UInt32 calls; + public UInt32 sets; + public UInt32 nulls; + public UInt32 redundants; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public UInt32[] viewports; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public UInt32[] rects; + } + + [StructLayout(LayoutKind.Sequential)] + public class FetchFrameOutputStats + { + public UInt32 calls; + public UInt32 sets; + public UInt32 nulls; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public UInt32[] bindslots; + }; + [StructLayout(LayoutKind.Sequential)] public class FetchFrameStatistics { @@ -387,6 +437,16 @@ namespace renderdoc public FetchFrameVertexBindStats vertices; [CustomMarshalAs(CustomUnmanagedType.CustomClass)] public FetchFrameLayoutBindStats layouts; + [CustomMarshalAs(CustomUnmanagedType.FixedArray, FixedLength = (int)ShaderStageType.Count)] + public FetchFrameShaderStats[] shaders; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public FetchFrameBlendStats blends; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public FetchFrameDepthStencilStats depths; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public FetchFrameRasterizationStats rasters; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public FetchFrameOutputStats outputs; }; [StructLayout(LayoutKind.Sequential)] diff --git a/renderdocui/Windows/StatisticsViewer.cs b/renderdocui/Windows/StatisticsViewer.cs index c68f2ce02..8f95d4eb7 100644 --- a/renderdocui/Windows/StatisticsViewer.cs +++ b/renderdocui/Windows/StatisticsViewer.cs @@ -100,7 +100,7 @@ namespace renderdocui.Windows if (totalUpdates.instanced > 0) { - statisticsLog.AppendText("\nHistogram of instance counts:\n"); + statisticsLog.AppendText("\nInstance counts:\n"); UInt32 maxCount = 0; int maxWithValue = 0; int maximum = totalUpdates.counts.Length; @@ -137,6 +137,31 @@ namespace renderdocui.Windows statisticsLog.AppendText(String.Format("Total calls: {0}, indirect: {1}\n", totalUpdates.calls, totalUpdates.indirect)); } + private string CreateSimpleIntegerHistogram(string legend, UInt32[] array) + { + UInt32 maxCount = 0; + int maxWithValue = 0; + + for (var o = 0; o < array.Length; o++) + { + UInt32 value = array[o]; + if (value > 0) + maxWithValue = o; + maxCount = Math.Max(maxCount, value); + } + + string text = String.Format("\n{0}:\n", legend); + + for (var o = 0; o <= maxWithValue; o++) + { + UInt32 count = array[o]; + int slice = SliceForString(Stars, count, maxCount); + text += String.Format("{0,4}: {1} {2}\n", o, Stars.Substring(0, slice), CountOrEmpty(count)); + } + + return text; + } + private void AppendInputAssemblerStatistics(FetchFrameInfo frameInfo) { FetchFrameIndexBindStats totalIndexStats = new FetchFrameIndexBindStats(); @@ -184,23 +209,32 @@ namespace renderdocui.Windows statisticsLog.AppendText(String.Format("Total layout calls: {0}, non-null layout sets: {1}, null layout sets: {2}\n", totalLayoutStats.calls, totalLayoutStats.sets, totalLayoutStats.nulls)); statisticsLog.AppendText(String.Format("Total vertex calls: {0}, non-null vertex sets: {1}, null vertex sets: {2}\n", totalVertexStats.calls, totalVertexStats.sets, totalVertexStats.nulls)); - statisticsLog.AppendText("\nHistogram of aggregate vertex slot counts per invocation:\n"); - UInt32 maxCount = 0; - int maxWithValue = 0; - for (var s = 1; s < totalVertexStats.bindslots.Length; s++) + statisticsLog.AppendText(CreateSimpleIntegerHistogram("Aggregate vertex slot counts per invocation", totalVertexStats.bindslots)); + } + + private void AppendShaderStatistics(FetchFrameInfo frameInfo) + { + FetchFrameShaderStats[] shaders = frameInfo.stats.shaders; + FetchFrameShaderStats totalShadersPerStage = new FetchFrameShaderStats(); + for (var s = (int)ShaderStageType.First; s < (int)ShaderStageType.Count; s++) { - UInt32 value = totalVertexStats.bindslots[s]; - if (value > 0) - maxWithValue = s; - maxCount = Math.Max(maxCount, value); + totalShadersPerStage.calls += shaders[s].calls; + totalShadersPerStage.sets += shaders[s].sets; + totalShadersPerStage.nulls += shaders[s].nulls; + totalShadersPerStage.redundants += shaders[s].redundants; } - for (var s = 1; s <= maxWithValue; s++) + statisticsLog.AppendText("\n*** Shader Set Statistics ***\n\n"); + + for (var s = (int)ShaderStageType.First; s < (int)ShaderStageType.Count; s++) { - UInt32 count = totalVertexStats.bindslots[s]; - int slice = SliceForString(Stars, count, maxCount); - statisticsLog.AppendText(String.Format("{0,2}: {1} {2}\n", s, Stars.Substring(0, slice), CountOrEmpty(count))); + statisticsLog.AppendText(String.Format("{0} calls: {1}, non-null shader sets: {2}, null shader sets: {3}, redundant shader sets: {4}\n", + m_Core.CurPipelineState.Abbrev((ShaderStageType)s), shaders[s].calls, + shaders[s].sets, shaders[s].nulls, shaders[s].redundants)); } + + statisticsLog.AppendText(String.Format("Total calls: {0}, non-null shader sets: {1}, null shader sets: {2}, reundant shader sets: {3}\n", + totalShadersPerStage.calls, totalShadersPerStage.sets, totalShadersPerStage.nulls, totalShadersPerStage.redundants)); } private void AppendConstantBindStatistics(FetchFrameInfo frameInfo) @@ -276,27 +310,11 @@ namespace renderdocui.Windows statisticsLog.AppendText(String.Format("Total calls: {0}, non-null buffer sets: {1}, null buffer sets: {2}\n", totalConstantsForAllStages.calls, totalConstantsForAllStages.sets, totalConstantsForAllStages.nulls)); - statisticsLog.AppendText("\nHistogram of aggregate slot counts per invocation across all stages:\n"); + statisticsLog.AppendText(CreateSimpleIntegerHistogram("Aggregate slot counts per invocation across all stages", totalConstantsForAllStages.bindslots)); + + statisticsLog.AppendText("\nAggregate constant buffer sizes across all stages:\n"); UInt32 maxCount = 0; int maxWithValue = 0; - for (var s = 1; s < totalConstantsForAllStages.bindslots.Length; s++) - { - UInt32 value = totalConstantsForAllStages.bindslots[s]; - if (value > 0) - maxWithValue = s; - maxCount = Math.Max(maxCount, value); - } - - for (var s = 1; s <= maxWithValue; s++) - { - UInt32 count = totalConstantsForAllStages.bindslots[s]; - int slice = SliceForString(Stars, count, maxCount); - statisticsLog.AppendText(String.Format("{0,2}: {1} {2}\n", s, Stars.Substring(0, slice), CountOrEmpty(count))); - } - - statisticsLog.AppendText("\nHistogram of aggregate constant buffer sizes across all stages:\n"); - maxCount = 0; - maxWithValue = 0; for (var s = 0; s < totalConstantsForAllStages.sizes.Length; s++) { UInt32 value = totalConstantsForAllStages.sizes[s]; @@ -368,23 +386,7 @@ namespace renderdocui.Windows statisticsLog.AppendText(String.Format("Total calls: {0}, non-null sampler sets: {1}, null sampler sets: {2}\n", totalSamplersForAllStages.calls, totalSamplersForAllStages.sets, totalSamplersForAllStages.nulls)); - statisticsLog.AppendText("\nHistogram of aggregate slot counts per invocation across all stages:\n"); - UInt32 maxCount = 0; - int maxWithValue = 0; - for (var s = 1; s < totalSamplersForAllStages.bindslots.Length; s++) - { - UInt32 value = totalSamplersForAllStages.bindslots[s]; - if (value > 0) - maxWithValue = s; - maxCount = Math.Max(maxCount, value); - } - - for (var s = 1; s <= maxWithValue; s++) - { - UInt32 count = totalSamplersForAllStages.bindslots[s]; - int slice = SliceForString(Stars, count, maxCount); - statisticsLog.AppendText(String.Format("{0,2}: {1} {2}\n", s, Stars.Substring(0, slice), CountOrEmpty(count))); - } + statisticsLog.AppendText(CreateSimpleIntegerHistogram("Aggregate slot counts per invocation across all stages", totalSamplersForAllStages.bindslots)); } private void AppendResourceBindStatistics(FetchFrameInfo frameInfo) @@ -458,7 +460,7 @@ namespace renderdocui.Windows UInt32 maxCount = 0; int maxWithCount = 0; - statisticsLog.AppendText("\nHistogram of resource types across all stages:\n"); + statisticsLog.AppendText("\nResource types across all stages:\n"); for (var s = 0; s < totalResourcesForAllStages.types.Length; s++) { UInt32 count = totalResourcesForAllStages.types[s]; @@ -475,24 +477,7 @@ namespace renderdocui.Windows statisticsLog.AppendText(String.Format("{0,16}: {1} {2}\n", type.ToString(), Stars.Substring(0, slice), CountOrEmpty(count))); } - maxCount = 0; - maxWithCount = 0; - - statisticsLog.AppendText("\nHistogram of aggregate slot counts per invocation across all stages:\n"); - for (var s = 1; s < totalResourcesForAllStages.bindslots.Length; s++) - { - UInt32 count = totalResourcesForAllStages.bindslots[s]; - if (count > 0) - maxWithCount = s; - maxCount = Math.Max(maxCount, count); - } - - for (var s = 1; s <= maxWithCount; s++) - { - UInt32 count = totalResourcesForAllStages.bindslots[s]; - int slice = SliceForString(Stars, count, maxCount); - statisticsLog.AppendText(String.Format("{0,3}: {1} {2}\n", s, Stars.Substring(0, slice), CountOrEmpty(count))); - } + statisticsLog.AppendText(CreateSimpleIntegerHistogram("Aggregate slot counts per invocation across all stages", totalResourcesForAllStages.bindslots)); } private void AppendUpdateStatistics(FetchFrameInfo frameInfo) @@ -524,7 +509,7 @@ namespace renderdocui.Windows statisticsLog.AppendText(String.Format("Total calls: {0}, client-updated memory: {1}, server-updated memory: {2}\n", totalUpdates.calls, totalUpdates.clients, totalUpdates.servers)); - statisticsLog.AppendText("\nHistogram of updated resource type:\n"); + statisticsLog.AppendText("\nUpdated resource types:\n"); UInt32 maxCount = 0; int maxWithValue = 0; for (var s = 1; s < totalUpdates.types.Length; s++) @@ -543,7 +528,7 @@ namespace renderdocui.Windows statisticsLog.AppendText(String.Format("{0,16}: {1} {2}\n", type.ToString(), Stars.Substring(0, slice), CountOrEmpty(count))); } - statisticsLog.AppendText("\nHistogram of updated resource size:\n"); + statisticsLog.AppendText("\nUpdated resource sizes:\n"); maxCount = 0; maxWithValue = 0; for (var s = 0; s < totalUpdates.sizes.Length; s++) @@ -562,15 +547,54 @@ namespace renderdocui.Windows } } + private void AppendBlendStatistics(FetchFrameInfo frameInfo) + { + FetchFrameBlendStats blends = frameInfo.stats.blends; + statisticsLog.AppendText("\n*** Blend Statistics ***\n"); + statisticsLog.AppendText(String.Format("Blend calls: {0} non-null sets: {1} null (default) sets: {2} redundant sets: {3}\n", blends.calls, blends.sets, blends.nulls, blends.redundants)); + } + + private void AppendDepthStencilStatistics(FetchFrameInfo frameInfo) + { + FetchFrameDepthStencilStats depths = frameInfo.stats.depths; + statisticsLog.AppendText("\n*** Depth Stencil Statistics ***\n"); + statisticsLog.AppendText(String.Format("Depth/stencil calls: {0} non-null sets: {1}, null (default) sets: {2}, redundant sets: {3}\n", depths.calls, depths.sets, depths.nulls, depths.redundants)); + } + + private void AppendRasterizationStatistics(FetchFrameInfo frameInfo) + { + FetchFrameRasterizationStats rasters = frameInfo.stats.rasters; + statisticsLog.AppendText("\n*** Rasterization Statistics ***\n"); + statisticsLog.AppendText(String.Format("Rasterization calls: {0} non-null sets: {1}, null (default) sets: {2}, redundant sets: {3}\n", rasters.calls, rasters.sets, rasters.nulls, rasters.redundants)); + statisticsLog.AppendText(CreateSimpleIntegerHistogram("Viewports set", rasters.viewports)); + statisticsLog.AppendText(CreateSimpleIntegerHistogram("Scissors set", rasters.rects)); + } + + private void AppendOutputStatistics(FetchFrameInfo frameInfo) + { + FetchFrameOutputStats outputs = frameInfo.stats.outputs; + statisticsLog.AppendText("\n*** Output Statistics ***\n"); + statisticsLog.AppendText(String.Format("Output calls: {0} non-null sets: {1}, null sets: {2}\n", outputs.calls, outputs.sets, outputs.nulls)); + statisticsLog.AppendText(CreateSimpleIntegerHistogram("Outputs set", outputs.bindslots)); + } + private void AppendDetailedInformation(FetchFrameInfo frameInfo) { + if (frameInfo.stats.recorded == 0) + return; + AppendDrawStatistics(frameInfo); AppendDispatchStatistics(frameInfo); AppendInputAssemblerStatistics(frameInfo); + AppendShaderStatistics(frameInfo); AppendConstantBindStatistics(frameInfo); AppendSamplerBindStatistics(frameInfo); AppendResourceBindStatistics(frameInfo); + AppendBlendStatistics(frameInfo); + AppendDepthStencilStatistics(frameInfo); + AppendRasterizationStatistics(frameInfo); AppendUpdateStatistics(frameInfo); + AppendOutputStatistics(frameInfo); } private void CountContributingEvents(FetchDrawcall draw, ref uint drawCount, ref uint dispatchCount, ref uint diagnosticCount) @@ -594,6 +618,48 @@ namespace renderdocui.Windows } } + public string AppendAPICallSummary(FetchFrameInfo frameInfo, uint numAPICalls) + { + if (frameInfo.stats.recorded == 0) + return ""; + + uint numConstantSets = 0; + uint numSamplerSets = 0; + uint numResourceSets = 0; + uint numShaderSets = 0; + + for (var s = (int)ShaderStageType.First; s < (int)ShaderStageType.Count; s++) + { + numConstantSets += frameInfo.stats.constants[s].calls; + numSamplerSets += frameInfo.stats.samplers[s].calls; + numResourceSets += frameInfo.stats.resources[s].calls; + numShaderSets += frameInfo.stats.shaders[s].calls; + } + + uint numResourceUpdates = frameInfo.stats.updates.calls; + uint numIndexVertexSets = (frameInfo.stats.indices.calls + frameInfo.stats.vertices.calls + frameInfo.stats.layouts.calls); + uint numDraws = frameInfo.stats.draws.calls; + uint numDispatches = frameInfo.stats.dispatches.calls; + uint numBlendSets = frameInfo.stats.blends.calls; + uint numDepthStencilSets = frameInfo.stats.depths.calls; + uint numRasterizationSets = frameInfo.stats.rasters.calls; + uint numOutputSets = frameInfo.stats.outputs.calls; + + string calls = ""; + calls += String.Format("API calls: {0}\n", numAPICalls); + calls += String.Format("\tIndex/vertex bind calls: {0}\n", numIndexVertexSets); + calls += String.Format("\tConstant bind calls: {0}\n", numConstantSets); + calls += String.Format("\tSampler bind calls: {0}\n", numSamplerSets); + calls += String.Format("\tResource bind calls: {0}\n", numResourceSets); + calls += String.Format("\tShader set calls: {0}\n", numShaderSets); + calls += String.Format("\tBlend set calls: {0}\n", numBlendSets); + calls += String.Format("\tDepth/stencil set calls: {0}\n", numDepthStencilSets); + calls += String.Format("\tRasterization set calls: {0}\n", numRasterizationSets); + calls += String.Format("\tResource update calls: {0}\n", numResourceUpdates); + calls += String.Format("\tOutput set calls: {0}\n", numOutputSets); + return calls; + } + public void OnLogfileLoaded() { statisticsLog.Clear(); @@ -610,40 +676,7 @@ namespace renderdocui.Windows foreach (var d in m_Core.CurDrawcalls) CountContributingEvents(d, ref drawCount, ref dispatchCount, ref diagnosticCount); - uint numAPIcalls = lastDraw.eventID - diagnosticCount; - - // #mivance only recording this for comparison vis a vis draw call - // iteration, we want to preserve the old stats data for the - // backends which aren't recording statistics - bool statsRecorded = false; - uint numDraws = 0; - uint numDispatches = 0; - uint numIndexVertexSets = 0; - uint numConstantSets = 0; - uint numSamplerSets = 0; - uint numResourceSets = 0; - uint numResourceUpdates = 0; - - FetchFrameInfo frameInfo = m_Core.FrameInfo; - - { - if (frameInfo.stats.recorded != 0) - { - statsRecorded = true; - - for (var s = (int)ShaderStageType.First; s < (int)ShaderStageType.Count; s++) - { - numConstantSets += frameInfo.stats.constants[s].calls; - numSamplerSets += frameInfo.stats.samplers[s].calls; - numResourceSets += frameInfo.stats.resources[s].calls; - } - - numResourceUpdates += frameInfo.stats.updates.calls; - numIndexVertexSets += (frameInfo.stats.indices.calls + frameInfo.stats.vertices.calls + frameInfo.stats.layouts.calls); - numDraws += frameInfo.stats.draws.calls; - numDispatches += frameInfo.stats.dispatches.calls; - } - } + uint numAPIcalls = lastDraw.eventID - (drawCount + dispatchCount + diagnosticCount); int numTextures = m_Core.CurTextures.Length; int numBuffers = m_Core.CurBuffers.Length; @@ -702,6 +735,8 @@ namespace renderdocui.Windows largeTexW /= largeTexCount; largeTexH /= largeTexCount; + FetchFrameInfo frameInfo = m_Core.FrameInfo; + UInt64 persistentData = frameInfo.persistentSize; float compressedMB = (float)fileSize / (1024.0f * 1024.0f); @@ -714,9 +749,8 @@ namespace renderdocui.Windows Path.GetFileName(m_Core.LogFileName), compressedMB, uncompressedMB, compressRatio, persistentMB, initDataMB); string draws = String.Format("Draw calls: {0}\nDispatch calls: {1}\n", drawCount, dispatchCount); - string calls = statsRecorded ? String.Format("API calls: {0}\n\tIndex/vertex bind calls: {1}\n\tConstant bind calls: {2}\n\tSampler bind calls: {3}\n\tResource bind calls: {4}\n\tResource update calls: {5}\n", - numAPIcalls, numIndexVertexSets, numConstantSets, numSamplerSets, numResourceSets, numResourceUpdates) : ""; - string ratio = String.Format("API:Draw call ratio: {0}\n\n", (float)numAPIcalls / (float)drawCount); + string calls = AppendAPICallSummary(frameInfo, numAPIcalls); + string ratio = String.Format("API:Draw/Dispatch call ratio: {0}\n\n", (float)numAPIcalls / (float)(drawCount + dispatchCount)); string textures = String.Format("{0} Textures - {1:N2} MB ({2:N2} MB over 32x32), {3} RTs - {4:N2} MB.\nAvg. tex dimension: {5}x{6} ({7}x{8} over 32x32)\n", numTextures, (float)TexBytes / (1024.0f * 1024.0f), (float)LargeTexBytes / (1024.0f * 1024.0f), numRTs, (float)RTBytes / (1024.0f * 1024.0f), @@ -735,8 +769,7 @@ namespace renderdocui.Windows statisticsLog.AppendText(buffers); statisticsLog.AppendText(load); - if (statsRecorded) - AppendDetailedInformation(frameInfo); + AppendDetailedInformation(frameInfo); statisticsLog.Select(0, 0); }