From 73a5357419d9f744817fa270d061fe7deb2db3d1 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 4 Feb 2019 13:41:42 +0000 Subject: [PATCH] Fix handling of primitive restart with a vertex offset --- qrenderdoc/Windows/BufferViewer.cpp | 23 ++++++---- qrenderdoc/Windows/BufferViewer.h | 1 + renderdoc/replay/replay_driver.cpp | 11 +++++ .../demos/d3d11/d3d11_primitive_restart.cpp | 20 ++++++++ util/test/demos/vk/vk_draw_zoo.cpp | 46 ++++++++++++++----- 5 files changed, 80 insertions(+), 21 deletions(-) diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index 80a266523..4d425d458 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -334,7 +334,7 @@ struct BufferData size_t stride; }; -uint32_t CalcIndex(BufferData *data, uint32_t vertID, int32_t baseVertex) +uint32_t CalcIndex(BufferData *data, uint32_t vertID, int32_t baseVertex, uint32_t primRestart) { byte *idxData = data->data + vertID * sizeof(uint32_t); if(idxData + sizeof(uint32_t) > data->end) @@ -342,6 +342,10 @@ uint32_t CalcIndex(BufferData *data, uint32_t vertID, int32_t baseVertex) uint32_t idx = *(uint32_t *)idxData; + // check for primitive restart *before* adding base vertex + if(primRestart && idx == primRestart) + return idx; + // apply base vertex but clamp to 0 if subtracting if(baseVertex < 0) { @@ -595,7 +599,7 @@ public: if(indices && indices->data) { - idx = CalcIndex(indices, row, baseVertex); + idx = CalcIndex(indices, row, baseVertex, primRestart); if(primRestart && idx == primRestart) return col == 1 ? lit("--") : lit(" Restart"); @@ -608,7 +612,7 @@ public: { // if we have separate displayIndices, fetch that for display instead if(displayIndices && displayIndices->data) - idx = CalcIndex(displayIndices, row, displayBaseVertex); + idx = CalcIndex(displayIndices, row, displayBaseVertex, primRestart); if(idx == ~0U) return outOfBounds(); @@ -1697,7 +1701,7 @@ void BufferViewer::RT_FetchMeshData(IReplayController *r) } else if(draw->indexByteWidth == 4) { - uint16_t primRestart = m_ModelVSIn->primRestart; + uint32_t primRestart = m_ModelVSIn->primRestart; memcpy(indices, idata.data(), qMin(idata.size(), draw->numIndices * sizeof(uint32_t))); @@ -1753,7 +1757,7 @@ void BufferViewer::RT_FetchMeshData(IReplayController *r) offset = draw->vertexOffset; if(draw->baseVertex > 0) - maxIdx += (uint32_t)draw->baseVertex; + maxIdx = qMax(maxIdx, maxIdx + (uint32_t)draw->baseVertex); } if(pi && pv) @@ -1764,7 +1768,7 @@ void BufferViewer::RT_FetchMeshData(IReplayController *r) if(used) { bytebuf bufdata = r->GetBufferData(vb.resourceId, vb.byteOffset + offset * vb.byteStride, - (maxIdx + 1) * vb.byteStride + maxAttrOffset); + qMax(maxIdx, maxIdx + 1) * vb.byteStride + maxAttrOffset); buf->data = new byte[bufdata.size()]; memcpy(buf->data, bufdata.data(), bufdata.size()); @@ -1896,6 +1900,7 @@ void BufferViewer::RT_FetchMeshData(IReplayController *r) bbox->input[i].buffers = models[i]->buffers; bbox->input[i].indices = models[i]->indices; bbox->input[i].baseVertex = models[i]->baseVertex; + bbox->input[i].primRestart = models[i]->primRestart; bbox->input[i].count = models[i]->numRows; @@ -1953,9 +1958,9 @@ void BufferViewer::calcBoundingData(CalcBoundingBoxData &bbox) if(s.indices && s.indices->data) { - idx = CalcIndex(s.indices, row, s.baseVertex); + idx = CalcIndex(s.indices, row, s.baseVertex, s.primRestart); - if(idx == ~0U) + if(idx == ~0U || (s.primRestart && idx == s.primRestart)) continue; } @@ -3286,7 +3291,7 @@ void BufferViewer::exportData(const BufferExport ¶ms) if(model->indices && model->indices->data) { - idx = CalcIndex(model->indices, i, model->baseVertex); + idx = CalcIndex(model->indices, i, model->baseVertex, model->primRestart); // completely omit primitive restart indices if(model->primRestart && idx == model->primRestart) diff --git a/qrenderdoc/Windows/BufferViewer.h b/qrenderdoc/Windows/BufferViewer.h index 2e8bb5e0d..28841d0a5 100644 --- a/qrenderdoc/Windows/BufferViewer.h +++ b/qrenderdoc/Windows/BufferViewer.h @@ -177,6 +177,7 @@ private: uint32_t count; BufferData *indices = NULL; int32_t baseVertex; + uint32_t primRestart; QList buffers; } input[3]; diff --git a/renderdoc/replay/replay_driver.cpp b/renderdoc/replay/replay_driver.cpp index b3c1f3ae2..7f55d7867 100644 --- a/renderdoc/replay/replay_driver.cpp +++ b/renderdoc/replay/replay_driver.cpp @@ -287,6 +287,17 @@ FloatVector HighlightCache::InterpretVertex(const byte *data, uint32_t vert, con } vert = indices[vert]; + + if(IsStrip(cfg.position.topology)) + { + if((cfg.position.indexByteStride == 1 && vert == 0xff) || + (cfg.position.indexByteStride == 2 && vert == 0xffff) || + (cfg.position.indexByteStride == 4 && vert == 0xffffffff)) + { + valid = false; + return ret; + } + } } return HighlightCache::InterpretVertex(data, vert, cfg.position.vertexByteStride, diff --git a/util/test/demos/d3d11/d3d11_primitive_restart.cpp b/util/test/demos/d3d11/d3d11_primitive_restart.cpp index ee3079015..d3228ebec 100644 --- a/util/test/demos/d3d11/d3d11_primitive_restart.cpp +++ b/util/test/demos/d3d11/d3d11_primitive_restart.cpp @@ -78,6 +78,19 @@ struct Primitive_Restart : D3D11GraphicsTest ID3D11BufferPtr ib = MakeBuffer().Index().Data(idx); + uint16_t idx2[] = { + // strip 0 + 10, 11, 12, 13, 14, 15, 16, 17, + + // restart + 0xffff, + + // strip 1 + 18, 19, 20, 21, 22, 23, 24, 25, + }; + + ID3D11BufferPtr ib2 = MakeBuffer().Index().Data(idx2); + while(Running()) { ClearRenderTargetView(bbRTV, {0.4f, 0.5f, 0.6f, 1.0f}); @@ -96,6 +109,13 @@ struct Primitive_Restart : D3D11GraphicsTest ctx->DrawIndexed(17, 0, 0); + ClearRenderTargetView(bbRTV, {0.4f, 0.5f, 0.6f, 1.0f}); + + ctx->IASetIndexBuffer(ib2, DXGI_FORMAT_R16_UINT, 0); + + // should get identical results with the vertex offset + ctx->DrawIndexed(17, 0, -10); + Present(); } diff --git a/util/test/demos/vk/vk_draw_zoo.cpp b/util/test/demos/vk/vk_draw_zoo.cpp index 980ad3a5d..e5d814ec8 100644 --- a/util/test/demos/vk/vk_draw_zoo.cpp +++ b/util/test/demos/vk/vk_draw_zoo.cpp @@ -156,7 +156,7 @@ void main() {Vec3f(0.5f, 0.0f, 0.0f), Vec4f(1.0f, 0.1f, 1.0f, 1.0f), Vec2f(1.0f, 0.0f)}, }; - AllocatedBuffer vb1(allocator, vkh::BufferCreateInfo(sizeof(DefaultA2V) * 50, + AllocatedBuffer vb1(allocator, vkh::BufferCreateInfo(sizeof(DefaultA2V) * 66000, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT), VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU})); @@ -165,6 +165,8 @@ void main() DefaultA2V *src = (DefaultA2V *)vertData; DefaultA2V *dst = (DefaultA2V *)vb1.map(); + memset(dst, 0x5c, sizeof(DefaultA2V) * 66000); + // up-pointing triangle to offset 0 memcpy(dst + 0, src + 1, sizeof(DefaultA2V)); memcpy(dst + 1, src + 2, sizeof(DefaultA2V)); @@ -250,7 +252,7 @@ void main() VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU})); { - uint32_t *dst = (uint32_t *)ib1.map(); + uint16_t *dst = (uint16_t *)ib1.map(); memset(dst, 0, sizeof(uint32_t) * 100); @@ -279,7 +281,7 @@ void main() dst[44] = 32; dst[45] = 33; dst[46] = 34; - dst[47] = 0xffffffff; + dst[47] = 0xffff; dst[48] = 36; dst[49] = 37; dst[50] = 38; @@ -287,6 +289,19 @@ void main() dst[52] = 40; dst[53] = 41; + dst[54] = 130; + dst[55] = 131; + dst[56] = 132; + dst[57] = 133; + dst[58] = 134; + dst[59] = 0xffff; + dst[60] = 136; + dst[61] = 137; + dst[62] = 138; + dst[63] = 139; + dst[64] = 140; + dst[65] = 141; + ib1.unmap(); } @@ -346,35 +361,35 @@ void main() // basic test vkCmdSetViewport(cmd, 0, 1, &vp); vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer}, {0}); - vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 3, 1, 0, 0, 0); vp.x += vp.width; // test with first index vkCmdSetViewport(cmd, 0, 1, &vp); vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer}, {0}); - vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 3, 1, 5, 0, 0); vp.x += vp.width; // test with first index and vertex offset vkCmdSetViewport(cmd, 0, 1, &vp); vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer}, {0}); - vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 3, 1, 13, -50, 0); vp.x += vp.width; // test with first index and vertex offset and vbuffer offset vkCmdSetViewport(cmd, 0, 1, &vp); vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer}, {10 * sizeof(DefaultA2V)}); - vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 3, 1, 23, -100, 0); vp.x += vp.width; // test with first index and vertex offset and vbuffer offset and ibuffer offset vkCmdSetViewport(cmd, 0, 1, &vp); vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer}, {19 * sizeof(DefaultA2V)}); - vkCmdBindIndexBuffer(cmd, ib1.buffer, 14 * sizeof(uint32_t), VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 14 * sizeof(uint16_t), VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 3, 1, 23, -100, 0); vp.x += vp.width; @@ -383,10 +398,17 @@ void main() // indexed strip with primitive restart vkCmdSetViewport(cmd, 0, 1, &vp); vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer}, {0}); - vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 12, 1, 42, 0, 0); vp.x += vp.width; + // indexed strip with primitive restart and vertex offset + vkCmdSetViewport(cmd, 0, 1, &vp); + vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer}, {0}); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT16); + vkCmdDrawIndexed(cmd, 12, 1, 54, -100, 0); + vp.x += vp.width; + // adjust to next row vp.x = 0.0f; vp.y += vp.height; @@ -425,21 +447,21 @@ void main() // basic test vkCmdSetViewport(cmd, 0, 1, &vp); vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer, vb2.buffer}, {0, 0}); - vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 3, 2, 5, 0, 0); vp.x += vp.width; // basic test with first instance vkCmdSetViewport(cmd, 0, 1, &vp); vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer, vb2.buffer}, {0, 0}); - vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 3, 2, 13, -50, 5); vp.x += vp.width; // basic test with first instance and instance buffer offset vkCmdSetViewport(cmd, 0, 1, &vp); vkh::cmdBindVertexBuffers(cmd, 0, {vb1.buffer, vb2.buffer}, {0, 8 * sizeof(Vec4f)}); - vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(cmd, ib1.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 3, 2, 23, -80, 5); vp.x += vp.width;