Replace FormatElement with ShaderConstant/ShaderVariableType

* FormatElement is now a static BufferFormatter class to help generate and parse
  buffer formatting strings
This commit is contained in:
baldurk committed 2019-11-29 13:53:44 +00:00
1 parent 4214aa45bf
commit b3979262a5
21 files changed
+929 -666

No files matched your search

File diff suppressed because it is too large. Load diff
+2
View File
@@ -736,6 +736,8 @@ void CaptureContext::LoadCapture(const rdcstr &captureFile, const ReplayOptions
{
m_CaptureTemporary = temporary;
BufferFormatter::Init(m_APIProps.pipelineType);
m_CaptureMods = CaptureModifications::NoModifications;
rdcarray<ICaptureViewer *> viewers(m_CaptureViewers);
+1 -1
View File
@@ -2191,4 +2191,4 @@ void *AccessWaylandPlatformInterface(const QByteArray &resource, QWindow *window
{
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
return native->nativeResourceForWindow(resource, window);
}
}
+23 -19
View File
@@ -74,33 +74,37 @@ inline QMetaType::Type GetVariantMetatype(const QVariant &v)
return (QMetaType::Type)v.type();
}
struct FormatElement
struct BufferFormatter
{
Q_DECLARE_TR_FUNCTIONS(FormatElement);
Q_DECLARE_TR_FUNCTIONS(BufferFormatter);
static GraphicsAPI m_API;
static QString DeclareStruct(QList<QString> &declaredStructs, const QString &name,
const rdcarray<ShaderConstant> &members, uint32_t requiredByteStride);
public:
FormatElement();
FormatElement(const QString &Name, uint offs, bool rowMat, uint matDim, ResourceFormat f,
bool hexDisplay, bool rgbDisplay);
BufferFormatter() = default;
static QList<FormatElement> ParseFormatString(const QString &formatString, uint64_t maxLen,
bool tightPacking, QString &errors);
static void Init(GraphicsAPI api) { m_API = api; }
static ShaderConstant ParseFormatString(const QString &formatString, uint64_t maxLen,
bool tightPacking, QString &errors);
static QString GenerateTextureBufferFormat(const TextureDescription &tex);
static QString GetTextureFormatString(const TextureDescription &tex);
static QString GetBufferFormatString(const ShaderResource &res, const ResourceFormat &viewFormat,
uint64_t &baseByteOffset);
ShaderVariable GetShaderVar(const byte *&data, const byte *end) const;
QString name;
ResourceFormat format;
uint32_t offset;
uint32_t matrixdim;
bool rowmajor;
bool hex, rgb;
static QString DeclareStruct(const QString &name, const rdcarray<ShaderConstant> &members,
uint32_t requiredByteStride);
static QString DeclarePaddingBytes(uint32_t bytes);
};
QVariantList GetVariants(ResourceFormat rowFormat, uint32_t rowCount, const byte *&data,
const byte *end);
QVariantList GetVariants(ResourceFormat rowFormat, uint32_t rowCount, uint32_t rowByteStride,
const byte *&data, const byte *end);
ResourceFormat GetInterpretedResourceFormat(const ShaderConstant &elem);
void SetInterpretedResourceFormat(ShaderConstant &elem, ResourceFormatType interpretType,
CompType interpretCompType);
ShaderVariable InterpretShaderVar(const ShaderConstant &elem, const byte *data, const byte *end);
QString TypeString(const ShaderVariable &v);
QString RowString(const ShaderVariable &v, uint32_t row, VarType type = VarType::Unknown);
+173 -98
View File
@@ -356,8 +356,8 @@ struct BufferConfiguration
BufferData *indices = NULL;
int32_t baseVertex = 0;
QList<FormatElement> columns;
QList<BufferElementProperties> props;
rdcarray<ShaderConstant> columns;
rdcarray<BufferElementProperties> props;
QVector<PixelValue> generics;
QVector<bool> genericsEnabled;
@@ -450,12 +450,12 @@ struct BufferConfiguration
// look for an exact match
for(int i = 0; posEl == -1 && i < columns.count(); i++)
{
const FormatElement &el = columns[i];
const ShaderConstant &el = columns[i];
if(el.name.compare(lit("POSITION"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("POSITION0"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("POS"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("POS0"), Qt::CaseInsensitive) == 0)
if(QString(el.name).compare(lit("POSITION"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("POSITION0"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("POS"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("POS0"), Qt::CaseInsensitive) == 0)
{
posEl = i;
break;
@@ -465,9 +465,9 @@ struct BufferConfiguration
// try anything containing position
for(int i = 0; posEl == -1 && i < columns.count(); i++)
{
const FormatElement &el = columns[i];
const ShaderConstant &el = columns[i];
if(el.name.contains(lit("POSITION"), Qt::CaseInsensitive))
if(QString(el.name).contains(lit("POSITION"), Qt::CaseInsensitive))
{
posEl = i;
break;
@@ -477,9 +477,9 @@ struct BufferConfiguration
// OK last resort, just look for 'pos'
for(int i = 0; posEl == -1 && i < columns.count(); i++)
{
const FormatElement &el = columns[i];
const ShaderConstant &el = columns[i];
if(el.name.contains(lit("POS"), Qt::CaseInsensitive))
if(QString(el.name).contains(lit("POS"), Qt::CaseInsensitive))
{
posEl = i;
break;
@@ -505,14 +505,14 @@ struct BufferConfiguration
// prioritise TEXCOORD over general COLOR
for(int i = 0; i < columns.count(); i++)
{
const FormatElement &el = columns[i];
const ShaderConstant &el = columns[i];
if(el.name.compare(lit("TEXCOORD"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("TEXCOORD0"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("TEX"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("TEX0"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("UV"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("UV0"), Qt::CaseInsensitive) == 0)
if(QString(el.name).compare(lit("TEXCOORD"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("TEXCOORD0"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("TEX"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("TEX0"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("UV"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("UV0"), Qt::CaseInsensitive) == 0)
{
secondEl = i;
break;
@@ -521,12 +521,12 @@ struct BufferConfiguration
for(int i = 0; secondEl == -1 && i < columns.count(); i++)
{
const FormatElement &el = columns[i];
const ShaderConstant &el = columns[i];
if(el.name.compare(lit("COLOR"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("COLOR0"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("COL"), Qt::CaseInsensitive) == 0 ||
el.name.compare(lit("COL0"), Qt::CaseInsensitive) == 0)
if(QString(el.name).compare(lit("COLOR"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("COLOR0"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("COL"), Qt::CaseInsensitive) == 0 ||
QString(el.name).compare(lit("COL0"), Qt::CaseInsensitive) == 0)
{
secondEl = i;
break;
@@ -631,7 +631,7 @@ public:
}
else
{
const FormatElement &el = elementForColumn(section);
const ShaderConstant &el = elementForColumn(section);
const BufferElementProperties &prop = propForColumn(section);
if(prop.format.compCount == 1 || role == columnGroupRole)
@@ -731,20 +731,21 @@ public:
}
else
{
const FormatElement &el = elementForColumn(col);
const ShaderConstant &el = elementForColumn(col);
const BufferElementProperties &prop = propForColumn(col);
if(el.rgb && prop.buffer < config.buffers.size())
if(el.type.descriptor.displayAsRGB && prop.buffer < config.buffers.size())
{
const byte *data = config.buffers[prop.buffer]->data();
const byte *end = config.buffers[prop.buffer]->end();
data += config.buffers[prop.buffer]->stride * row;
data += el.offset;
data += el.byteOffset;
// only slightly wasteful, we need to fetch all variants together
// since some formats are packed and can't be read individually
QVariantList list = GetVariants(prop.format, el.matrixdim, data, end);
QVariantList list = GetVariants(prop.format, el.type.descriptor.rows,
el.type.descriptor.matrixByteStride, data, end);
if(!list.isEmpty())
{
@@ -835,7 +836,7 @@ public:
return idx;
}
const FormatElement &el = elementForColumn(col);
const ShaderConstant &el = elementForColumn(col);
const BufferElementProperties &prop = propForColumn(col);
if(useGenerics(col))
@@ -855,24 +856,25 @@ public:
else
data += config.buffers[prop.buffer]->stride * instIdx;
data += el.offset;
data += el.byteOffset;
// only slightly wasteful, we need to fetch all variants together
// since some formats are packed and can't be read individually
QVariantList list = GetVariants(prop.format, el.matrixdim, data, end);
QVariantList list = GetVariants(prop.format, el.type.descriptor.rows,
el.type.descriptor.matrixByteStride, data, end);
int comp = componentForIndex(col);
if(comp < list.count())
{
uint32_t rowdim = el.matrixdim;
uint32_t coldim = prop.format.compCount;
uint32_t rowdim = el.type.descriptor.rows;
uint32_t coldim = el.type.descriptor.columns;
if(rowdim == 1)
{
QVariant v;
if(el.rowmajor)
if(el.type.descriptor.rowMajorStorage)
v = list[comp];
else
v = list[comp * rowdim];
@@ -893,7 +895,7 @@ public:
if(r > 0)
ret += lit("\n");
if(el.rowmajor)
if(el.type.descriptor.rowMajorStorage)
ret += interpretVariant(list[comp + r * coldim], el, prop);
else
ret += interpretVariant(list[r + comp * rowdim], el, prop);
@@ -969,7 +971,7 @@ public:
return columnLookup[col - reservedColumnCount()];
}
const FormatElement &elementForColumn(int col) const
const ShaderConstant &elementForColumn(int col) const
{
return config.columns[columnLookup[col - reservedColumnCount()]];
}
@@ -1065,7 +1067,7 @@ private:
}
QString outOfBounds() const { return lit("---"); }
QString interpretGeneric(int col, const FormatElement &el, const BufferElementProperties &prop) const
QString interpretGeneric(int col, const ShaderConstant &el, const BufferElementProperties &prop) const
{
int comp = componentForIndex(col);
@@ -1090,7 +1092,7 @@ private:
return outOfBounds();
}
QString interpretVariant(const QVariant &v, const FormatElement &el,
QString interpretVariant(const QVariant &v, const ShaderConstant &el,
const BufferElementProperties &prop) const
{
QString ret;
@@ -1128,10 +1130,10 @@ private:
else if(vt == QMetaType::UInt || vt == QMetaType::UShort || vt == QMetaType::UChar)
{
uint u = v.toUInt();
if(el.hex && prop.format.type == ResourceFormatType::Regular)
if(el.type.descriptor.displayAsHex && prop.format.type == ResourceFormatType::Regular)
ret = Formatter::HexFormat(u, prop.format.compByteWidth);
else
ret = Formatter::Format(u, el.hex);
ret = Formatter::Format(u, el.type.descriptor.displayAsHex);
}
else if(vt == QMetaType::Int || vt == QMetaType::Short || vt == QMetaType::SChar)
{
@@ -1143,7 +1145,7 @@ private:
}
else if(vt == QMetaType::ULongLong)
{
ret = Formatter::Format((uint64_t)v.toULongLong(), el.hex);
ret = Formatter::Format((uint64_t)v.toULongLong(), el.type.descriptor.displayAsHex);
}
else if(vt == QMetaType::LongLong)
{
@@ -1164,7 +1166,7 @@ private:
struct CachedElData
{
const FormatElement *el = NULL;
const ShaderConstant *el = NULL;
const BufferElementProperties *prop = NULL;
const byte *data = NULL;
@@ -1203,15 +1205,15 @@ struct CalcBoundingBoxData
BBoxData output;
};
void CacheDataForIteration(QVector<CachedElData> &cache, const QList<FormatElement> &columns,
const QList<BufferElementProperties> &props,
void CacheDataForIteration(QVector<CachedElData> &cache, const rdcarray<ShaderConstant> &columns,
const rdcarray<BufferElementProperties> &props,
const QList<BufferData *> buffers, uint32_t inst)
{
cache.reserve(columns.count());
for(int col = 0; col < columns.count(); col++)
{
const FormatElement &el = columns[col];
const ShaderConstant &el = columns[col];
const BufferElementProperties &prop = props[col];
CachedElData d;
@@ -1219,7 +1221,7 @@ void CacheDataForIteration(QVector<CachedElData> &cache, const QList<FormatEleme
d.el = &el;
d.prop = &prop;
d.byteSize = prop.format.ElementSize() * el.matrixdim;
d.byteSize = prop.format.ElementSize() * el.type.descriptor.rows;
d.nulls = QByteArray(d.byteSize, '\0');
if(prop.instancerate > 0)
@@ -1232,7 +1234,7 @@ void CacheDataForIteration(QVector<CachedElData> &cache, const QList<FormatEleme
d.stride = buffers[prop.buffer]->stride;
d.data += el.offset;
d.data += el.byteOffset;
if(prop.perinstance)
d.data += d.stride * d.instIdx;
@@ -1243,8 +1245,8 @@ void CacheDataForIteration(QVector<CachedElData> &cache, const QList<FormatEleme
}
static void ConfigureColumnsForShader(ICaptureContext &ctx, const ShaderReflection *shader,
QList<FormatElement> &columns,
QList<BufferElementProperties> &props)
rdcarray<ShaderConstant> &columns,
rdcarray<BufferElementProperties> &props)
{
if(!shader)
return;
@@ -1255,12 +1257,11 @@ static void ConfigureColumnsForShader(ICaptureContext &ctx, const ShaderReflecti
int i = 0, posidx = -1;
for(const SigParameter &sig : shader->outputSignature)
{
FormatElement f;
ShaderConstant f;
BufferElementProperties p;
f.name = !sig.varName.isEmpty() ? sig.varName : sig.semanticIdxName;
f.rowmajor = false;
f.matrixdim = 1;
f.type.descriptor.columns = sig.compCount;
p.buffer = 0;
p.perinstance = false;
@@ -1293,7 +1294,7 @@ static void ConfigureColumnsForShader(ICaptureContext &ctx, const ShaderReflecti
for(i = 0; i < columns.count(); i++)
{
BufferElementProperties &prop = props[i];
FormatElement &sig = columns[i];
ShaderConstant &el = columns[i];
uint numComps = prop.format.compCount;
uint elemSize = prop.format.compType == CompType::Double ? 8U : 4U;
@@ -1307,7 +1308,7 @@ static void ConfigureColumnsForShader(ICaptureContext &ctx, const ShaderReflecti
offset = AlignUp(offset, 4U * elemSize);
}
sig.offset = offset;
el.byteOffset = offset;
offset += numComps * elemSize;
}
@@ -1331,10 +1332,9 @@ static void ConfigureMeshColumns(ICaptureContext &ctx, PopulateBufferData *bufda
if(!a.used)
continue;
FormatElement f(a.name, a.byteOffset,
false, // row major matrix
1, // matrix dimension
a.format, false, false);
ShaderConstant f;
f.name = a.name;
f.byteOffset = a.byteOffset;
BufferElementProperties p;
p.buffer = a.vertexBuffer;
@@ -1342,12 +1342,12 @@ static void ConfigureMeshColumns(ICaptureContext &ctx, PopulateBufferData *bufda
p.instancerate = a.instanceRate;
p.format = a.format;
bufdata->vsinConfig.genericsEnabled[bufdata->vsinConfig.columns.size()] = false;
bufdata->vsinConfig.genericsEnabled[bufdata->vsinConfig.columns.count()] = false;
if(a.genericEnabled)
{
bufdata->vsinConfig.genericsEnabled[bufdata->vsinConfig.columns.size()] = true;
bufdata->vsinConfig.generics[bufdata->vsinConfig.columns.size()] = a.genericValue;
bufdata->vsinConfig.genericsEnabled[bufdata->vsinConfig.columns.count()] = true;
bufdata->vsinConfig.generics[bufdata->vsinConfig.columns.count()] = a.genericValue;
}
bufdata->vsinConfig.columns.push_back(f);
@@ -1514,16 +1514,16 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat
uint32_t maxAttrOffset = 0;
for(int c = 0; c < data->vsinConfig.columns.size(); c++)
for(int c = 0; c < data->vsinConfig.columns.count(); c++)
{
const FormatElement &col = data->vsinConfig.columns[c];
const ShaderConstant &col = data->vsinConfig.columns[c];
const BufferElementProperties &prop = data->vsinConfig.props[c];
if(prop.buffer == vbIdx)
{
used = true;
maxAttrOffset = qMax(maxAttrOffset, col.offset);
maxAttrOffset = qMax(maxAttrOffset, col.byteOffset);
if(prop.perinstance)
pi = true;
@@ -1647,6 +1647,70 @@ static void RT_FetchMeshData(IReplayController *r, ICaptureContext &ctx, Populat
}
}
static int MaxNumRows(const ShaderConstant &c)
{
int ret = c.type.descriptor.rows;
for(const ShaderConstant &child : c.type.members)
ret = qMax(ret, MaxNumRows(child));
return ret;
}
static void UnrollConstant(rdcstr prefix, const ShaderConstant &constant,
rdcarray<ShaderConstant> &columns,
rdcarray<BufferElementProperties> &props)
{
bool isArray = constant.type.descriptor.elements > 1;
rdcstr baseName = constant.name;
if(!prefix.isEmpty())
baseName = prefix + "." + baseName;
if(constant.type.members.isEmpty())
{
BufferElementProperties prop;
prop.format = GetInterpretedResourceFormat(constant);
ShaderConstant c = constant;
if(isArray)
{
for(uint32_t a = 0; a < constant.type.descriptor.elements; a++)
{
c.name = QFormatStr("%1[%2]").arg(baseName).arg(a);
columns.push_back(c);
props.push_back(prop);
}
}
else
{
c.name = baseName;
columns.push_back(c);
props.push_back(prop);
}
return;
}
// struct, expand by members
for(uint32_t a = 0; a < qMax(1U, constant.type.descriptor.elements); a++)
{
for(const ShaderConstant &child : constant.type.members)
{
UnrollConstant(isArray ? QFormatStr("%1[%2]").arg(baseName).arg(a) : QString(baseName), child,
columns, props);
}
}
}
static void UnrollConstant(const ShaderConstant &constant, rdcarray<ShaderConstant> &columns,
rdcarray<BufferElementProperties> &props)
{
UnrollConstant("", constant, columns, props);
}
BufferViewer::BufferViewer(ICaptureContext &ctx, bool meshview, QWidget *parent)
: QFrame(parent), ui(new Ui::BufferViewer), m_Ctx(ctx)
{
@@ -2158,9 +2222,9 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
len = 0;
QString errors;
bufdata->vsinConfig.columns = FormatElement::ParseFormatString(m_Format, len, true, errors);
for(int i = 0; i < bufdata->vsinConfig.columns.size(); i++)
bufdata->vsinConfig.props.push_back({});
ShaderConstant constant = BufferFormatter::ParseFormatString(m_Format, len, true, errors);
UnrollConstant(constant, bufdata->vsinConfig.columns, bufdata->vsinConfig.props);
ClearModels();
}
@@ -2241,7 +2305,7 @@ void BufferViewer::OnEventChanged(uint32_t eventId)
buf->stride = 0;
for(int i = 0; i < bufdata->vsinConfig.props.count(); i++)
buf->stride += bufdata->vsinConfig.props[i].format.ElementSize() *
bufdata->vsinConfig.columns[i].matrixdim;
bufdata->vsinConfig.columns[i].type.descriptor.rows;
buf->stride = qMax((size_t)1, buf->stride);
@@ -2432,7 +2496,7 @@ void BufferViewer::calcBoundingData(CalcBoundingBoxData &bbox)
for(int col = 0; col < s.columns.count(); col++)
{
const CachedElData &d = cache[col];
const FormatElement *el = d.el;
const ShaderConstant *el = d.el;
const BufferElementProperties *prop = d.prop;
float *minOut = (float *)&minOutputList[col];
@@ -2445,7 +2509,8 @@ void BufferViewer::calcBoundingData(CalcBoundingBoxData &bbox)
if(!prop->perinstance)
bytes += d.stride * idx;
QVariantList list = GetVariants(prop->format, el->matrixdim, bytes, d.end);
QVariantList list = GetVariants(prop->format, el->type.descriptor.rows,
el->type.descriptor.matrixByteStride, bytes, d.end);
for(int comp = 0; comp < 4 && comp < list.count(); comp++)
{
@@ -2622,7 +2687,7 @@ void BufferViewer::UI_CalculateMeshFormats()
m_VSInPosition.indexByteStride = 4U;
{
const FormatElement &el = vsinConfig.columns[elIdx];
const ShaderConstant &el = vsinConfig.columns[elIdx];
const BufferElementProperties &prop = vsinConfig.props[elIdx];
m_VSInPosition.instanced = prop.perinstance;
@@ -2632,7 +2697,7 @@ void BufferViewer::UI_CalculateMeshFormats()
{
m_VSInPosition.vertexResourceId = vbs[prop.buffer].resourceId;
m_VSInPosition.vertexByteStride = vbs[prop.buffer].byteStride;
m_VSInPosition.vertexByteOffset = vbs[prop.buffer].byteOffset + el.offset +
m_VSInPosition.vertexByteOffset = vbs[prop.buffer].byteOffset + el.byteOffset +
draw->vertexOffset * m_VSInPosition.vertexByteStride;
}
else
@@ -2649,7 +2714,7 @@ void BufferViewer::UI_CalculateMeshFormats()
if(elIdx >= 0 && elIdx < vsinConfig.columns.count())
{
const FormatElement &el = vsinConfig.columns[elIdx];
const ShaderConstant &el = vsinConfig.columns[elIdx];
const BufferElementProperties &prop = vsinConfig.props[elIdx];
m_VSInSecondary.instanced = prop.perinstance;
@@ -2659,7 +2724,7 @@ void BufferViewer::UI_CalculateMeshFormats()
{
m_VSInSecondary.vertexResourceId = vbs[prop.buffer].resourceId;
m_VSInSecondary.vertexByteStride = vbs[prop.buffer].byteStride;
m_VSInSecondary.vertexByteOffset = vbs[prop.buffer].byteOffset + el.offset +
m_VSInSecondary.vertexByteOffset = vbs[prop.buffer].byteOffset + el.byteOffset +
draw->vertexOffset * m_VSInSecondary.vertexByteStride;
}
else
@@ -2685,11 +2750,11 @@ void BufferViewer::UI_CalculateMeshFormats()
if(elIdx < 0 || elIdx >= vsoutConfig.columns.count())
elIdx = 0;
const FormatElement &el = vsoutConfig.columns[elIdx];
const ShaderConstant &el = vsoutConfig.columns[elIdx];
const BufferElementProperties &prop = vsoutConfig.props[elIdx];
m_PostVSPosition = m_PostVS;
m_PostVSPosition.vertexByteOffset += el.offset;
m_PostVSPosition.vertexByteOffset += el.byteOffset;
m_PostVSPosition.unproject = prop.systemValue == ShaderBuiltin::Position;
// if geometry/tessellation is enabled, don't unproject VS output data
@@ -2702,7 +2767,7 @@ void BufferViewer::UI_CalculateMeshFormats()
if(elIdx >= 0 && elIdx < vsoutConfig.columns.count())
{
m_PostVSSecondary = m_PostVS;
m_PostVSSecondary.vertexByteOffset += vsoutConfig.columns[elIdx].offset;
m_PostVSSecondary.vertexByteOffset += vsoutConfig.columns[elIdx].byteOffset;
m_PostVSSecondary.showAlpha = m_ModelVSOut->secondaryAlpha();
}
}
@@ -2721,11 +2786,11 @@ void BufferViewer::UI_CalculateMeshFormats()
if(elIdx < 0 || elIdx >= gsoutConfig.columns.count())
elIdx = 0;
const FormatElement &el = gsoutConfig.columns[elIdx];
const ShaderConstant &el = gsoutConfig.columns[elIdx];
const BufferElementProperties &prop = gsoutConfig.props[elIdx];
m_PostGSPosition = m_PostGS;
m_PostGSPosition.vertexByteOffset += el.offset;
m_PostGSPosition.vertexByteOffset += el.byteOffset;
m_PostGSPosition.unproject = prop.systemValue == ShaderBuiltin::Position;
elIdx = m_ModelGSOut->secondaryColumn();
@@ -2733,7 +2798,7 @@ void BufferViewer::UI_CalculateMeshFormats()
if(elIdx >= 0 && elIdx < gsoutConfig.columns.count())
{
m_PostGSSecondary = m_PostGS;
m_PostGSSecondary.vertexByteOffset += gsoutConfig.columns[elIdx].offset;
m_PostGSSecondary.vertexByteOffset += gsoutConfig.columns[elIdx].byteOffset;
m_PostGSSecondary.showAlpha = m_ModelGSOut->secondaryAlpha();
}
}
@@ -3190,16 +3255,35 @@ void BufferViewer::CalcColumnWidth(int maxNumRows)
floatProp.format = floatFmt;
intProp.format = intFmt;
ShaderConstant elem;
elem.name = headerText;
elem.byteOffset = 0;
elem.type.descriptor.rows = maxNumRows;
bufconfig.columns.clear();
bufconfig.columns.push_back(FormatElement(headerText, 0, false, maxNumRows, floatFmt, false, false));
bufconfig.columns.push_back(elem);
bufconfig.props.push_back(floatProp);
bufconfig.columns.push_back(FormatElement(headerText, 4, false, 1, floatFmt, false, false));
elem.type.descriptor.rows = 1;
elem.byteOffset = 4;
bufconfig.columns.push_back(elem);
bufconfig.props.push_back(floatProp);
bufconfig.columns.push_back(FormatElement(headerText, 8, false, 1, floatFmt, false, false));
elem.byteOffset = 8;
bufconfig.columns.push_back(elem);
bufconfig.props.push_back(floatProp);
bufconfig.columns.push_back(FormatElement(headerText, 12, false, 1, intFmt, true, false));
elem.byteOffset = 12;
bufconfig.columns.push_back(elem);
bufconfig.props.push_back(intProp);
bufconfig.columns.push_back(FormatElement(headerText, 16, false, 1, intFmt, false, false));
elem.byteOffset = 16;
bufconfig.columns.push_back(elem);
bufconfig.props.push_back(intProp);
bufconfig.numRows = 2;
@@ -3359,14 +3443,9 @@ void BufferViewer::processFormat(const QString &format)
if(len == UINT64_MAX)
len = 0;
QList<FormatElement> cols = FormatElement::ParseFormatString(format, len, true, errors);
ShaderConstant cols = BufferFormatter::ParseFormatString(format, len, true, errors);
int maxNumRows = 1;
for(const FormatElement &c : cols)
maxNumRows = qMax(maxNumRows, (int)c.matrixdim);
CalcColumnWidth(maxNumRows);
CalcColumnWidth(MaxNumRows(cols));
ClearModels();
@@ -3374,11 +3453,7 @@ void BufferViewer::processFormat(const QString &format)
ui->formatSpecifier->setFormat(format);
uint32_t stride = 0;
for(const FormatElement &el : cols)
stride += el.format.ElementSize() * el.matrixdim;
stride = qMax(1U, stride);
uint32_t stride = qMax(1U, cols.type.descriptor.arrayByteStride);
ui->byteRangeStart->setSingleStep((int)stride);
ui->byteRangeLength->setSingleStep((int)stride);
@@ -3496,7 +3571,7 @@ void BufferViewer::exportData(const BufferExport &params)
for(int col = 0; col < cache.count(); col++)
{
const CachedElData &d = cache[col];
const FormatElement *el = d.el;
const ShaderConstant *el = d.el;
const BufferElementProperties *prop = d.prop;
if(d.data)
+6 -16
View File
@@ -122,7 +122,7 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
if(reflection == NULL || m_slot >= reflection->constantBlocks.size())
{
// save expansion before clearing
if(m_formatOverride.empty())
if(m_formatOverride.type.members.empty())
{
RDTreeViewExpansionState &prevShaderExpansionState =
ui->variables->getInternalExpansion(qHash(ToQStr(prevShader)));
@@ -133,7 +133,7 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
return;
}
if(!m_formatOverride.empty())
if(!m_formatOverride.type.members.empty())
{
m_Ctx.Replay().AsyncInvoke([this, offs, size, wasEmpty](IReplayController *r) {
bytebuf data = r->GetBufferData(m_cbuffer, offs, size);
@@ -265,14 +265,14 @@ void ConstantBufferPreviewer::processFormat(const QString &format)
{
if(format.isEmpty())
{
m_formatOverride.clear();
m_formatOverride = ShaderConstant();
ui->formatSpecifier->setErrors(QString());
}
else
{
QString errors;
m_formatOverride = FormatElement::ParseFormatString(format, 0, false, errors);
m_formatOverride = BufferFormatter::ParseFormatString(format, 0, false, errors);
ui->formatSpecifier->setErrors(errors);
}
@@ -348,17 +348,7 @@ void ConstantBufferPreviewer::updateLabels()
rdcarray<ShaderVariable> ConstantBufferPreviewer::applyFormatOverride(const bytebuf &bytes)
{
QVector<ShaderVariable> variables;
ShaderVariable var = InterpretShaderVar(m_formatOverride, bytes.begin(), bytes.end());
variables.resize(m_formatOverride.length());
for(int i = 0; i < m_formatOverride.length(); i++)
{
const byte *b = bytes.begin() + m_formatOverride[i].offset;
variables[i] = m_formatOverride[i].GetShaderVar(b, bytes.end());
}
rdcarray<ShaderVariable> ret;
ret = variables.toStdVector();
return ret;
return var.members;
}
+2 -2
View File
@@ -34,7 +34,7 @@ class ConstantBufferPreviewer;
class QTextStream;
class RDTreeWidgetItem;
struct FormatElement;
struct BufferFormatter;
class ConstantBufferPreviewer : public QFrame, public IConstantBufferPreviewer, public ICaptureViewer
{
@@ -89,5 +89,5 @@ private:
static QList<ConstantBufferPreviewer *> m_Previews;
QList<FormatElement> m_formatOverride;
ShaderConstant m_formatOverride;
};
@@ -1958,7 +1958,7 @@ void D3D11PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
if(tex->type == TextureType::Buffer)
{
IBufferViewer *viewer = m_Ctx.ViewTextureAsBuffer(
tex->resourceId, Subresource(), FormatElement::GenerateTextureBufferFormat(*tex));
tex->resourceId, Subresource(), BufferFormatter::GetTextureFormatString(*tex));
m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this);
}
@@ -2067,7 +2067,7 @@ void D3D11PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
if(shaderRes)
{
format = m_Common.GenerateBufferFormatter(*shaderRes, view.res.viewFormat, offs);
format = BufferFormatter::GetBufferFormatString(*shaderRes, view.res.viewFormat, offs);
if(view.res.bufferFlags & D3DBufferViewFlags::Raw)
format = lit("xint");
@@ -1845,7 +1845,7 @@ void D3D12PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
if(tex->type == TextureType::Buffer)
{
IBufferViewer *viewer = m_Ctx.ViewTextureAsBuffer(
tex->resourceId, Subresource(), FormatElement::GenerateTextureBufferFormat(*tex));
tex->resourceId, Subresource(), BufferFormatter::GetTextureFormatString(*tex));
m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this);
}
@@ -1920,7 +1920,7 @@ void D3D12PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
if(shaderRes)
{
format = m_Common.GenerateBufferFormatter(*shaderRes, view.res.viewFormat, offs);
format = BufferFormatter::GetBufferFormatString(*shaderRes, view.res.viewFormat, offs);
if(view.res.bufferFlags & D3DBufferViewFlags::Raw)
format = lit("xint");
@@ -2144,7 +2144,7 @@ void GLPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int c
if(tex->type == TextureType::Buffer)
{
IBufferViewer *viewer = m_Ctx.ViewTextureAsBuffer(
tex->resourceId, Subresource(), FormatElement::GenerateTextureBufferFormat(*tex));
tex->resourceId, Subresource(), BufferFormatter::GetTextureFormatString(*tex));
m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this);
}
@@ -2165,7 +2165,7 @@ void GLPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int c
const ShaderResource &shaderRes = stage->reflection->readWriteResources[buf.bindPoint];
QString format = m_Common.GenerateBufferFormatter(shaderRes, ResourceFormat(), buf.offset);
QString format = BufferFormatter::GetBufferFormatString(shaderRes, ResourceFormat(), buf.offset);
if(buf.ID != ResourceId())
{
@@ -694,169 +694,6 @@ QString PipelineStateViewer::declareStruct(QList<QString> &declaredStructs, cons
return ret;
}
QString PipelineStateViewer::GenerateBufferFormatter(const ShaderResource &res,
const ResourceFormat &viewFormat,
uint64_t &baseByteOffset)
{
QString format;
if(!res.variableType.members.empty())
{
if(m_Ctx.APIProps().pipelineType == GraphicsAPI::Vulkan ||
m_Ctx.APIProps().pipelineType == GraphicsAPI::OpenGL)
{
const rdcarray<ShaderConstant> &members = res.variableType.members;
format += QFormatStr("struct %1\n{\n").arg(res.name);
// GL/Vulkan allow fixed-sized members before the array-of-structs. This can't be
// represented in a buffer format so we skip it
if(members.count() > 1)
{
format += tr(" // members skipped as they are fixed size:\n");
baseByteOffset += members.back().byteOffset;
}
QString varTypeName;
QString comment = lit("// ");
for(int i = 0; i < members.count(); i++)
{
QString arraySize;
if(members[i].type.descriptor.elements > 1)
arraySize = QFormatStr("[%1]").arg(members[i].type.descriptor.elements);
varTypeName = members[i].type.descriptor.name;
if(i + 1 == members.count())
{
comment = arraySize = QString();
if(members.count() > 1)
format +=
lit(" // final array struct @ byte offset %1\n").arg(members.back().byteOffset);
// give GL nameless structs a better name
if(varTypeName.isEmpty() || varTypeName == lit("struct"))
varTypeName = lit("root_struct");
}
format +=
QFormatStr(" %1%2 %3%4;\n").arg(comment).arg(varTypeName).arg(members[i].name).arg(arraySize);
}
format += lit("}");
// if the last member is a struct, declare it
if(!members.back().type.members.isEmpty())
{
QList<QString> declaredStructs;
format = declareStruct(declaredStructs, varTypeName, members.back().type.members,
members.back().type.descriptor.arrayByteStride) +
lit("\n") + format;
}
}
else
{
QList<QString> declaredStructs;
format = declareStruct(declaredStructs, res.variableType.descriptor.name,
res.variableType.members, 0);
}
}
else
{
const auto &desc = res.variableType.descriptor;
if(viewFormat.type == ResourceFormatType::Undefined)
{
if(desc.type == VarType::Unknown)
{
format = desc.name;
}
else
{
if(desc.rowMajorStorage)
format += lit("row_major ");
format += ToQStr(desc.type);
if(desc.rows > 1 && desc.columns > 1)
format += QFormatStr("%1x%2").arg(desc.rows).arg(desc.columns);
else if(desc.columns > 1)
format += QString::number(desc.columns);
if(!desc.name.empty())
format += lit(" ") + desc.name;
if(desc.elements > 1)
format += QFormatStr("[%1]").arg(desc.elements);
}
}
else
{
if(viewFormat.type == ResourceFormatType::R10G10B10A2)
{
if(viewFormat.compType == CompType::UInt)
format = lit("uintten");
if(viewFormat.compType == CompType::UNorm)
format = lit("unormten");
}
else if(viewFormat.type == ResourceFormatType::R11G11B10)
{
format = lit("floateleven");
}
else
{
switch(viewFormat.compByteWidth)
{
case 1:
{
if(viewFormat.compType == CompType::UNorm || viewFormat.compType == CompType::UNormSRGB)
format = lit("unormb");
if(viewFormat.compType == CompType::SNorm)
format = lit("snormb");
if(viewFormat.compType == CompType::UInt)
format = lit("ubyte");
if(viewFormat.compType == CompType::SInt)
format = lit("byte");
break;
}
case 2:
{
if(viewFormat.compType == CompType::UNorm || viewFormat.compType == CompType::UNormSRGB)
format = lit("unormh");
if(viewFormat.compType == CompType::SNorm)
format = lit("snormh");
if(viewFormat.compType == CompType::UInt)
format = lit("ushort");
if(viewFormat.compType == CompType::SInt)
format = lit("short");
if(viewFormat.compType == CompType::Float)
format = lit("half");
break;
}
case 4:
{
if(viewFormat.compType == CompType::UNorm || viewFormat.compType == CompType::UNormSRGB)
format = lit("unormf");
if(viewFormat.compType == CompType::SNorm)
format = lit("snormf");
if(viewFormat.compType == CompType::UInt)
format = lit("uint");
if(viewFormat.compType == CompType::SInt)
format = lit("int");
if(viewFormat.compType == CompType::Float)
format = lit("float");
break;
}
}
format += QString::number(viewFormat.compCount);
}
}
}
return format;
}
void PipelineStateViewer::MakeShaderVariablesHLSL(bool cbufferContents,
const rdcarray<ShaderConstant> &vars,
QString &struct_contents, QString &struct_defs)
@@ -71,9 +71,6 @@ public:
const ShaderBindpointMapping &bindpointMapping,
const ShaderReflection *shaderDetails);
QString GenerateBufferFormatter(const ShaderResource &res, const ResourceFormat &viewFormat,
uint64_t &baseByteOffset);
QString GetVBufferFormatString(uint32_t slot);
void setTopologyDiagram(QLabel *diagram, Topology topo);
@@ -2540,7 +2540,7 @@ void VulkanPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, i
if(tex->type == TextureType::Buffer)
{
IBufferViewer *viewer = m_Ctx.ViewTextureAsBuffer(
tex->resourceId, Subresource(), FormatElement::GenerateTextureBufferFormat(*tex));
tex->resourceId, Subresource(), BufferFormatter::GetTextureFormatString(*tex));
m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this);
}
@@ -2569,7 +2569,7 @@ void VulkanPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, i
? stage->reflection->readWriteResources[buf.bindPoint]
: stage->reflection->readOnlyResources[buf.bindPoint];
format = m_Common.GenerateBufferFormatter(shaderRes, buf.fmt, buf.offset);
format = BufferFormatter::GetBufferFormatString(shaderRes, buf.fmt, buf.offset);
}
if(buf.ID != ResourceId())
+1 -1
View File
@@ -451,7 +451,7 @@ void ResourceInspector::on_viewContents_clicked()
if(tex->type == TextureType::Buffer)
{
IBufferViewer *viewer = m_Ctx.ViewTextureAsBuffer(
tex->resourceId, Subresource(), FormatElement::GenerateTextureBufferFormat(*tex));
tex->resourceId, Subresource(), BufferFormatter::GetTextureFormatString(*tex));
m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this);
}
+1 -1
View File
@@ -3622,7 +3622,7 @@ void TextureViewer::on_viewTexBuffer_clicked()
{
IBufferViewer *viewer =
m_Ctx.ViewTextureAsBuffer(texptr->resourceId, m_TexDisplay.subresource,
FormatElement::GenerateTextureBufferFormat(*texptr));
BufferFormatter::GetTextureFormatString(*texptr));
m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this);
}
+1 -1
View File
@@ -168,7 +168,7 @@ SOURCES += Code/qrenderdoc.cpp \
Code/CaptureContext.cpp \
Code/ScintillaSyntax.cpp \
Code/QRDUtils.cpp \
Code/FormatElement.cpp \
Code/BufferFormatter.cpp \
Code/Resources.cpp \
Code/RGPInterop.cpp \
Code/pyrenderdoc/PythonContext.cpp \
+1 -1
View File
@@ -574,7 +574,7 @@
<ForcedIncludeFiles>
</ForcedIncludeFiles>
</ClCompile>
<ClCompile Include="Code\FormatElement.cpp" />
<ClCompile Include="Code\BufferFormatter.cpp" />
<ClCompile Include="Code\Interface\Analytics.cpp" />
<ClCompile Include="Code\Interface\PersistantConfig.cpp" />
<ClCompile Include="Code\Interface\QRDInterface.cpp" />
+3 -3
View File
@@ -369,9 +369,6 @@
<ClCompile Include="Windows\Dialogs\VirtualFileDialog.cpp">
<Filter>Windows\Dialogs</Filter>
</ClCompile>
<ClCompile Include="Code\FormatElement.cpp">
<Filter>Code</Filter>
</ClCompile>
<ClCompile Include="Windows\DebugMessageView.cpp">
<Filter>Windows</Filter>
</ClCompile>
@@ -729,6 +726,9 @@
<ClCompile Include="$(IntDir)generated\moc_ReplayOptionsSelector.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="Code\BufferFormatter.cpp">
<Filter>Code</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="3rdparty\flowlayout\FlowLayout.h">
+21 -2
View File
@@ -186,7 +186,7 @@ DOCUMENT(R"(Represents the base type of a shader variable in debugging or consta
An unknown type.
)");
enum class VarType : uint32_t
enum class VarType : uint8_t
{
Float = 0,
Double,
@@ -199,11 +199,30 @@ enum class VarType : uint32_t
ULong,
SByte,
UByte,
Unknown = ~0U,
Unknown = 0xFF,
};
DECLARE_REFLECTION_ENUM(VarType);
DOCUMENT(R"(Get the byte size of a variable type.
:param VarType type: The variable type
:return: The size in bytes of this type
:rtype: int
)");
constexpr uint32_t VarTypeByteSize(VarType type)
{
// temporarily disable clang-format to make this more readable.
// Ideally we'd use a simple switch() but VS2015 doesn't support that :(.
// clang-format off
return (type == VarType::UByte || type == VarType::SByte) ? 1
: (type == VarType::Half || type == VarType::UShort || type == VarType::SShort) ? 2
: (type == VarType::Float || type == VarType::UInt || type == VarType::SInt ) ? 4
: (type == VarType::Double || type == VarType::ULong || type == VarType::SLong ) ? 8
: 0;
// clang-format on
}
DOCUMENT(R"(Represents the component type of a channel in a texture or element in a structure.
.. data:: Typeless
+12 -6
View File
@@ -635,6 +635,12 @@ struct ShaderVariableDescriptor
return name < o.name;
return false;
}
DOCUMENT("The name of the type of this constant, e.g. a ``struct`` name.");
rdcstr name;
DOCUMENT("The number of elements in the array, or 1 if it's not an array.");
uint32_t elements = 1;
DOCUMENT("The number of bytes between the start of one element in the array and the next.");
uint32_t arrayByteStride = 0;
DOCUMENT("The :class:`VarType` that this basic constant stores.");
VarType type = VarType::Unknown;
DOCUMENT("The number of rows in this matrix.");
@@ -645,12 +651,12 @@ struct ShaderVariableDescriptor
uint8_t matrixByteStride = 0;
DOCUMENT("``True`` if the matrix is stored as row major instead of column major.");
bool rowMajorStorage = false;
DOCUMENT("The number of elements in the array, or 1 if it's not an array.");
uint32_t elements = 1;
DOCUMENT("The number of bytes between the start of one element in the array and the next.");
uint32_t arrayByteStride = 0;
DOCUMENT("The name of the type of this constant, e.g. a ``struct`` name.");
rdcstr name;
DOCUMENT("``True`` if the contents of this variable should be displayed as hex.");
bool displayAsHex = false;
DOCUMENT(R"(``True`` if the contents of this variable should be displayed as RGB color (where
possible).
)");
bool displayAsRGB = false;
};
DECLARE_REFLECTION_STRUCT(ShaderVariableDescriptor);
+2
View File
@@ -181,6 +181,8 @@ void DoSerialise(SerialiserType &ser, ShaderVariableDescriptor &el)
SERIALISE_MEMBER(elements);
SERIALISE_MEMBER(arrayByteStride);
SERIALISE_MEMBER(name);
SERIALISE_MEMBER(displayAsHex);
SERIALISE_MEMBER(displayAsRGB);
SIZE_CHECK(40);
}