From 30dd13feb8b3ad99e5c8f737b28b6e4c9fbf5a6b Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 23 Feb 2021 13:53:26 +0000 Subject: [PATCH] Pull index byte width and topology out of drawcall state * These are treated as state on most APIs, only GL treats it as a drawcall parameter. --- .../examples/renderdoc/decode_mesh.py | 2 +- .../examples/renderdoc/decode_mesh.rst | 2 +- qrenderdoc/Windows/BufferViewer.cpp | 58 +++++------ .../D3D11PipelineStateViewer.cpp | 85 ++++++++-------- .../D3D12PipelineStateViewer.cpp | 70 +++++++------- .../PipelineState/GLPipelineStateViewer.cpp | 48 +++++----- .../VulkanPipelineStateViewer.cpp | 90 ++++++++--------- qrenderdoc/Windows/PixelHistoryView.cpp | 3 +- renderdoc/api/replay/d3d11_pipestate.h | 11 +++ renderdoc/api/replay/d3d12_pipestate.h | 11 +++ renderdoc/api/replay/data_types.h | 12 --- renderdoc/api/replay/gl_pipestate.h | 15 +++ renderdoc/api/replay/pipestate.h | 19 +++- renderdoc/api/replay/pipestate.inl | 29 ++++++ renderdoc/api/replay/vk_pipestate.h | 11 +++ renderdoc/driver/d3d11/d3d11_context.cpp | 8 -- renderdoc/driver/d3d11/d3d11_pixelhistory.cpp | 11 ++- renderdoc/driver/d3d11/d3d11_replay.cpp | 9 ++ .../driver/d3d12/d3d12_command_list_wrap.cpp | 2 - renderdoc/driver/d3d12/d3d12_commands.cpp | 6 -- renderdoc/driver/d3d12/d3d12_replay.cpp | 3 + renderdoc/driver/gl/gl_driver.cpp | 10 ++ renderdoc/driver/gl/gl_driver.h | 11 +++ renderdoc/driver/gl/gl_overlay.cpp | 16 ++-- renderdoc/driver/gl/gl_postvs.cpp | 47 +++++---- renderdoc/driver/gl/gl_replay.cpp | 5 + .../driver/gl/wrappers/gl_draw_funcs.cpp | 96 +++++++++---------- renderdoc/driver/vulkan/vk_core.cpp | 11 --- renderdoc/driver/vulkan/vk_overlay.cpp | 19 ++-- renderdoc/driver/vulkan/vk_pixelhistory.cpp | 9 +- renderdoc/driver/vulkan/vk_postvs.cpp | 6 +- renderdoc/driver/vulkan/vk_replay.cpp | 3 + renderdoc/replay/renderdoc_serialise.inl | 27 +++--- renderdoc/replay/replay_driver.cpp | 8 +- renderdoc/replay/replay_driver.h | 4 +- util/test/rdtest/analyse.py | 2 +- util/test/rdtest/shared/Draw_Zoo.py | 4 +- util/test/rdtest/testcase.py | 8 +- .../tests/D3D11/D3D11_Primitive_Restart.py | 4 +- util/test/tests/GL/GL_Draw_Zoo.py | 9 +- util/test/tests/Iter_Test.py | 6 +- .../tests/Vulkan/VK_Extended_Dynamic_State.py | 2 +- util/test/tests/Vulkan/VK_Int8_IBuffer.py | 4 +- 43 files changed, 462 insertions(+), 354 deletions(-) diff --git a/docs/python_api/examples/renderdoc/decode_mesh.py b/docs/python_api/examples/renderdoc/decode_mesh.py index adcf9c02a..d7c434b30 100644 --- a/docs/python_api/examples/renderdoc/decode_mesh.py +++ b/docs/python_api/examples/renderdoc/decode_mesh.py @@ -88,7 +88,7 @@ def getMeshInputs(controller, draw): meshInput = MeshData() meshInput.indexResourceId = ib.resourceId meshInput.indexByteOffset = ib.byteOffset - meshInput.indexByteStride = draw.indexByteWidth + meshInput.indexByteStride = ib.byteStride meshInput.baseVertex = draw.baseVertex meshInput.indexOffset = draw.indexOffset meshInput.numIndices = draw.numIndices diff --git a/docs/python_api/examples/renderdoc/decode_mesh.rst b/docs/python_api/examples/renderdoc/decode_mesh.rst index ed3ba6e94..ec76a22b2 100644 --- a/docs/python_api/examples/renderdoc/decode_mesh.rst +++ b/docs/python_api/examples/renderdoc/decode_mesh.rst @@ -30,7 +30,7 @@ In the object we pass both the indices (which does not vary per attribute in our meshInput = MeshData() meshInput.indexResourceId = ib.resourceId meshInput.indexByteOffset = ib.byteOffset - meshInput.indexByteStride = draw.indexByteWidth + meshInput.indexByteStride = ib.byteStride meshInput.baseVertex = draw.baseVertex meshInput.indexOffset = draw.indexOffset meshInput.numIndices = draw.numIndices diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index 89b052ef6..c89aaea43 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -1575,7 +1575,7 @@ static void ConfigureMeshColumns(ICaptureContext &ctx, PopulateBufferData *bufda BufferDescription *buf = ctx.GetBuffer(ib.resourceId); if(buf) { - uint64_t offset = ib.byteOffset + draw->indexOffset * draw->indexByteWidth; + uint64_t offset = ib.byteOffset + draw->indexOffset * ib.byteStride; if(offset > buf->length) bytesAvailable = 0; else @@ -1589,7 +1589,7 @@ static void ConfigureMeshColumns(ICaptureContext &ctx, PopulateBufferData *bufda // drawing more than this many indices will read off the end of the index buffer - which while // technically not invalid is certainly not intended, so serves as a good 'upper bound' - numRowsUpperBound = bytesAvailable / qMax(1U, draw->indexByteWidth); + numRowsUpperBound = bytesAvailable / qMax(1U, ib.byteStride); } else { @@ -1674,8 +1674,8 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat bytebuf idata; if(ib.resourceId != ResourceId() && draw && (draw->flags & DrawFlags::Indexed)) { - uint64_t readBytes = numIndices * draw->indexByteWidth; - uint32_t offset = draw->indexOffset * draw->indexByteWidth; + uint64_t readBytes = numIndices * ib.byteStride; + uint32_t offset = draw->indexOffset * ib.byteStride; if(ib.byteSize > offset) readBytes = qMin(ib.byteSize - offset, readBytes); @@ -1691,9 +1691,9 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat data->vsinConfig.indices = new BufferData(); - if(draw && draw->indexByteWidth != 0 && !idata.isEmpty()) + if(draw && ib.byteStride != 0 && !idata.isEmpty()) data->vsinConfig.indices->storage.resize( - sizeof(uint32_t) * qMin(numIndices, ((uint32_t)idata.size() / draw->indexByteWidth))); + sizeof(uint32_t) * qMin(numIndices, ((uint32_t)idata.size() / ib.byteStride))); else if(draw && (draw->flags & DrawFlags::Indexed)) data->vsinConfig.indices->storage.resize(sizeof(uint32_t)); @@ -1706,7 +1706,7 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat if(draw && !idata.isEmpty()) { maxIndex = 0; - if(draw->indexByteWidth == 1) + if(ib.byteStride == 1) { uint8_t primRestart = data->vsinConfig.primRestart & 0xff; @@ -1719,7 +1719,7 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat maxIndex = qMax(maxIndex, indices[i]); } } - else if(draw->indexByteWidth == 2) + else if(ib.byteStride == 2) { uint16_t primRestart = data->vsinConfig.primRestart & 0xffff; @@ -1733,7 +1733,7 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat maxIndex = qMax(maxIndex, indices[i]); } } - else if(draw->indexByteWidth == 4) + else if(ib.byteStride == 4) { uint32_t primRestart = data->vsinConfig.primRestart; @@ -1848,23 +1848,23 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat data->vsoutConfig.displayIndices->ref(); data->vsoutConfig.indices = new BufferData(); - if(draw && draw->indexByteWidth != 0 && !idata.isEmpty()) + if(draw && ib.byteStride != 0 && !idata.isEmpty()) { data->vsoutConfig.indices->storage.resize(sizeof(uint32_t) * numIndices); indices = (uint32_t *)data->vsoutConfig.indices->data(); - if(draw->indexByteWidth == 1) + if(ib.byteStride == 1) { for(size_t i = 0; i < idata.size() && (uint32_t)i < numIndices; i++) indices[i] = (uint32_t)idata[i]; } - else if(draw->indexByteWidth == 2) + else if(ib.byteStride == 2) { uint16_t *src = (uint16_t *)idata.data(); for(size_t i = 0; i < idata.size() / sizeof(uint16_t) && (uint32_t)i < numIndices; i++) indices[i] = (uint32_t)src[i]; } - else if(draw->indexByteWidth == 4) + else if(ib.byteStride == 4) { memcpy(indices, idata.data(), qMin(idata.size(), numIndices * sizeof(uint32_t))); } @@ -2532,14 +2532,16 @@ void BufferViewer::OnEventChanged(uint32_t eventId) ClearModels(); - if(m_Ctx.CurPipelineState().IsStripRestartEnabled() && draw && - (draw->flags & DrawFlags::Indexed) && SupportsRestart(draw->topology)) - { - bufdata->vsinConfig.primRestart = m_Ctx.CurPipelineState().GetStripRestartIndex(); + const PipeState &pipe = m_Ctx.CurPipelineState(); - if(draw->indexByteWidth == 1) + if(pipe.IsStripRestartEnabled() && draw && (draw->flags & DrawFlags::Indexed) && + SupportsRestart(pipe.GetPrimitiveTopology())) + { + bufdata->vsinConfig.primRestart = pipe.GetStripRestartIndex(); + + if(pipe.GetIBuffer().byteStride == 1) bufdata->vsinConfig.primRestart &= 0xff; - else if(draw->indexByteWidth == 2) + else if(pipe.GetIBuffer().byteStride == 2) bufdata->vsinConfig.primRestart &= 0xffff; bufdata->vsoutConfig.primRestart = bufdata->vsinConfig.primRestart; @@ -3075,7 +3077,9 @@ void BufferViewer::UI_CalculateMeshFormats() if(!m_MeshView) return; - rdcarray vbs = m_Ctx.CurPipelineState().GetVBuffers(); + const PipeState &pipe = m_Ctx.CurPipelineState(); + + rdcarray vbs = pipe.GetVBuffers(); const DrawcallDescription *draw = m_Ctx.CurDrawcall(); if(draw) @@ -3083,10 +3087,10 @@ void BufferViewer::UI_CalculateMeshFormats() m_VSInPosition = MeshFormat(); m_VSInSecondary = MeshFormat(); - m_VSInPosition.allowRestart = m_Ctx.CurPipelineState().IsStripRestartEnabled() && + m_VSInPosition.allowRestart = pipe.IsStripRestartEnabled() && (draw->flags & DrawFlags::Indexed) && - SupportsRestart(draw->topology); - m_VSInPosition.restartIndex = m_Ctx.CurPipelineState().GetStripRestartIndex(); + SupportsRestart(pipe.GetPrimitiveTopology()); + m_VSInPosition.restartIndex = pipe.GetStripRestartIndex(); const BufferConfiguration &vsinConfig = m_ModelVSIn->getConfig(); @@ -3104,12 +3108,12 @@ void BufferViewer::UI_CalculateMeshFormats() if((draw->flags & DrawFlags::Instanced) && draw->numInstances == 0) m_VSInPosition.numIndices = 0; - m_VSInPosition.topology = draw->topology; - m_VSInPosition.indexByteStride = draw->indexByteWidth; + BoundVBuffer ib = pipe.GetIBuffer(); + m_VSInPosition.topology = pipe.GetPrimitiveTopology(); + m_VSInPosition.indexByteStride = ib.byteStride; m_VSInPosition.baseVertex = draw->baseVertex; - BoundVBuffer ib = m_Ctx.CurPipelineState().GetIBuffer(); m_VSInPosition.indexResourceId = ib.resourceId; - m_VSInPosition.indexByteOffset = ib.byteOffset + draw->indexOffset * draw->indexByteWidth; + m_VSInPosition.indexByteOffset = ib.byteOffset + draw->indexOffset * ib.byteStride; m_VSInPosition.indexByteSize = ib.byteSize; if((draw->flags & DrawFlags::Indexed) && m_VSInPosition.indexByteStride == 0) diff --git a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp index f408b309a..b6a7cfd58 100644 --- a/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D11PipelineStateViewer.cpp @@ -1356,19 +1356,17 @@ void D3D11PipelineStateViewer::setState() ui->iaLayouts->endUpdate(); ui->iaLayouts->verticalScrollBar()->setValue(vs); - Topology topo = draw ? draw->topology : Topology::Unknown; - - int numCPs = PatchList_Count(topo); + int numCPs = PatchList_Count(state.inputAssembly.topology); if(numCPs > 0) { ui->topology->setText(tr("PatchList (%1 Control Points)").arg(numCPs)); } else { - ui->topology->setText(ToQStr(topo)); + ui->topology->setText(ToQStr(state.inputAssembly.topology)); } - m_Common.setTopologyDiagram(ui->topologyDiagram, topo); + m_Common.setTopologyDiagram(ui->topologyDiagram, state.inputAssembly.topology); bool ibufferUsed = draw && (draw->flags & DrawFlags::Indexed); @@ -1391,27 +1389,27 @@ void D3D11PipelineStateViewer::setState() length = buf->length; RDTreeWidgetItem *node = new RDTreeWidgetItem( - {tr("Index"), state.inputAssembly.indexBuffer.resourceId, draw ? draw->indexByteWidth : 0, - state.inputAssembly.indexBuffer.byteOffset, (qulonglong)length, QString()}); + {tr("Index"), state.inputAssembly.indexBuffer.resourceId, + state.inputAssembly.indexBuffer.byteStride, state.inputAssembly.indexBuffer.byteOffset, + (qulonglong)length, QString()}); QString iformat; - if(draw) - { - if(draw->indexByteWidth == 1) - iformat = lit("ubyte"); - else if(draw->indexByteWidth == 2) - iformat = lit("ushort"); - else if(draw->indexByteWidth == 4) - iformat = lit("uint"); - iformat += lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(draw->topology)); - } + if(state.inputAssembly.indexBuffer.byteStride == 1) + iformat = lit("ubyte"); + else if(state.inputAssembly.indexBuffer.byteStride == 2) + iformat = lit("ushort"); + else if(state.inputAssembly.indexBuffer.byteStride == 4) + iformat = lit("uint"); - node->setTag( - QVariant::fromValue(D3D11VBIBTag(state.inputAssembly.indexBuffer.resourceId, - state.inputAssembly.indexBuffer.byteOffset + - (draw ? draw->indexOffset * draw->indexByteWidth : 0), - iformat))); + iformat += + lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(state.inputAssembly.topology)); + + node->setTag(QVariant::fromValue(D3D11VBIBTag( + state.inputAssembly.indexBuffer.resourceId, + state.inputAssembly.indexBuffer.byteOffset + + (draw ? draw->indexOffset * state.inputAssembly.indexBuffer.byteStride : 0), + iformat))); if(!ibufferUsed) setInactiveRow(node); @@ -1433,23 +1431,22 @@ void D3D11PipelineStateViewer::setState() {tr("Index"), tr("No Buffer Set"), lit("-"), lit("-"), lit("-"), QString()}); QString iformat; - if(draw) - { - if(draw->indexByteWidth == 1) - iformat = lit("ubyte"); - else if(draw->indexByteWidth == 2) - iformat = lit("ushort"); - else if(draw->indexByteWidth == 4) - iformat = lit("uint"); - iformat += lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(draw->topology)); - } + if(state.inputAssembly.indexBuffer.byteStride == 1) + iformat = lit("ubyte"); + else if(state.inputAssembly.indexBuffer.byteStride == 2) + iformat = lit("ushort"); + else if(state.inputAssembly.indexBuffer.byteStride == 4) + iformat = lit("uint"); - node->setTag( - QVariant::fromValue(D3D11VBIBTag(state.inputAssembly.indexBuffer.resourceId, - state.inputAssembly.indexBuffer.byteOffset + - (draw ? draw->indexOffset * draw->indexByteWidth : 0), - iformat))); + iformat += + lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(state.inputAssembly.topology)); + + node->setTag(QVariant::fromValue(D3D11VBIBTag( + state.inputAssembly.indexBuffer.resourceId, + state.inputAssembly.indexBuffer.byteOffset + + (draw ? draw->indexOffset * state.inputAssembly.indexBuffer.byteStride : 0), + iformat))); setEmptyRow(node); m_EmptyNodes.push_back(node); @@ -2537,13 +2534,10 @@ void D3D11PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D11Pipe } QString ifmt = lit("UNKNOWN"); - if(draw) - { - if(draw->indexByteWidth == 2) - ifmt = lit("R16_UINT"); - if(draw->indexByteWidth == 4) - ifmt = lit("R32_UINT"); - } + if(ia.indexBuffer.byteStride == 2) + ifmt = lit("R16_UINT"); + if(ia.indexBuffer.byteStride == 4) + ifmt = lit("R32_UINT"); m_Common.exportHTMLTable(xml, {tr("Buffer"), tr("Format"), tr("Offset"), tr("Byte Length")}, {name, ifmt, ia.indexBuffer.byteOffset, (qulonglong)length}); @@ -2552,8 +2546,7 @@ void D3D11PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D11Pipe xml.writeStartElement(lit("p")); xml.writeEndElement(); - m_Common.exportHTMLTable(xml, {tr("Primitive Topology")}, - {ToQStr(draw ? draw->topology : Topology::Unknown)}); + m_Common.exportHTMLTable(xml, {tr("Primitive Topology")}, {ToQStr(ia.topology)}); } void D3D11PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D11Pipe::Shader &sh) diff --git a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp index c42dc1550..9bce01ea6 100644 --- a/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/D3D12PipelineStateViewer.cpp @@ -1453,19 +1453,17 @@ void D3D12PipelineStateViewer::setState() ui->iaLayouts->endUpdate(); ui->iaLayouts->verticalScrollBar()->setValue(vs); - Topology topo = draw ? draw->topology : Topology::Unknown; - - int numCPs = PatchList_Count(topo); + int numCPs = PatchList_Count(state.inputAssembly.topology); if(numCPs > 0) { ui->topology->setText(tr("PatchList (%1 Control Points)").arg(numCPs)); } else { - ui->topology->setText(ToQStr(topo)); + ui->topology->setText(ToQStr(state.inputAssembly.topology)); } - m_Common.setTopologyDiagram(ui->topologyDiagram, topo); + m_Common.setTopologyDiagram(ui->topologyDiagram, state.inputAssembly.topology); bool ibufferUsed = draw && (draw->flags & DrawFlags::Indexed); @@ -1485,23 +1483,24 @@ void D3D12PipelineStateViewer::setState() BufferDescription *buf = m_Ctx.GetBuffer(state.inputAssembly.indexBuffer.resourceId); RDTreeWidgetItem *node = new RDTreeWidgetItem( - {tr("Index"), state.inputAssembly.indexBuffer.resourceId, draw ? draw->indexByteWidth : 0, + {tr("Index"), state.inputAssembly.indexBuffer.resourceId, + (qulonglong)state.inputAssembly.indexBuffer.byteStride, (qulonglong)state.inputAssembly.indexBuffer.byteOffset, (qulonglong)length, QString()}); QString iformat; - if(draw) - { - if(draw->indexByteWidth == 1) - iformat = lit("ubyte"); - else if(draw->indexByteWidth == 2) - iformat = lit("ushort"); - else if(draw->indexByteWidth == 4) - iformat = lit("uint"); - iformat += lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(draw->topology)); - } + if(state.inputAssembly.indexBuffer.byteStride == 1) + iformat = lit("ubyte"); + else if(state.inputAssembly.indexBuffer.byteStride == 2) + iformat = lit("ushort"); + else if(state.inputAssembly.indexBuffer.byteStride == 4) + iformat = lit("uint"); - uint32_t drawOffset = (draw ? draw->indexOffset * draw->indexByteWidth : 0); + iformat += + lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(state.inputAssembly.topology)); + + uint32_t drawOffset = + (draw ? draw->indexOffset * state.inputAssembly.indexBuffer.byteStride : 0); node->setTag(QVariant::fromValue( D3D12VBIBTag(state.inputAssembly.indexBuffer.resourceId, @@ -1540,19 +1539,19 @@ void D3D12PipelineStateViewer::setState() {tr("Index"), tr("No Buffer Set"), lit("-"), lit("-"), lit("-"), QString()}); QString iformat; - if(draw) - { - if(draw->indexByteWidth == 1) - iformat = lit("ubyte"); - else if(draw->indexByteWidth == 2) - iformat = lit("ushort"); - else if(draw->indexByteWidth == 4) - iformat = lit("uint"); - iformat += lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(draw->topology)); - } + if(state.inputAssembly.indexBuffer.byteStride == 1) + iformat = lit("ubyte"); + else if(state.inputAssembly.indexBuffer.byteStride == 2) + iformat = lit("ushort"); + else if(state.inputAssembly.indexBuffer.byteStride == 4) + iformat = lit("uint"); - uint32_t drawOffset = (draw ? draw->indexOffset * draw->indexByteWidth : 0); + iformat += + lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(state.inputAssembly.topology)); + + uint32_t drawOffset = + (draw ? draw->indexOffset * state.inputAssembly.indexBuffer.byteStride : 0); node->setTag(QVariant::fromValue( D3D12VBIBTag(state.inputAssembly.indexBuffer.resourceId, @@ -2557,13 +2556,11 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe length = qMin(length, (uint64_t)ia.indexBuffer.byteSize); QString ifmt = lit("UNKNOWN"); - if(draw) - { - if(draw->indexByteWidth == 2) - ifmt = lit("R16_UINT"); - if(draw->indexByteWidth == 4) - ifmt = lit("R32_UINT"); - } + + if(ia.indexBuffer.byteStride == 2) + ifmt = lit("R16_UINT"); + if(ia.indexBuffer.byteStride == 4) + ifmt = lit("R32_UINT"); m_Common.exportHTMLTable(xml, {tr("Buffer"), tr("Format"), tr("Offset"), tr("Byte Length")}, {name, ifmt, (qulonglong)ia.indexBuffer.byteOffset, (qulonglong)length}); @@ -2572,8 +2569,7 @@ void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe xml.writeStartElement(lit("p")); xml.writeEndElement(); - m_Common.exportHTMLTable(xml, {tr("Primitive Topology")}, - {ToQStr(draw ? draw->topology : Topology::Unknown)}); + m_Common.exportHTMLTable(xml, {tr("Primitive Topology")}, {ToQStr(ia.topology)}); } void D3D12PipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const D3D12Pipe::Shader &sh, diff --git a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp index 9497847dd..57694b14d 100644 --- a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp @@ -1329,19 +1329,17 @@ void GLPipelineStateViewer::setState() ui->viAttrs->endUpdate(); ui->viAttrs->verticalScrollBar()->setValue(vs); - Topology topo = draw ? draw->topology : Topology::Unknown; - - int numCPs = PatchList_Count(topo); + int numCPs = PatchList_Count(state.vertexInput.topology); if(numCPs > 0) { ui->topology->setText(tr("PatchList (%1 Control Points)").arg(numCPs)); } else { - ui->topology->setText(ToQStr(topo)); + ui->topology->setText(ToQStr(state.vertexInput.topology)); } - m_Common.setTopologyDiagram(ui->topologyDiagram, topo); + m_Common.setTopologyDiagram(ui->topologyDiagram, state.vertexInput.topology); bool ibufferUsed = draw && (draw->flags & DrawFlags::Indexed); @@ -1383,25 +1381,26 @@ void GLPipelineStateViewer::setState() length = buf->length; RDTreeWidgetItem *node = new RDTreeWidgetItem({tr("Element"), state.vertexInput.indexBuffer, - draw ? draw->indexByteWidth : 0, 0, 0, + state.vertexInput.indexByteStride, 0, 0, (qulonglong)length, QString()}); QString iformat; if(draw) { - if(draw->indexByteWidth == 1) + if(state.vertexInput.indexByteStride == 1) iformat = lit("ubyte"); - else if(draw->indexByteWidth == 2) + else if(state.vertexInput.indexByteStride == 2) iformat = lit("ushort"); - else if(draw->indexByteWidth == 4) + else if(state.vertexInput.indexByteStride == 4) iformat = lit("uint"); - iformat += lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(draw->topology)); + iformat += + lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(state.vertexInput.topology)); } - node->setTag(QVariant::fromValue(GLVBIBTag(state.vertexInput.indexBuffer, - draw ? draw->indexOffset * draw->indexByteWidth : 0, - iformat))); + node->setTag(QVariant::fromValue( + GLVBIBTag(state.vertexInput.indexBuffer, + draw ? draw->indexOffset * state.vertexInput.indexByteStride : 0, iformat))); if(!ibufferUsed) setInactiveRow(node); @@ -1425,19 +1424,20 @@ void GLPipelineStateViewer::setState() QString iformat; if(draw) { - if(draw->indexByteWidth == 1) + if(state.vertexInput.indexByteStride == 1) iformat = lit("ubyte"); - else if(draw->indexByteWidth == 2) + else if(state.vertexInput.indexByteStride == 2) iformat = lit("ushort"); - else if(draw->indexByteWidth == 4) + else if(state.vertexInput.indexByteStride == 4) iformat = lit("uint"); - iformat += lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(draw->topology)); + iformat += + lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(state.vertexInput.topology)); } - node->setTag(QVariant::fromValue(GLVBIBTag(state.vertexInput.indexBuffer, - draw ? draw->indexOffset * draw->indexByteWidth : 0, - iformat))); + node->setTag(QVariant::fromValue( + GLVBIBTag(state.vertexInput.indexBuffer, + draw ? draw->indexOffset * state.vertexInput.indexByteStride : 0, iformat))); setEmptyRow(node); m_EmptyNodes.push_back(node); @@ -2510,11 +2510,11 @@ void GLPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const GLPipe::Vert QString ifmt = lit("UNKNOWN"); if(draw) { - if(draw->indexByteWidth == 1) + if(vtx.indexByteStride == 1) ifmt = lit("UNSIGNED_BYTE"); - else if(draw->indexByteWidth == 2) + else if(vtx.indexByteStride == 2) ifmt = lit("UNSIGNED_SHORT"); - else if(draw->indexByteWidth == 4) + else if(vtx.indexByteStride == 4) ifmt = lit("UNSIGNED_INT"); } @@ -2526,7 +2526,7 @@ void GLPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const GLPipe::Vert xml.writeEndElement(); m_Common.exportHTMLTable(xml, {tr("Primitive Topology")}, - {ToQStr(draw ? draw->topology : Topology::Unknown)}); + {ToQStr(draw ? vtx.topology : Topology::Unknown)}); { xml.writeStartElement(tr("h3")); diff --git a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp index fe4cc222b..852f0ba8e 100644 --- a/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/VulkanPipelineStateViewer.cpp @@ -1950,19 +1950,17 @@ void VulkanPipelineStateViewer::setState() m_VBNodes.clear(); m_EmptyNodes.clear(); - Topology topo = draw != NULL ? draw->topology : Topology::Unknown; - - int numCPs = PatchList_Count(topo); + int numCPs = PatchList_Count(state.inputAssembly.topology); if(numCPs > 0) { ui->topology->setText(tr("PatchList (%1 Control Points)").arg(numCPs)); } else { - ui->topology->setText(ToQStr(topo)); + ui->topology->setText(ToQStr(state.inputAssembly.topology)); } - m_Common.setTopologyDiagram(ui->topologyDiagram, topo); + m_Common.setTopologyDiagram(ui->topologyDiagram, state.inputAssembly.topology); ui->primRestart->setVisible(state.inputAssembly.primitiveRestartEnable); @@ -1989,26 +1987,25 @@ void VulkanPipelineStateViewer::setState() RDTreeWidgetItem *node = new RDTreeWidgetItem( {tr("Index"), state.inputAssembly.indexBuffer.resourceId, tr("Index"), lit("-"), (qulonglong)state.inputAssembly.indexBuffer.byteOffset, - draw != NULL ? draw->indexByteWidth : 0, (qulonglong)length, QString()}); + (qulonglong)state.inputAssembly.indexBuffer.byteStride, (qulonglong)length, QString()}); QString iformat; - if(draw) - { - if(draw->indexByteWidth == 1) - iformat = lit("ubyte"); - else if(draw->indexByteWidth == 2) - iformat = lit("ushort"); - else if(draw->indexByteWidth == 4) - iformat = lit("uint"); - iformat += lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(draw->topology)); - } + if(state.inputAssembly.indexBuffer.byteStride == 1) + iformat = lit("ubyte"); + else if(state.inputAssembly.indexBuffer.byteStride == 2) + iformat = lit("ushort"); + else if(state.inputAssembly.indexBuffer.byteStride == 4) + iformat = lit("uint"); - node->setTag(QVariant::fromValue( - VulkanVBIBTag(state.inputAssembly.indexBuffer.resourceId, - state.inputAssembly.indexBuffer.byteOffset + - (draw ? draw->indexOffset * draw->indexByteWidth : 0), - iformat))); + iformat += + lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(state.inputAssembly.topology)); + + node->setTag(QVariant::fromValue(VulkanVBIBTag( + state.inputAssembly.indexBuffer.resourceId, + state.inputAssembly.indexBuffer.byteOffset + + (draw ? draw->indexOffset * state.inputAssembly.indexBuffer.byteStride : 0), + iformat))); if(!ibufferUsed) setInactiveRow(node); @@ -2030,23 +2027,22 @@ void VulkanPipelineStateViewer::setState() lit("-"), lit("-"), lit("-"), QString()}); QString iformat; - if(draw) - { - if(draw->indexByteWidth == 1) - iformat = lit("ubyte"); - else if(draw->indexByteWidth == 2) - iformat = lit("ushort"); - else if(draw->indexByteWidth == 4) - iformat = lit("uint"); - iformat += lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(draw->topology)); - } + if(state.inputAssembly.indexBuffer.byteStride == 1) + iformat = lit("ubyte"); + else if(state.inputAssembly.indexBuffer.byteStride == 2) + iformat = lit("ushort"); + else if(state.inputAssembly.indexBuffer.byteStride == 4) + iformat = lit("uint"); - node->setTag(QVariant::fromValue( - VulkanVBIBTag(state.inputAssembly.indexBuffer.resourceId, - state.inputAssembly.indexBuffer.byteOffset + - (draw ? draw->indexOffset * draw->indexByteWidth : 0), - iformat))); + iformat += + lit(" indices[%1]").arg(RENDERDOC_NumVerticesPerPrimitive(state.inputAssembly.topology)); + + node->setTag(QVariant::fromValue(VulkanVBIBTag( + state.inputAssembly.indexBuffer.resourceId, + state.inputAssembly.indexBuffer.byteOffset + + (draw ? draw->indexOffset * state.inputAssembly.indexBuffer.byteStride : 0), + iformat))); setEmptyRow(node); m_EmptyNodes.push_back(node); @@ -3149,15 +3145,13 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe:: } QString ifmt = lit("UNKNOWN"); - if(draw) - { - if(draw->indexByteWidth == 1) - ifmt = lit("UINT8"); - else if(draw->indexByteWidth == 2) - ifmt = lit("UINT16"); - else if(draw->indexByteWidth == 4) - ifmt = lit("UINT32"); - } + + if(ia.indexBuffer.byteStride == 1) + ifmt = lit("UINT8"); + else if(ia.indexBuffer.byteStride == 2) + ifmt = lit("UINT16"); + else if(ia.indexBuffer.byteStride == 4) + ifmt = lit("UINT32"); m_Common.exportHTMLTable( xml, {tr("Buffer"), tr("Format"), tr("Offset"), tr("Byte Length"), tr("Primitive Restart")}, @@ -3168,9 +3162,9 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe:: xml.writeStartElement(lit("p")); xml.writeEndElement(); - m_Common.exportHTMLTable(xml, {tr("Primitive Topology"), tr("Tessellation Control Points")}, - {ToQStr(draw ? draw->topology : Topology::Unknown), - m_Ctx.CurVulkanPipelineState()->tessellation.numControlPoints}); + m_Common.exportHTMLTable( + xml, {tr("Primitive Topology"), tr("Tessellation Control Points")}, + {ToQStr(ia.topology), m_Ctx.CurVulkanPipelineState()->tessellation.numControlPoints}); } void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe::Shader &sh) diff --git a/qrenderdoc/Windows/PixelHistoryView.cpp b/qrenderdoc/Windows/PixelHistoryView.cpp index 7a903e89c..53c6d9ee8 100644 --- a/qrenderdoc/Windows/PixelHistoryView.cpp +++ b/qrenderdoc/Windows/PixelHistoryView.cpp @@ -798,7 +798,8 @@ void PixelHistoryView::jumpToPrimitive(EventTag tag) if(draw) { - uint32_t vertIdx = RENDERDOC_VertexOffset(draw->topology, tag.primitive); + uint32_t vertIdx = + RENDERDOC_VertexOffset(m_Ctx.CurPipelineState().GetPrimitiveTopology(), tag.primitive); if(vertIdx != ~0U) viewer->ScrollToRow(vertIdx); diff --git a/renderdoc/api/replay/d3d11_pipestate.h b/renderdoc/api/replay/d3d11_pipestate.h index 1424f4968..106f5c573 100644 --- a/renderdoc/api/replay/d3d11_pipestate.h +++ b/renderdoc/api/replay/d3d11_pipestate.h @@ -152,6 +152,11 @@ struct IndexBuffer DOCUMENT("The byte offset from the start of the buffer to the beginning of the index data."); uint32_t byteOffset = 0; + + DOCUMENT(R"(The number of bytes for each index in the index buffer. Typically 2 or 4 bytes but +it can be 0 if no index buffer is bound. +)"); + uint32_t byteStride = 0; }; DOCUMENT("Describes the input assembler data."); @@ -188,6 +193,12 @@ struct InputAssembly :type: D3D11IndexBuffer )"); IndexBuffer indexBuffer; + + DOCUMENT(R"(The current primitive topology. + +:type: Topology +)"); + Topology topology = Topology::Unknown; }; DOCUMENT("Describes the details of a D3D11 resource view - any one of UAV, SRV, RTV or DSV."); diff --git a/renderdoc/api/replay/d3d12_pipestate.h b/renderdoc/api/replay/d3d12_pipestate.h index 7754b49f5..b21139bde 100644 --- a/renderdoc/api/replay/d3d12_pipestate.h +++ b/renderdoc/api/replay/d3d12_pipestate.h @@ -157,6 +157,11 @@ struct IndexBuffer DOCUMENT("The number of bytes available in this index buffer."); uint32_t byteSize = 0; + + DOCUMENT(R"(The number of bytes for each index in the index buffer. Typically 2 or 4 bytes but +it can be 0 if no index buffer is bound. +)"); + uint32_t byteStride = 0; }; DOCUMENT("Describes the input assembler state in the PSO."); @@ -189,6 +194,12 @@ struct InputAssembly If the value is 0, strip cutting is disabled. )"); uint32_t indexStripCutValue = 0; + + DOCUMENT(R"(The current primitive topology. + +:type: Topology +)"); + Topology topology = Topology::Unknown; }; // immediate indicates either a root parameter (not in a table), or static samplers diff --git a/renderdoc/api/replay/data_types.h b/renderdoc/api/replay/data_types.h index 955569ef5..b7dab2eeb 100644 --- a/renderdoc/api/replay/data_types.h +++ b/renderdoc/api/replay/data_types.h @@ -1559,9 +1559,6 @@ struct DrawcallDescription dispatchThreadsDimension[0] = dispatchThreadsDimension[1] = dispatchThreadsDimension[2] = 0; dispatchBase[0] = dispatchBase[1] = dispatchBase[2] = 0; - indexByteWidth = 0; - topology = Topology::Unknown; - copySource = ResourceId(); copyDestination = ResourceId(); @@ -1638,15 +1635,6 @@ struct DrawcallDescription )"); rdcfixedarray dispatchBase; - DOCUMENT(R"(The width in bytes of each index. - -Valid values are 1 (depending on API), 2 or 4, or 0 if the drawcall is not an indexed draw. -)"); - uint32_t indexByteWidth; - - DOCUMENT("The :class:`Topology` used in this drawcall."); - Topology topology; - DOCUMENT(R"(The :class:`ResourceId` identifying the source object in a copy, resolve or blit operation. )"); diff --git a/renderdoc/api/replay/gl_pipestate.h b/renderdoc/api/replay/gl_pipestate.h index 0ebb8259e..d8bb4b1a9 100644 --- a/renderdoc/api/replay/gl_pipestate.h +++ b/renderdoc/api/replay/gl_pipestate.h @@ -160,6 +160,21 @@ struct VertexInput DOCUMENT("The :class:`ResourceId` of the index buffer."); ResourceId indexBuffer; + DOCUMENT(R"(The byte width of the index buffer - typically 1, 2 or 4 bytes. It can be 0 for +non-indexed draws. + +.. note:: + This does not correspond to a real GL state since the index type is specified per-draw in the call + itself. This is an implicit state derived from the last (or current) drawcall at any given event. +)"); + uint32_t indexByteStride = 0; + DOCUMENT(R"(The byte width of the index buffer - typically 1, 2 or 4 bytes. + +.. note:: + This does not correspond to a real GL state since the topology is specified per-draw in the call + itself. This is an implicit state derived from the last (or current) drawcall at any given event. +)"); + Topology topology = Topology::Unknown; DOCUMENT("``True`` if primitive restart is enabled for strip primitives."); bool primitiveRestart = false; DOCUMENT("The index value to use to indicate a strip restart."); diff --git a/renderdoc/api/replay/pipestate.h b/renderdoc/api/replay/pipestate.h index 2b0769ac3..0f341d699 100644 --- a/renderdoc/api/replay/pipestate.h +++ b/renderdoc/api/replay/pipestate.h @@ -259,9 +259,26 @@ For some APIs that don't distinguish by entry point, this may be empty. )"); ResourceId GetShader(ShaderStage stage) const; + DOCUMENT(R"(Returns the current primitive topology. + +.. note:: + On OpenGL the primitive topology is not part of any state, but is specified in each drawcall. + In this case the current topology is whichever was last specified to a drawcall, as if there was + implicit state set by a draw. + +:return: The current primitive topology. +:rtype: Topology +)"); + Topology GetPrimitiveTopology() const; + DOCUMENT(R"(Retrieves the current index buffer binding. -:return: A :class:`BoundVBuffer` with the index buffer details. The stride is always 0. +.. note:: + On OpenGL the index stride/width is not part of any state, but is specified in each drawcall. + In this case the current stride is whichever was last specified to a drawcall, as if there was + implicit state set by a draw. + +:return: A :class:`BoundVBuffer` with the index buffer details :rtype: BoundVBuffer )"); BoundVBuffer GetIBuffer() const; diff --git a/renderdoc/api/replay/pipestate.inl b/renderdoc/api/replay/pipestate.inl index e11eb9817..77c779480 100644 --- a/renderdoc/api/replay/pipestate.inl +++ b/renderdoc/api/replay/pipestate.inl @@ -474,24 +474,28 @@ BoundVBuffer PipeState::GetIBuffer() const { ret.resourceId = m_D3D11->inputAssembly.indexBuffer.resourceId; ret.byteOffset = m_D3D11->inputAssembly.indexBuffer.byteOffset; + ret.byteStride = m_D3D11->inputAssembly.indexBuffer.byteStride; ret.byteSize = ~0ULL; } else if(IsCaptureD3D12()) { ret.resourceId = m_D3D12->inputAssembly.indexBuffer.resourceId; ret.byteOffset = m_D3D12->inputAssembly.indexBuffer.byteOffset; + ret.byteStride = m_D3D12->inputAssembly.indexBuffer.byteStride; ret.byteSize = m_D3D12->inputAssembly.indexBuffer.byteSize; } else if(IsCaptureGL()) { ret.resourceId = m_GL->vertexInput.indexBuffer; ret.byteOffset = 0; // GL only has per-draw index offset + ret.byteStride = m_GL->vertexInput.indexByteStride; ret.byteSize = ~0ULL; } else if(IsCaptureVK()) { ret.resourceId = m_Vulkan->inputAssembly.indexBuffer.resourceId; ret.byteOffset = m_Vulkan->inputAssembly.indexBuffer.byteOffset; + ret.byteStride = m_Vulkan->inputAssembly.indexBuffer.byteStride; ret.byteSize = ~0ULL; } } @@ -602,6 +606,31 @@ rdcarray PipeState::GetVBuffers() const return ret; } +Topology PipeState::GetPrimitiveTopology() const +{ + if(IsCaptureLoaded()) + { + if(IsCaptureD3D11()) + { + return m_D3D11->inputAssembly.topology; + } + else if(IsCaptureD3D12()) + { + return m_D3D12->inputAssembly.topology; + } + else if(IsCaptureVK()) + { + return m_Vulkan->inputAssembly.topology; + } + else if(IsCaptureGL()) + { + return m_GL->vertexInput.topology; + } + } + + return Topology::Unknown; +} + rdcarray PipeState::GetVertexInputs() const { auto striequal = [](const rdcstr &a, const rdcstr &b) { diff --git a/renderdoc/api/replay/vk_pipestate.h b/renderdoc/api/replay/vk_pipestate.h index eb252c21e..34627d925 100644 --- a/renderdoc/api/replay/vk_pipestate.h +++ b/renderdoc/api/replay/vk_pipestate.h @@ -358,6 +358,11 @@ struct IndexBuffer DOCUMENT("The byte offset from the start of the buffer to the beginning of the index data."); uint64_t byteOffset = 0; + + DOCUMENT(R"(The number of bytes for each index in the index buffer. Typically 2 or 4 bytes but +it can be 0 if no index buffer is bound. +)"); + uint32_t byteStride = 0; }; DOCUMENT("Describes the vulkan input assembly configuration."); @@ -376,6 +381,12 @@ struct InputAssembly :type: VKIndexBuffer )"); IndexBuffer indexBuffer; + + DOCUMENT(R"(The current primitive topology. + +:type: Topology +)"); + Topology topology = Topology::Unknown; }; DOCUMENT("Describes the configuration of a single vertex attribute."); diff --git a/renderdoc/driver/d3d11/d3d11_context.cpp b/renderdoc/driver/d3d11/d3d11_context.cpp index fec80100c..12db15bb9 100644 --- a/renderdoc/driver/d3d11/d3d11_context.cpp +++ b/renderdoc/driver/d3d11/d3d11_context.cpp @@ -1124,14 +1124,6 @@ void WrappedID3D11DeviceContext::AddDrawcall(const DrawcallDescription &d, bool draw.eventId = m_CurEventID; draw.drawcallId = m_CurDrawcallID; - draw.indexByteWidth = 0; - if(m_CurrentPipelineState->IA.IndexFormat == DXGI_FORMAT_R16_UINT) - draw.indexByteWidth = 2; - if(m_CurrentPipelineState->IA.IndexFormat == DXGI_FORMAT_R32_UINT) - draw.indexByteWidth = 4; - - draw.topology = MakePrimitiveTopology(m_CurrentPipelineState->IA.Topo); - for(int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { draw.outputs[i] = ResourceId(); diff --git a/renderdoc/driver/d3d11/d3d11_pixelhistory.cpp b/renderdoc/driver/d3d11/d3d11_pixelhistory.cpp index 6b9572eb7..92a241ce6 100644 --- a/renderdoc/driver/d3d11/d3d11_pixelhistory.cpp +++ b/renderdoc/driver/d3d11/d3d11_pixelhistory.cpp @@ -2399,21 +2399,24 @@ rdcarray D3D11Replay::PixelHistory(rdcarray event m_pImmediateContext->Begin(testQueries[0]); + Topology topo = + MakePrimitiveTopology(m_pImmediateContext->GetCurrentPipelineState()->IA.Topo); + // do draw if(draw->flags & DrawFlags::Indexed) { // TODO once pixel history distinguishes between instances, draw only the instance for // this fragment m_pImmediateContext->DrawIndexedInstanced( - RENDERDOC_NumVerticesPerPrimitive(draw->topology), RDCMAX(1U, draw->numInstances), - draw->indexOffset + RENDERDOC_VertexOffset(draw->topology, history[h].primitiveID), + RENDERDOC_NumVerticesPerPrimitive(topo), RDCMAX(1U, draw->numInstances), + draw->indexOffset + RENDERDOC_VertexOffset(topo, history[h].primitiveID), draw->baseVertex, draw->instanceOffset); } else { m_pImmediateContext->DrawInstanced( - RENDERDOC_NumVerticesPerPrimitive(draw->topology), RDCMAX(1U, draw->numInstances), - draw->vertexOffset + RENDERDOC_VertexOffset(draw->topology, history[h].primitiveID), + RENDERDOC_NumVerticesPerPrimitive(topo), RDCMAX(1U, draw->numInstances), + draw->vertexOffset + RENDERDOC_VertexOffset(topo, history[h].primitiveID), draw->instanceOffset); } diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index a9061d4af..7979e16ac 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -740,6 +740,15 @@ void D3D11Replay::SavePipelineState(uint32_t eventId) ret.inputAssembly.indexBuffer.resourceId = rm->GetOriginalID(GetIDForDeviceChild(rs->IA.IndexBuffer)); ret.inputAssembly.indexBuffer.byteOffset = rs->IA.IndexOffset; + switch(rs->IA.IndexFormat) + { + case DXGI_FORMAT_R32_UINT: ret.inputAssembly.indexBuffer.byteStride = 4; break; + case DXGI_FORMAT_R16_UINT: ret.inputAssembly.indexBuffer.byteStride = 2; break; + case DXGI_FORMAT_R8_UINT: ret.inputAssembly.indexBuffer.byteStride = 1; break; + default: ret.inputAssembly.indexBuffer.byteStride = 0; break; + } + + ret.inputAssembly.topology = MakePrimitiveTopology(rs->IA.Topo); ///////////////////////////////////////////////// // Shaders diff --git a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp index 9fac17368..fedba9988 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp @@ -3690,8 +3690,6 @@ void WrappedID3D12GraphicsCommandList::PatchExecuteIndirect(BakedCmdListInfo &in DrawFlags::Indirect; curDraw.name = StringFormat::Fmt("[%u] arg%u: IndirectDrawIndexed(<%u, %u>)", i, a, curDraw.numIndices, curDraw.numInstances); - curDraw.topology = MakePrimitiveTopology(state.topo); - curDraw.indexByteWidth = state.ibuffer.bytewidth; fakeChunk->name = curDraw.name; diff --git a/renderdoc/driver/d3d12/d3d12_commands.cpp b/renderdoc/driver/d3d12/d3d12_commands.cpp index 4073104f3..74f1ed76b 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.cpp +++ b/renderdoc/driver/d3d12/d3d12_commands.cpp @@ -1858,14 +1858,8 @@ void D3D12CommandData::AddDrawcall(const DrawcallDescription &d, bool hasEvents, draw.depthOut = ResourceId(); - draw.indexByteWidth = 0; - draw.topology = Topology::Unknown; - if(m_LastCmdListID != ResourceId()) { - draw.topology = MakePrimitiveTopology(m_BakedCmdListInfo[m_LastCmdListID].state.topo); - draw.indexByteWidth = m_BakedCmdListInfo[m_LastCmdListID].state.ibuffer.bytewidth; - rdcarray rts = m_BakedCmdListInfo[m_LastCmdListID].state.GetRTVIDs(); for(size_t i = 0; i < ARRAY_COUNT(draw.outputs); i++) diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index ba04fd7df..4dc3793c8 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -1390,6 +1390,9 @@ void D3D12Replay::SavePipelineState(uint32_t eventId) state.inputAssembly.indexBuffer.resourceId = rm->GetOriginalID(rs.ibuffer.buf); state.inputAssembly.indexBuffer.byteOffset = rs.ibuffer.offs; state.inputAssembly.indexBuffer.byteSize = rs.ibuffer.size; + state.inputAssembly.indexBuffer.byteStride = rs.ibuffer.bytewidth; + + state.inputAssembly.topology = MakePrimitiveTopology(rs.topo); } ///////////////////////////////////////////////// diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 2422e9686..10212b330 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -5542,6 +5542,10 @@ void WrappedOpenGL::AddDrawcall(const DrawcallDescription &d, bool hasEvents) draw.eventId = m_CurEventID; draw.drawcallId = m_CurDrawcallID; + m_DrawcallParams.resize_for_index(m_CurEventID); + m_DrawcallParams[m_CurEventID].indexWidth = m_LastIndexWidth; + m_DrawcallParams[m_CurEventID].topo = m_LastTopology; + GLenum type; GLuint curCol[8] = {0}; GLuint curDepth = 0; @@ -5647,6 +5651,12 @@ const DrawcallDescription *WrappedOpenGL::GetDrawcall(uint32_t eventId) return m_Drawcalls[eventId]; } +const GLDrawParams &WrappedOpenGL::GetDrawcallParameters(uint32_t eventId) +{ + m_DrawcallParams.resize_for_index(eventId); + return m_DrawcallParams[eventId]; +} + void WrappedOpenGL::ReplayLog(uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType) { bool partial = true; diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index 42997415b..6ff7a2670 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -96,6 +96,12 @@ struct ContextShareGroup } }; +struct GLDrawParams +{ + uint32_t indexWidth = 0; + Topology topo = Topology::Unknown; +}; + class WrappedOpenGL : public IFrameCapturer { private: @@ -264,6 +270,7 @@ private: rdcarray m_CapturedFrames; rdcarray m_Drawcalls; + rdcarray m_DrawcallParams; // replay @@ -292,6 +299,9 @@ private: DrawcallDescription m_ParentDrawcall; + Topology m_LastTopology = Topology::Unknown; + uint32_t m_LastIndexWidth = 0; + rdcarray m_DrawcallStack; std::map> m_ResourceUses; @@ -648,6 +658,7 @@ public: const DrawcallDescription &GetRootDraw() { return m_ParentDrawcall; } const DrawcallDescription *GetDrawcall(uint32_t eventId); + const GLDrawParams &GetDrawcallParameters(uint32_t eventId); void SuppressDebugMessages(bool suppress) { m_SuppressDebugMessages = suppress; } rdcarray GetUsage(ResourceId id) { return m_ResourceUses[id]; } diff --git a/renderdoc/driver/gl/gl_overlay.cpp b/renderdoc/driver/gl/gl_overlay.cpp index 5884071a1..7e61a66a1 100644 --- a/renderdoc/driver/gl/gl_overlay.cpp +++ b/renderdoc/driver/gl/gl_overlay.cpp @@ -732,6 +732,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug drv.glGetIntegerv(eGL_ELEMENT_ARRAY_BUFFER_BINDING, &idxbuf); const DrawcallDescription *draw = m_pDriver->GetDrawcall(eventId); + const GLDrawParams &drawParams = m_pDriver->GetDrawcallParameters(eventId); rdcarray patchedIndices; @@ -739,7 +740,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug if(idxbuf) { rdcarray idxs; - uint32_t offset = draw->indexOffset * draw->indexByteWidth; + uint32_t offset = draw->indexOffset * drawParams.indexWidth; uint32_t length = 1; drv.glGetNamedBufferParameterivEXT(idxbuf, eGL_BUFFER_SIZE, (GLint *)&length); @@ -747,13 +748,13 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug drv.glGetBufferSubData( eGL_ELEMENT_ARRAY_BUFFER, offset, RDCMIN(GLsizeiptr(length - offset), - GLsizeiptr(draw->numIndices) * GLsizeiptr(draw->indexByteWidth)), + GLsizeiptr(draw->numIndices) * GLsizeiptr(drawParams.indexWidth)), &idxs[0]); // unbind the real index buffer drv.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, 0); - uint32_t expectedSize = draw->numIndices * draw->indexByteWidth; + uint32_t expectedSize = draw->numIndices * drawParams.indexWidth; if(idxs.size() < expectedSize) { @@ -762,9 +763,10 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug } PatchLineStripIndexBuffer( - draw, draw->indexByteWidth == 1 ? (uint8_t *)idxs.data() : (uint8_t *)NULL, - draw->indexByteWidth == 2 ? (uint16_t *)idxs.data() : (uint16_t *)NULL, - draw->indexByteWidth == 4 ? (uint32_t *)idxs.data() : (uint32_t *)NULL, patchedIndices); + draw, drawParams.topo, + drawParams.indexWidth == 1 ? (uint8_t *)idxs.data() : (uint8_t *)NULL, + drawParams.indexWidth == 2 ? (uint16_t *)idxs.data() : (uint16_t *)NULL, + drawParams.indexWidth == 4 ? (uint32_t *)idxs.data() : (uint32_t *)NULL, patchedIndices); } else { @@ -773,7 +775,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, Debug idxs.resize(draw->numIndices); for(uint32_t i = 0; i < draw->numIndices; i++) idxs[i] = i; - PatchLineStripIndexBuffer(draw, NULL, NULL, idxs.data(), patchedIndices); + PatchLineStripIndexBuffer(draw, drawParams.topo, NULL, NULL, idxs.data(), patchedIndices); } GLboolean primRestart = drv.glIsEnabled(eGL_PRIMITIVE_RESTART_FIXED_INDEX); diff --git a/renderdoc/driver/gl/gl_postvs.cpp b/renderdoc/driver/gl/gl_postvs.cpp index 28a4c18e4..33f07a461 100644 --- a/renderdoc/driver/gl/gl_postvs.cpp +++ b/renderdoc/driver/gl/gl_postvs.cpp @@ -266,6 +266,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) GLuint stageSrcPrograms[4] = {}; const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eventId); + const GLDrawParams &drawParams = m_pDriver->GetDrawcallParameters(eventId); if(drawcall->numIndices == 0 || !(drawcall->flags & DrawFlags::Drawcall) || ((drawcall->flags & DrawFlags::Instanced) && drawcall->numInstances == 0)) @@ -803,8 +804,8 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) ResourceId idxId = rm->GetResID(BufferRes(drv.GetCtx(), elArrayBuffer)); bytebuf idxdata; - GetBufferData(idxId, drawcall->indexOffset * drawcall->indexByteWidth, - drawcall->numIndices * drawcall->indexByteWidth, idxdata); + GetBufferData(idxId, drawcall->indexOffset * drawParams.indexWidth, + drawcall->numIndices * drawParams.indexWidth, idxdata); rdcarray indices; @@ -814,17 +815,17 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) // only read as many indices as were available in the buffer uint32_t numIndices = - RDCMIN(uint32_t(idxdata.size() / drawcall->indexByteWidth), drawcall->numIndices); + RDCMIN(uint32_t(idxdata.size() / drawParams.indexWidth), drawcall->numIndices); // grab all unique vertex indices referenced for(uint32_t i = 0; i < numIndices; i++) { uint32_t i32 = 0; - if(drawcall->indexByteWidth == 1) + if(drawParams.indexWidth == 1) i32 = uint32_t(idx8[i]); - else if(drawcall->indexByteWidth == 2) + else if(drawParams.indexWidth == 2) i32 = uint32_t(idx16[i]); - else if(drawcall->indexByteWidth == 4) + else if(drawParams.indexWidth == 4) i32 = idx32[i]; auto it = std::lower_bound(indices.begin(), indices.end(), i32); @@ -924,7 +925,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) uint32_t stripRestartValue32 = 0; - if(SupportsRestart(drawcall->topology) && + if(SupportsRestart(drawParams.topo) && (rs.Enabled[GLRenderState::eEnabled_PrimitiveRestart] || rs.Enabled[GLRenderState::eEnabled_PrimitiveRestartFixedIndex])) { @@ -935,7 +936,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) // rebase existing index buffer to point from 0 onwards (which will index into our // stream-out'd vertex buffer) - if(drawcall->indexByteWidth == 1) + if(drawParams.indexWidth == 1) { uint8_t stripRestartValue = stripRestartValue32 & 0xff; @@ -948,7 +949,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) idx8[i] = uint8_t(indexRemap[idx8[i]]); } } - else if(drawcall->indexByteWidth == 2) + else if(drawParams.indexWidth == 2) { uint16_t stripRestartValue = stripRestartValue32 & 0xffff; @@ -1116,7 +1117,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) drv.glUnmapNamedBufferEXT(DebugData.feedbackBuffer); // store everything out to the PostVS data cache - m_PostVSData[eventId].vsin.topo = drawcall->topology; + m_PostVSData[eventId].vsin.topo = drawParams.topo; m_PostVSData[eventId].vsout.buf = vsoutBuffer; m_PostVSData[eventId].vsout.vertStride = stride; m_PostVSData[eventId].vsout.nearPlane = nearp; @@ -1131,7 +1132,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) (stride * primsWritten) / RDCMAX(1U, drawcall->numInstances); m_PostVSData[eventId].vsout.idxBuf = 0; - m_PostVSData[eventId].vsout.idxByteWidth = drawcall->indexByteWidth; + m_PostVSData[eventId].vsout.idxByteWidth = drawParams.indexWidth; if(m_PostVSData[eventId].vsout.useIndices && idxBuf) { m_PostVSData[eventId].vsout.idxBuf = idxBuf; @@ -1139,7 +1140,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) m_PostVSData[eventId].vsout.hasPosOut = hasPosition; - m_PostVSData[eventId].vsout.topo = drawcall->topology; + m_PostVSData[eventId].vsout.topo = drawParams.topo; } if(tesRefl || gsRefl) @@ -1430,9 +1431,9 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) maxOutputSize *= drawcall->numInstances; uint32_t numInputPrimitives = drawcall->numIndices; - GLenum drawtopo = MakeGLPrimitiveTopology(drawcall->topology); + GLenum drawtopo = MakeGLPrimitiveTopology(drawParams.topo); - switch(drawcall->topology) + switch(drawParams.topo) { case Topology::Unknown: case Topology::PointList: break; @@ -1478,7 +1479,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) case Topology::PatchList_30CPs: case Topology::PatchList_31CPs: case Topology::PatchList_32CPs: - numInputPrimitives /= PatchList_Count(drawcall->topology); + numInputPrimitives /= PatchList_Count(drawParams.topo); break; } @@ -1552,9 +1553,9 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) } GLenum idxType = eGL_UNSIGNED_BYTE; - if(drawcall->indexByteWidth == 2) + if(drawParams.indexWidth == 2) idxType = eGL_UNSIGNED_SHORT; - else if(drawcall->indexByteWidth == 4) + else if(drawParams.indexWidth == 4) idxType = eGL_UNSIGNED_INT; // instanced draws must be replayed one at a time so we can record the number of primitives @@ -1607,7 +1608,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) drv.glDrawElementsInstancedBaseVertexBaseInstance( drawtopo, drawcall->numIndices, idxType, (const void *)(uintptr_t(drawcall->indexOffset) * - uintptr_t(drawcall->indexByteWidth)), + uintptr_t(drawParams.indexWidth)), inst, drawcall->baseVertex, drawcall->instanceOffset); } else @@ -1615,7 +1616,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) drv.glDrawElementsInstancedBaseVertex( drawtopo, drawcall->numIndices, idxType, (const void *)(uintptr_t(drawcall->indexOffset) * - uintptr_t(drawcall->indexByteWidth)), + uintptr_t(drawParams.indexWidth)), inst, drawcall->baseVertex); } } @@ -1649,16 +1650,14 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) { drv.glDrawElementsInstancedBaseVertexBaseInstance( drawtopo, drawcall->numIndices, idxType, - (const void *)(uintptr_t(drawcall->indexOffset) * - uintptr_t(drawcall->indexByteWidth)), + (const void *)(uintptr_t(drawcall->indexOffset) * uintptr_t(drawParams.indexWidth)), drawcall->numInstances, drawcall->baseVertex, drawcall->instanceOffset); } else { drv.glDrawElementsInstancedBaseVertex( drawtopo, drawcall->numIndices, idxType, - (const void *)(uintptr_t(drawcall->indexOffset) * - uintptr_t(drawcall->indexByteWidth)), + (const void *)(uintptr_t(drawcall->indexOffset) * uintptr_t(drawParams.indexWidth)), drawcall->numInstances, drawcall->baseVertex); } } @@ -1680,7 +1679,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId) { drv.glDrawElementsBaseVertex( drawtopo, drawcall->numIndices, idxType, - (const void *)(uintptr_t(drawcall->indexOffset) * uintptr_t(drawcall->indexByteWidth)), + (const void *)(uintptr_t(drawcall->indexOffset) * uintptr_t(drawParams.indexWidth)), drawcall->baseVertex); } diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 38267cc58..34ae92877 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -810,6 +810,11 @@ void GLReplay::SavePipelineState(uint32_t eventId) ? ~0U : rs.PrimitiveRestartIndex; + const GLDrawParams &drawParams = m_pDriver->GetDrawcallParameters(eventId); + + pipe.vertexInput.indexByteStride = drawParams.indexWidth; + pipe.vertexInput.topology = drawParams.topo; + // Vertex buffers and attributes GLint numVBufferBindings = 16; drv.glGetIntegerv(eGL_MAX_VERTEX_ATTRIB_BINDINGS, &numVBufferBindings); diff --git a/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp index d2d0a56ae..e86c8b34a 100644 --- a/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_draw_funcs.cpp @@ -687,7 +687,7 @@ bool WrappedOpenGL::Serialise_glDrawTransformFeedback(SerialiserType &ser, GLenu draw.flags |= DrawFlags::Drawcall; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddDrawcall(draw, true); } @@ -759,7 +759,7 @@ bool WrappedOpenGL::Serialise_glDrawTransformFeedbackInstanced(SerialiserType &s draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddDrawcall(draw, true); } @@ -830,7 +830,7 @@ bool WrappedOpenGL::Serialise_glDrawTransformFeedbackStream(SerialiserType &ser, draw.flags |= DrawFlags::Drawcall; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddDrawcall(draw, true); } @@ -905,7 +905,7 @@ bool WrappedOpenGL::Serialise_glDrawTransformFeedbackStreamInstanced(SerialiserT draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddDrawcall(draw, true); } @@ -975,7 +975,7 @@ bool WrappedOpenGL::Serialise_glDrawArrays(SerialiserType &ser, GLenum mode, GLi draw.flags |= DrawFlags::Drawcall; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddDrawcall(draw, true); } @@ -1236,7 +1236,7 @@ bool WrappedOpenGL::Serialise_glDrawArraysIndirect(SerialiserType &ser, GLenum m draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced | DrawFlags::Indirect; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddDrawcall(draw, true); @@ -1312,7 +1312,7 @@ bool WrappedOpenGL::Serialise_glDrawArraysInstanced(SerialiserType &ser, GLenum draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddDrawcall(draw, true); } @@ -1392,7 +1392,7 @@ bool WrappedOpenGL::Serialise_glDrawArraysInstancedBaseInstance(SerialiserType & draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddDrawcall(draw, true); } @@ -1472,8 +1472,8 @@ bool WrappedOpenGL::Serialise_glDrawElements(SerialiserType &ser, GLenum mode, G draw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddDrawcall(draw, true); } @@ -1555,8 +1555,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsIndirect(SerialiserType &ser, GLenum draw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed | DrawFlags::Instanced | DrawFlags::Indirect; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddDrawcall(draw, true); @@ -1637,8 +1637,8 @@ bool WrappedOpenGL::Serialise_glDrawRangeElements(SerialiserType &ser, GLenum mo draw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddDrawcall(draw, true); } @@ -1721,8 +1721,8 @@ bool WrappedOpenGL::Serialise_glDrawRangeElementsBaseVertex(SerialiserType &ser, draw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddDrawcall(draw, true); } @@ -1803,8 +1803,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsBaseVertex(SerialiserType &ser, GLen draw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddDrawcall(draw, true); } @@ -1883,8 +1883,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstanced(SerialiserType &ser, GLenu draw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed | DrawFlags::Instanced; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddDrawcall(draw, true); } @@ -1968,8 +1968,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseInstance(SerialiserType draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced | DrawFlags::Indexed; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddDrawcall(draw, true); } @@ -2056,8 +2056,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseVertex(SerialiserType & draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced | DrawFlags::Indexed; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddDrawcall(draw, true); } @@ -2143,8 +2143,8 @@ bool WrappedOpenGL::Serialise_glDrawElementsInstancedBaseVertexBaseInstance( draw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced | DrawFlags::Indexed; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddDrawcall(draw, true); } @@ -2217,7 +2217,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawArrays(SerialiserType &ser, GLenum mode draw.name = StringFormat::Fmt("%s(%i)", ToStr(gl_CurChunk).c_str(), drawcount); draw.flags |= DrawFlags::MultiDraw; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddEvent(); AddDrawcall(draw, true); @@ -2238,7 +2238,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawArrays(SerialiserType &ser, GLenum mode multidraw.flags |= DrawFlags::Drawcall; - multidraw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddEvent(); AddDrawcall(multidraw, true); @@ -2376,10 +2376,10 @@ bool WrappedOpenGL::Serialise_glMultiDrawElements(SerialiserType &ser, GLenum mo draw.name = StringFormat::Fmt("%s(%i)", ToStr(gl_CurChunk).c_str(), drawcount); draw.flags |= DrawFlags::MultiDraw; - draw.indexByteWidth = IdxSize; + m_LastIndexWidth = IdxSize; draw.numIndices = 0; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddEvent(); AddDrawcall(draw, true); @@ -2394,7 +2394,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawElements(SerialiserType &ser, GLenum mo multidraw.drawIndex = i; multidraw.numIndices = count[i]; multidraw.indexOffset = (uint32_t)(indices[i] & 0xFFFFFFFF); - multidraw.indexByteWidth = IdxSize; + m_LastIndexWidth = IdxSize; multidraw.indexOffset /= IdxSize; @@ -2403,7 +2403,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawElements(SerialiserType &ser, GLenum mo multidraw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed; - multidraw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddEvent(); AddDrawcall(multidraw, true); @@ -2547,8 +2547,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsBaseVertex(SerialiserType &ser, draw.flags |= DrawFlags::MultiDraw; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddEvent(); AddDrawcall(draw, true); @@ -2572,8 +2572,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsBaseVertex(SerialiserType &ser, multidraw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed; - multidraw.topology = MakePrimitiveTopology(mode); - multidraw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddEvent(); AddDrawcall(multidraw, true); @@ -2702,7 +2702,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirect(SerialiserType &ser, GLe draw.flags |= DrawFlags::MultiDraw; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddEvent(); AddDrawcall(draw, true); @@ -2746,7 +2746,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirect(SerialiserType &ser, GLe multidraw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced | DrawFlags::Indirect; - multidraw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); // add a fake chunk for this individual indirect draw SDChunk *fakeChunk = new SDChunk(multidraw.name); @@ -2924,8 +2924,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirect(SerialiserType &ser, G draw.flags |= DrawFlags::MultiDraw; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddEvent(); AddDrawcall(draw, true); @@ -2971,8 +2971,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirect(SerialiserType &ser, G multidraw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed | DrawFlags::Instanced | DrawFlags::Indirect; - multidraw.topology = MakePrimitiveTopology(mode); - multidraw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; // add a fake chunk for this individual indirect draw SDChunk *fakeChunk = new SDChunk(multidraw.name); @@ -3154,7 +3154,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirectCount(SerialiserType &ser draw.flags |= DrawFlags::MultiDraw; - draw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); AddEvent(); AddDrawcall(draw, true); @@ -3198,7 +3198,7 @@ bool WrappedOpenGL::Serialise_glMultiDrawArraysIndirectCount(SerialiserType &ser multidraw.flags |= DrawFlags::Drawcall | DrawFlags::Instanced | DrawFlags::Indirect; - multidraw.topology = MakePrimitiveTopology(mode); + m_LastTopology = MakePrimitiveTopology(mode); // add a fake chunk for this individual indirect draw SDChunk *fakeChunk = new SDChunk(multidraw.name); @@ -3385,8 +3385,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirectCount(SerialiserType &s draw.flags |= DrawFlags::MultiDraw; - draw.topology = MakePrimitiveTopology(mode); - draw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; AddEvent(); AddDrawcall(draw, true); @@ -3432,8 +3432,8 @@ bool WrappedOpenGL::Serialise_glMultiDrawElementsIndirectCount(SerialiserType &s multidraw.flags |= DrawFlags::Drawcall | DrawFlags::Indexed | DrawFlags::Instanced | DrawFlags::Indirect; - multidraw.topology = MakePrimitiveTopology(mode); - multidraw.indexByteWidth = IdxSize; + m_LastTopology = MakePrimitiveTopology(mode); + m_LastIndexWidth = IdxSize; // add a fake chunk for this individual indirect draw SDChunk *fakeChunk = new SDChunk(multidraw.name); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index de3be29c0..1102bfb2d 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -4022,19 +4022,8 @@ void WrappedVulkan::AddDrawcall(const DrawcallDescription &d, bool hasEvents) draw.depthOut = ResourceId(); - draw.indexByteWidth = 0; - draw.topology = Topology::Unknown; - if(m_LastCmdBufferID != ResourceId()) { - ResourceId pipe = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.graphics.pipeline; - if(pipe != ResourceId()) - draw.topology = - MakePrimitiveTopology(m_BakedCmdBufferInfo[m_LastCmdBufferID].state.primitiveTopology, - m_CreationInfo.m_Pipeline[pipe].patchControlPoints); - - draw.indexByteWidth = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.ibuffer.bytewidth; - ResourceId fb = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.GetFramebuffer(); ResourceId rp = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.renderPass; uint32_t sp = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass; diff --git a/renderdoc/driver/vulkan/vk_overlay.cpp b/renderdoc/driver/vulkan/vk_overlay.cpp index 5623619a9..df7c57b62 100644 --- a/renderdoc/driver/vulkan/vk_overlay.cpp +++ b/renderdoc/driver/vulkan/vk_overlay.cpp @@ -410,8 +410,8 @@ void VulkanDebugManager::PatchLineStripIndexBuffer(const DrawcallDescription *dr if(draw->flags & DrawFlags::Indexed) { GetBufferData(rs.ibuffer.buf, - rs.ibuffer.offs + uint64_t(draw->indexOffset) * draw->indexByteWidth, - uint64_t(draw->numIndices) * draw->indexByteWidth, indices); + rs.ibuffer.offs + uint64_t(draw->indexOffset) * rs.ibuffer.bytewidth, + uint64_t(draw->numIndices) * rs.ibuffer.bytewidth, indices); if(rs.ibuffer.bytewidth == 4) idx32 = (uint32_t *)indices.data(); @@ -424,7 +424,8 @@ void VulkanDebugManager::PatchLineStripIndexBuffer(const DrawcallDescription *dr // we just patch up to 32-bit since we'll be adding more indices and we might overflow 16-bit. rdcarray patchedIndices; - ::PatchLineStripIndexBuffer(draw, idx8, idx16, idx32, patchedIndices); + ::PatchLineStripIndexBuffer(draw, MakePrimitiveTopology(rs.primitiveTopology, 3), idx8, idx16, + idx32, patchedIndices); indexBuffer.Create(m_pDriver, m_Device, patchedIndices.size() * sizeof(uint32_t), 1, GPUBuffer::eGPUBufferIBuffer); @@ -918,11 +919,11 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D { rs->polygonMode = VK_POLYGON_MODE_LINE; } - else if(mainDraw->topology == Topology::TriangleList || - mainDraw->topology == Topology::TriangleStrip || - mainDraw->topology == Topology::TriangleFan || - mainDraw->topology == Topology::TriangleList_Adj || - mainDraw->topology == Topology::TriangleStrip_Adj) + else if(prevstate.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || + prevstate.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP || + prevstate.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN || + prevstate.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY || + prevstate.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY) { // bad drivers (aka mobile) won't have non-solid fill mode, so we have to fall back to // manually patching the index buffer and using a line list. This doesn't work with @@ -947,7 +948,7 @@ ResourceId VulkanReplay::RenderOverlay(ResourceId texid, FloatVector clearCol, D else { RDCWARN("Unable to draw wireframe overlay for %s topology draw via software patching", - ToStr(mainDraw->topology).c_str()); + ToStr(prevstate.primitiveTopology).c_str()); } } diff --git a/renderdoc/driver/vulkan/vk_pixelhistory.cpp b/renderdoc/driver/vulkan/vk_pixelhistory.cpp index b386f372a..e008d5412 100644 --- a/renderdoc/driver/vulkan/vk_pixelhistory.cpp +++ b/renderdoc/driver/vulkan/vk_pixelhistory.cpp @@ -2700,6 +2700,9 @@ struct VulkanPixelHistoryDiscardedFragmentsCallback : VulkanPixelHistoryCallback for(uint32_t i = 0; i < state.views.size(); i++) ScissorToPixel(state.views[i], state.scissors[i]); state.graphics.pipeline = GetResID(newPipe); + const VulkanCreationInfo::Pipeline &p = + m_pDriver->GetDebugManager()->GetPipelineInfo(state.graphics.pipeline); + Topology topo = MakePrimitiveTopology(state.primitiveTopology, p.patchControlPoints); state.BindPipeline(m_pDriver, cmd, VulkanRenderState::BindGraphics, false); for(uint32_t i = 0; i < primIds.size(); i++) { @@ -2708,9 +2711,9 @@ struct VulkanPixelHistoryDiscardedFragmentsCallback : VulkanPixelHistoryCallback const DrawcallDescription *drawcall = m_pDriver->GetDrawcall(eid); uint32_t primId = primIds[i]; DrawcallDescription draw = *drawcall; - draw.numIndices = RENDERDOC_NumVerticesPerPrimitive(drawcall->topology); - draw.indexOffset += RENDERDOC_VertexOffset(drawcall->topology, primId); - draw.vertexOffset += RENDERDOC_VertexOffset(drawcall->topology, primId); + draw.numIndices = RENDERDOC_NumVerticesPerPrimitive(topo); + draw.indexOffset += RENDERDOC_VertexOffset(topo, primId); + draw.vertexOffset += RENDERDOC_VertexOffset(topo, primId); // TODO once pixel history distinguishes between instances, draw only the instance for // this fragment. // TODO replay with a dummy index buffer so that all primitives other than the target one are diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index 3d4f3d6ea..91e01ce97 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -1286,7 +1286,7 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state) // set defaults so that we don't try to fetch this output again if something goes wrong and the // same event is selected again { - m_PostVS.Data[eventId].vsin.topo = MakeVkPrimitiveTopology(drawcall->topology); + m_PostVS.Data[eventId].vsin.topo = state.primitiveTopology; m_PostVS.Data[eventId].vsout.buf = VK_NULL_HANDLE; m_PostVS.Data[eventId].vsout.bufmem = VK_NULL_HANDLE; m_PostVS.Data[eventId].vsout.instStride = 0; @@ -1300,7 +1300,7 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state) m_PostVS.Data[eventId].vsout.idxbuf = VK_NULL_HANDLE; m_PostVS.Data[eventId].vsout.idxbufmem = VK_NULL_HANDLE; - m_PostVS.Data[eventId].vsout.topo = MakeVkPrimitiveTopology(drawcall->topology); + m_PostVS.Data[eventId].vsout.topo = state.primitiveTopology; } // no outputs from this shader? unexpected but theoretically possible (dummy VS before @@ -1428,7 +1428,7 @@ void VulkanReplay::FetchVSOut(uint32_t eventId, VulkanRenderState &state) if(drawcall->flags & DrawFlags::Indexed) { const bool restart = pipeCreateInfo.pInputAssemblyState->primitiveRestartEnable && - SupportsRestart(drawcall->topology); + SupportsRestart(MakePrimitiveTopology(state.primitiveTopology, 3)); bytebuf idxdata; rdcarray indices; uint8_t *idx8 = NULL; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 063acd797..3614b49c3 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -1109,7 +1109,10 @@ void VulkanReplay::SavePipelineState(uint32_t eventId) // Input Assembly m_VulkanPipelineState.inputAssembly.indexBuffer.resourceId = rm->GetOriginalID(state.ibuffer.buf); m_VulkanPipelineState.inputAssembly.indexBuffer.byteOffset = state.ibuffer.offs; + m_VulkanPipelineState.inputAssembly.indexBuffer.byteStride = state.ibuffer.bytewidth; m_VulkanPipelineState.inputAssembly.primitiveRestartEnable = p.primitiveRestartEnable; + m_VulkanPipelineState.inputAssembly.topology = + MakePrimitiveTopology(state.primitiveTopology, p.patchControlPoints); // Vertex Input m_VulkanPipelineState.vertexInput.attributes.resize(p.vertexAttrs.size()); diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index 5573af6f4..732fdff3d 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -568,9 +568,6 @@ void DoSerialise(SerialiserType &ser, DrawcallDescription &el) SERIALISE_MEMBER(dispatchThreadsDimension); SERIALISE_MEMBER(dispatchBase); - SERIALISE_MEMBER(indexByteWidth); - SERIALISE_MEMBER(topology); - SERIALISE_MEMBER(copySource); SERIALISE_MEMBER(copySourceSubresource); SERIALISE_MEMBER(copyDestination); @@ -585,7 +582,7 @@ void DoSerialise(SerialiserType &ser, DrawcallDescription &el) SERIALISE_MEMBER(events); SERIALISE_MEMBER(children); - SIZE_CHECK(320); + SIZE_CHECK(312); } template @@ -1059,6 +1056,7 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::IndexBuffer &el) { SERIALISE_MEMBER(resourceId); SERIALISE_MEMBER(byteOffset); + SERIALISE_MEMBER(byteStride); SIZE_CHECK(16); } @@ -1072,8 +1070,9 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::InputAssembly &el) SERIALISE_MEMBER_OPT_EMPTY(bytecode); SERIALISE_MEMBER(vertexBuffers); SERIALISE_MEMBER(indexBuffer); + SERIALISE_MEMBER(topology); - SIZE_CHECK(80); + SIZE_CHECK(88); } template @@ -1263,7 +1262,7 @@ void DoSerialise(SerialiserType &ser, D3D11Pipe::State &el) SERIALISE_MEMBER(predication); - SIZE_CHECK(2080); + SIZE_CHECK(2088); } #pragma endregion D3D11 pipeline state @@ -1301,6 +1300,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::IndexBuffer &el) SERIALISE_MEMBER(resourceId); SERIALISE_MEMBER(byteOffset); SERIALISE_MEMBER(byteSize); + SERIALISE_MEMBER(byteStride); SIZE_CHECK(24); } @@ -1313,6 +1313,7 @@ void DoSerialise(SerialiserType &ser, D3D12Pipe::InputAssembly &el) SERIALISE_MEMBER(indexBuffer); SERIALISE_MEMBER(indexStripCutValue); + SERIALISE_MEMBER(topology); SIZE_CHECK(80); } @@ -1580,11 +1581,13 @@ void DoSerialise(SerialiserType &ser, GLPipe::VertexInput &el) SERIALISE_MEMBER(attributes); SERIALISE_MEMBER(vertexBuffers); SERIALISE_MEMBER(indexBuffer); + SERIALISE_MEMBER(indexByteStride); + SERIALISE_MEMBER(topology); SERIALISE_MEMBER(primitiveRestart); SERIALISE_MEMBER(restartIndex); SERIALISE_MEMBER(provokingVertexLast); - SIZE_CHECK(80); + SIZE_CHECK(88); } template @@ -1843,7 +1846,7 @@ void DoSerialise(SerialiserType &ser, GLPipe::State &el) SERIALISE_MEMBER(hints); - SIZE_CHECK(2016); + SIZE_CHECK(2024); } #pragma endregion OpenGL pipeline state @@ -1938,8 +1941,9 @@ void DoSerialise(SerialiserType &ser, VKPipe::IndexBuffer &el) { SERIALISE_MEMBER(resourceId); SERIALISE_MEMBER(byteOffset); + SERIALISE_MEMBER(byteStride); - SIZE_CHECK(16); + SIZE_CHECK(24); } template @@ -1947,8 +1951,9 @@ void DoSerialise(SerialiserType &ser, VKPipe::InputAssembly &el) { SERIALISE_MEMBER(primitiveRestartEnable); SERIALISE_MEMBER(indexBuffer); + SERIALISE_MEMBER(topology); - SIZE_CHECK(24); + SIZE_CHECK(40); } template @@ -2274,7 +2279,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::State &el) SERIALISE_MEMBER(conditionalRendering); - SIZE_CHECK(1912); + SIZE_CHECK(1928); } #pragma endregion Vulkan pipeline state diff --git a/renderdoc/replay/replay_driver.cpp b/renderdoc/replay/replay_driver.cpp index 699631192..c7026676c 100644 --- a/renderdoc/replay/replay_driver.cpp +++ b/renderdoc/replay/replay_driver.cpp @@ -181,8 +181,8 @@ void SetupDrawcallPointers(rdcarray &drawcallTable, } } -void PatchLineStripIndexBuffer(const DrawcallDescription *draw, uint8_t *idx8, uint16_t *idx16, - uint32_t *idx32, rdcarray &patchedIndices) +void PatchLineStripIndexBuffer(const DrawcallDescription *draw, Topology topology, uint8_t *idx8, + uint16_t *idx16, uint32_t *idx32, rdcarray &patchedIndices) { const uint32_t restart = 0xffffffff; @@ -190,7 +190,7 @@ void PatchLineStripIndexBuffer(const DrawcallDescription *draw, uint8_t *idx8, u (idx16 ? idx16[index + (offs)] \ : (idx32 ? idx32[index + (offs)] : (idx8 ? idx8[index + (offs)] : index + (offs)))) - switch(draw->topology) + switch(topology) { case Topology::TriangleList: { @@ -268,7 +268,7 @@ void PatchLineStripIndexBuffer(const DrawcallDescription *draw, uint8_t *idx8, u break; } default: - RDCERR("Unsupported topology %s for line-list patching", ToStr(draw->topology).c_str()); + RDCERR("Unsupported topology %s for line-list patching", ToStr(topology).c_str()); return; } diff --git a/renderdoc/replay/replay_driver.h b/renderdoc/replay/replay_driver.h index 011a5d2c9..5b2b874fe 100644 --- a/renderdoc/replay/replay_driver.h +++ b/renderdoc/replay/replay_driver.h @@ -303,8 +303,8 @@ void SetupDrawcallPointers(rdcarray &drawcallTable, // for hardware/APIs that can't do line rasterization, manually expand any triangle input topology // to a linestrip with strip restart indices. -void PatchLineStripIndexBuffer(const DrawcallDescription *draw, uint8_t *idx8, uint16_t *idx16, - uint32_t *idx32, rdcarray &patchedIndices); +void PatchLineStripIndexBuffer(const DrawcallDescription *draw, Topology topology, uint8_t *idx8, + uint16_t *idx16, uint32_t *idx32, rdcarray &patchedIndices); void PatchTriangleFanRestartIndexBufer(rdcarray &patchedIndices, uint32_t restartIndex); diff --git a/util/test/rdtest/analyse.py b/util/test/rdtest/analyse.py index 175600a1f..aca65b93b 100644 --- a/util/test/rdtest/analyse.py +++ b/util/test/rdtest/analyse.py @@ -59,7 +59,7 @@ def fetch_indices(controller: rd.ReplayController, draw: rd.DrawcallDescription, pipe = controller.GetPipelineState() restart_idx = pipe.GetStripRestartIndex() & ((1 << (mesh.indexByteStride*8)) - 1) - restart_enabled = pipe.IsStripRestartEnabled() and rd.IsStrip(draw.topology) + restart_enabled = pipe.IsStripRestartEnabled() and rd.IsStrip(pipe.GetPrimitiveTopology()) # If we have an index buffer if mesh.indexResourceId != rd.ResourceId.Null(): diff --git a/util/test/rdtest/shared/Draw_Zoo.py b/util/test/rdtest/shared/Draw_Zoo.py index daaa07ffc..37abe043c 100644 --- a/util/test/rdtest/shared/Draw_Zoo.py +++ b/util/test/rdtest/shared/Draw_Zoo.py @@ -66,7 +66,9 @@ class Draw_Zoo(rdtest.TestCase): if 'restarts' in ref_data: restarts = ref_data['restarts'] - striprestart_index = self.pipe.GetStripRestartIndex() & ((1 << (draw.indexByteWidth*8)) - 1) + ib = self.pipe.GetIBuffer() + + striprestart_index = self.pipe.GetStripRestartIndex() & ((1 << (ib.byteStride*8)) - 1) for v in range(num_verts): if v in restarts: diff --git a/util/test/rdtest/testcase.py b/util/test/rdtest/testcase.py index 8016c3027..3ece88517 100644 --- a/util/test/rdtest/testcase.py +++ b/util/test/rdtest/testcase.py @@ -268,12 +268,12 @@ class TestCase: else: num_indices = min(num_indices, draw.numIndices) - ioffs = draw.indexOffset * draw.indexByteWidth + ioffs = draw.indexOffset * ib.byteStride mesh = rd.MeshFormat() mesh.numIndices = num_indices mesh.indexByteOffset = ib.byteOffset + ioffs - mesh.indexByteStride = draw.indexByteWidth + mesh.indexByteStride = ib.byteStride mesh.indexResourceId = ib.resourceId mesh.baseVertex = draw.baseVertex @@ -311,12 +311,12 @@ class TestCase: ib: rd.BoundVBuffer = self.controller.GetPipelineState().GetIBuffer() - ioffs = draw.indexOffset * draw.indexByteWidth + ioffs = draw.indexOffset * ib.byteStride in_mesh = rd.MeshFormat() in_mesh.numIndices = num_indices in_mesh.indexByteOffset = ib.byteOffset + ioffs - in_mesh.indexByteStride = draw.indexByteWidth + in_mesh.indexByteStride = ib.byteStride in_mesh.indexResourceId = ib.resourceId in_mesh.baseVertex = draw.baseVertex diff --git a/util/test/tests/D3D11/D3D11_Primitive_Restart.py b/util/test/tests/D3D11/D3D11_Primitive_Restart.py index ccccc3d22..73cfc1952 100644 --- a/util/test/tests/D3D11/D3D11_Primitive_Restart.py +++ b/util/test/tests/D3D11/D3D11_Primitive_Restart.py @@ -16,8 +16,10 @@ class D3D11_Primitive_Restart(rdtest.TestCase): postvs_data = self.get_postvs(draw, rd.MeshDataStage.VSOut, 0, draw.numIndices) + ib = pipe.GetIBuffer() + # Calculate the strip restart index for this index width - striprestart_index = pipe.GetStripRestartIndex() & ((1 << (draw.indexByteWidth*8)) - 1) + striprestart_index = pipe.GetStripRestartIndex() & ((1 << (ib.byteStride*8)) - 1) # We don't check all of the output, we check a few key vertices to ensure they match up postvs_ref = { diff --git a/util/test/tests/GL/GL_Draw_Zoo.py b/util/test/tests/GL/GL_Draw_Zoo.py index 1136f05b7..b990c15c6 100644 --- a/util/test/tests/GL/GL_Draw_Zoo.py +++ b/util/test/tests/GL/GL_Draw_Zoo.py @@ -19,8 +19,11 @@ class GL_Draw_Zoo(rdtest.Draw_Zoo): pipe = self.controller.GetPipelineState() + ib = pipe.GetIBuffer() + + self.check(pipe.IsStripRestartEnabled()) - self.check((pipe.GetStripRestartIndex() & ((1 << (draw.indexByteWidth*8)) - 1)) == 0xffff) + self.check((pipe.GetStripRestartIndex() & ((1 << (ib.byteStride*8)) - 1)) == 0xffff) draw = self.find_draw("GL_PRIMITIVE_RESTART_FIXED_INDEX") @@ -32,5 +35,7 @@ class GL_Draw_Zoo(rdtest.Draw_Zoo): pipe = self.controller.GetPipelineState() + ib = pipe.GetIBuffer() + self.check(pipe.IsStripRestartEnabled()) - self.check((pipe.GetStripRestartIndex() & ((1 << (draw.indexByteWidth*8)) - 1)) == 0xffff) + self.check((pipe.GetStripRestartIndex() & ((1 << (ib.byteStride*8)) - 1)) == 0xffff) diff --git a/util/test/tests/Iter_Test.py b/util/test/tests/Iter_Test.py index 65359778d..384bbf8a4 100644 --- a/util/test/tests/Iter_Test.py +++ b/util/test/tests/Iter_Test.py @@ -82,8 +82,8 @@ class Iter_Test(rdtest.TestCase): mesh = rd.MeshFormat() mesh.indexResourceId = ib.resourceId - mesh.indexByteStride = draw.indexByteWidth - mesh.indexByteOffset = ib.byteOffset + draw.indexOffset * draw.indexByteWidth + mesh.indexByteStride = ib.byteStride + mesh.indexByteOffset = ib.byteOffset + draw.indexOffset * ib.byteStride mesh.indexByteSize = ib.byteSize mesh.baseVertex = draw.baseVertex @@ -95,7 +95,7 @@ class Iter_Test(rdtest.TestCase): idx = indices[0] - striprestart_index = pipe.GetStripRestartIndex() & ((1 << (draw.indexByteWidth*8)) - 1) + striprestart_index = pipe.GetStripRestartIndex() & ((1 << (ib.byteStride*8)) - 1) if pipe.IsStripRestartEnabled() and idx == striprestart_index: return diff --git a/util/test/tests/Vulkan/VK_Extended_Dynamic_State.py b/util/test/tests/Vulkan/VK_Extended_Dynamic_State.py index 2c9363d79..945225ed2 100644 --- a/util/test/tests/Vulkan/VK_Extended_Dynamic_State.py +++ b/util/test/tests/Vulkan/VK_Extended_Dynamic_State.py @@ -95,7 +95,7 @@ class VK_Extended_Dynamic_State(rdtest.TestCase): vkpipe: rd.VKState = self.controller.GetVulkanPipelineState() - self.check(draw.topology == rd.Topology.TriangleList) + self.check(vkpipe.inputAssembly.topology == rd.Topology.TriangleList) self.check(vkpipe.depthStencil.depthTestEnable == True) self.check(vkpipe.depthStencil.depthWriteEnable == True) diff --git a/util/test/tests/Vulkan/VK_Int8_IBuffer.py b/util/test/tests/Vulkan/VK_Int8_IBuffer.py index 2db5b58b2..3625f0d57 100644 --- a/util/test/tests/Vulkan/VK_Int8_IBuffer.py +++ b/util/test/tests/Vulkan/VK_Int8_IBuffer.py @@ -16,8 +16,10 @@ class VK_Int8_IBuffer(rdtest.TestCase): postvs_data = self.get_postvs(draw, rd.MeshDataStage.VSOut, 0, draw.numIndices) + ib = pipe.GetIBuffer() + # Calculate the strip restart index for this index width - striprestart_index = pipe.GetStripRestartIndex() & ((1 << (draw.indexByteWidth*8)) - 1) + striprestart_index = pipe.GetStripRestartIndex() & ((1 << (ib.byteStride*8)) - 1) # We don't check all of the output, we check a few key vertices to ensure they match up postvs_ref = {