mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 09:00:44 +00:00
Use packing rules when generating format strings for structs
* This allows the calling code to pass a hint of what packing is known or likely to be used, meaning less generated manual offsetting/padding when the implicit rules cover it.
This commit is contained in:
+191
-106
@@ -201,6 +201,46 @@ void BufferFormatter::EstimatePackingRules(Packing::Rules &pack, const ShaderCon
|
||||
}
|
||||
}
|
||||
|
||||
QString BufferFormatter::DeclarePacking(Packing::Rules pack)
|
||||
{
|
||||
if(pack == Packing::D3DCB)
|
||||
return lit("#pack(cbuffer)");
|
||||
else if(pack == Packing::std140)
|
||||
return lit("#pack(std140)");
|
||||
else if(pack == Packing::std430)
|
||||
return lit("#pack(std430)");
|
||||
else if(pack == Packing::D3DUAV) // this is also C but we call it 'structured' for D3D
|
||||
return lit("#pack(structured)");
|
||||
else if(pack == Packing::Scalar)
|
||||
return lit("#pack(scalar)");
|
||||
|
||||
// packing doesn't match a premade ruleset. Emit individual specifiers
|
||||
QString ret;
|
||||
if(pack.vector_align_component)
|
||||
ret += lit("#pack(vector_align_component) // vectors are aligned to their component\n");
|
||||
else
|
||||
ret +=
|
||||
lit("#pack(no_vector_align_component) // vectors are aligned evenly (float3 as float4)\n");
|
||||
if(pack.tight_arrays)
|
||||
ret += lit("#pack(tight_arrays) // arrays are packed tightly\n");
|
||||
else
|
||||
ret += lit("#pack(no_tight_arrays) // arrays are padded to 16-byte boundaries\n");
|
||||
if(pack.vector_straddle_16b)
|
||||
ret += lit("#pack(vector_straddle_16b) // vectors can straddle 16-byte boundaries\n");
|
||||
else
|
||||
ret += lit("#pack(no_vector_straddle_16b) // vectors cannot straddle 16-byte boundaries\n");
|
||||
if(pack.trailing_overlap)
|
||||
ret +=
|
||||
lit("#pack(trailing_overlap) // variables can overlap trailing padding after "
|
||||
"arrays/structs\n");
|
||||
else
|
||||
ret +=
|
||||
lit("#pack(no_trailing_overlap) // variables cannot overlap trailing padding after "
|
||||
"arrays/structs\n");
|
||||
|
||||
return ret.trimmed();
|
||||
}
|
||||
|
||||
Packing::Rules BufferFormatter::EstimatePackingRules(const rdcarray<ShaderConstant> &members)
|
||||
{
|
||||
Packing::Rules pack;
|
||||
@@ -1295,7 +1335,7 @@ ShaderConstant BufferFormatter::ParseFormatString(const QString &formatString, u
|
||||
|
||||
// if we aren't using tight arrays the stride is at least 16 bytes
|
||||
el.type.descriptor.arrayByteStride = elAlignment;
|
||||
if(el.type.descriptor.columns > 1)
|
||||
if(el.type.descriptor.rows > 1 || el.type.descriptor.columns > 1)
|
||||
el.type.descriptor.arrayByteStride = elSize;
|
||||
|
||||
if(!pack.tight_arrays)
|
||||
@@ -1457,6 +1497,7 @@ ShaderConstant BufferFormatter::ParseFormatString(const QString &formatString, u
|
||||
if(!success || root.structDef.type.members.isEmpty())
|
||||
{
|
||||
root.structDef.type.members.clear();
|
||||
root.structDef.type.descriptor.type = VarType::Struct;
|
||||
|
||||
ShaderConstant el;
|
||||
el.byteOffset = 0;
|
||||
@@ -1474,6 +1515,7 @@ ShaderConstant BufferFormatter::ParseFormatString(const QString &formatString, u
|
||||
el.type.descriptor.columns * VarTypeByteSize(el.type.descriptor.type);
|
||||
|
||||
root.structDef.type.members.push_back(el);
|
||||
root.structDef.type.descriptor.arrayByteStride = el.type.descriptor.arrayByteStride;
|
||||
}
|
||||
|
||||
return root.structDef;
|
||||
@@ -1604,7 +1646,7 @@ QString BufferFormatter::GetTextureFormatString(const TextureDescription &tex)
|
||||
return QFormatStr("%1 %2[%3];").arg(baseType).arg(varName).arg(w);
|
||||
}
|
||||
|
||||
QString BufferFormatter::GetBufferFormatString(const ShaderResource &res,
|
||||
QString BufferFormatter::GetBufferFormatString(Packing::Rules pack, const ShaderResource &res,
|
||||
const ResourceFormat &viewFormat,
|
||||
uint64_t &baseByteOffset)
|
||||
{
|
||||
@@ -1620,7 +1662,7 @@ QString BufferFormatter::GetBufferFormatString(const ShaderResource &res,
|
||||
// if there is only one member in the root array, we can just call DeclareStruct directly
|
||||
if(members.count() <= 1)
|
||||
{
|
||||
format = DeclareStruct(declaredStructs, res.name, members, 0, QString());
|
||||
format = DeclareStruct(pack, declaredStructs, res.name, members, 0, QString());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1658,15 +1700,21 @@ QString BufferFormatter::GetBufferFormatString(const ShaderResource &res,
|
||||
// needed
|
||||
fakeLastMember[0].byteOffset = 0;
|
||||
|
||||
format = DeclareStruct(declaredStructs, res.name, fakeLastMember,
|
||||
if(fakeLastMember[0].type.descriptor.elements != ~0U)
|
||||
fakeLastMember[0].type.descriptor.arrayByteStride *=
|
||||
fakeLastMember[0].type.descriptor.elements;
|
||||
|
||||
format = DeclareStruct(pack, declaredStructs, res.name, fakeLastMember,
|
||||
fakeLastMember[0].type.descriptor.arrayByteStride, fixedPrefixString);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
format = DeclareStruct(declaredStructs, res.variableType.descriptor.name,
|
||||
format = DeclareStruct(pack, declaredStructs, res.variableType.descriptor.name,
|
||||
res.variableType.members, 0, QString());
|
||||
}
|
||||
|
||||
format = QFormatStr("%1\n\n%2").arg(DeclarePacking(pack)).arg(format);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1763,31 +1811,49 @@ QString BufferFormatter::GetBufferFormatString(const ShaderResource &res,
|
||||
return format;
|
||||
}
|
||||
|
||||
uint32_t BufferFormatter::GetVarStraddleSize(const ShaderConstant &var)
|
||||
{
|
||||
if(var.type.descriptor.type == VarType::Enum)
|
||||
return var.type.descriptor.arrayByteStride;
|
||||
|
||||
// structs don't themselves have a straddle size
|
||||
// this is fine because the struct members itself don't straddle, and the alignment of the max of
|
||||
// their members. A struct that contains a vector will have to satisfy that vector's alignment. on
|
||||
// std140/430 this means the struct will be aligned such that as long as its members don't
|
||||
// straddle then any aligned placement of the struct they also won't straddle.
|
||||
// for D3D cbuffers where vectors have float alignment, structs are aligned to 16 always.
|
||||
// all others are scalar so straddling is allowed - i.e there is no packing scheme that disallows
|
||||
// straddling but allows vector AND struct placement so freely that a vector member could avoid
|
||||
// straddling until the struct is placed at a particular offset.
|
||||
if(!var.type.members.empty())
|
||||
return 0;
|
||||
|
||||
if(var.type.descriptor.rows > 1)
|
||||
return var.type.descriptor.matrixByteStride;
|
||||
|
||||
return VarTypeByteSize(var.type.descriptor.type) * var.type.descriptor.columns;
|
||||
}
|
||||
|
||||
uint32_t BufferFormatter::GetVarSize(const ShaderConstant &var)
|
||||
{
|
||||
uint32_t size = var.type.descriptor.rows * var.type.descriptor.columns;
|
||||
uint32_t typeSize = VarTypeByteSize(var.type.descriptor.type);
|
||||
if(typeSize > 1)
|
||||
size *= typeSize;
|
||||
if(var.type.descriptor.elements > 1 && var.type.descriptor.elements != ~0U)
|
||||
return var.type.descriptor.arrayByteStride * var.type.descriptor.elements;
|
||||
|
||||
if(var.type.descriptor.type == VarType::Enum)
|
||||
size = var.type.descriptor.arrayByteStride;
|
||||
return var.type.descriptor.arrayByteStride;
|
||||
|
||||
if(!var.type.members.empty())
|
||||
return var.type.descriptor.arrayByteStride;
|
||||
|
||||
if(var.type.descriptor.rows > 1)
|
||||
{
|
||||
if(var.type.descriptor.RowMajor())
|
||||
size = var.type.descriptor.matrixByteStride * var.type.descriptor.rows;
|
||||
return var.type.descriptor.matrixByteStride * var.type.descriptor.rows;
|
||||
else
|
||||
size = var.type.descriptor.matrixByteStride * var.type.descriptor.columns;
|
||||
return var.type.descriptor.matrixByteStride * var.type.descriptor.columns;
|
||||
}
|
||||
|
||||
if(var.type.descriptor.type != VarType::Enum && !var.type.members.empty())
|
||||
size = GetStructVarSize(var.type.members);
|
||||
|
||||
if(var.type.descriptor.elements > 1 && var.type.descriptor.elements != ~0U)
|
||||
size *= var.type.descriptor.elements;
|
||||
|
||||
return size;
|
||||
return VarTypeByteSize(var.type.descriptor.type) * var.type.descriptor.columns;
|
||||
}
|
||||
|
||||
uint32_t BufferFormatter::GetAlignment(Packing::Rules pack, const ShaderConstant &c)
|
||||
@@ -1833,10 +1899,13 @@ uint32_t BufferFormatter::GetAlignment(Packing::Rules pack, const ShaderConstant
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t BufferFormatter::GetStructVarSize(const rdcarray<ShaderConstant> &members)
|
||||
uint32_t BufferFormatter::GetUnpaddedStructSize(const rdcarray<ShaderConstant> &members)
|
||||
{
|
||||
uint32_t lastMemberStart = 0;
|
||||
|
||||
if(members.empty())
|
||||
return 0;
|
||||
|
||||
const ShaderConstant *lastChild = &members.back();
|
||||
|
||||
lastMemberStart += lastChild->byteOffset;
|
||||
@@ -1852,8 +1921,8 @@ uint32_t BufferFormatter::GetStructVarSize(const rdcarray<ShaderConstant> &membe
|
||||
return lastMemberStart + GetVarSize(*lastChild);
|
||||
}
|
||||
|
||||
QString BufferFormatter::DeclareStruct(QList<QString> &declaredStructs, const QString &name,
|
||||
const rdcarray<ShaderConstant> &members,
|
||||
QString BufferFormatter::DeclareStruct(Packing::Rules pack, QList<QString> &declaredStructs,
|
||||
const QString &name, const rdcarray<ShaderConstant> &members,
|
||||
uint32_t requiredByteStride, QString innerSkippedPrefixString)
|
||||
{
|
||||
QString ret;
|
||||
@@ -1864,15 +1933,68 @@ QString BufferFormatter::DeclareStruct(QList<QString> &declaredStructs, const QS
|
||||
|
||||
uint32_t offset = 0;
|
||||
|
||||
uint32_t structAlignment = 1;
|
||||
|
||||
for(int i = 0; i < members.count(); i++)
|
||||
{
|
||||
const uint32_t alignment = GetAlignment(pack, members[i]);
|
||||
const uint32_t vecsize = GetVarStraddleSize(members[i]);
|
||||
const uint32_t size = GetVarSize(members[i]);
|
||||
structAlignment = std::max(structAlignment, alignment);
|
||||
|
||||
offset = AlignUp(offset, alignment);
|
||||
|
||||
// if things can't straddle 16-byte boundaries, check that and enforce
|
||||
if(!pack.vector_straddle_16b)
|
||||
{
|
||||
if(offset / 16 != (offset + vecsize - 1) / 16)
|
||||
offset = AlignUp(offset, 16U);
|
||||
}
|
||||
|
||||
// if we don't have tight arrays, arrays and structs begin at 16-byte boundaries
|
||||
if(!pack.tight_arrays &&
|
||||
(members[i].type.descriptor.type == VarType::Struct ||
|
||||
members[i].type.descriptor.elements > 1 || members[i].type.descriptor.rows > 1))
|
||||
{
|
||||
offset = AlignUp(offset, 16U);
|
||||
}
|
||||
|
||||
// if this variable is placed later, add an offset annotation
|
||||
if(offset < members[i].byteOffset)
|
||||
ret += lit(" [[offset(%1)]]\n").arg(members[i].byteOffset);
|
||||
else if(offset > members[i].byteOffset)
|
||||
qCritical() << "Unexpected offset overlow at" << QString(members[i].name) << "in"
|
||||
qCritical() << "Unexpected offset overlap at" << QString(members[i].name) << "in"
|
||||
<< QString(name);
|
||||
|
||||
offset = members[i].byteOffset + GetVarSize(members[i]);
|
||||
offset = members[i].byteOffset;
|
||||
|
||||
offset += size;
|
||||
|
||||
// if we allow trailing overlap, remove the padding at the end of the struct/array
|
||||
if(pack.trailing_overlap)
|
||||
{
|
||||
if(members[i].type.descriptor.type == VarType::Struct)
|
||||
{
|
||||
offset -= (members[i].type.descriptor.arrayByteStride -
|
||||
GetUnpaddedStructSize(members[i].type.members));
|
||||
}
|
||||
else if((members[i].type.descriptor.elements > 1 || members[i].type.descriptor.rows > 1) &&
|
||||
!pack.tight_arrays)
|
||||
{
|
||||
uint8_t vecSize = members[i].type.descriptor.columns;
|
||||
|
||||
if(members[i].type.descriptor.rows > 1 && members[i].type.descriptor.ColMajor())
|
||||
vecSize = members[i].type.descriptor.rows;
|
||||
|
||||
uint32_t elSize = GetAlignment(pack, members[i]);
|
||||
if(pack.vector_align_component)
|
||||
elSize *= vecSize;
|
||||
|
||||
// the padding is the stride (which is rounded up to 16 for non-tight arrays) minus the size
|
||||
// of the last vector (whether or not this is an array of scalars, vectors or matrices
|
||||
offset -= 16 - elSize;
|
||||
}
|
||||
}
|
||||
|
||||
QString arraySize;
|
||||
if(members[i].type.descriptor.elements > 1 && members[i].type.descriptor.elements != ~0U)
|
||||
@@ -1887,17 +2009,20 @@ QString BufferFormatter::DeclareStruct(QList<QString> &declaredStructs, const QS
|
||||
|
||||
varTypeName = pointeeType.descriptor.name;
|
||||
|
||||
varTypeName =
|
||||
varTypeName.replace(QLatin1Char('['), QLatin1Char('_')).replace(QLatin1Char(']'), QString());
|
||||
|
||||
if(!declaredStructs.contains(varTypeName))
|
||||
{
|
||||
declaredStructs.push_back(varTypeName);
|
||||
ret = DeclareStruct(declaredStructs, varTypeName, pointeeType.members,
|
||||
ret = DeclareStruct(pack, declaredStructs, varTypeName, pointeeType.members,
|
||||
pointeeType.descriptor.arrayByteStride, QString()) +
|
||||
lit("\n") + ret;
|
||||
}
|
||||
|
||||
varTypeName += lit("*");
|
||||
}
|
||||
else if(!members[i].type.members.isEmpty())
|
||||
else if(members[i].type.descriptor.type == VarType::Struct)
|
||||
{
|
||||
// GL structs don't give us typenames (boo!) so give them unique names. This will mean some
|
||||
// structs get duplicated if they're used in multiple places, but not much we can do about
|
||||
@@ -1905,10 +2030,13 @@ QString BufferFormatter::DeclareStruct(QList<QString> &declaredStructs, const QS
|
||||
if(varTypeName.isEmpty() || varTypeName == lit("struct"))
|
||||
varTypeName = lit("anon%1").arg(declaredStructs.size());
|
||||
|
||||
varTypeName =
|
||||
varTypeName.replace(QLatin1Char('['), QLatin1Char('_')).replace(QLatin1Char(']'), QString());
|
||||
|
||||
if(!declaredStructs.contains(varTypeName))
|
||||
{
|
||||
declaredStructs.push_back(varTypeName);
|
||||
ret = DeclareStruct(declaredStructs, varTypeName, members[i].type.members,
|
||||
ret = DeclareStruct(pack, declaredStructs, varTypeName, members[i].type.members,
|
||||
members[i].type.descriptor.arrayByteStride, QString()) +
|
||||
lit("\n") + ret;
|
||||
}
|
||||
@@ -1919,47 +2047,49 @@ QString BufferFormatter::DeclareStruct(QList<QString> &declaredStructs, const QS
|
||||
if(varName.isEmpty())
|
||||
varName = QFormatStr("_child%1").arg(i);
|
||||
|
||||
if(varName[0] == QLatin1Char('['))
|
||||
varName =
|
||||
varName.replace(QLatin1Char('['), QLatin1Char('_')).replace(QLatin1Char(']'), QString());
|
||||
|
||||
if(members[i].type.descriptor.rows > 1)
|
||||
{
|
||||
if(members[i].type.descriptor.RowMajor())
|
||||
{
|
||||
varTypeName = lit("[[row_major]] ") + varTypeName;
|
||||
|
||||
uint32_t tightStride =
|
||||
VarTypeByteSize(members[i].type.descriptor.type) * members[i].type.descriptor.columns;
|
||||
uint32_t stride = GetAlignment(pack, members[i]);
|
||||
|
||||
if(tightStride < members[i].type.descriptor.matrixByteStride)
|
||||
{
|
||||
varTypeName = lit("[[matrix_stride(%1)]] %2")
|
||||
.arg(members[i].type.descriptor.matrixByteStride)
|
||||
.arg(varTypeName);
|
||||
}
|
||||
}
|
||||
else
|
||||
if(pack.vector_align_component)
|
||||
{
|
||||
uint32_t tightStride =
|
||||
VarTypeByteSize(members[i].type.descriptor.type) * members[i].type.descriptor.rows;
|
||||
|
||||
if(tightStride < members[i].type.descriptor.matrixByteStride)
|
||||
{
|
||||
varTypeName = lit("[[matrix_stride(%1)]] %2")
|
||||
.arg(members[i].type.descriptor.matrixByteStride)
|
||||
.arg(varTypeName);
|
||||
}
|
||||
if(members[i].type.descriptor.RowMajor())
|
||||
stride *= members[i].type.descriptor.columns;
|
||||
else
|
||||
stride *= members[i].type.descriptor.rows;
|
||||
}
|
||||
|
||||
if(!pack.tight_arrays)
|
||||
stride = 16;
|
||||
|
||||
if(stride != members[i].type.descriptor.matrixByteStride)
|
||||
ret += lit("// unexpected matrix stride %1").arg(members[i].type.descriptor.matrixByteStride);
|
||||
}
|
||||
|
||||
ret += QFormatStr(" %1 %2%3;\n").arg(varTypeName).arg(varName).arg(arraySize);
|
||||
}
|
||||
|
||||
// if we don't have tight arrays, struct byte strides are always 16-byte aligned
|
||||
if(!pack.tight_arrays)
|
||||
{
|
||||
structAlignment = 16;
|
||||
}
|
||||
|
||||
offset = AlignUp(offset, structAlignment);
|
||||
|
||||
if(requiredByteStride > 0)
|
||||
{
|
||||
const uint32_t structEnd = GetStructVarSize(members);
|
||||
|
||||
if(requiredByteStride > structEnd)
|
||||
ret = lit("[[size(%1)]] %2").arg(requiredByteStride).arg(ret);
|
||||
else if(requiredByteStride != structEnd)
|
||||
qCritical() << "Unexpected stride overlow at struct" << name;
|
||||
if(requiredByteStride > offset)
|
||||
ret = lit("[[size(%1)]]\n%2").arg(requiredByteStride).arg(ret);
|
||||
else if(requiredByteStride != offset)
|
||||
ret = lit("// Unexpected size of struct %1\n%2").arg(requiredByteStride).arg(ret);
|
||||
}
|
||||
|
||||
ret += lit("}\n");
|
||||
@@ -1967,11 +2097,15 @@ QString BufferFormatter::DeclareStruct(QList<QString> &declaredStructs, const QS
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString BufferFormatter::DeclareStruct(const QString &name, const rdcarray<ShaderConstant> &members,
|
||||
QString BufferFormatter::DeclareStruct(Packing::Rules pack, const QString &name,
|
||||
const rdcarray<ShaderConstant> &members,
|
||||
uint32_t requiredByteStride)
|
||||
{
|
||||
QList<QString> declaredStructs;
|
||||
return DeclareStruct(declaredStructs, name, members, requiredByteStride, QString());
|
||||
QString structDef =
|
||||
DeclareStruct(pack, declaredStructs, name, members, requiredByteStride, QString());
|
||||
|
||||
return QFormatStr("%1\n\n%2").arg(DeclarePacking(pack)).arg(structDef);
|
||||
}
|
||||
|
||||
ResourceFormat GetInterpretedResourceFormat(const ShaderConstant &elem)
|
||||
@@ -2024,7 +2158,7 @@ static void FillShaderVarData(ShaderVariable &var, const ShaderConstant &elem, c
|
||||
|
||||
if(objs.isEmpty())
|
||||
{
|
||||
var.name = "-";
|
||||
var.name = elem.name;
|
||||
var.value = ShaderValue();
|
||||
return;
|
||||
}
|
||||
@@ -2033,10 +2167,7 @@ static void FillShaderVarData(ShaderVariable &var, const ShaderConstant &elem, c
|
||||
{
|
||||
for(uint32_t inner = 0; inner < innerCount; inner++)
|
||||
{
|
||||
uint32_t dst = outer * elem.type.descriptor.columns + inner;
|
||||
|
||||
if(colMajor)
|
||||
dst = inner * elem.type.descriptor.columns + outer;
|
||||
uint32_t dst = outer * innerCount + inner;
|
||||
|
||||
QVariant o = objs[src];
|
||||
|
||||
@@ -2699,29 +2830,6 @@ QString TypeString(const ShaderVariable &v)
|
||||
else if(v.type == VarType::ConstantBlock)
|
||||
typeStr = lit("Constant Block");
|
||||
|
||||
if(v.flags & ShaderVariableFlags::HexDisplay)
|
||||
{
|
||||
if(v.type == VarType::ULong)
|
||||
typeStr = lit("[[hex]] long");
|
||||
else if(v.type == VarType::UInt)
|
||||
typeStr = lit("[[hex]] int");
|
||||
else if(v.type == VarType::UShort)
|
||||
typeStr = lit("[[hex]] short");
|
||||
else if(v.type == VarType::UByte)
|
||||
typeStr = lit("[[hex]] byte");
|
||||
}
|
||||
else if(v.flags & ShaderVariableFlags::BinaryDisplay)
|
||||
{
|
||||
if(v.type == VarType::ULong)
|
||||
typeStr = lit("[[binary]] long");
|
||||
else if(v.type == VarType::UInt)
|
||||
typeStr = lit("[[binary]] int");
|
||||
else if(v.type == VarType::UShort)
|
||||
typeStr = lit("[[binary]] short");
|
||||
else if(v.type == VarType::UByte)
|
||||
typeStr = lit("[[binary]] byte");
|
||||
}
|
||||
|
||||
if(v.type == VarType::Unknown)
|
||||
return lit("Typeless");
|
||||
if(v.rows == 1 && v.columns == 1)
|
||||
@@ -2890,29 +2998,6 @@ QString RowTypeString(const ShaderVariable &v)
|
||||
|
||||
QString typeStr = ToQStr(v.type);
|
||||
|
||||
if(v.flags & ShaderVariableFlags::HexDisplay)
|
||||
{
|
||||
if(v.type == VarType::ULong)
|
||||
typeStr = lit("[[hex]] long");
|
||||
else if(v.type == VarType::UInt)
|
||||
typeStr = lit("[[hex]] int");
|
||||
else if(v.type == VarType::UShort)
|
||||
typeStr = lit("[[hex]] short");
|
||||
else if(v.type == VarType::UByte)
|
||||
typeStr = lit("[[hex]] byte");
|
||||
}
|
||||
else if(v.flags & ShaderVariableFlags::BinaryDisplay)
|
||||
{
|
||||
if(v.type == VarType::ULong)
|
||||
typeStr = lit("[[binary]] long");
|
||||
else if(v.type == VarType::UInt)
|
||||
typeStr = lit("[[binary]] int");
|
||||
else if(v.type == VarType::UShort)
|
||||
typeStr = lit("[[binary]] short");
|
||||
else if(v.type == VarType::UByte)
|
||||
typeStr = lit("[[binary]] byte");
|
||||
}
|
||||
|
||||
if(v.columns == 1)
|
||||
return typeStr;
|
||||
|
||||
|
||||
@@ -1068,8 +1068,9 @@ bool RichResourceTextMouseEvent(const QWidget *owner, const QVariant &var, QRect
|
||||
QString formatter;
|
||||
|
||||
if(!ptrType.members.isEmpty())
|
||||
formatter = BufferFormatter::DeclareStruct(ptrType.descriptor.name, ptrType.members,
|
||||
ptrType.descriptor.arrayByteStride);
|
||||
formatter = BufferFormatter::DeclareStruct(
|
||||
BufferFormatter::EstimatePackingRules(ptrType.members), ptrType.descriptor.name,
|
||||
ptrType.members, ptrType.descriptor.arrayByteStride);
|
||||
|
||||
IBufferViewer *view = ctx.ViewBuffer(ptr->offset, ~0ULL, ptr->base, formatter);
|
||||
|
||||
|
||||
+11
-11
@@ -182,15 +182,17 @@ private:
|
||||
|
||||
static GraphicsAPI m_API;
|
||||
|
||||
static QString DeclareStruct(QList<QString> &declaredStructs, const QString &name,
|
||||
const rdcarray<ShaderConstant> &members, uint32_t requiredByteStride,
|
||||
QString innerSkippedPrefixString);
|
||||
|
||||
static uint32_t GetVarSize(const ShaderConstant &var);
|
||||
static QString DeclareStruct(Packing::Rules pack, QList<QString> &declaredStructs,
|
||||
const QString &name, const rdcarray<ShaderConstant> &members,
|
||||
uint32_t requiredByteStride, QString innerSkippedPrefixString);
|
||||
|
||||
static uint32_t GetAlignment(Packing::Rules pack, const ShaderConstant &constant);
|
||||
static uint32_t GetUnpaddedStructSize(const rdcarray<ShaderConstant> &members);
|
||||
static uint32_t GetVarSize(const ShaderConstant &var);
|
||||
static uint32_t GetVarStraddleSize(const ShaderConstant &var);
|
||||
|
||||
static void EstimatePackingRules(Packing::Rules &pack, const ShaderConstant &constant);
|
||||
static QString DeclarePacking(Packing::Rules pack);
|
||||
|
||||
public:
|
||||
BufferFormatter() = default;
|
||||
@@ -202,13 +204,11 @@ public:
|
||||
static Packing::Rules EstimatePackingRules(const rdcarray<ShaderConstant> &members);
|
||||
|
||||
static QString GetTextureFormatString(const TextureDescription &tex);
|
||||
static QString GetBufferFormatString(const ShaderResource &res, const ResourceFormat &viewFormat,
|
||||
uint64_t &baseByteOffset);
|
||||
static QString GetBufferFormatString(Packing::Rules pack, const ShaderResource &res,
|
||||
const ResourceFormat &viewFormat, uint64_t &baseByteOffset);
|
||||
|
||||
static QString DeclareStruct(const QString &name, const rdcarray<ShaderConstant> &members,
|
||||
uint32_t requiredByteStride);
|
||||
|
||||
static uint32_t GetStructVarSize(const rdcarray<ShaderConstant> &members);
|
||||
static QString DeclareStruct(Packing::Rules pack, const QString &name,
|
||||
const rdcarray<ShaderConstant> &members, uint32_t requiredByteStride);
|
||||
};
|
||||
|
||||
QVariantList GetVariants(ResourceFormat format, const ShaderConstant &var, const byte *&data,
|
||||
|
||||
@@ -466,6 +466,8 @@ struct BufferConfiguration
|
||||
uint32_t numRows = 0, unclampedNumRows = 0;
|
||||
uint32_t pagingOffset = 0;
|
||||
|
||||
uint32_t formatStride = 0;
|
||||
|
||||
QString noDraw;
|
||||
|
||||
bool noVertices = false;
|
||||
@@ -2676,6 +2678,8 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
|
||||
|
||||
UnrollConstant(constant, bufdata->vsinConfig.columns, bufdata->vsinConfig.props);
|
||||
|
||||
bufdata->vsinConfig.formatStride = constant.type.descriptor.arrayByteStride;
|
||||
|
||||
ClearModels();
|
||||
}
|
||||
|
||||
@@ -2735,7 +2739,7 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
|
||||
buf = new BufferData;
|
||||
|
||||
// calculate tight stride
|
||||
buf->stride = qMax(1U, BufferFormatter::GetStructVarSize(bufdata->vsinConfig.columns));
|
||||
buf->stride = std::max(1U, bufdata->vsinConfig.formatStride);
|
||||
|
||||
// the "permanent" range starts at ByteOffset and goes for m_ByteSize
|
||||
uint64_t rangeStart = m_ByteOffset;
|
||||
|
||||
@@ -135,7 +135,9 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_formatOverride.type.members.empty())
|
||||
ui->setFormat->setEnabled(reflection->constantBlocks[m_slot].bufferBacked);
|
||||
|
||||
if(!m_formatOverride.type.members.empty() && reflection->constantBlocks[m_slot].bufferBacked)
|
||||
{
|
||||
if(!inlineData.empty() && m_cbuffer == ResourceId())
|
||||
{
|
||||
@@ -209,6 +211,17 @@ void ConstantBufferPreviewer::on_setFormat_toggled(bool checked)
|
||||
ui->splitter->setCollapsible(1, false);
|
||||
ui->splitter->setSizes({1, 1});
|
||||
ui->splitter->handle(1)->setEnabled(true);
|
||||
|
||||
const ShaderReflection *reflection = m_Ctx.CurPipelineState().GetShaderReflection(m_stage);
|
||||
|
||||
if(IsD3D(m_Ctx.APIProps().pipelineType))
|
||||
ui->formatSpecifier->setFormat(
|
||||
BufferFormatter::DeclareStruct(Packing::D3DCB, reflection->constantBlocks[m_slot].name,
|
||||
reflection->constantBlocks[m_slot].variables, 0));
|
||||
else
|
||||
ui->formatSpecifier->setFormat(BufferFormatter::DeclareStruct(
|
||||
BufferFormatter::EstimatePackingRules(reflection->constantBlocks[m_slot].variables),
|
||||
reflection->constantBlocks[m_slot].name, reflection->constantBlocks[m_slot].variables, 0));
|
||||
}
|
||||
|
||||
void ConstantBufferPreviewer::on_resourceDetails_clicked()
|
||||
|
||||
@@ -2157,7 +2157,8 @@ void D3D11PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
|
||||
|
||||
if(shaderRes)
|
||||
{
|
||||
format = BufferFormatter::GetBufferFormatString(*shaderRes, view.res.viewFormat, offs);
|
||||
format = BufferFormatter::GetBufferFormatString(Packing::D3DUAV, *shaderRes,
|
||||
view.res.viewFormat, offs);
|
||||
|
||||
if(view.res.bufferFlags & D3DBufferViewFlags::Raw)
|
||||
format = lit("xint");
|
||||
|
||||
@@ -2271,7 +2271,8 @@ void D3D12PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
|
||||
|
||||
if(shaderRes)
|
||||
{
|
||||
format = BufferFormatter::GetBufferFormatString(*shaderRes, view.res.viewFormat, offs);
|
||||
format = BufferFormatter::GetBufferFormatString(Packing::D3DUAV, *shaderRes,
|
||||
view.res.viewFormat, offs);
|
||||
|
||||
if(view.res.bufferFlags & D3DBufferViewFlags::Raw)
|
||||
format = lit("xint");
|
||||
|
||||
@@ -2315,7 +2315,9 @@ void GLPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int c
|
||||
if(!shaderRes)
|
||||
return;
|
||||
|
||||
QString format = BufferFormatter::GetBufferFormatString(*shaderRes, ResourceFormat(), buf.offset);
|
||||
QString format = BufferFormatter::GetBufferFormatString(
|
||||
BufferFormatter::EstimatePackingRules(shaderRes->variableType.members), *shaderRes,
|
||||
ResourceFormat(), buf.offset);
|
||||
|
||||
if(buf.ID != ResourceId())
|
||||
{
|
||||
|
||||
@@ -3035,7 +3035,9 @@ void VulkanPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, i
|
||||
? stage->reflection->readWriteResources[buf.bindPoint]
|
||||
: stage->reflection->readOnlyResources[buf.bindPoint];
|
||||
|
||||
format = BufferFormatter::GetBufferFormatString(shaderRes, buf.fmt, buf.offset);
|
||||
format = BufferFormatter::GetBufferFormatString(
|
||||
BufferFormatter::EstimatePackingRules(shaderRes.variableType.members), shaderRes, buf.fmt,
|
||||
buf.offset);
|
||||
}
|
||||
|
||||
if(buf.ID != ResourceId())
|
||||
|
||||
Reference in New Issue
Block a user