From 7da04de99801b14fa8272c919e25c511e3b13c4b Mon Sep 17 00:00:00 2001 From: baldurk Date: Sat, 27 Sep 2014 21:41:35 +0100 Subject: [PATCH] Stream-out as point list for vs-out draws to get vertex reuse * For vertex shader output only, we do the streamout as a point list and render each vertex once then we can reuse the same(ish) index buffer and topology as the original draw. * For GS/DS out there will likely be some expansion of verts so we do the same as we used to. --- renderdoc/driver/d3d11/d3d11_common.cpp | 73 ++++++++ renderdoc/driver/d3d11/d3d11_common.h | 1 + renderdoc/driver/d3d11/d3d11_debug.cpp | 226 ++++++++++++++++++------ renderdoc/driver/d3d11/d3d11_debug.h | 7 +- renderdoc/driver/d3d11/d3d11_replay.cpp | 71 +------- renderdoc/replay/replay_output.cpp | 2 +- renderdocui/Windows/BufferViewer.cs | 81 +++++++-- 7 files changed, 321 insertions(+), 140 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_common.cpp b/renderdoc/driver/d3d11/d3d11_common.cpp index 0f6986344..056a81653 100644 --- a/renderdoc/driver/d3d11/d3d11_common.cpp +++ b/renderdoc/driver/d3d11/d3d11_common.cpp @@ -63,6 +63,79 @@ HMODULE GetD3DCompiler() return ret; } +PrimitiveTopology MakePrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY Topo) +{ + switch(Topo) + { + default: + case D3D_PRIMITIVE_TOPOLOGY_UNDEFINED: + break; + case D3D_PRIMITIVE_TOPOLOGY_POINTLIST: + return eTopology_PointList; + break; + case D3D_PRIMITIVE_TOPOLOGY_LINELIST: + return eTopology_LineList; + break; + case D3D_PRIMITIVE_TOPOLOGY_LINESTRIP: + return eTopology_LineStrip; + break; + case D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST: + return eTopology_TriangleList; + break; + case D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: + return eTopology_TriangleStrip; + break; + case D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ: + return eTopology_LineList_Adj; + break; + case D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ: + return eTopology_LineStrip_Adj; + break; + case D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ: + return eTopology_TriangleList_Adj; + break; + case D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ: + return eTopology_TriangleStrip_Adj; + break; + case D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST: + case D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST: + return PrimitiveTopology(eTopology_PatchList_1CPs + (Topo - D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST) ); + break; + } + + return eTopology_Unknown; +} + DXGI_FORMAT MakeDXGIFormat(ResourceFormat fmt) { DXGI_FORMAT ret = DXGI_FORMAT_UNKNOWN; diff --git a/renderdoc/driver/d3d11/d3d11_common.h b/renderdoc/driver/d3d11/d3d11_common.h index 355b5c700..ec6d7776a 100644 --- a/renderdoc/driver/d3d11/d3d11_common.h +++ b/renderdoc/driver/d3d11/d3d11_common.h @@ -43,6 +43,7 @@ HMODULE GetD3DCompiler(); ResourceFormat MakeResourceFormat(DXGI_FORMAT fmt); DXGI_FORMAT MakeDXGIFormat(ResourceFormat fmt); +PrimitiveTopology MakePrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY Topo); ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc); diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index a5008cf12..b194d2513 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -331,7 +331,9 @@ D3D11DebugManager::~D3D11DebugManager() for(auto it=m_PostVSData.begin(); it != m_PostVSData.end(); ++it) { SAFE_RELEASE(it->second.vsout.buf); + SAFE_RELEASE(it->second.vsout.idxBuf); SAFE_RELEASE(it->second.gsout.buf); + SAFE_RELEASE(it->second.gsout.idxBuf); } m_PostVSData.clear(); @@ -3751,7 +3753,7 @@ PostVSMeshData D3D11DebugManager::GetPostVSBuffers(uint32_t frameID, uint32_t ev PostVSData postvs = GetPostVSBuffers(frameID, eventID); PostVSData::StageData s = postvs.GetStage(stage); ret.numVerts = s.numVerts; - ret.topo = (PrimitiveTopology)s.topo; + ret.topo = MakePrimitiveTopology(s.topo); if(s.buf != NULL) ret.buf = GetBufferData(s.buf, 0, 0); else @@ -3866,10 +3868,13 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) if(a.find("POSITION") != string::npos) { // force to 4 components, as we need it, and store its offset - if(a.find("SV_POSITION") != string::npos) + if(a.find("SV_POSITION") != string::npos || sign.systemValue == eAttr_Position || posoffset == ~0U) + { decl.ComponentCount = 4; - numPosComponents = decl.ComponentCount; - posoffset = stride; + + posoffset = stride; + numPosComponents = decl.ComponentCount; + } } stride += decl.ComponentCount * sizeof(float); @@ -3903,7 +3908,108 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) m_pImmediateContext->SOSetTargets( 1, &m_SOBuffer, &offset ); m_pImmediateContext->Begin(m_SOStatsQuery); - m_WrappedDevice->ReplayLog(frameID, 0, eventID, eReplay_OnlyDraw); + + const FetchDrawcall *drawcall = m_WrappedDevice->GetDrawcall(frameID, eventID); + + ID3D11Buffer *idxBuf = NULL; + DXGI_FORMAT idxFmt = DXGI_FORMAT_UNKNOWN; + + if((drawcall->flags & eDraw_UseIBuffer) == 0) + { + m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + m_pImmediateContext->Draw(drawcall->numIndices, drawcall->vertexOffset); + m_pImmediateContext->IASetPrimitiveTopology(topo); + } + else // drawcall is indexed + { + UINT idxOffs = 0; + + m_WrappedContext->IAGetIndexBuffer(&idxBuf, &idxFmt, &idxOffs); + bool index16 = (idxFmt == DXGI_FORMAT_R16_UINT); + UINT bytesize = index16 ? 2 : 4; + + ID3D11Buffer *origBuf = idxBuf; + + vector idxdata = GetBufferData(idxBuf, idxOffs + drawcall->indexOffset*bytesize, drawcall->numIndices*bytesize); + + SAFE_RELEASE(idxBuf); + + vector indices; + + uint16_t *idx16 = (uint16_t *)&idxdata[0]; + uint32_t *idx32 = (uint32_t *)&idxdata[0]; + + // grab all unique vertex indices referenced + for(uint32_t i=0; i < drawcall->numIndices; i++) + { + uint32_t i32 = index16 ? uint32_t(idx16[i]) : idx32[i]; + + auto it = std::lower_bound(indices.begin(), indices.end(), i32); + + if(it != indices.end() && *it == i32) + continue; + + indices.insert(it, i32); + } + + // An index buffer could be something like: 500, 501, 502, 501, 503, 502 + // in which case we can't use the existing index buffer without filling 499 slots of vertex + // data with padding. Instead we rebase the indices based on the smallest vertex so it becomes + // 0, 1, 2, 1, 3, 2 and then that matches our stream-out'd buffer. + // + // Since we want the indices to be preserved in order to easily match up inputs to outputs, + // but shifted, fill in gaps in our streamout vertex buffer with the lowest index value. + // (use the lowest index value so that even the gaps are a 'valid' vertex, rather than + // potentially garbage data). + uint32_t minindex = indices[0]; + + // indices[] contains ascending unique vertex indices referenced. Fill gaps with minindex + for(size_t i=1; i < indices.size(); i++) + { + if(indices[i]-1 > indices[i-1]) + { + size_t gapsize = size_t( (indices[i]-1) - indices[i-1] ); + + indices.insert(indices.begin()+i, gapsize, minindex); + + i += gapsize; + } + } + + D3D11_BUFFER_DESC desc = { UINT(sizeof(uint32_t)*indices.size()), D3D11_USAGE_IMMUTABLE, D3D11_BIND_INDEX_BUFFER, 0, 0, 0 }; + D3D11_SUBRESOURCE_DATA initData = { &indices[0], desc.ByteWidth, desc.ByteWidth }; + + m_pDevice->CreateBuffer(&desc, &initData, &idxBuf); + + m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + m_pImmediateContext->IASetIndexBuffer(idxBuf, DXGI_FORMAT_R32_UINT, 0); + SAFE_RELEASE(idxBuf); + + m_pImmediateContext->DrawIndexed((UINT)indices.size(), 0, drawcall->vertexOffset); + + m_pImmediateContext->IASetPrimitiveTopology(topo); + m_pImmediateContext->IASetIndexBuffer(UNWRAP(WrappedID3D11Buffer, origBuf), idxFmt, idxOffs); + + // rebase existing index buffer to point from 0 onwards (which will index into our + // stream-out'd vertex buffer) + if(index16) + { + for(uint32_t i=0; i < drawcall->numIndices; i++) + idx16[i] -= uint16_t(minindex&0xffff); + } + else + { + for(uint32_t i=0; i < drawcall->numIndices; i++) + idx32[i] -= minindex; + } + + desc.ByteWidth = (UINT)idxdata.size(); + initData.pSysMem = &idxdata[0]; + initData.SysMemPitch = initData.SysMemSlicePitch = desc.ByteWidth; + + m_WrappedDevice->CreateBuffer(&desc, &initData, &idxBuf); + } + m_pImmediateContext->End(m_SOStatsQuery); m_pImmediateContext->GSSetShader(NULL, NULL, 0); @@ -3935,7 +4041,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) D3D11_BUFFER_DESC bufferDesc = { - stride * (uint32_t)numPrims.NumPrimitivesWritten*3, + stride * (uint32_t)numPrims.NumPrimitivesWritten, D3D11_USAGE_IMMUTABLE, D3D11_BIND_VERTEX_BUFFER, 0, @@ -4022,10 +4128,19 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) m_PostVSData[idx].vsout.buf = vsoutBuffer; m_PostVSData[idx].vsout.posOffset = posoffset; m_PostVSData[idx].vsout.vertStride = stride; - m_PostVSData[idx].vsout.numPrims = (uint32_t)numPrims.NumPrimitivesWritten; m_PostVSData[idx].vsout.nearPlane = nearp; m_PostVSData[idx].vsout.farPlane = farp; + m_PostVSData[idx].vsout.useIndices = (drawcall->flags & eDraw_UseIBuffer) > 0; + m_PostVSData[idx].vsout.numVerts = drawcall->numIndices; + + m_PostVSData[idx].vsout.idxBuf = NULL; + if(m_PostVSData[idx].vsout.useIndices && idxBuf) + { + m_PostVSData[idx].vsout.idxBuf = idxBuf; + m_PostVSData[idx].vsout.idxFmt = idxFmt; + } + m_PostVSData[idx].vsout.topo = topo; } else @@ -4035,34 +4150,14 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) m_PostVSData[idx].vsout.buf = NULL; m_PostVSData[idx].vsout.posOffset = ~0U; m_PostVSData[idx].vsout.vertStride = 0; - m_PostVSData[idx].vsout.numPrims = 0; m_PostVSData[idx].vsout.nearPlane = 0.0f; m_PostVSData[idx].vsout.farPlane = 0.0f; + m_PostVSData[idx].vsout.useIndices = false; + m_PostVSData[idx].vsout.idxBuf = NULL; m_PostVSData[idx].vsout.topo = topo; } - // streamout expands strips unfortunately - if(topo == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP) - m_PostVSData[idx].vsout.topo = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - else if(topo == D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP) - m_PostVSData[idx].vsout.topo = D3D11_PRIMITIVE_TOPOLOGY_LINELIST; - else if(topo == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ) - m_PostVSData[idx].vsout.topo = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ; - else if(topo == D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ) - m_PostVSData[idx].vsout.topo = D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ; - - switch(m_PostVSData[idx].vsout.topo) - { - case D3D11_PRIMITIVE_TOPOLOGY_POINTLIST: - m_PostVSData[idx].vsout.numVerts = m_PostVSData[idx].vsout.numPrims; break; - case D3D11_PRIMITIVE_TOPOLOGY_LINELIST: - m_PostVSData[idx].vsout.numVerts = m_PostVSData[idx].vsout.numPrims*2; break; - default: - case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST: - m_PostVSData[idx].vsout.numVerts = m_PostVSData[idx].vsout.numPrims*3; break; - } - if(dxbcGS || dxbcDS) { stride = 0; @@ -4092,15 +4187,17 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) decl.ComponentCount = sign.compCount&0xff; string a = strupper(string(decl.SemanticName)); - - // force to 4 components, as we need it, and store its offset + if(a.find("POSITION") != string::npos) { // force to 4 components, as we need it, and store its offset - if(a.find("SV_POSITION") != string::npos) + if(a.find("SV_POSITION") != string::npos || sign.systemValue == eAttr_Position || posoffset == ~0U) + { decl.ComponentCount = 4; - numPosComponents = decl.ComponentCount; - posoffset = stride; + + posoffset = stride; + numPosComponents = decl.ComponentCount; + } } stride += decl.ComponentCount * sizeof(float); @@ -4253,9 +4350,10 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) m_PostVSData[idx].gsout.buf = gsoutBuffer; m_PostVSData[idx].gsout.posOffset = posoffset; m_PostVSData[idx].gsout.vertStride = stride; - m_PostVSData[idx].gsout.numPrims = (uint32_t)numPrims.NumPrimitivesWritten; m_PostVSData[idx].gsout.nearPlane = nearp; m_PostVSData[idx].gsout.farPlane = farp; + m_PostVSData[idx].gsout.useIndices = false; + m_PostVSData[idx].gsout.idxBuf = NULL; D3D11_PRIMITIVE_TOPOLOGY topo = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; @@ -4300,12 +4398,14 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) switch(m_PostVSData[idx].gsout.topo) { case D3D11_PRIMITIVE_TOPOLOGY_POINTLIST: - m_PostVSData[idx].gsout.numVerts = m_PostVSData[idx].gsout.numPrims; break; + m_PostVSData[idx].gsout.numVerts = (uint32_t)numPrims.NumPrimitivesWritten; break; case D3D11_PRIMITIVE_TOPOLOGY_LINELIST: - m_PostVSData[idx].gsout.numVerts = m_PostVSData[idx].gsout.numPrims*2; break; + case D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ: + m_PostVSData[idx].gsout.numVerts = (uint32_t)numPrims.NumPrimitivesWritten*2; break; default: case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST: - m_PostVSData[idx].gsout.numVerts = m_PostVSData[idx].gsout.numPrims*3; break; + case D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ: + m_PostVSData[idx].gsout.numVerts = (uint32_t)numPrims.NumPrimitivesWritten*3; break; } } } @@ -4435,16 +4535,29 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve for(size_t i=0; i < events.size()-1; i++) { PostVSData data = GetPostVSBuffers(frameID, events[i]); - const PostVSData::StageData &stage = data.GetStage(cfg.type); + PostVSData::StageData stage = data.GetStage(cfg.type); + + if(stage.buf == NULL && cfg.type == eMeshDataStage_GSOut) + stage = data.GetStage(eMeshDataStage_VSOut); if(stage.buf) { - if(stage.topo < D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ) - { + if(stage.topo > D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST) + m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + else m_pImmediateContext->IASetPrimitiveTopology(stage.topo); - ID3D11Buffer *buf = UNWRAP(WrappedID3D11Buffer, stage.buf); - m_pImmediateContext->IASetVertexBuffers(0, 1, &buf, (UINT *)&stage.vertStride, (UINT *)&stage.posOffset); + ID3D11Buffer *buf = UNWRAP(WrappedID3D11Buffer, stage.buf); + m_pImmediateContext->IASetVertexBuffers(0, 1, &buf, (UINT *)&stage.vertStride, (UINT *)&stage.posOffset); + if(stage.useIndices) + { + buf = UNWRAP(WrappedID3D11Buffer, stage.idxBuf); + m_pImmediateContext->IASetIndexBuffer(buf, stage.idxFmt, 0); + + m_pImmediateContext->DrawIndexed(stage.numVerts, 0, 0); + } + else + { m_pImmediateContext->Draw(stage.numVerts, 0); } } @@ -4457,12 +4570,22 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve const PostVSData::StageData &stage = data.GetStage(cfg.type); if(stage.buf) { - if(stage.topo < D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ) - { + if(stage.topo > D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST) + m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + else m_pImmediateContext->IASetPrimitiveTopology(stage.topo); - - ID3D11Buffer *buf = UNWRAP(WrappedID3D11Buffer, stage.buf); - m_pImmediateContext->IASetVertexBuffers(0, 1, &buf, (UINT *)&stage.vertStride, (UINT *)&stage.posOffset); + + ID3D11Buffer *buf = UNWRAP(WrappedID3D11Buffer, stage.buf); + m_pImmediateContext->IASetVertexBuffers(0, 1, &buf, (UINT *)&stage.vertStride, (UINT *)&stage.posOffset); + if(stage.useIndices) + { + buf = UNWRAP(WrappedID3D11Buffer, stage.idxBuf); + m_pImmediateContext->IASetIndexBuffer(buf, stage.idxFmt, 0); + + m_pImmediateContext->DrawIndexed(stage.numVerts, 0, 0); + } + else + { m_pImmediateContext->Draw(stage.numVerts, 0); } } @@ -4609,7 +4732,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve m_pImmediateContext->IASetVertexBuffers(m_MeshDisplayNULLVB, 1, &vb, &dummy, &dummy); // draw solid shaded mode - if(cfg.solidShadeMode != eShade_None) + if(cfg.solidShadeMode != eShade_None && pipeState.m_IA.Topology < eTopology_PatchList_1CPs) { m_pImmediateContext->RSSetState(m_DebugRender.RastState); @@ -4638,7 +4761,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve } // draw wireframe mode - if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw) + if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw || pipeState.m_IA.Topology >= eTopology_PatchList_1CPs) { m_pImmediateContext->RSSetState(m_WireframeHelpersRS); @@ -4650,6 +4773,9 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, const vector &eve m_pImmediateContext->PSSetConstantBuffers(0, 1, &m_DebugRender.GenericPSCBuffer); + if(pipeState.m_IA.Topology >= eTopology_PatchList_1CPs) + m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + m_WrappedDevice->ReplayLog(frameID, 0, events[0], eReplay_OnlyDraw); } } diff --git a/renderdoc/driver/d3d11/d3d11_debug.h b/renderdoc/driver/d3d11/d3d11_debug.h index 01af205af..ae709fc52 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.h +++ b/renderdoc/driver/d3d11/d3d11_debug.h @@ -58,10 +58,13 @@ struct PostVSData D3D11_PRIMITIVE_TOPOLOGY topo; uint32_t numVerts; - uint32_t numPrims; uint32_t posOffset; uint32_t vertStride; + bool useIndices; + ID3D11Buffer *idxBuf; + DXGI_FORMAT idxFmt; + float nearPlane; float farPlane; } vsin, vsout, gsout; @@ -282,7 +285,7 @@ class D3D11DebugManager bool m_ShaderCacheDirty, m_CacheShaders; map m_ShaderCache; - static const int m_SOBufferSize = 16*1024*1024; + static const int m_SOBufferSize = 32*1024*1024; ID3D11Buffer *m_SOBuffer; ID3D11Buffer *m_SOStagingBuffer; ID3D11Query *m_SOStatsQuery; diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 7161ee56e..79e28b6e4 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -354,75 +354,8 @@ D3D11PipelineState D3D11Replay::MakePipelineState() ///////////////////////////////////////////////// // Input Assembler ///////////////////////////////////////////////// - - switch(rs->IA.Topo) - { - default: - case D3D_PRIMITIVE_TOPOLOGY_UNDEFINED: - ret.m_IA.Topology = eTopology_Unknown; - break; - case D3D_PRIMITIVE_TOPOLOGY_POINTLIST: - ret.m_IA.Topology = eTopology_PointList; - break; - case D3D_PRIMITIVE_TOPOLOGY_LINELIST: - ret.m_IA.Topology = eTopology_LineList; - break; - case D3D_PRIMITIVE_TOPOLOGY_LINESTRIP: - ret.m_IA.Topology = eTopology_LineStrip; - break; - case D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST: - ret.m_IA.Topology = eTopology_TriangleList; - break; - case D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: - ret.m_IA.Topology = eTopology_TriangleStrip; - break; - case D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ: - ret.m_IA.Topology = eTopology_LineList_Adj; - break; - case D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ: - ret.m_IA.Topology = eTopology_LineStrip_Adj; - break; - case D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ: - ret.m_IA.Topology = eTopology_TriangleList_Adj; - break; - case D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ: - ret.m_IA.Topology = eTopology_TriangleStrip_Adj; - break; - case D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_6_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_7_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_8_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_9_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_10_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_11_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_12_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_13_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_14_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_15_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_17_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_18_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_19_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_20_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_21_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_22_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_23_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_24_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_25_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_26_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_27_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_28_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_29_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_30_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_31_CONTROL_POINT_PATCHLIST: - case D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST: - ret.m_IA.Topology = PrimitiveTopology(eTopology_PatchList_1CPs + (rs->IA.Topo - D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST) ); - break; - } + + ret.m_IA.Topology = MakePrimitiveTopology(rs->IA.Topo); D3D11ResourceManager *rm = m_pDevice->GetResourceManager(); diff --git a/renderdoc/replay/replay_output.cpp b/renderdoc/replay/replay_output.cpp index c87d588e4..93762485b 100644 --- a/renderdoc/replay/replay_output.cpp +++ b/renderdoc/replay/replay_output.cpp @@ -175,7 +175,7 @@ void ReplayOutput::RefreshOverlay() } else if(!passEvents.empty()) { - uint32_t prev = passEvents[0]; + uint32_t prev = 0; for(size_t i=0; i < passEvents.size(); i++) { diff --git a/renderdocui/Windows/BufferViewer.cs b/renderdocui/Windows/BufferViewer.cs index 9a63205d1..b3d778f6e 100644 --- a/renderdocui/Windows/BufferViewer.cs +++ b/renderdocui/Windows/BufferViewer.cs @@ -83,6 +83,7 @@ namespace renderdocui.Windows private class Dataset { public uint IndexCount = 0; + public uint IndexAdd = 0; public PrimitiveTopology Topology = PrimitiveTopology.Unknown; @@ -672,6 +673,22 @@ namespace renderdocui.Windows ret.Drawcall = draw; ret.Topology = m_Core.CurPipelineState.DrawTopology; + ResourceId ibuffer = ResourceId.Null; + uint ioffset = 0; + ResourceFormat ifmt = null; + + m_Core.CurPipelineState.GetIBuffer(out ibuffer, out ioffset, out ifmt); + + if (draw != null && (draw.flags & DrawcallFlags.UseIBuffer) == 0) + { + ibuffer = ResourceId.Null; + ioffset = 0; + } + + ret.IndexFormat = new FormatElement("", 0, 0, false, false, 1, ifmt, false); + ret.IndexBuffer = ibuffer; + ret.IndexOffset = ioffset; + if (type != MeshDataStage.VSIn) { ShaderReflection details = null; @@ -716,7 +733,6 @@ namespace renderdocui.Windows ret.Strides = new uint[] { offset }; ret.Offsets = new uint[] { 0 }; ret.Buffers = null; - ret.IndexBuffer = ResourceId.Null; return ret; } @@ -753,27 +769,11 @@ namespace renderdocui.Windows } } - ResourceId ibuffer = ResourceId.Null; - uint ioffset = 0; - ResourceFormat ifmt = null; - - m_Core.CurPipelineState.GetIBuffer(out ibuffer, out ioffset, out ifmt); - - if (draw != null && (draw.flags & DrawcallFlags.UseIBuffer) == 0) - { - ibuffer = ResourceId.Null; - ioffset = 0; - } - ret.BufferFormats = f; ret.Strides = s; ret.Offsets = o; ret.Buffers = bs; - ret.IndexFormat = new FormatElement("", 0, 0, false, false, 1, ifmt, false); - ret.IndexBuffer = ibuffer; - ret.IndexOffset = ioffset; - return ret; } @@ -786,6 +786,7 @@ namespace renderdocui.Windows Dataset ret = new Dataset(); ret.IndexCount = 0; + ret.IndexAdd = 0; if (input == null) return ret; @@ -839,6 +840,50 @@ namespace renderdocui.Windows ret.Indices = null; + if (postvs != null && type == MeshDataStage.VSOut && + (input.Drawcall.flags & DrawcallFlags.UseIBuffer) > 0 && input.IndexBuffer != ResourceId.Null) + { + ret.IndexCount = input.Drawcall.numIndices; + + byte[] rawidxs = r.GetBufferData(input.IndexBuffer, + input.IndexOffset + input.Drawcall.indexOffset * input.IndexFormat.format.compByteWidth, + ret.IndexCount * input.IndexFormat.format.compByteWidth); + + ret.Indices = new uint[rawidxs.Length / input.IndexFormat.format.compByteWidth]; + + if (input.IndexFormat.format.compByteWidth == 2) + { + ushort[] tmp = new ushort[rawidxs.Length / 2]; + + Buffer.BlockCopy(rawidxs, 0, tmp, 0, rawidxs.Length); + + for (int i = 0; i < tmp.Length; i++) + { + ret.Indices[i] = tmp[i]; + } + } + else if (input.IndexFormat.format.compByteWidth == 4) + { + Buffer.BlockCopy(rawidxs, 0, ret.Indices, 0, rawidxs.Length); + } + + uint minIndex = ret.Indices[0]; + foreach (var i in ret.Indices) + { + if (input.IndexFormat.format.compByteWidth == 2 && i == UInt16.MaxValue) + continue; + if (input.IndexFormat.format.compByteWidth == 4 && i == UInt32.MaxValue) + continue; + + minIndex = Math.Min(minIndex, i); + } + + for (int idx = 0; idx < ret.Indices.Length; idx++) + ret.Indices[idx] -= minIndex; + + ret.IndexAdd = minIndex; + } + return ret; } else if (input.Buffers != null && m_Output != null) @@ -1423,7 +1468,7 @@ namespace renderdocui.Windows if (outOfBoundsIdx) rowdata[1] = "-"; else - rowdata[1] = index; + rowdata[1] = index + data.IndexAdd; bool strip = state.m_Data.Topology == PrimitiveTopology.LineStrip || state.m_Data.Topology == PrimitiveTopology.LineStrip_Adj ||