Fix handling of primitive restart with a vertex offset

This commit is contained in:
baldurk
2019-02-04 18:06:09 +00:00
parent 12ce67b228
commit 73a5357419
5 changed files with 80 additions and 21 deletions
+14 -9
View File
@@ -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 &params)
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)
+1
View File
@@ -177,6 +177,7 @@ private:
uint32_t count;
BufferData *indices = NULL;
int32_t baseVertex;
uint32_t primRestart;
QList<BufferData *> buffers;
} input[3];
+11
View File
@@ -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,
@@ -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();
}
+34 -12
View File
@@ -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;