Make mesh output buffer resizing a little more conservative

* Instead of calculating the mesh output size exponentially by continuously
  doubling, we instead double up to a reasonable size (256MB) and then just
  allocate only enough to cover what we need after that point. This avoids
  getting into the situation where a mesh needs 1.04GB of data and we allocate a
  2GB buffer - which may then fail.
This commit is contained in:
baldurk
2018-08-27 17:09:16 +01:00
parent 5287a44e80
commit 63be6d261c
5 changed files with 40 additions and 25 deletions
+7 -8
View File
@@ -324,8 +324,7 @@ void D3D11Replay::InitPostVSBuffers(uint32_t eventId)
if(m_SOBufferSize < outputSize)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize < outputSize)
m_SOBufferSize *= 2;
m_SOBufferSize = CalcMeshOutputSize(m_SOBufferSize, outputSize);
RDCWARN("Resizing stream-out buffer from %llu to %llu", oldSize, m_SOBufferSize);
CreateSOBuffers();
@@ -439,8 +438,7 @@ void D3D11Replay::InitPostVSBuffers(uint32_t eventId)
if(m_SOBufferSize < outputSize)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize < outputSize)
m_SOBufferSize *= 2;
m_SOBufferSize = CalcMeshOutputSize(m_SOBufferSize, outputSize);
RDCWARN("Resizing stream-out buffer from %llu to %llu", oldSize, m_SOBufferSize);
CreateSOBuffers();
if(!m_SOStagingBuffer)
@@ -777,11 +775,12 @@ void D3D11Replay::InitPostVSBuffers(uint32_t eventId)
sizeof(D3D11_QUERY_DATA_SO_STATISTICS), 0);
} while(hr == S_FALSE);
if(m_SOBufferSize < stride * numPrims.PrimitivesStorageNeeded * 3)
uint64_t outputSize = stride * numPrims.PrimitivesStorageNeeded * 3;
if(m_SOBufferSize < outputSize)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize < stride * numPrims.PrimitivesStorageNeeded * 3)
m_SOBufferSize *= 2;
m_SOBufferSize = CalcMeshOutputSize(m_SOBufferSize, outputSize);
RDCWARN("Resizing stream-out buffer from %llu to %llu", oldSize, m_SOBufferSize);
CreateSOBuffers();
if(!m_SOStagingBuffer)
@@ -900,7 +899,7 @@ void D3D11Replay::InitPostVSBuffers(uint32_t eventId)
(uint32_t)bytesWritten, D3D11_USAGE_IMMUTABLE, D3D11_BIND_VERTEX_BUFFER, 0, 0, 0,
};
if(bytesWritten >= m_SOBufferSize)
if(bytesWritten > m_SOBufferSize)
{
RDCERR("Generated output data too large: %08x", bufferDesc.ByteWidth);
+13 -11
View File
@@ -329,8 +329,7 @@ void D3D12Replay::InitPostVSBuffers(uint32_t eventId)
if(m_SOBufferSize < outputSize)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize < outputSize)
m_SOBufferSize *= 2;
m_SOBufferSize = CalcMeshOutputSize(m_SOBufferSize, outputSize);
RDCWARN("Resizing stream-out buffer from %llu to %llu for output data", oldSize,
m_SOBufferSize);
recreate = true;
@@ -434,11 +433,12 @@ void D3D12Replay::InitPostVSBuffers(uint32_t eventId)
indexRemap[indices[i]] = i;
}
if(m_SOBufferSize / sizeof(Vec4f) < indices.size() * sizeof(uint32_t))
outputSize = uint64_t(indices.size() * sizeof(uint32_t) * sizeof(Vec4f));
if(m_SOBufferSize < outputSize)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize / sizeof(Vec4f) < indices.size() * sizeof(uint32_t))
m_SOBufferSize *= 2;
m_SOBufferSize = CalcMeshOutputSize(m_SOBufferSize, outputSize);
RDCWARN("Resizing stream-out buffer from %llu to %llu for indices", oldSize, m_SOBufferSize);
recreate = true;
}
@@ -886,11 +886,12 @@ void D3D12Replay::InitPostVSBuffers(uint32_t eventId)
range.End = 0;
m_SOStagingBuffer->Unmap(0, &range);
if(m_SOBufferSize < data->PrimitivesStorageNeeded * 3 * stride)
uint64_t outputSize = data->PrimitivesStorageNeeded * 3 * stride;
if(m_SOBufferSize < outputSize)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize < data->PrimitivesStorageNeeded * 3 * stride)
m_SOBufferSize *= 2;
m_SOBufferSize = CalcMeshOutputSize(m_SOBufferSize, outputSize);
RDCWARN("Resizing stream-out buffer from %llu to %llu for output", oldSize, m_SOBufferSize);
CreateSOBuffers();
}
@@ -1025,11 +1026,12 @@ void D3D12Replay::InitPostVSBuffers(uint32_t eventId)
D3D12_QUERY_DATA_SO_STATISTICS *data;
hr = m_SOStagingBuffer->Map(0, &range, (void **)&data);
if(m_SOBufferSize < data->PrimitivesStorageNeeded * 3 * stride)
uint64_t outputSize = data->PrimitivesStorageNeeded * 3 * stride;
if(m_SOBufferSize < outputSize)
{
uint64_t oldSize = m_SOBufferSize;
while(m_SOBufferSize < data->PrimitivesStorageNeeded * 3 * stride)
m_SOBufferSize *= 2;
m_SOBufferSize = CalcMeshOutputSize(m_SOBufferSize, outputSize);
RDCWARN("Resizing stream-out buffer from %llu to %llu for output", oldSize, m_SOBufferSize);
CreateSOBuffers();
+4 -6
View File
@@ -375,8 +375,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId)
if(DebugData.feedbackBufferSize < outputSize)
{
uint64_t oldSize = DebugData.feedbackBufferSize;
while(DebugData.feedbackBufferSize < outputSize)
DebugData.feedbackBufferSize *= 2;
DebugData.feedbackBufferSize = CalcMeshOutputSize(DebugData.feedbackBufferSize, outputSize);
RDCWARN("Resizing xfb buffer from %llu to %llu for output", oldSize,
DebugData.feedbackBufferSize);
if(DebugData.feedbackBufferSize > INTPTR_MAX)
@@ -495,8 +494,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId)
if(DebugData.feedbackBufferSize < outputSize)
{
uint64_t oldSize = DebugData.feedbackBufferSize;
while(DebugData.feedbackBufferSize < outputSize)
DebugData.feedbackBufferSize *= 2;
DebugData.feedbackBufferSize = CalcMeshOutputSize(DebugData.feedbackBufferSize, outputSize);
RDCWARN("Resizing xfb buffer from %llu to %llu for output", oldSize,
DebugData.feedbackBufferSize);
if(DebugData.feedbackBufferSize > INTPTR_MAX)
@@ -1051,8 +1049,8 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId)
if(DebugData.feedbackBufferSize < maxOutputSize)
{
uint64_t oldSize = DebugData.feedbackBufferSize;
while(DebugData.feedbackBufferSize < maxOutputSize)
DebugData.feedbackBufferSize *= 2;
DebugData.feedbackBufferSize =
CalcMeshOutputSize(DebugData.feedbackBufferSize, maxOutputSize);
RDCWARN("Conservatively resizing xfb buffer from %llu to %llu for output", oldSize,
DebugData.feedbackBufferSize);
if(DebugData.feedbackBufferSize > INTPTR_MAX)
+14
View File
@@ -207,6 +207,20 @@ void PatchLineStripIndexBuffer(const DrawcallDescription *draw, uint8_t *idx8, u
#undef IDX_VALUE
}
uint64_t CalcMeshOutputSize(uint64_t curSize, uint64_t requiredOutput)
{
// resize exponentially up to 256MB to avoid repeated resizes
while(curSize < requiredOutput && curSize < 0x10000000ULL)
curSize *= 2;
// after that, just align the required size up to 16MB and allocate that. Otherwise we can
// vastly-overallocate at large sizes.
if(curSize < requiredOutput)
curSize = AlignUp(requiredOutput, 0x1000000ULL);
return curSize;
}
FloatVector HighlightCache::InterpretVertex(const byte *data, uint32_t vert, const MeshDisplay &cfg,
const byte *end, bool useidx, bool &valid)
{
+2
View File
@@ -236,6 +236,8 @@ DrawcallDescription *SetupDrawcallPointers(std::vector<DrawcallDescription *> &d
void PatchLineStripIndexBuffer(const DrawcallDescription *draw, uint8_t *idx8, uint16_t *idx16,
uint32_t *idx32, std::vector<uint32_t> &patchedIndices);
uint64_t CalcMeshOutputSize(uint64_t curSize, uint64_t requiredOutput);
// simple cache for when we need buffer data for highlighting
// vertices, typical use will be lots of vertices in the same
// mesh, not jumping back and forth much between meshes.