Handle NULL index buffer being bound for indexed draws better

This commit is contained in:
baldurk
2015-01-28 02:23:17 +00:00
parent a703dc54d0
commit 6d64fc7a1a
3 changed files with 63 additions and 20 deletions
+21 -6
View File
@@ -3952,6 +3952,11 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
indices.insert(it, i32);
}
// if we read out of bounds, we'll also have a 0 index being referenced
// (as 0 is read)
if(numIndices < drawcall->numIndices)
indices.insert(indices.begin(), 0);
// An index buffer could be something like: 500, 501, 502, 501, 503, 502
// in which case we can't use the existing index buffer without filling 499 slots of vertex
// data with padding. Instead we rebase the indices based on the smallest vertex so it becomes
@@ -3979,7 +3984,10 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
D3D11_BUFFER_DESC desc = { UINT(sizeof(uint32_t)*indices.size()), D3D11_USAGE_IMMUTABLE, D3D11_BIND_INDEX_BUFFER, 0, 0, 0 };
D3D11_SUBRESOURCE_DATA initData = { &indices[0], desc.ByteWidth, desc.ByteWidth };
m_pDevice->CreateBuffer(&desc, &initData, &idxBuf);
if(!indices.empty())
m_pDevice->CreateBuffer(&desc, &initData, &idxBuf);
else
idxBuf = NULL;
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
m_pImmediateContext->IASetIndexBuffer(idxBuf, DXGI_FORMAT_R32_UINT, 0);
@@ -4010,7 +4018,10 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
initData.pSysMem = &idxdata[0];
initData.SysMemPitch = initData.SysMemSlicePitch = desc.ByteWidth;
m_WrappedDevice->CreateBuffer(&desc, &initData, &idxBuf);
if(desc.ByteWidth > 0)
m_WrappedDevice->CreateBuffer(&desc, &initData, &idxBuf);
else
idxBuf = NULL;
}
m_pImmediateContext->End(m_SOStatsQuery);
@@ -4783,6 +4794,8 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
m_pImmediateContext->IASetVertexBuffers(0, 2, vbs, str, offs);
if(ibuf)
m_pImmediateContext->IASetIndexBuffer(ibuf, ifmt, ioffs);
else
m_pImmediateContext->IASetIndexBuffer(NULL, DXGI_FORMAT_UNKNOWN, NULL);
// draw solid shaded mode
if(cfg.solidShadeMode != eShade_None && cfg.position.topo < eTopology_PatchList_1CPs)
@@ -4811,7 +4824,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
m_pImmediateContext->GSSetShader(m_DebugRender.MeshGS, NULL, 0);
}
if(ibuf)
if(cfg.position.idxByteWidth)
m_pImmediateContext->DrawIndexed(cfg.position.numVerts, 0, 0);
else
m_pImmediateContext->Draw(cfg.position.numVerts, 0);
@@ -4841,7 +4854,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
else
m_pImmediateContext->IASetPrimitiveTopology(topo);
if(ibuf)
if(cfg.position.idxByteWidth)
m_pImmediateContext->DrawIndexed(cfg.position.numVerts, 0, 0);
else
m_pImmediateContext->Draw(cfg.position.numVerts, 0);
@@ -4907,7 +4920,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
m_HighlightCache.data = GetBufferData(cfg.position.buf, 0, 0);
if(ibuf == NULL || stage == eMeshDataStage_GSOut)
if(cfg.position.idxByteWidth == 0 || stage == eMeshDataStage_GSOut)
{
m_HighlightCache.indices.clear();
m_HighlightCache.useidx = false;
@@ -4916,7 +4929,9 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
{
m_HighlightCache.useidx = true;
vector<byte> idxdata = GetBufferData(cfg.position.idxbuf, ioffs, cfg.position.numVerts*bytesize);
vector<byte> idxdata;
if(cfg.position.idxbuf != ResourceId())
idxdata = GetBufferData(cfg.position.idxbuf, ioffs, cfg.position.numVerts*bytesize);
uint16_t *idx16 = (uint16_t *)&idxdata[0];
uint32_t *idx32 = (uint32_t *)&idxdata[0];
+27 -11
View File
@@ -1918,6 +1918,11 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
indices.insert(it, i32);
}
// if we read out of bounds, we'll also have a 0 index being referenced
// (as 0 is read)
if(numIndices < drawcall->numIndices)
indices.insert(indices.begin(), 0);
// An index buffer could be something like: 500, 501, 502, 501, 503, 502
// in which case we can't use the existing index buffer without filling 499 slots of vertex
// data with padding. Instead we rebase the indices based on the smallest vertex so it becomes
@@ -1984,9 +1989,12 @@ void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
// make the index buffer that can be used to render this postvs data - the original
// indices, rebased with minindex being 0 (since we transform feedback to the start
// of our feedback buffer).
gl.glGenBuffers(1, &idxBuf);
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, idxBuf);
gl.glNamedBufferStorageEXT(idxBuf, (GLsizeiptr)idxdata.size(), &idxdata[0], 0);
if(!idxdata.empty())
{
gl.glGenBuffers(1, &idxBuf);
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, idxBuf);
gl.glNamedBufferStorageEXT(idxBuf, (GLsizeiptr)idxdata.size(), &idxdata[0], 0);
}
// restore previous element array buffer binding
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, elArrayBuffer);
@@ -2794,7 +2802,7 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_FILL);
if(cfg.position.idxbuf != ResourceId())
if(cfg.position.idxByteWidth)
{
GLenum idxtype = eGL_UNSIGNED_BYTE;
if(cfg.position.idxByteWidth == 2)
@@ -2802,8 +2810,11 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
else if(cfg.position.idxByteWidth == 4)
idxtype = eGL_UNSIGNED_INT;
GLuint ib = m_pDriver->GetResourceManager()->GetCurrentResource(cfg.position.idxbuf).name;
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, ib);
if(cfg.position.idxbuf != ResourceId())
{
GLuint ib = m_pDriver->GetResourceManager()->GetCurrentResource(cfg.position.idxbuf).name;
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, ib);
}
gl.glDrawElements(topo, cfg.position.numVerts, idxtype, (const void *)(cfg.position.idxoffs));
}
else
@@ -2834,7 +2845,7 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_LINE);
if(cfg.position.idxbuf != ResourceId())
if(cfg.position.idxByteWidth)
{
GLenum idxtype = eGL_UNSIGNED_BYTE;
if(cfg.position.idxByteWidth == 2)
@@ -2842,8 +2853,11 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
else if(cfg.position.idxByteWidth == 4)
idxtype = eGL_UNSIGNED_INT;
GLuint ib = m_pDriver->GetResourceManager()->GetCurrentResource(cfg.position.idxbuf).name;
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, ib);
if(cfg.position.idxbuf != ResourceId())
{
GLuint ib = m_pDriver->GetResourceManager()->GetCurrentResource(cfg.position.idxbuf).name;
gl.glBindBuffer(eGL_ELEMENT_ARRAY_BUFFER, ib);
}
gl.glDrawElements(topo != eGL_PATCHES ? topo : eGL_POINTS, cfg.position.numVerts, idxtype, (const void *)(cfg.position.idxoffs));
}
else
@@ -2902,7 +2916,7 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
m_HighlightCache.data = GetBufferData(cfg.position.buf, 0, 0);
if(cfg.position.idxbuf == ResourceId() || stage == eMeshDataStage_GSOut)
if(cfg.position.idxByteWidth == 0 || stage == eMeshDataStage_GSOut)
{
m_HighlightCache.indices.clear();
m_HighlightCache.useidx = false;
@@ -2911,7 +2925,9 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
{
m_HighlightCache.useidx = true;
vector<byte> idxdata = GetBufferData(cfg.position.idxbuf, cfg.position.idxoffs, cfg.position.numVerts*bytesize);
vector<byte> idxdata;
if(cfg.position.idxbuf != ResourceId())
idxdata = GetBufferData(cfg.position.idxbuf, cfg.position.idxoffs, cfg.position.numVerts*bytesize);
uint8_t *idx8 = (uint8_t *)&idxdata[0];
uint16_t *idx16 = (uint16_t *)&idxdata[0];
+15 -3
View File
@@ -891,7 +891,7 @@ namespace renderdocui.Windows
foreach (var f in input.BufferFormats)
stride += f.ByteSize;
if (stride != 0)
if (stride != 0 && (input.Drawcall.flags & DrawcallFlags.UseIBuffer) == 0)
ret.IndexCount = Math.Min(ret.IndexCount, (uint)ret.Buffers[0].Length / stride);
}
@@ -1585,7 +1585,8 @@ namespace renderdocui.Windows
index = data.Indices[rowIdx];
}
}
else if (input.Drawcall != null && (input.Drawcall.flags & DrawcallFlags.UseIBuffer) != 0 && state == m_VSIn)
else if (input.Drawcall != null && (input.Drawcall.flags & DrawcallFlags.UseIBuffer) != 0 &&
(state == m_VSIn || state == m_VSOut))
{
// no index buffer, but indexed drawcall
index = 0;
@@ -2296,7 +2297,7 @@ namespace renderdocui.Windows
{
m_MeshDisplay.position.idxbuf = ui.m_Data.PostVS.idxbuf;
m_MeshDisplay.position.idxoffs = 0;
m_MeshDisplay.position.idxByteWidth = ui.m_Data.PostVS.idxByteWidth;
m_MeshDisplay.position.idxByteWidth = ui.m_Input.Drawcall.indexByteWidth;
m_MeshDisplay.position.buf = ui.m_Data.PostVS.buf;
m_MeshDisplay.position.offset = ui.m_Data.PostVS.offset + pos.offset;
@@ -2306,6 +2307,17 @@ namespace renderdocui.Windows
m_MeshDisplay.position.numVerts = ui.m_Data.PostVS.numVerts;
}
if ((ui.m_Input.Drawcall.flags & DrawcallFlags.UseIBuffer) == 0)
{
m_MeshDisplay.position.idxbuf = ResourceId.Null;
m_MeshDisplay.position.idxoffs = 0;
m_MeshDisplay.position.idxByteWidth = 0;
}
else
{
m_MeshDisplay.position.idxByteWidth = Math.Max(1, m_MeshDisplay.position.idxByteWidth);
}
m_MeshDisplay.position.unproject = false;
// near and far plane handled elsewhere