Fix handling of buffer truncation and zero-sized buffers

This commit is contained in:
baldurk
2020-05-29 17:26:29 +01:00
parent 9f0787da33
commit a0a373a8e1
36 changed files with 1038 additions and 242 deletions
+63 -29
View File
@@ -1522,16 +1522,23 @@ static void ConfigureMeshColumns(ICaptureContext &ctx, PopulateBufferData *bufda
BoundVBuffer ib = ctx.CurPipelineState().GetIBuffer();
uint32_t bytesAvailable = 0;
uint32_t bytesAvailable = ib.byteSize;
BufferDescription *buf = ctx.GetBuffer(ib.resourceId);
if(buf)
if(bytesAvailable == ~0U)
{
uint64_t offset = ib.byteOffset - draw->indexOffset * draw->indexByteWidth;
if(offset > buf->length)
bytesAvailable = 0;
BufferDescription *buf = ctx.GetBuffer(ib.resourceId);
if(buf)
{
uint64_t offset = ib.byteOffset - draw->indexOffset * draw->indexByteWidth;
if(offset > buf->length)
bytesAvailable = 0;
else
bytesAvailable = buf->length - offset;
}
else
bytesAvailable = buf->length - offset;
{
bytesAvailable = 0;
}
}
// drawing more than this many indices will read off the end of the index buffer - which while
@@ -1548,12 +1555,25 @@ static void ConfigureMeshColumns(ICaptureContext &ctx, PopulateBufferData *bufda
if(vb.byteStride == 0)
continue;
BufferDescription *buf = ctx.GetBuffer(vb.resourceId);
if(buf)
uint32_t bytesAvailable = vb.byteSize;
if(bytesAvailable == ~0U)
{
numRowsUpperBound = qMax(numRowsUpperBound,
uint32_t(buf->length - vb.byteOffset) / qMax(1U, vb.byteStride));
BufferDescription *buf = ctx.GetBuffer(vb.resourceId);
if(buf)
{
if(vb.byteOffset > buf->length)
bytesAvailable = 0;
else
bytesAvailable = buf->length - vb.byteOffset;
}
else
{
bytesAvailable = 0;
}
}
numRowsUpperBound = qMax(numRowsUpperBound, bytesAvailable / qMax(1U, vb.byteStride));
}
// if there are no vertex buffers we can't clamp.
@@ -1596,8 +1616,18 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat
bytebuf idata;
if(ib.resourceId != ResourceId() && draw && (draw->flags & DrawFlags::Indexed))
idata = r->GetBufferData(ib.resourceId, ib.byteOffset + draw->indexOffset * draw->indexByteWidth,
draw->numIndices * draw->indexByteWidth);
{
uint64_t readBytes = draw->numIndices * draw->indexByteWidth;
uint32_t offset = draw->indexOffset * draw->indexByteWidth;
if(ib.byteSize > offset)
readBytes = qMin(ib.byteSize - offset, readBytes);
else
readBytes = 0;
if(readBytes > 0)
idata = r->GetBufferData(ib.resourceId, ib.byteOffset + offset, readBytes);
}
if(data->vsinConfig.indices)
data->vsinConfig.indices->deref();
@@ -1605,7 +1635,8 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat
data->vsinConfig.indices = new BufferData();
if(draw && draw->indexByteWidth != 0 && !idata.isEmpty())
data->vsinConfig.indices->storage.resize(sizeof(uint32_t) * draw->numIndices);
data->vsinConfig.indices->storage.resize(
sizeof(uint32_t) * qMin(draw->numIndices, ((uint32_t)idata.size() / draw->indexByteWidth)));
else if(draw && (draw->flags & DrawFlags::Indexed))
data->vsinConfig.indices->storage.resize(sizeof(uint32_t));
@@ -1716,8 +1747,17 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat
BufferData *buf = new BufferData;
if(used)
{
buf->storage = r->GetBufferData(vb.resourceId, vb.byteOffset + offset * vb.byteStride,
qMax(maxIdx, maxIdx + 1) * vb.byteStride + maxAttrOffset);
uint64_t readBytes = qMax(maxIdx, maxIdx + 1) * vb.byteStride + maxAttrOffset;
offset *= vb.byteStride;
if(vb.byteSize > offset)
readBytes = qMin(vb.byteSize - offset, readBytes);
else
readBytes = 0;
if(readBytes > 0)
buf->storage = r->GetBufferData(vb.resourceId, vb.byteOffset + offset, readBytes);
buf->stride = vb.byteStride;
}
@@ -2410,12 +2450,8 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
}
else
{
uint64_t len = m_ByteSize;
if(len == UINT64_MAX)
len = 0;
QString errors;
ShaderConstant constant = BufferFormatter::ParseFormatString(m_Format, len, true, errors);
ShaderConstant constant = BufferFormatter::ParseFormatString(m_Format, m_ByteSize, true, errors);
UnrollConstant(constant, bufdata->vsinConfig.columns, bufdata->vsinConfig.props);
@@ -2487,8 +2523,6 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
uint64_t unclampedLen = m_ByteSize;
if(unclampedLen == UINT64_MAX)
unclampedLen = 0;
if(unclampedLen == 0)
{
uint64_t bufLen = m_IsBuffer ? m_Ctx.GetBuffer(m_BufferID)->length : 0;
uint64_t bufOffs = m_ByteOffset;
@@ -2505,7 +2539,8 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
if(m_IsBuffer)
{
buf->storage = r->GetBufferData(m_BufferID, CurrentByteOffset(), clampedLen);
if(clampedLen > 0)
buf->storage = r->GetBufferData(m_BufferID, CurrentByteOffset(), clampedLen);
}
else
{
@@ -2949,6 +2984,7 @@ void BufferViewer::UI_CalculateMeshFormats()
BoundVBuffer ib = m_Ctx.CurPipelineState().GetIBuffer();
m_VSInPosition.indexResourceId = ib.resourceId;
m_VSInPosition.indexByteOffset = ib.byteOffset + draw->indexOffset * draw->indexByteWidth;
m_VSInPosition.indexByteSize = ib.byteSize;
if((draw->flags & DrawFlags::Indexed) && m_VSInPosition.indexByteStride == 0)
m_VSInPosition.indexByteStride = 4U;
@@ -2966,6 +3002,7 @@ void BufferViewer::UI_CalculateMeshFormats()
m_VSInPosition.vertexByteStride = vbs[prop.buffer].byteStride;
m_VSInPosition.vertexByteOffset = vbs[prop.buffer].byteOffset + el.byteOffset +
draw->vertexOffset * m_VSInPosition.vertexByteStride;
m_VSInPosition.vertexByteSize = vbs[prop.buffer].byteSize;
}
else
{
@@ -2993,6 +3030,7 @@ void BufferViewer::UI_CalculateMeshFormats()
m_VSInSecondary.vertexByteStride = vbs[prop.buffer].byteStride;
m_VSInSecondary.vertexByteOffset = vbs[prop.buffer].byteOffset + el.byteOffset +
draw->vertexOffset * m_VSInSecondary.vertexByteStride;
m_VSInSecondary.vertexByteSize = vbs[prop.buffer].byteSize;
}
else
{
@@ -3770,11 +3808,7 @@ void BufferViewer::processFormat(const QString &format)
BufferConfiguration bufconfig;
uint64_t len = m_ByteSize;
if(len == UINT64_MAX)
len = 0;
ShaderConstant cols = BufferFormatter::ParseFormatString(format, len, true, errors);
ShaderConstant cols = BufferFormatter::ParseFormatString(format, m_ByteSize, true, errors);
CalcColumnWidth(MaxNumRows(cols));