Remove fixed limit on stream-out size for D3D11/D3D12. Refs #585

* For VS output we can statically determine how much space is needed and
  allocate more if we need to.
* For tessellation/geometry shader output, we need to run a query to see
  if there was enough output space, then reallocate and run it again.
* On GL there isn't a built-in xfb query, only as an extension with poor
  support, so we just resize to allow the maximum expansion.
This commit is contained in:
baldurk
2017-04-25 15:59:57 +01:00
parent 4ac0a7948c
commit 319d144891
6 changed files with 648 additions and 246 deletions
+154 -105
View File
@@ -1189,24 +1189,12 @@ void D3D11DebugManager::ShutdownStreamOut()
bool D3D11DebugManager::InitStreamOut()
{
CreateSOBuffers();
m_MeshDisplayLayout = NULL;
D3D11_BUFFER_DESC bufferDesc = {
m_SOBufferSize, D3D11_USAGE_DEFAULT, D3D11_BIND_STREAM_OUTPUT, 0, 0, 0};
HRESULT hr = S_OK;
hr = m_pDevice->CreateBuffer(&bufferDesc, NULL, &m_SOBuffer);
if(FAILED(hr))
RDCERR("Failed to create m_SOBuffer %08x", hr);
bufferDesc.Usage = D3D11_USAGE_STAGING;
bufferDesc.BindFlags = 0;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
hr = m_pDevice->CreateBuffer(&bufferDesc, NULL, &m_SOStagingBuffer);
if(FAILED(hr))
RDCERR("Failed to create m_SOStagingBuffer %08x", hr);
D3D11_QUERY_DESC qdesc;
qdesc.MiscFlags = 0;
qdesc.Query = D3D11_QUERY_SO_STATISTICS;
@@ -1351,6 +1339,29 @@ bool D3D11DebugManager::InitStreamOut()
return true;
}
void D3D11DebugManager::CreateSOBuffers()
{
HRESULT hr = S_OK;
SAFE_RELEASE(m_SOBuffer);
SAFE_RELEASE(m_SOStagingBuffer);
D3D11_BUFFER_DESC bufferDesc = {
m_SOBufferSize, D3D11_USAGE_DEFAULT, D3D11_BIND_STREAM_OUTPUT, 0, 0, 0};
hr = m_pDevice->CreateBuffer(&bufferDesc, NULL, &m_SOBuffer);
if(FAILED(hr))
RDCERR("Failed to create m_SOBuffer %08x", hr);
bufferDesc.Usage = D3D11_USAGE_STAGING;
bufferDesc.BindFlags = 0;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
hr = m_pDevice->CreateBuffer(&bufferDesc, NULL, &m_SOStagingBuffer);
if(FAILED(hr))
RDCERR("Failed to create m_SOStagingBuffer %08x", hr);
}
bool D3D11DebugManager::InitFontRendering()
{
HRESULT hr = S_OK;
@@ -3832,33 +3843,48 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t eventID)
SAFE_RELEASE(streamoutGS);
UINT offset = 0;
m_pImmediateContext->SOSetTargets(1, &m_SOBuffer, &offset);
m_pImmediateContext->Begin(m_SOStatsQueries[0]);
ID3D11Buffer *idxBuf = NULL;
DXGI_FORMAT idxFmt = DXGI_FORMAT_UNKNOWN;
UINT idxOffs = 0;
m_WrappedContext->IAGetIndexBuffer(&idxBuf, &idxFmt, &idxOffs);
ID3D11Buffer *origBuf = idxBuf;
if(!(drawcall->flags & DrawFlags::UseIBuffer))
{
m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
uint32_t outputSize = stride * drawcall->numIndices;
if(drawcall->flags & DrawFlags::Instanced)
outputSize *= drawcall->numInstances;
if(m_SOBufferSize < outputSize)
{
int oldSize = m_SOBufferSize;
while(m_SOBufferSize < outputSize)
m_SOBufferSize *= 2;
RDCWARN("Resizing stream-out buffer from %d to %d", oldSize, m_SOBufferSize);
CreateSOBuffers();
}
m_pImmediateContext->SOSetTargets(1, &m_SOBuffer, &offset);
m_pImmediateContext->Begin(m_SOStatsQueries[0]);
if(drawcall->flags & DrawFlags::Instanced)
m_pImmediateContext->DrawInstanced(drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
else
m_pImmediateContext->Draw(drawcall->numIndices, drawcall->vertexOffset);
m_pImmediateContext->IASetPrimitiveTopology(topo);
m_pImmediateContext->End(m_SOStatsQueries[0]);
}
else // drawcall is indexed
{
UINT idxOffs = 0;
m_WrappedContext->IAGetIndexBuffer(&idxBuf, &idxFmt, &idxOffs);
bool index16 = (idxFmt == DXGI_FORMAT_R16_UINT);
UINT bytesize = index16 ? 2 : 4;
ID3D11Buffer *origBuf = idxBuf;
vector<byte> idxdata;
GetBufferData(idxBuf, idxOffs + drawcall->indexOffset * bytesize,
drawcall->numIndices * bytesize, idxdata, true);
@@ -3941,14 +3967,30 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t eventID)
m_pImmediateContext->IASetIndexBuffer(idxBuf, DXGI_FORMAT_R32_UINT, 0);
SAFE_RELEASE(idxBuf);
uint32_t outputSize = stride * (uint32_t)indices.size();
if(drawcall->flags & DrawFlags::Instanced)
outputSize *= drawcall->numInstances;
if(m_SOBufferSize < outputSize)
{
int oldSize = m_SOBufferSize;
while(m_SOBufferSize < outputSize)
m_SOBufferSize *= 2;
RDCWARN("Resizing stream-out buffer from %d to %d", oldSize, m_SOBufferSize);
CreateSOBuffers();
}
m_pImmediateContext->SOSetTargets(1, &m_SOBuffer, &offset);
m_pImmediateContext->Begin(m_SOStatsQueries[0]);
if(drawcall->flags & DrawFlags::Instanced)
m_pImmediateContext->DrawIndexedInstanced((UINT)indices.size(), drawcall->numInstances, 0,
0, drawcall->instanceOffset);
else
m_pImmediateContext->DrawIndexed((UINT)indices.size(), 0, 0);
m_pImmediateContext->IASetPrimitiveTopology(topo);
m_pImmediateContext->IASetIndexBuffer(UNWRAP(WrappedID3D11Buffer, origBuf), idxFmt, idxOffs);
m_pImmediateContext->End(m_SOStatsQueries[0]);
// rebase existing index buffer to point to the right elements in our stream-out'd
// vertex buffer
@@ -3984,7 +4026,8 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t eventID)
idxBuf = NULL;
}
m_pImmediateContext->End(m_SOStatsQueries[0]);
m_pImmediateContext->IASetPrimitiveTopology(topo);
m_pImmediateContext->IASetIndexBuffer(UNWRAP(WrappedID3D11Buffer, origBuf), idxFmt, idxOffs);
m_pImmediateContext->GSSetShader(NULL, NULL, 0);
m_pImmediateContext->SOSetTargets(0, NULL, NULL);
@@ -4023,15 +4066,6 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t eventID)
0,
0};
if(bufferDesc.ByteWidth >= m_SOBufferSize)
{
RDCERR("Generated output data too large: %08x", bufferDesc.ByteWidth);
m_pImmediateContext->Unmap(m_SOStagingBuffer, 0);
SAFE_RELEASE(idxBuf);
return;
}
ID3D11Buffer *vsoutBuffer = NULL;
// we need to map this data into memory for read anyway, might as well make this VB
@@ -4222,60 +4256,18 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t eventID)
SAFE_RELEASE(streamoutGS);
UINT offset = 0;
m_pImmediateContext->SOSetTargets(1, &m_SOBuffer, &offset);
// instanced draws must be replayed one at a time so we can record the number of primitives from
// each drawcall, as due to expansion this can vary per-instance.
if(drawcall->flags & DrawFlags::Instanced)
D3D11_QUERY_DATA_SO_STATISTICS numPrims = {0};
// do the whole draw, and if our output buffer isn't large enough then loop around.
while(true)
{
// if there is only one instance it's a trivial case and we don't need to bother with the
// expensive path
if(drawcall->numInstances > 1)
m_pImmediateContext->Begin(m_SOStatsQueries[0]);
m_pImmediateContext->SOSetTargets(1, &m_SOBuffer, &offset);
if(drawcall->flags & DrawFlags::Instanced)
{
// ensure we have enough queries
while(m_SOStatsQueries.size() < drawcall->numInstances)
{
D3D11_QUERY_DESC qdesc;
qdesc.MiscFlags = 0;
qdesc.Query = D3D11_QUERY_SO_STATISTICS;
ID3D11Query *q = NULL;
hr = m_pDevice->CreateQuery(&qdesc, &q);
if(FAILED(hr))
RDCERR("Failed to create m_SOStatsQuery %08x", hr);
m_SOStatsQueries.push_back(q);
}
// do incremental draws to get the output size. We have to do this O(N^2) style because
// there's no way to replay only a single instance. We have to replay 1, 2, 3, ... N
// instances and count the total number of verts each time, then we can see from the
// difference how much each instance wrote.
for(uint32_t inst = 1; inst <= drawcall->numInstances; inst++)
{
if(drawcall->flags & DrawFlags::UseIBuffer)
{
m_pImmediateContext->SOSetTargets(1, &m_SOBuffer, &offset);
m_pImmediateContext->Begin(m_SOStatsQueries[inst - 1]);
m_pImmediateContext->DrawIndexedInstanced(drawcall->numIndices, inst,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
m_pImmediateContext->End(m_SOStatsQueries[inst - 1]);
}
else
{
m_pImmediateContext->SOSetTargets(1, &m_SOBuffer, &offset);
m_pImmediateContext->Begin(m_SOStatsQueries[inst - 1]);
m_pImmediateContext->DrawInstanced(drawcall->numIndices, inst, drawcall->vertexOffset,
drawcall->instanceOffset);
m_pImmediateContext->End(m_SOStatsQueries[inst - 1]);
}
}
}
else
{
m_pImmediateContext->Begin(m_SOStatsQueries[0]);
if(drawcall->flags & DrawFlags::UseIBuffer)
{
m_pImmediateContext->DrawIndexedInstanced(drawcall->numIndices, drawcall->numInstances,
@@ -4287,34 +4279,92 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t eventID)
m_pImmediateContext->DrawInstanced(drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
}
m_pImmediateContext->End(m_SOStatsQueries[0]);
}
}
else
{
m_pImmediateContext->Begin(m_SOStatsQueries[0]);
// trying to stream out a stream-out-auto based drawcall would be bad!
// instead just draw the number of verts we pre-calculated
if(drawcall->flags & DrawFlags::Auto)
{
m_pImmediateContext->Draw(drawcall->numIndices, 0);
}
else
{
if(drawcall->flags & DrawFlags::UseIBuffer)
// trying to stream out a stream-out-auto based drawcall would be bad!
// instead just draw the number of verts we pre-calculated
if(drawcall->flags & DrawFlags::Auto)
{
m_pImmediateContext->DrawIndexed(drawcall->numIndices, drawcall->indexOffset,
drawcall->baseVertex);
m_pImmediateContext->Draw(drawcall->numIndices, 0);
}
else
{
m_pImmediateContext->Draw(drawcall->numIndices, drawcall->vertexOffset);
if(drawcall->flags & DrawFlags::UseIBuffer)
{
m_pImmediateContext->DrawIndexed(drawcall->numIndices, drawcall->indexOffset,
drawcall->baseVertex);
}
else
{
m_pImmediateContext->Draw(drawcall->numIndices, drawcall->vertexOffset);
}
}
}
m_pImmediateContext->End(m_SOStatsQueries[0]);
do
{
hr = m_pImmediateContext->GetData(m_SOStatsQueries[0], &numPrims,
sizeof(D3D11_QUERY_DATA_SO_STATISTICS), 0);
} while(hr == S_FALSE);
if(m_SOBufferSize < stride * (uint32_t)numPrims.PrimitivesStorageNeeded * 3)
{
int oldSize = m_SOBufferSize;
while(m_SOBufferSize < stride * (uint32_t)numPrims.PrimitivesStorageNeeded * 3)
m_SOBufferSize *= 2;
RDCWARN("Resizing stream-out buffer from %d to %d", oldSize, m_SOBufferSize);
CreateSOBuffers();
continue;
}
break;
}
// instanced draws must be replayed one at a time so we can record the number of primitives from
// each drawcall, as due to expansion this can vary per-instance.
if(drawcall->flags & DrawFlags::Instanced && drawcall->numInstances > 1)
{
// ensure we have enough queries
while(m_SOStatsQueries.size() < drawcall->numInstances)
{
D3D11_QUERY_DESC qdesc;
qdesc.MiscFlags = 0;
qdesc.Query = D3D11_QUERY_SO_STATISTICS;
ID3D11Query *q = NULL;
hr = m_pDevice->CreateQuery(&qdesc, &q);
if(FAILED(hr))
RDCERR("Failed to create m_SOStatsQuery %08x", hr);
m_SOStatsQueries.push_back(q);
}
// do incremental draws to get the output size. We have to do this O(N^2) style because
// there's no way to replay only a single instance. We have to replay 1, 2, 3, ... N
// instances and count the total number of verts each time, then we can see from the
// difference how much each instance wrote.
for(uint32_t inst = 1; inst <= drawcall->numInstances; inst++)
{
if(drawcall->flags & DrawFlags::UseIBuffer)
{
m_pImmediateContext->SOSetTargets(1, &m_SOBuffer, &offset);
m_pImmediateContext->Begin(m_SOStatsQueries[inst - 1]);
m_pImmediateContext->DrawIndexedInstanced(drawcall->numIndices, inst, drawcall->indexOffset,
drawcall->baseVertex, drawcall->instanceOffset);
m_pImmediateContext->End(m_SOStatsQueries[inst - 1]);
}
else
{
m_pImmediateContext->SOSetTargets(1, &m_SOBuffer, &offset);
m_pImmediateContext->Begin(m_SOStatsQueries[inst - 1]);
m_pImmediateContext->DrawInstanced(drawcall->numIndices, inst, drawcall->vertexOffset,
drawcall->instanceOffset);
m_pImmediateContext->End(m_SOStatsQueries[inst - 1]);
}
}
}
m_pImmediateContext->GSSetShader(NULL, NULL, 0);
@@ -4322,7 +4372,6 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t eventID)
m_pImmediateContext->CopyResource(m_SOStagingBuffer, m_SOBuffer);
D3D11_QUERY_DATA_SO_STATISTICS numPrims = {0};
std::vector<D3D11PostVSData::InstData> instData;
if((drawcall->flags & DrawFlags::Instanced) && drawcall->numInstances > 1)
+4 -3
View File
@@ -336,9 +336,9 @@ private:
bool m_ShaderCacheDirty, m_CacheShaders;
map<uint32_t, ID3DBlob *> m_ShaderCache;
static const int m_SOBufferSize = 32 * 1024 * 1024;
ID3D11Buffer *m_SOBuffer;
ID3D11Buffer *m_SOStagingBuffer;
uint32_t m_SOBufferSize = 32 * 1024 * 1024;
ID3D11Buffer *m_SOBuffer = NULL;
ID3D11Buffer *m_SOStagingBuffer = NULL;
std::vector<ID3D11Query *> m_SOStatsQueries;
// event -> data
map<uint32_t, D3D11PostVSData> m_PostVSData;
@@ -369,6 +369,7 @@ private:
ID3D11Buffer *m_TriHighlightHelper;
bool InitStreamOut();
void CreateSOBuffers();
void ShutdownStreamOut();
// font/text rendering
+331 -118
View File
@@ -216,65 +216,7 @@ D3D12DebugManager::D3D12DebugManager(WrappedID3D12Device *wrapper)
m_CustomShaderTex = NULL;
{
D3D12_RESOURCE_DESC soBufDesc;
soBufDesc.Alignment = 0;
soBufDesc.DepthOrArraySize = 1;
soBufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
// need to allow UAV access to reset the counter each time
soBufDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
soBufDesc.Format = DXGI_FORMAT_UNKNOWN;
soBufDesc.Height = 1;
soBufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
soBufDesc.MipLevels = 1;
soBufDesc.SampleDesc.Count = 1;
soBufDesc.SampleDesc.Quality = 0;
// add 64 bytes for the counter at the start
soBufDesc.Width = m_SOBufferSize + 64;
D3D12_HEAP_PROPERTIES heapProps;
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
hr = m_WrappedDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &soBufDesc,
D3D12_RESOURCE_STATE_STREAM_OUT, NULL,
__uuidof(ID3D12Resource), (void **)&m_SOBuffer);
if(FAILED(hr))
{
RDCERR("Failed to create SO output buffer, HRESULT: 0x%08x", hr);
return;
}
soBufDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
heapProps.Type = D3D12_HEAP_TYPE_READBACK;
hr = m_WrappedDevice->CreateCommittedResource(
&heapProps, D3D12_HEAP_FLAG_NONE, &soBufDesc, D3D12_RESOURCE_STATE_COPY_DEST, NULL,
__uuidof(ID3D12Resource), (void **)&m_SOStagingBuffer);
if(FAILED(hr))
{
RDCERR("Failed to create readback buffer, HRESULT: 0x%08x", hr);
return;
}
soBufDesc.Width = m_SOPatchedIndexBufferSize;
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
hr = m_WrappedDevice->CreateCommittedResource(
&heapProps, D3D12_HEAP_FLAG_NONE, &soBufDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
__uuidof(ID3D12Resource), (void **)&m_SOPatchedIndexBuffer);
if(FAILED(hr))
{
RDCERR("Failed to create SO index buffer, HRESULT: 0x%08x", hr);
return;
}
}
CreateSOBuffers();
{
D3D12_RESOURCE_DESC readbackDesc;
@@ -1406,6 +1348,100 @@ D3D12DebugManager::~D3D12DebugManager()
RenderDoc::Inst().GetCrashHandler()->UnregisterMemoryRegion(this);
}
void D3D12DebugManager::CreateSOBuffers()
{
HRESULT hr = S_OK;
SAFE_RELEASE(m_SOBuffer);
SAFE_RELEASE(m_SOStagingBuffer);
SAFE_RELEASE(m_SOPatchedIndexBuffer);
SAFE_RELEASE(m_SOQueryHeap);
D3D12_RESOURCE_DESC soBufDesc;
soBufDesc.Alignment = 0;
soBufDesc.DepthOrArraySize = 1;
soBufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
// need to allow UAV access to reset the counter each time
soBufDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
soBufDesc.Format = DXGI_FORMAT_UNKNOWN;
soBufDesc.Height = 1;
soBufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
soBufDesc.MipLevels = 1;
soBufDesc.SampleDesc.Count = 1;
soBufDesc.SampleDesc.Quality = 0;
// add 64 bytes for the counter at the start
soBufDesc.Width = m_SOBufferSize + 64;
D3D12_HEAP_PROPERTIES heapProps;
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
hr = m_WrappedDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &soBufDesc,
D3D12_RESOURCE_STATE_STREAM_OUT, NULL,
__uuidof(ID3D12Resource), (void **)&m_SOBuffer);
if(FAILED(hr))
{
RDCERR("Failed to create SO output buffer, HRESULT: 0x%08x", hr);
return;
}
soBufDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
heapProps.Type = D3D12_HEAP_TYPE_READBACK;
hr = m_WrappedDevice->CreateCommittedResource(
&heapProps, D3D12_HEAP_FLAG_NONE, &soBufDesc, D3D12_RESOURCE_STATE_COPY_DEST, NULL,
__uuidof(ID3D12Resource), (void **)&m_SOStagingBuffer);
if(FAILED(hr))
{
RDCERR("Failed to create readback buffer, HRESULT: 0x%08x", hr);
return;
}
// this is a buffer of unique indices, so it allows for
// the worst case - float4 per vertex, all unique indices.
soBufDesc.Width = m_SOBufferSize / sizeof(Vec4f);
heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
hr = m_WrappedDevice->CreateCommittedResource(
&heapProps, D3D12_HEAP_FLAG_NONE, &soBufDesc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
__uuidof(ID3D12Resource), (void **)&m_SOPatchedIndexBuffer);
if(FAILED(hr))
{
RDCERR("Failed to create SO index buffer, HRESULT: 0x%08x", hr);
return;
}
D3D12_QUERY_HEAP_DESC queryDesc;
queryDesc.Count = 16;
queryDesc.NodeMask = 1;
queryDesc.Type = D3D12_QUERY_HEAP_TYPE_SO_STATISTICS;
hr = m_WrappedDevice->CreateQueryHeap(&queryDesc, __uuidof(m_SOQueryHeap), (void **)&m_SOQueryHeap);
if(FAILED(hr))
{
RDCERR("Failed to create SO query heap, HRESULT: 0x%08x", hr);
return;
}
D3D12_UNORDERED_ACCESS_VIEW_DESC counterDesc = {};
counterDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
counterDesc.Format = DXGI_FORMAT_R32_UINT;
counterDesc.Buffer.FirstElement = 0;
counterDesc.Buffer.NumElements = 4;
m_WrappedDevice->CreateUnorderedAccessView(m_SOBuffer, NULL, &counterDesc,
GetCPUHandle(STREAM_OUT_UAV));
m_WrappedDevice->CreateUnorderedAccessView(m_SOBuffer, NULL, &counterDesc,
GetUAVClearHandle(STREAM_OUT_UAV));
}
string D3D12DebugManager::GetShaderBlob(const char *source, const char *entry,
const uint32_t compileFlags, const char *profile,
ID3DBlob **srcblob)
@@ -3911,8 +3947,28 @@ void D3D12DebugManager::InitPostVSBuffers(uint32_t eventID)
ID3D12Resource *idxBuf = NULL;
bool recreate = false;
uint64_t outputSize = stride * drawcall->numIndices * drawcall->numInstances;
if(m_SOBufferSize < outputSize)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize < outputSize)
m_SOBufferSize *= 2;
RDCWARN("Resizing stream-out buffer from %llu to %llu for output data", oldSize,
m_SOBufferSize);
recreate = true;
}
if(!(drawcall->flags & DrawFlags::UseIBuffer))
{
if(recreate)
{
m_WrappedDevice->GPUSync();
CreateSOBuffers();
}
m_DebugList->Reset(m_DebugAlloc, NULL);
rs.ApplyState(m_DebugList);
@@ -4000,10 +4056,20 @@ void D3D12DebugManager::InitPostVSBuffers(uint32_t eventID)
indexRemap[indices[i]] = i;
}
if(indices.size() > m_SOPatchedIndexBufferSize / sizeof(uint32_t))
if(m_SOBufferSize / sizeof(Vec4f) < indices.size() * sizeof(uint32_t))
{
RDCWARN("Too many unique indices, clamping.");
indices.resize(m_SOPatchedIndexBufferSize / sizeof(uint32_t));
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize / sizeof(Vec4f) < indices.size() * sizeof(uint32_t))
m_SOBufferSize *= 2;
RDCWARN("Resizing stream-out buffer from %llu to %llu for indices", oldSize, m_SOBufferSize);
recreate = true;
}
if(recreate)
{
m_WrappedDevice->GPUSync();
CreateSOBuffers();
}
FillBuffer(m_SOPatchedIndexBuffer, 0, &indices[0], indices.size() * sizeof(uint32_t));
@@ -4118,18 +4184,6 @@ void D3D12DebugManager::InitPostVSBuffers(uint32_t eventID)
m_DebugList->DiscardResource(m_SOBuffer, NULL);
m_DebugList->ResourceBarrier(1, &sobarr);
D3D12_UNORDERED_ACCESS_VIEW_DESC counterDesc = {};
counterDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
counterDesc.Format = DXGI_FORMAT_R32_UINT;
counterDesc.Buffer.FirstElement = 0;
counterDesc.Buffer.NumElements = 4;
m_WrappedDevice->CreateUnorderedAccessView(m_SOBuffer, NULL, &counterDesc,
GetCPUHandle(STREAM_OUT_UAV));
m_WrappedDevice->CreateUnorderedAccessView(m_SOBuffer, NULL, &counterDesc,
GetUAVClearHandle(STREAM_OUT_UAV));
UINT zeroes[4] = {0, 0, 0, 0};
m_DebugList->ClearUnorderedAccessViewUint(
GetGPUHandle(STREAM_OUT_UAV), GetUAVClearHandle(STREAM_OUT_UAV), m_SOBuffer, zeroes, 0, NULL);
@@ -4169,16 +4223,6 @@ void D3D12DebugManager::InitPostVSBuffers(uint32_t eventID)
// skip past the counter
byteData += 64;
if(numBytesWritten >= m_SOBufferSize)
{
RDCERR("Generated output data too large: %08x", numBytesWritten);
m_SOStagingBuffer->Unmap(0, &range);
SAFE_RELEASE(idxBuf);
SAFE_RELEASE(soSig);
return;
}
uint64_t numPrims = numBytesWritten / stride;
ID3D12Resource *vsoutBuffer = NULL;
@@ -4390,27 +4434,126 @@ void D3D12DebugManager::InitPostVSBuffers(uint32_t eventID)
return;
}
m_DebugList->Reset(m_DebugAlloc, NULL);
rs.ApplyState(m_DebugList);
m_DebugList->SetPipelineState(pipe);
if(soSig)
{
m_DebugList->SetGraphicsRootSignature(soSig);
rs.ApplyGraphicsRootElements(m_DebugList);
}
D3D12_STREAM_OUTPUT_BUFFER_VIEW view;
view.BufferFilledSizeLocation = m_SOBuffer->GetGPUVirtualAddress();
view.BufferLocation = m_SOBuffer->GetGPUVirtualAddress() + 64;
view.SizeInBytes = m_SOBufferSize;
// draws with multiple instances must be replayed one at a time so we can record the number of
// primitives from each drawcall, as due to expansion this can vary per-instance.
if(drawcall->numInstances > 1)
{
m_DebugList->Reset(m_DebugAlloc, NULL);
rs.ApplyState(m_DebugList);
m_DebugList->SetPipelineState(pipe);
if(soSig)
{
m_DebugList->SetGraphicsRootSignature(soSig);
rs.ApplyGraphicsRootElements(m_DebugList);
}
view.BufferFilledSizeLocation = m_SOBuffer->GetGPUVirtualAddress();
view.BufferLocation = m_SOBuffer->GetGPUVirtualAddress() + 64;
view.SizeInBytes = m_SOBufferSize;
// do a dummy draw to make sure we have enough space in the output buffer
m_DebugList->SOSetTargets(0, 1, &view);
m_DebugList->BeginQuery(m_SOQueryHeap, D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0, 0);
// because the result is expanded we don't have to remap index buffers or anything
if(drawcall->flags & DrawFlags::UseIBuffer)
{
m_DebugList->DrawIndexedInstanced(drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
}
else
{
m_DebugList->DrawInstanced(drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
}
m_DebugList->EndQuery(m_SOQueryHeap, D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0, 0);
m_DebugList->ResolveQueryData(m_SOQueryHeap, D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0, 0, 1,
m_SOStagingBuffer, 0);
m_DebugList->Close();
ID3D12CommandList *l = m_DebugList;
m_WrappedDevice->GetQueue()->ExecuteCommandLists(1, &l);
m_WrappedDevice->GPUSync();
// check that things are OK, and resize up if needed
D3D12_RANGE range;
range.Begin = 0;
range.End = (SIZE_T)sizeof(D3D12_QUERY_DATA_SO_STATISTICS);
D3D12_QUERY_DATA_SO_STATISTICS *data;
hr = m_SOStagingBuffer->Map(0, &range, (void **)&data);
D3D12_QUERY_DATA_SO_STATISTICS result = *data;
range.End = 0;
m_SOStagingBuffer->Unmap(0, &range);
if(m_SOBufferSize < data->PrimitivesStorageNeeded * 3 * stride)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize < data->PrimitivesStorageNeeded * 3 * stride)
m_SOBufferSize *= 2;
RDCWARN("Resizing stream-out buffer from %llu to %llu for output", oldSize, m_SOBufferSize);
CreateSOBuffers();
}
view.BufferFilledSizeLocation = m_SOBuffer->GetGPUVirtualAddress();
view.BufferLocation = m_SOBuffer->GetGPUVirtualAddress() + 64;
view.SizeInBytes = m_SOBufferSize;
m_DebugAlloc->Reset();
// now do the actual stream out
m_DebugList->Reset(m_DebugAlloc, NULL);
// first need to reset the counter byte values which may have either been written to above, or
// are newly created
{
D3D12_RESOURCE_BARRIER sobarr = {};
sobarr.Transition.pResource = m_SOBuffer;
sobarr.Transition.StateBefore = D3D12_RESOURCE_STATE_STREAM_OUT;
sobarr.Transition.StateAfter = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
m_DebugList->ResourceBarrier(1, &sobarr);
D3D12_UNORDERED_ACCESS_VIEW_DESC counterDesc = {};
counterDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
counterDesc.Format = DXGI_FORMAT_R32_UINT;
counterDesc.Buffer.FirstElement = 0;
counterDesc.Buffer.NumElements = 4;
UINT zeroes[4] = {0, 0, 0, 0};
m_DebugList->ClearUnorderedAccessViewUint(GetGPUHandle(STREAM_OUT_UAV),
GetUAVClearHandle(STREAM_OUT_UAV), m_SOBuffer,
zeroes, 0, NULL);
std::swap(sobarr.Transition.StateBefore, sobarr.Transition.StateAfter);
m_DebugList->ResourceBarrier(1, &sobarr);
}
rs.ApplyState(m_DebugList);
m_DebugList->SetPipelineState(pipe);
if(soSig)
{
m_DebugList->SetGraphicsRootSignature(soSig);
rs.ApplyGraphicsRootElements(m_DebugList);
}
// reserve space for enough 'buffer filled size' locations
view.BufferLocation = m_SOBuffer->GetGPUVirtualAddress() +
AlignUp(uint64_t(drawcall->numInstances * sizeof(UINT64)), 64ULL);
@@ -4439,26 +4582,93 @@ void D3D12DebugManager::InitPostVSBuffers(uint32_t eventID)
}
}
m_DebugList->Close();
l = m_DebugList;
m_WrappedDevice->GetQueue()->ExecuteCommandLists(1, &l);
m_WrappedDevice->GPUSync();
// the last draw will have written the actual data we want into the buffer
}
else
{
m_DebugList->SOSetTargets(0, 1, &view);
// this only loops if we find from a query that we need to resize up
while(true)
{
m_DebugList->Reset(m_DebugAlloc, NULL);
// because the result is expanded we don't have to remap index buffers or anything
if(drawcall->flags & DrawFlags::UseIBuffer)
{
m_DebugList->DrawIndexedInstanced(drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
}
else
{
m_DebugList->DrawInstanced(drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
rs.ApplyState(m_DebugList);
m_DebugList->SetPipelineState(pipe);
if(soSig)
{
m_DebugList->SetGraphicsRootSignature(soSig);
rs.ApplyGraphicsRootElements(m_DebugList);
}
view.BufferFilledSizeLocation = m_SOBuffer->GetGPUVirtualAddress();
view.BufferLocation = m_SOBuffer->GetGPUVirtualAddress() + 64;
view.SizeInBytes = m_SOBufferSize;
m_DebugList->SOSetTargets(0, 1, &view);
m_DebugList->BeginQuery(m_SOQueryHeap, D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0, 0);
// because the result is expanded we don't have to remap index buffers or anything
if(drawcall->flags & DrawFlags::UseIBuffer)
{
m_DebugList->DrawIndexedInstanced(drawcall->numIndices, drawcall->numInstances,
drawcall->indexOffset, drawcall->baseVertex,
drawcall->instanceOffset);
}
else
{
m_DebugList->DrawInstanced(drawcall->numIndices, drawcall->numInstances,
drawcall->vertexOffset, drawcall->instanceOffset);
}
m_DebugList->EndQuery(m_SOQueryHeap, D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0, 0);
m_DebugList->ResolveQueryData(m_SOQueryHeap, D3D12_QUERY_TYPE_SO_STATISTICS_STREAM0, 0, 1,
m_SOStagingBuffer, 0);
m_DebugList->Close();
ID3D12CommandList *l = m_DebugList;
m_WrappedDevice->GetQueue()->ExecuteCommandLists(1, &l);
m_WrappedDevice->GPUSync();
// check that things are OK, and resize up if needed
D3D12_RANGE range;
range.Begin = 0;
range.End = (SIZE_T)sizeof(D3D12_QUERY_DATA_SO_STATISTICS);
D3D12_QUERY_DATA_SO_STATISTICS *data;
hr = m_SOStagingBuffer->Map(0, &range, (void **)&data);
if(m_SOBufferSize < data->PrimitivesStorageNeeded * 3 * stride)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize < data->PrimitivesStorageNeeded * 3 * stride)
m_SOBufferSize *= 2;
RDCWARN("Resizing stream-out buffer from %llu to %llu for output", oldSize, m_SOBufferSize);
CreateSOBuffers();
continue;
}
range.End = 0;
m_SOStagingBuffer->Unmap(0, &range);
m_DebugAlloc->Reset();
break;
}
}
m_DebugList->Reset(m_DebugAlloc, NULL);
D3D12_RESOURCE_BARRIER sobarr = {};
sobarr.Transition.pResource = m_SOBuffer;
sobarr.Transition.StateBefore = D3D12_RESOURCE_STATE_STREAM_OUT;
@@ -4542,15 +4752,6 @@ void D3D12DebugManager::InitPostVSBuffers(uint32_t eventID)
// skip past the counter(s)
byteData += (view.BufferLocation - m_SOBuffer->GetGPUVirtualAddress());
if(numBytesWritten >= m_SOBufferSize)
{
RDCERR("Generated output data too large: %08x", numBytesWritten);
m_SOStagingBuffer->Unmap(0, &range);
SAFE_RELEASE(soSig);
return;
}
uint64_t numVerts = numBytesWritten / stride;
ID3D12Resource *gsoutBuffer = NULL;
@@ -5298,6 +5499,9 @@ void D3D12DebugManager::RenderMesh(uint32_t eventID, const vector<MeshFormat> &s
list->IASetPrimitiveTopology(MakeD3DPrimitiveTopology(fmt.topo));
if(PatchList_Count(fmt.topo) > 0)
list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
if(fmt.idxByteWidth && fmt.idxbuf != ResourceId())
{
ID3D12Resource *ib =
@@ -5337,6 +5541,9 @@ void D3D12DebugManager::RenderMesh(uint32_t eventID, const vector<MeshFormat> &s
list->IASetVertexBuffers(1, 1, &view);
list->IASetPrimitiveTopology(MakeD3DPrimitiveTopology(cfg.position.topo));
if(PatchList_Count(cfg.position.topo) > 0)
list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
}
SolidShade solidShadeMode = cfg.solidShadeMode;
@@ -5639,6 +5846,9 @@ void D3D12DebugManager::RenderMesh(uint32_t eventID, const vector<MeshFormat> &s
list->IASetPrimitiveTopology(MakeD3DPrimitiveTopology(helper.topo));
if(PatchList_Count(helper.topo) > 0)
list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
list->SetGraphicsRootConstantBufferView(0, UploadConstants(&vertexData, sizeof(vertexData)));
list->SetPipelineState(cache.pipes[MeshDisplayPipelines::ePipe_Solid]);
@@ -5702,6 +5912,9 @@ void D3D12DebugManager::RenderMesh(uint32_t eventID, const vector<MeshFormat> &s
list->IASetPrimitiveTopology(MakeD3DPrimitiveTopology(helper.topo));
if(PatchList_Count(helper.topo) > 0)
list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
list->SetPipelineState(cache.pipes[MeshDisplayPipelines::ePipe_Solid]);
{
+7 -9
View File
@@ -39,7 +39,6 @@ class D3D12DebugManager
{
public:
D3D12DebugManager(WrappedID3D12Device *wrapper);
~D3D12DebugManager();
uint64_t MakeOutputWindow(WindowingSystem system, void *data, bool depth);
@@ -319,6 +318,8 @@ private:
const char *profile, ID3DBlob **srcblob);
ID3DBlob *MakeFixedColShader(float overlayConsts[4]);
void CreateSOBuffers();
struct MeshDisplayPipelines
{
enum
@@ -390,14 +391,11 @@ private:
uint32_t m_PickSize;
ID3D12Resource *m_PickResultBuf;
static const int m_SOBufferSize = 32 * 1024 * 1024;
ID3D12Resource *m_SOBuffer;
ID3D12Resource *m_SOStagingBuffer;
// this is a buffer of unique indices, so it allows for
// the worst case - float4 per vertex, all unique indices.
static const int m_SOPatchedIndexBufferSize = m_SOBufferSize / 16;
ID3D12Resource *m_SOPatchedIndexBuffer;
uint64_t m_SOBufferSize = 128;
ID3D12Resource *m_SOBuffer = NULL;
ID3D12Resource *m_SOStagingBuffer = NULL;
ID3D12Resource *m_SOPatchedIndexBuffer = NULL;
ID3D12QueryHeap *m_SOQueryHeap = NULL;
map<uint32_t, D3D12PostVSData> m_PostVSData;
map<uint32_t, uint32_t> m_PostVSAlias;
+151 -11
View File
@@ -665,7 +665,8 @@ void GLReplay::InitDebugData()
gl.glBindTransformFeedback(eGL_TRANSFORM_FEEDBACK, DebugData.feedbackObj);
gl.glBindBuffer(eGL_TRANSFORM_FEEDBACK_BUFFER, DebugData.feedbackBuffer);
gl.glNamedBufferDataEXT(DebugData.feedbackBuffer, 32 * 1024 * 1024, NULL, eGL_DYNAMIC_READ);
gl.glNamedBufferDataEXT(DebugData.feedbackBuffer, DebugData.feedbackBufferSize, NULL,
eGL_DYNAMIC_READ);
gl.glBindBufferBase(eGL_TRANSFORM_FEEDBACK_BUFFER, 0, DebugData.feedbackBuffer);
gl.glBindTransformFeedback(eGL_TRANSFORM_FEEDBACK, 0);
@@ -3581,19 +3582,35 @@ void GLReplay::InitPostVSBuffers(uint32_t eventID)
gl.glBindTransformFeedback(eGL_TRANSFORM_FEEDBACK, DebugData.feedbackObj);
// need to rebind this here because of an AMD bug that seems to ignore the buffer
// bindings in the feedback object - or at least it errors if the default feedback
// object has no buffers bound. Fortunately the state is still object-local so
// we don't have to restore the buffer binding on the default feedback object.
gl.glBindBufferBase(eGL_TRANSFORM_FEEDBACK_BUFFER, 0, DebugData.feedbackBuffer);
GLuint idxBuf = 0;
gl.glBeginQuery(eGL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, DebugData.feedbackQueries[0]);
gl.glBeginTransformFeedback(eGL_POINTS);
if(!(drawcall->flags & DrawFlags::UseIBuffer))
{
uint32_t outputSize = drawcall->numIndices * drawcall->numInstances * stride;
if(drawcall->flags & DrawFlags::Instanced)
outputSize *= drawcall->numInstances;
// resize up the buffer if needed for the vertex output data
if(DebugData.feedbackBufferSize < outputSize)
{
uint32_t oldSize = DebugData.feedbackBufferSize;
while(DebugData.feedbackBufferSize < outputSize)
DebugData.feedbackBufferSize *= 2;
RDCWARN("Resizing xfb buffer from %u to %u for output", oldSize, DebugData.feedbackBufferSize);
gl.glNamedBufferDataEXT(DebugData.feedbackBuffer, DebugData.feedbackBufferSize, NULL,
eGL_DYNAMIC_READ);
}
// need to rebind this here because of an AMD bug that seems to ignore the buffer
// bindings in the feedback object - or at least it errors if the default feedback
// object has no buffers bound. Fortunately the state is still object-local so
// we don't have to restore the buffer binding on the default feedback object.
gl.glBindBufferBase(eGL_TRANSFORM_FEEDBACK_BUFFER, 0, DebugData.feedbackBuffer);
gl.glBeginQuery(eGL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, DebugData.feedbackQueries[0]);
gl.glBeginTransformFeedback(eGL_POINTS);
if(drawcall->flags & DrawFlags::Instanced)
{
if(HasExt[ARB_base_instance])
@@ -3682,6 +3699,31 @@ void GLReplay::InitPostVSBuffers(uint32_t eventID)
gl.glNamedBufferDataEXT(indexSetBuffer, sizeof(uint32_t) * indices.size(), &indices[0],
eGL_STATIC_DRAW);
uint32_t outputSize = (uint32_t)indices.size() * drawcall->numInstances * stride;
if(drawcall->flags & DrawFlags::Instanced)
outputSize *= drawcall->numInstances;
// resize up the buffer if needed for the vertex output data
if(DebugData.feedbackBufferSize < outputSize)
{
uint32_t oldSize = DebugData.feedbackBufferSize;
while(DebugData.feedbackBufferSize < outputSize)
DebugData.feedbackBufferSize *= 2;
RDCWARN("Resizing xfb buffer from %u to %u for output", oldSize, DebugData.feedbackBufferSize);
gl.glNamedBufferDataEXT(DebugData.feedbackBuffer, DebugData.feedbackBufferSize, NULL,
eGL_DYNAMIC_READ);
}
// need to rebind this here because of an AMD bug that seems to ignore the buffer
// bindings in the feedback object - or at least it errors if the default feedback
// object has no buffers bound. Fortunately the state is still object-local so
// we don't have to restore the buffer binding on the default feedback object.
gl.glBindBufferBase(eGL_TRANSFORM_FEEDBACK_BUFFER, 0, DebugData.feedbackBuffer);
gl.glBeginQuery(eGL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, DebugData.feedbackQueries[0]);
gl.glBeginTransformFeedback(eGL_POINTS);
if(drawcall->flags & DrawFlags::Instanced)
{
if(HasExt[ARB_base_instance])
@@ -4104,28 +4146,126 @@ void GLReplay::InitPostVSBuffers(uint32_t eventID)
GLenum shaderOutMode = eGL_TRIANGLES;
GLenum lastOutTopo = eGL_TRIANGLES;
uint32_t maxOutputSize = stride;
if(drawcall->flags & DrawFlags::Instanced)
maxOutputSize *= drawcall->numInstances;
uint32_t numInputPrimitives = drawcall->numIndices;
GLenum drawtopo = MakeGLPrimitiveTopology(drawcall->topology);
switch(drawcall->topology)
{
case Topology::PointList: break;
case Topology::LineList: numInputPrimitives /= 2; break;
case Topology::LineStrip: numInputPrimitives -= 1; break;
case Topology::LineLoop: break;
case Topology::TriangleList: numInputPrimitives /= 3; break;
case Topology::TriangleStrip:
case Topology::TriangleFan: numInputPrimitives -= 2; break;
case Topology::LineList_Adj: numInputPrimitives /= 4; break;
case Topology::LineStrip_Adj: numInputPrimitives -= 3; break;
case Topology::TriangleList_Adj: numInputPrimitives /= 6; break;
case Topology::TriangleStrip_Adj: numInputPrimitives -= 5; break;
case Topology::PatchList_1CPs:
case Topology::PatchList_2CPs:
case Topology::PatchList_3CPs:
case Topology::PatchList_4CPs:
case Topology::PatchList_5CPs:
case Topology::PatchList_6CPs:
case Topology::PatchList_7CPs:
case Topology::PatchList_8CPs:
case Topology::PatchList_9CPs:
case Topology::PatchList_10CPs:
case Topology::PatchList_11CPs:
case Topology::PatchList_12CPs:
case Topology::PatchList_13CPs:
case Topology::PatchList_14CPs:
case Topology::PatchList_15CPs:
case Topology::PatchList_16CPs:
case Topology::PatchList_17CPs:
case Topology::PatchList_18CPs:
case Topology::PatchList_19CPs:
case Topology::PatchList_20CPs:
case Topology::PatchList_21CPs:
case Topology::PatchList_22CPs:
case Topology::PatchList_23CPs:
case Topology::PatchList_24CPs:
case Topology::PatchList_25CPs:
case Topology::PatchList_26CPs:
case Topology::PatchList_27CPs:
case Topology::PatchList_28CPs:
case Topology::PatchList_29CPs:
case Topology::PatchList_30CPs:
case Topology::PatchList_31CPs:
case Topology::PatchList_32CPs:
numInputPrimitives /= PatchList_Count(drawcall->topology);
break;
}
if(lastProg == gsProg)
{
gl.glGetProgramiv(gsProg, eGL_GEOMETRY_OUTPUT_TYPE, (GLint *)&shaderOutMode);
GLint maxVerts = 1;
gl.glGetProgramiv(gsProg, eGL_GEOMETRY_VERTICES_OUT, (GLint *)&maxVerts);
if(shaderOutMode == eGL_TRIANGLE_STRIP)
{
lastOutTopo = eGL_TRIANGLES;
maxVerts = RDCMAX(3, maxVerts);
}
else if(shaderOutMode == eGL_LINE_STRIP)
{
lastOutTopo = eGL_LINES;
maxVerts = RDCMAX(2, maxVerts);
}
else if(shaderOutMode == eGL_POINTS)
{
lastOutTopo = eGL_POINTS;
maxVerts = RDCMAX(1, maxVerts);
}
maxOutputSize *= maxVerts * numInputPrimitives;
}
else if(lastProg == tesProg)
{
gl.glGetProgramiv(tesProg, eGL_TESS_GEN_MODE, (GLint *)&shaderOutMode);
uint32_t outputPrimitiveVerts = 1;
if(shaderOutMode == eGL_QUADS)
{
lastOutTopo = eGL_TRIANGLES;
outputPrimitiveVerts = 3;
}
else if(shaderOutMode == eGL_ISOLINES)
{
lastOutTopo = eGL_LINES;
outputPrimitiveVerts = 2;
}
else if(shaderOutMode == eGL_TRIANGLES)
{
lastOutTopo = eGL_TRIANGLES;
outputPrimitiveVerts = 3;
}
// assume an average maximum tessellation level of 32
maxOutputSize *= 32 * outputPrimitiveVerts * numInputPrimitives;
}
GLenum drawtopo = MakeGLPrimitiveTopology(drawcall->topology);
// resize up the buffer if needed for the vertex output data
if(DebugData.feedbackBufferSize < maxOutputSize)
{
uint32_t oldSize = DebugData.feedbackBufferSize;
while(DebugData.feedbackBufferSize < maxOutputSize)
DebugData.feedbackBufferSize *= 2;
RDCWARN("Conservatively resizing xfb buffer from %u to %u for output", oldSize,
DebugData.feedbackBufferSize);
gl.glNamedBufferDataEXT(DebugData.feedbackBuffer, DebugData.feedbackBufferSize, NULL,
eGL_DYNAMIC_READ);
}
GLenum idxType = eGL_UNSIGNED_BYTE;
if(drawcall->indexByteWidth == 2)
+1
View File
@@ -340,6 +340,7 @@ private:
GLuint feedbackObj;
std::vector<GLuint> feedbackQueries;
GLuint feedbackBuffer;
uint32_t feedbackBufferSize = 32 * 1024 * 1024;
GLuint pickPixelTex;
GLuint pickPixelFBO;