Add constant buffer previewer for qrenderdoc

This commit is contained in:
baldurk
2016-11-25 14:17:20 +01:00
parent 2f14e2ac70
commit a2d40f8061
16 changed files with 1962 additions and 83 deletions
-9
View File
@@ -53,15 +53,6 @@ class TextureViewer;
class CaptureDialog;
class QProgressDialog;
struct Formatter
{
static QString Format(float f) { return QString::number(f); }
static QString Format(double d) { return QString::number(d); }
static QString Format(uint32_t u) { return QString::number(u); }
static QString Format(uint16_t u) { return QString::number(u); }
static QString Format(int32_t i) { return QString::number(i); }
};
class CaptureContext
{
public:
+877
View File
@@ -0,0 +1,877 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include <QRegularExpression>
#include <QtMath>
#include "QRDUtils.h"
static QVariant interpret(const ResourceFormat &f, uint16_t comp)
{
if(f.compByteWidth != 2 || f.compType == eCompType_Float)
return QVariant();
if(f.compType == eCompType_SInt)
{
return (int16_t)comp;
}
else if(f.compType == eCompType_UInt)
{
return comp;
}
else if(f.compType == eCompType_SScaled)
{
return (float)((int16_t)comp);
}
else if(f.compType == eCompType_UScaled)
{
return (float)comp;
}
else if(f.compType == eCompType_UNorm)
{
return (float)comp / (float)0xffff;
}
else if(f.compType == eCompType_SNorm)
{
int16_t cast = (int16_t)comp;
float ret = -1.0f;
if(cast == -32768)
ret = -1.0f;
else
ret = ((float)cast) / 32767.0f;
return ret;
}
return QVariant();
}
static QVariant interpret(const ResourceFormat &f, byte comp)
{
if(f.compByteWidth != 1 || f.compType == eCompType_Float)
return QVariant();
if(f.compType == eCompType_SInt)
{
return (int8_t)comp;
}
else if(f.compType == eCompType_UInt)
{
return comp;
}
else if(f.compType == eCompType_SScaled)
{
return (float)((int8_t)comp);
}
else if(f.compType == eCompType_UScaled)
{
return (float)comp;
}
else if(f.compType == eCompType_UNorm)
{
return ((float)comp) / 255.0f;
}
else if(f.compType == eCompType_SNorm)
{
int8_t cast = (int8_t)comp;
float ret = -1.0f;
if(cast == -128)
ret = -1.0f;
else
ret = ((float)cast) / 127.0f;
return ret;
}
return QVariant();
}
FormatElement::FormatElement()
{
name = "";
buffer = 0;
offset = 0;
perinstance = false;
instancerate = 1;
rowmajor = false;
matrixdim = 0;
hex = false;
systemValue = eAttr_None;
}
FormatElement::FormatElement(const QString &Name, int buf, uint offs, bool pi, int ir, bool rowMat,
uint matDim, ResourceFormat f, bool h)
{
name = Name;
buffer = buf;
offset = offs;
format = f;
perinstance = pi;
instancerate = ir;
rowmajor = rowMat;
matrixdim = matDim;
hex = h;
systemValue = eAttr_None;
}
QList<FormatElement> FormatElement::ParseFormatString(const QString &formatString, uint64_t maxLen,
bool tightPacking, QString &errors)
{
QList<FormatElement> elems;
// regex doesn't account for trailing or preceeding whitespace, or comments
QRegularExpression regExpr(
"^(row_major\\s+)?" // row_major matrix
"("
"uintten|unormten"
"|unormh|unormb"
"|snormh|snormb"
"|bool" // bool is stored as 4-byte int
"|byte|short|int" // signed ints
"|ubyte|ushort|uint" // unsigned ints
"|xbyte|xshort|xint" // hex ints
"|half|float|double" // float types
"|vec|uvec|ivec" // OpenGL vector types
"|mat|umat|imat" // OpenGL matrix types
")"
"([1-9])?" // might be a vector
"(x[1-9])?" // or a matrix
"(\\s+[A-Za-z_][A-Za-z0-9_]*)?" // get identifier name
"(\\[[0-9]+\\])?" // optional array dimension
"(\\s*:\\s*[A-Za-z_][A-Za-z0-9_]*)?" // optional semantic
"$");
bool success = true;
errors = "";
QString text = formatString;
text = text.replace("{", "").replace("}", "");
QRegularExpression c_comments("/\\*[^*]*\\*+(?:[^*/][^*]*\\*+)*/");
QRegularExpression cpp_comments("//.*");
text = text.replace(c_comments, "").replace(cpp_comments, "");
uint32_t offset = 0;
// get each line and parse it to determine the format the user wanted
for(QString &l : text.split(QChar(';')))
{
QString line = l.trimmed();
if(line.isEmpty())
continue;
QRegularExpressionMatch match = regExpr.match(line);
if(!match.hasMatch())
{
errors = "Couldn't parse line:\n" + line;
success = false;
break;
}
QString basetype = match.captured(2);
bool row_major = !match.captured(1).isEmpty();
QString vectorDim = !match.captured(3).isEmpty() ? match.captured(3) : "1";
QString matrixDim = !match.captured(4).isEmpty() ? match.captured(4).mid(1) : "1";
QString name = !match.captured(5).isEmpty() ? match.captured(5).trimmed() : "data";
QString arrayDim = !match.captured(6).isEmpty() ? match.captured(6).trimmed() : "[1]";
arrayDim = arrayDim.mid(1, arrayDim.count() - 2);
if(!match.captured(4).isEmpty())
{
vectorDim.swap(matrixDim);
}
ResourceFormat fmt;
fmt.compType = eCompType_None;
bool hex = false;
FormatComponentType type = eCompType_Float;
uint32_t count = 0;
uint32_t arrayCount = 1;
uint32_t matrixCount = 0;
uint32_t width = 0;
// check for square matrix declarations like 'mat4' and 'mat3'
if(basetype == "mat" && !match.captured(4).isEmpty())
matrixDim = vectorDim;
// calculate format
{
bool ok = false;
count = vectorDim.toUInt(&ok);
if(!ok)
{
errors = "Invalid vector dimension on line:\n" + line;
success = false;
break;
}
arrayCount = arrayDim.toUInt(&ok);
if(!ok)
{
arrayCount = 1;
}
arrayCount = qMax(0U, arrayCount);
matrixCount = matrixDim.toUInt(&ok);
if(!ok)
{
errors = "Invalid matrix second dimension on line:\n" + line;
success = false;
break;
}
if(basetype == "bool")
{
type = eCompType_UInt;
width = 4;
}
else if(basetype == "byte")
{
type = eCompType_SInt;
width = 1;
}
else if(basetype == "ubyte" || basetype == "xbyte")
{
type = eCompType_UInt;
width = 1;
}
else if(basetype == "short")
{
type = eCompType_SInt;
width = 2;
}
else if(basetype == "ushort" || basetype == "xshort")
{
type = eCompType_UInt;
width = 2;
}
else if(basetype == "int" || basetype == "ivec" || basetype == "imat")
{
type = eCompType_SInt;
width = 4;
}
else if(basetype == "uint" || basetype == "xint" || basetype == "uvec" || basetype == "umat")
{
type = eCompType_UInt;
width = 4;
}
else if(basetype == "half")
{
type = eCompType_Float;
width = 2;
}
else if(basetype == "float" || basetype == "vec" || basetype == "mat")
{
type = eCompType_Float;
width = 4;
}
else if(basetype == "double")
{
type = eCompType_Double;
width = 8;
}
else if(basetype == "unormh")
{
type = eCompType_UNorm;
width = 2;
}
else if(basetype == "unormb")
{
type = eCompType_UNorm;
width = 1;
}
else if(basetype == "snormh")
{
type = eCompType_SNorm;
width = 2;
}
else if(basetype == "snormb")
{
type = eCompType_SNorm;
width = 1;
}
else if(basetype == "uintten")
{
fmt.compType = eCompType_UInt;
fmt.compCount = 4 * count;
fmt.compByteWidth = 1;
fmt.special = true;
fmt.specialFormat = eSpecial_R10G10B10A2;
}
else if(basetype == "unormten")
{
fmt.compType = eCompType_UInt;
fmt.compCount = 4 * count;
fmt.compByteWidth = 1;
fmt.special = true;
fmt.specialFormat = eSpecial_R10G10B10A2;
}
else
{
errors = "Unrecognised basic type on line:\n" + line;
success = false;
break;
}
}
if(basetype == "xint" || basetype == "xshort" || basetype == "xbyte")
hex = true;
if(fmt.compType == eCompType_None)
{
fmt.compType = type;
fmt.compCount = count;
fmt.compByteWidth = width;
}
if(arrayCount == 1)
{
FormatElement elem(name, 0, offset, false, 1, row_major, matrixCount, fmt, hex);
uint32_t advance = elem.byteSize();
if(!tightPacking)
{
// cbuffer packing always works in floats
advance = (advance + 3U) & (~3U);
// cbuffer packing doesn't allow elements to cross float4 boundaries, nudge up if this was
// the case
if(offset / 16 != (offset + elem.byteSize() - 1) / 16)
{
elem.offset = offset = (offset + 0xFU) & (~0xFU);
}
}
elems.push_back(elem);
offset += advance;
}
else
{
// when cbuffer packing, arrays are always aligned at float4 boundary
if(!tightPacking)
{
if(offset % 16 != 0)
{
offset = (offset + 0xFU) & (~0xFU);
}
}
for(uint a = 0; a < arrayCount; a++)
{
FormatElement elem(QString("%1[%2]").arg(name).arg(a), 0, offset, false, 1, row_major,
matrixCount, fmt, hex);
elems.push_back(elem);
uint32_t advance = elem.byteSize();
// cbuffer packing each array element is always float4 aligned
if(!tightPacking)
{
advance = (advance + 0xFU) & (~0xFU);
}
offset += advance;
}
}
}
if(!success || elems.isEmpty())
{
elems.clear();
ResourceFormat fmt;
fmt.compType = eCompType_UInt;
fmt.compByteWidth = 4;
fmt.compCount = 4;
if(maxLen > 0 && maxLen < 16)
fmt.compCount = 1;
if(maxLen > 0 && maxLen < 4)
fmt.compByteWidth = 1;
elems.push_back(FormatElement("data", 0, 0, false, 1, false, 1, fmt, true));
}
return elems;
}
template <typename T>
inline T readObj(const byte *&data, const byte *end, bool &ok)
{
if(data + sizeof(T) > end)
{
ok = false;
return T();
}
T ret = *(T *)data;
data += sizeof(T);
return ret;
}
QVariantList FormatElement::GetVariants(const byte *&data, const byte *end)
{
QVariantList ret;
bool ok = true;
if(format.special && format.specialFormat == eSpecial_R5G5B5A1)
{
uint16_t packed = readObj<uint16_t>(data, end, ok);
ret.push_back((float)((packed >> 0) & 0x1f) / 31.0f);
ret.push_back((float)((packed >> 5) & 0x1f) / 31.0f);
ret.push_back((float)((packed >> 10) & 0x1f) / 31.0f);
ret.push_back(((packed & 0x8000) > 0) ? 1.0f : 0.0f);
if(format.bgraOrder)
{
QVariant tmp = ret[2];
ret[2] = ret[0];
ret[0] = tmp;
}
}
else if(format.special && format.specialFormat == eSpecial_R5G6B5)
{
uint16_t packed = readObj<uint16_t>(data, end, ok);
ret.push_back((float)((packed >> 0) & 0x1f) / 31.0f);
ret.push_back((float)((packed >> 5) & 0x3f) / 63.0f);
ret.push_back((float)((packed >> 11) & 0x1f) / 31.0f);
if(format.bgraOrder)
{
QVariant tmp = ret[2];
ret[2] = ret[0];
ret[0] = tmp;
}
}
else if(format.special && format.specialFormat == eSpecial_R4G4B4A4)
{
uint16_t packed = readObj<uint16_t>(data, end, ok);
ret.push_back((float)((packed >> 0) & 0xf) / 15.0f);
ret.push_back((float)((packed >> 4) & 0xf) / 15.0f);
ret.push_back((float)((packed >> 8) & 0xf) / 15.0f);
ret.push_back((float)((packed >> 12) & 0xf) / 15.0f);
if(format.bgraOrder)
{
QVariant tmp = ret[2];
ret[2] = ret[0];
ret[0] = tmp;
}
}
else if(format.special && format.specialFormat == eSpecial_R10G10B10A2)
{
// allow for vectors of this format - for raw buffer viewer
for(int i = 0; i < int(format.compCount / 4); i++)
{
uint32_t packed = readObj<uint32_t>(data, end, ok);
uint32_t r = (packed >> 0) & 0x3ff;
uint32_t g = (packed >> 10) & 0x3ff;
uint32_t b = (packed >> 20) & 0x3ff;
uint32_t a = (packed >> 30) & 0x003;
if(format.bgraOrder)
{
uint32_t tmp = b;
b = r;
r = tmp;
}
if(format.compType == eCompType_UInt)
{
ret.push_back(r);
ret.push_back(g);
ret.push_back(b);
ret.push_back(a);
}
else if(format.compType == eCompType_UScaled)
{
ret.push_back((float)r);
ret.push_back((float)g);
ret.push_back((float)b);
ret.push_back((float)a);
}
else if(format.compType == eCompType_SInt || format.compType == eCompType_SScaled)
{
int ir, ig, ib, ia;
// interpret RGB as 10-bit signed integers
if(r <= 511)
ir = (int)r;
else
ir = ((int)r) - 1024;
if(g <= 511)
ig = (int)g;
else
ig = ((int)g) - 1024;
if(b <= 511)
ib = (int)b;
else
ib = ((int)b) - 1024;
// 2-bit signed integer
if(a <= 1)
ia = (int)a;
else
ia = ((int)a) - 4;
if(format.compType == eCompType_SInt)
{
ret.push_back(ir);
ret.push_back(ig);
ret.push_back(ib);
ret.push_back(ia);
}
else if(format.compType == eCompType_SScaled)
{
ret.push_back((float)ir);
ret.push_back((float)ig);
ret.push_back((float)ib);
ret.push_back((float)ia);
}
}
else
{
ret.push_back((float)r / 1023.0f);
ret.push_back((float)g / 1023.0f);
ret.push_back((float)b / 1023.0f);
ret.push_back((float)a / 3.0f);
}
}
}
else if(format.special && format.specialFormat == eSpecial_R11G11B10)
{
uint32_t packed = readObj<uint32_t>(data, end, ok);
uint32_t xMantissa = ((packed >> 0) & 0x3f);
uint32_t xExponent = ((packed >> 6) & 0x1f);
uint32_t yMantissa = ((packed >> 11) & 0x3f);
uint32_t yExponent = ((packed >> 17) & 0x1f);
uint32_t zMantissa = ((packed >> 22) & 0x1f);
uint32_t zExponent = ((packed >> 27) & 0x1f);
ret.push_back(((float)(xMantissa) / 64.0f) * qPow(2.0f, (float)xExponent - 15.0f));
ret.push_back(((float)(yMantissa) / 32.0f) * qPow(2.0f, (float)yExponent - 15.0f));
ret.push_back(((float)(zMantissa) / 32.0f) * qPow(2.0f, (float)zExponent - 15.0f));
}
else
{
int dim = (int)(qMax(matrixdim, 1U) * format.compCount);
for(int i = 0; i < dim; i++)
{
if(format.compType == eCompType_Float)
{
if(format.compByteWidth == 8)
ret.push_back(readObj<double>(data, end, ok));
else if(format.compByteWidth == 4)
ret.push_back(readObj<float>(data, end, ok));
else if(format.compByteWidth == 2)
ret.push_back(Maths_HalfToFloat(readObj<uint16_t>(data, end, ok)));
}
else if(format.compType == eCompType_SInt)
{
if(format.compByteWidth == 4)
ret.push_back((int)readObj<int32_t>(data, end, ok));
else if(format.compByteWidth == 2)
ret.push_back((int)readObj<int16_t>(data, end, ok));
else if(format.compByteWidth == 1)
ret.push_back((int)readObj<int8_t>(data, end, ok));
}
else if(format.compType == eCompType_UInt)
{
if(format.compByteWidth == 4)
ret.push_back((uint32_t)readObj<uint32_t>(data, end, ok));
else if(format.compByteWidth == 2)
ret.push_back((uint32_t)readObj<uint16_t>(data, end, ok));
else if(format.compByteWidth == 1)
ret.push_back((uint32_t)readObj<uint8_t>(data, end, ok));
}
else if(format.compType == eCompType_UScaled)
{
if(format.compByteWidth == 4)
ret.push_back((float)readObj<uint32_t>(data, end, ok));
else if(format.compByteWidth == 2)
ret.push_back((float)readObj<uint16_t>(data, end, ok));
else if(format.compByteWidth == 1)
ret.push_back((float)readObj<uint8_t>(data, end, ok));
}
else if(format.compType == eCompType_SScaled)
{
if(format.compByteWidth == 4)
ret.push_back((float)readObj<int32_t>(data, end, ok));
else if(format.compByteWidth == 2)
ret.push_back((float)readObj<int16_t>(data, end, ok));
else if(format.compByteWidth == 1)
ret.push_back((float)readObj<int8_t>(data, end, ok));
}
else if(format.compType == eCompType_Depth)
{
if(format.compByteWidth == 4)
{
// 32-bit depth is native floats
ret.push_back(readObj<float>(data, end, ok));
}
else if(format.compByteWidth == 3)
{
// 32-bit depth is normalised, masked against non-stencil bits
uint32_t f = readObj<uint32_t>(data, end, ok);
f &= 0x00ffffff;
ret.push_back((float)f / (float)0x00ffffff);
}
else if(format.compByteWidth == 2)
{
// 16-bit depth is normalised
float f = (float)readObj<uint16_t>(data, end, ok);
ret.push_back(f / (float)0x0000ffff);
}
}
else if(format.compType == eCompType_Double)
{
ret.push_back(readObj<double>(data, end, ok));
}
else
{
// unorm/snorm
if(format.compByteWidth == 4)
{
// should never hit this - no 32bit unorm/snorm type
qCritical() << "Unexpected 4-byte unorm/snorm value";
ret.push_back((float)readObj<uint32_t>(data, end, ok) / (float)0xffffffff);
}
else if(format.compByteWidth == 2)
{
ret.push_back(interpret(format, readObj<uint16_t>(data, end, ok)));
}
else if(format.compByteWidth == 1)
{
ret.push_back(interpret(format, readObj<uint8_t>(data, end, ok)));
}
}
}
if(format.bgraOrder)
{
QVariant tmp = ret[2];
ret[2] = ret[0];
ret[0] = tmp;
}
}
// we read off the end, return empty set
if(!ok)
ret.clear();
return ret;
}
ShaderVariable FormatElement::GetShaderVar(const byte *&data, const byte *end)
{
QVariantList objs = GetVariants(data, end);
ShaderVariable ret;
ret.name = name.toUtf8().data();
ret.type = eVar_Float;
if(format.compType == eCompType_UInt)
ret.type = eVar_UInt;
if(format.compType == eCompType_SInt)
ret.type = eVar_Int;
if(format.compType == eCompType_Double)
ret.type = eVar_Double;
ret.columns = qMin(format.compCount, 4U);
ret.rows = qMin(matrixdim, 4U);
ret.displayAsHex = hex;
for(uint32_t row = 0; row < ret.rows; row++)
{
for(uint32_t col = 0; col < ret.columns; col++)
{
uint32_t dst = row * ret.columns + col;
uint32_t src = row * format.compCount + col;
// if we partially read a failure, reset the variable and return
if((int)src >= objs.size())
{
ret.name = "-";
memset(ret.value.dv, 0, sizeof(ret.value.dv));
return ret;
}
const QVariant &o = objs[src];
if(ret.type == eVar_Double)
ret.value.dv[dst] = o.toDouble();
else if(ret.type == eVar_UInt)
ret.value.uv[dst] = o.toUInt();
else if(ret.type == eVar_Int)
ret.value.iv[dst] = o.toInt();
else
ret.value.fv[dst] = o.toFloat();
}
}
return ret;
}
uint32_t FormatElement::byteSize()
{
uint32_t vecSize = format.compByteWidth * format.compCount;
if(format.special)
{
if(format.specialFormat == eSpecial_R5G5B5A1 || format.specialFormat == eSpecial_R5G6B5 ||
format.specialFormat == eSpecial_R4G4B4A4)
vecSize = 2;
if(format.specialFormat == eSpecial_R10G10B10A2 || format.specialFormat == eSpecial_R11G11B10)
vecSize = 4;
}
return vecSize * matrixdim;
}
QString TypeString(const ShaderVariable &v)
{
if(v.members.count > 0)
{
if(v.isStruct)
return "struct";
else
return QString("%1[%2]").arg(TypeString(v.members[0]), v.members.count);
}
QString typeStr = ToQStr(v.type);
if(v.displayAsHex && v.type == eVar_UInt)
typeStr = "xint";
if(v.rows == 1 && v.columns == 1)
return typeStr;
if(v.rows == 1)
return QString("%1%2").arg(typeStr).arg(v.columns);
else
return QString("%1%2x%3").arg(typeStr).arg(v.rows).arg(v.columns);
}
template <typename el>
static QString RowValuesToString(int cols, el x, el y, el z, el w)
{
if(cols == 1)
return Formatter::Format(x);
else if(cols == 2)
return Formatter::Format(x) + ", " + Formatter::Format(y);
else if(cols == 3)
return Formatter::Format(x) + ", " + Formatter::Format(y) + ", " + Formatter::Format(z);
else
return Formatter::Format(x) + ", " + Formatter::Format(y) + ", " + Formatter::Format(z) + ", " +
Formatter::Format(w);
}
QString RowString(const ShaderVariable &v, uint32_t row)
{
if(v.type == eVar_Double)
return RowValuesToString((int)v.columns, v.value.dv[row * v.columns + 0],
v.value.dv[row * v.columns + 1], v.value.dv[row * v.columns + 2],
v.value.dv[row * v.columns + 3]);
else if(v.type == eVar_Int)
return RowValuesToString((int)v.columns, v.value.iv[row * v.columns + 0],
v.value.iv[row * v.columns + 1], v.value.iv[row * v.columns + 2],
v.value.iv[row * v.columns + 3]);
else if(v.type == eVar_UInt)
return RowValuesToString((int)v.columns, v.value.uv[row * v.columns + 0],
v.value.uv[row * v.columns + 1], v.value.uv[row * v.columns + 2],
v.value.uv[row * v.columns + 3]);
else
return RowValuesToString((int)v.columns, v.value.fv[row * v.columns + 0],
v.value.fv[row * v.columns + 1], v.value.fv[row * v.columns + 2],
v.value.fv[row * v.columns + 3]);
}
QString VarString(const ShaderVariable &v)
{
if(v.members.count > 0)
return "";
if(v.rows == 1)
return RowString(v, 0);
QString ret = "";
for(int i = 0; i < (int)v.rows; i++)
{
if(i > 0)
ret += ", ";
ret += "{" + RowString(v, i) + "}";
}
return "{ " + ret + " }";
}
QString RowTypeString(const ShaderVariable &v)
{
if(v.members.count > 0)
{
if(v.isStruct)
return "struct";
else
return "flibbertygibbet";
}
if(v.rows == 0 && v.columns == 0)
return "-";
QString typeStr = ToQStr(v.type);
if(v.displayAsHex && v.type == eVar_UInt)
typeStr = "xint";
if(v.columns == 1)
return typeStr;
return QString("%1%2").arg(typeStr).arg(v.columns);
}
+23
View File
@@ -29,6 +29,7 @@
#include <QJsonDocument>
#include <QMenu>
#include <QMetaMethod>
#include <QTreeWidget>
QString ToQStr(const ResourceUsage usage, const GraphicsAPI apitype)
{
@@ -478,3 +479,25 @@ void addGridLines(QGridLayout *grid)
}
}
}
QTreeWidgetItem *makeTreeNode(const std::initializer_list<QVariant> &values)
{
QTreeWidgetItem *ret = new QTreeWidgetItem();
int i = 0;
for(const QVariant &v : values)
ret->setData(i++, Qt::DisplayRole, v);
return ret;
}
QTreeWidgetItem *makeTreeNode(const QVariantList &values)
{
QTreeWidgetItem *ret = new QTreeWidgetItem();
int i = 0;
for(const QVariant &v : values)
ret->setData(i++, Qt::DisplayRole, v);
return ret;
}
+47
View File
@@ -314,6 +314,48 @@ QString ToQStr(const ResourceUsage usage, const GraphicsAPI apitype);
// overload for a couple of things that need to know the pipeline type when converting
QString ToQStr(const ShaderStageType stage, const GraphicsAPI apitype);
struct FormatElement
{
FormatElement();
FormatElement(const QString &Name, int buf, uint offs, bool pi, int ir, bool rowMat, uint matDim,
ResourceFormat f, bool h);
static QList<FormatElement> ParseFormatString(const QString &formatString, uint64_t maxLen,
bool tightPacking, QString &errors);
QVariantList GetVariants(const byte *&data, const byte *end);
ShaderVariable GetShaderVar(const byte *&data, const byte *end);
QString ElementString(const QVariant &var);
uint32_t byteSize();
QString name;
int buffer;
uint32_t offset;
bool perinstance;
int instancerate;
bool rowmajor;
uint32_t matrixdim;
ResourceFormat format;
bool hex;
SystemAttribute systemValue;
};
QString TypeString(const ShaderVariable &v);
QString RowString(const ShaderVariable &v, uint32_t row);
QString VarString(const ShaderVariable &v);
QString RowTypeString(const ShaderVariable &v);
struct Formatter
{
static QString Format(float f) { return QString::number(f); }
static QString Format(double d) { return QString::number(d); }
static QString Format(uint32_t u) { return QString::number(u); }
static QString Format(uint16_t u) { return QString::number(u); }
static QString Format(int32_t i) { return QString::number(i); }
};
bool SaveToJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier, uint32_t magicVersion);
bool LoadFromJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier,
uint32_t magicVersion);
@@ -506,3 +548,8 @@ public:
class QGridLayout;
void addGridLines(QGridLayout *grid);
class QTreeWidgetItem;
QTreeWidgetItem *makeTreeNode(const std::initializer_list<QVariant> &values);
QTreeWidgetItem *makeTreeNode(const QVariantList &values);
@@ -0,0 +1,86 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "BufferFormatSpecifier.h"
#include <QFontDatabase>
#include "Code/QRDUtils.h"
#include "ui_BufferFormatSpecifier.h"
BufferFormatSpecifier::BufferFormatSpecifier(QWidget *parent)
: QWidget(parent), ui(new Ui::BufferFormatSpecifier)
{
ui->setupUi(this);
QObject::connect(ui->toggleHelp, &QPushButton::clicked, this, &BufferFormatSpecifier::toggleHelp);
setErrors("");
ui->formatText->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
}
BufferFormatSpecifier::~BufferFormatSpecifier()
{
delete ui;
}
void BufferFormatSpecifier::toggleHelp()
{
ui->helpText->setVisible(!ui->helpText->isVisible());
if(ui->helpText->isVisible())
showHelp(true);
else
showHelp(false);
}
void BufferFormatSpecifier::setErrors(const QString &errors)
{
ui->errors->setText(errors);
if(errors.isEmpty())
ui->errors->setVisible(false);
else
ui->errors->setVisible(true);
}
void BufferFormatSpecifier::showHelp(bool help)
{
ui->helpText->setVisible(help);
if(help)
{
ui->gridLayout->removeWidget(ui->formatGroup);
ui->gridLayout->addWidget(ui->formatGroup, 1, 0, 1, 3);
}
else
{
ui->gridLayout->removeWidget(ui->formatGroup);
ui->gridLayout->addWidget(ui->formatGroup, 0, 0, 2, 3);
}
}
void BufferFormatSpecifier::on_apply_clicked()
{
setErrors("");
emit processFormat(ui->formatText->toPlainText());
}
@@ -0,0 +1,56 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#pragma once
#include <QWidget>
namespace Ui
{
class BufferFormatSpecifier;
}
class BufferFormatSpecifier : public QWidget
{
Q_OBJECT
public:
explicit BufferFormatSpecifier(QWidget *parent = 0);
~BufferFormatSpecifier();
void setErrors(const QString &errors);
void showHelp(bool help);
signals:
void processFormat(const QString &format);
public slots:
void toggleHelp();
private slots:
void on_apply_clicked();
private:
Ui::BufferFormatSpecifier *ui;
};
+146
View File
@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BufferFormatSpecifier</class>
<widget class="QWidget" name="BufferFormatSpecifier">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>713</width>
<height>633</height>
</rect>
</property>
<property name="windowTitle">
<string>Buffer Format</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<property name="horizontalSpacing">
<number>0</number>
</property>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="toggleHelp">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Toggle Help</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="apply">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="helpText">
<property name="text">
<string>Type in a buffer format declaration. Comments and {} braces are skipped, : semantics are ignored.
Declare each element as an hlsl/glsl variable, e.g: &quot;float4 first; float2 second; uint2 third;&quot; or vec4/vec2.
Basic types accepted: bool, byte, short, int, half, float, double.
Unsigned integer types: ubyte, ushort, uint
Hex-formatted integer types: xbyte, xshort, xint
Additionally special formats: unorm[hb] (half, byte) and snorm[hb], and uintten/unormten (10:10:10:2 packing)
Vectors (e.g. float4), matrices ([row_major] half3x4) and arrays (float[16]) are supported.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="formatGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Format</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QTextEdit" name="formatText"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="errors">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">color: rgb(171, 32, 32);</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,263 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "ConstantBufferPreviewer.h"
#include <QFontDatabase>
#include "ui_ConstantBufferPreviewer.h"
QList<ConstantBufferPreviewer *> ConstantBufferPreviewer::m_Previews;
ConstantBufferPreviewer::ConstantBufferPreviewer(CaptureContext *ctx, const ShaderStageType stage,
uint32_t slot, uint32_t idx, QWidget *parent)
: QFrame(parent), ui(new Ui::ConstantBufferPreviewer), m_Ctx(ctx)
{
ui->setupUi(this);
m_stage = stage;
m_slot = slot;
m_arrayIdx = idx;
QObject::connect(ui->formatSpecifier, &BufferFormatSpecifier::processFormat, this,
&ConstantBufferPreviewer::processFormat);
ui->formatSpecifier->showHelp(false);
ui->splitter->setCollapsible(1, true);
ui->splitter->setSizes({1, 0});
ui->splitter->handle(1)->setEnabled(false);
{
// Name | Value | Type
ui->variables->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
ui->variables->header()->setSectionResizeMode(1, QHeaderView::Stretch);
ui->variables->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
}
ui->variables->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
m_Previews.push_back(this);
m_Ctx->AddLogViewer(this);
}
ConstantBufferPreviewer::~ConstantBufferPreviewer()
{
m_Ctx->RemoveLogViewer(this);
m_Previews.removeOne(this);
delete ui;
}
ConstantBufferPreviewer *ConstantBufferPreviewer::has(ShaderStageType stage, uint32_t slot,
uint32_t idx)
{
for(ConstantBufferPreviewer *c : m_Previews)
{
if(c->m_stage == stage && c->m_slot == slot && c->m_arrayIdx == idx)
return c;
}
return NULL;
}
void ConstantBufferPreviewer::OnLogfileLoaded()
{
OnLogfileClosed();
}
void ConstantBufferPreviewer::OnLogfileClosed()
{
ui->variables->clear();
ui->saveCSV->setEnabled(false);
}
void ConstantBufferPreviewer::OnEventSelected(uint32_t eventID)
{
uint64_t offs = 0;
uint64_t size = 0;
m_Ctx->CurPipelineState.GetConstantBuffer(m_stage, m_slot, m_arrayIdx, m_cbuffer, offs, size);
m_shader = m_Ctx->CurPipelineState.GetShader(m_stage);
QString entryPoint = m_Ctx->CurPipelineState.GetShaderEntryPoint(m_stage);
ShaderReflection *reflection = m_Ctx->CurPipelineState.GetShaderReflection(m_stage);
updateLabels();
if(reflection == NULL || reflection->ConstantBlocks.count <= (int)m_slot)
{
setVariables({});
return;
}
if(!m_formatOverride.empty())
{
m_Ctx->Renderer()->AsyncInvoke([this, offs, size](IReplayRenderer *r) {
rdctype::array<byte> data;
r->GetBufferData(m_cbuffer, offs, size, &data);
rdctype::array<ShaderVariable> vars = applyFormatOverride(data);
GUIInvoke::call([this, vars] { setVariables(vars); });
});
}
else
{
m_Ctx->Renderer()->AsyncInvoke([this, entryPoint, offs](IReplayRenderer *r) {
rdctype::array<ShaderVariable> vars;
r->GetCBufferVariableContents(m_shader, entryPoint.toUtf8().data(), m_slot, m_cbuffer, offs,
&vars);
GUIInvoke::call([this, vars] { setVariables(vars); });
});
}
}
void ConstantBufferPreviewer::on_setFormat_toggled(bool checked)
{
if(!checked)
{
ui->splitter->setCollapsible(1, true);
ui->splitter->setSizes({1, 0});
ui->splitter->handle(1)->setEnabled(false);
processFormat("");
return;
}
ui->splitter->setCollapsible(1, false);
ui->splitter->setSizes({1, 1});
ui->splitter->handle(1)->setEnabled(true);
}
void ConstantBufferPreviewer::on_saveCSV_clicked()
{
}
void ConstantBufferPreviewer::processFormat(const QString &format)
{
if(format.isEmpty())
{
m_formatOverride.clear();
ui->formatSpecifier->setErrors("");
}
else
{
QString errors;
m_formatOverride = FormatElement::ParseFormatString(format, 0, false, errors);
ui->formatSpecifier->setErrors(errors);
}
OnEventSelected(m_Ctx->CurEvent());
}
void ConstantBufferPreviewer::addVariables(QTreeWidgetItem *root,
const rdctype::array<ShaderVariable> &vars)
{
for(const ShaderVariable &v : vars)
{
QTreeWidgetItem *n = makeTreeNode({ToQStr(v.name), VarString(v), TypeString(v)});
root->addChild(n);
if(v.rows > 1)
{
for(uint32_t i = 0; i < v.rows; i++)
n->addChild(makeTreeNode(
{QString("%1.row%2").arg(ToQStr(v.name)).arg(i), RowString(v, i), RowTypeString(v)}));
}
if(v.members.count > 0)
addVariables(n, v.members);
}
}
void ConstantBufferPreviewer::setVariables(const rdctype::array<ShaderVariable> &vars)
{
ui->variables->setUpdatesEnabled(false);
ui->variables->clear();
ui->saveCSV->setEnabled(false);
if(vars.count > 0)
{
addVariables(ui->variables->invisibleRootItem(), vars);
ui->saveCSV->setEnabled(true);
}
ui->variables->setUpdatesEnabled(true);
}
void ConstantBufferPreviewer::updateLabels()
{
QString bufName = "";
bool needName = true;
FetchBuffer *buf = m_Ctx ? m_Ctx->GetBuffer(m_cbuffer) : NULL;
if(buf)
{
bufName = buf->name;
if(buf->customName)
needName = false;
}
ShaderReflection *reflection = m_Ctx ? m_Ctx->CurPipelineState.GetShaderReflection(m_stage) : NULL;
if(reflection != NULL)
{
if(needName && (int)m_slot < reflection->ConstantBlocks.count &&
reflection->ConstantBlocks[m_slot].name.count > 0)
bufName = "<" + ToQStr(reflection->ConstantBlocks[m_slot].name) + ">";
}
ui->nameLabel->setText(bufName);
GraphicsAPI pipeType = eGraphicsAPI_D3D11;
if(m_Ctx != NULL)
pipeType = m_Ctx->APIProps().pipelineType;
QString title =
QString("%1 %2 %3").arg(ToQStr(m_stage, pipeType)).arg(IsD3D(pipeType) ? "CB" : "UBO").arg(m_slot);
if(m_Ctx != NULL && m_Ctx->CurPipelineState.SupportsResourceArrays())
title += QString(" [%1]").arg(m_arrayIdx);
ui->slotLabel->setText(title);
setWindowTitle(title);
}
rdctype::array<ShaderVariable> ConstantBufferPreviewer::applyFormatOverride(
const rdctype::array<byte> &bytes)
{
QVector<ShaderVariable> variables;
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());
}
rdctype::array<ShaderVariable> ret;
ret = variables.toStdVector();
return ret;
}
@@ -0,0 +1,80 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#pragma once
#include <QFrame>
#include "Code/CaptureContext.h"
namespace Ui
{
class ConstantBufferPreviewer;
}
struct FormatElement;
class ConstantBufferPreviewer : public QFrame, public ILogViewerForm
{
Q_OBJECT
public:
explicit ConstantBufferPreviewer(CaptureContext *ctx, const ShaderStageType stage, uint32_t slot,
uint32_t idx, QWidget *parent = 0);
~ConstantBufferPreviewer();
static ConstantBufferPreviewer *has(ShaderStageType stage, uint32_t slot, uint32_t idx);
void OnLogfileLoaded();
void OnLogfileClosed();
void OnEventSelected(uint32_t eventID);
private slots:
// automatic slots
void on_setFormat_toggled(bool checked);
void on_saveCSV_clicked();
// manual slots
void processFormat(const QString &format);
private:
Ui::ConstantBufferPreviewer *ui;
CaptureContext *m_Ctx = NULL;
ResourceId m_cbuffer;
ResourceId m_shader;
ShaderStageType m_stage = eShaderStage_Vertex;
uint32_t m_slot = 0;
uint32_t m_arrayIdx = 0;
rdctype::array<ShaderVariable> applyFormatOverride(const rdctype::array<byte> &data);
void addVariables(QTreeWidgetItem *root, const rdctype::array<ShaderVariable> &vars);
void setVariables(const rdctype::array<ShaderVariable> &vars);
void updateLabels();
static QList<ConstantBufferPreviewer *> m_Previews;
QList<FormatElement> m_formatOverride;
};
@@ -0,0 +1,242 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConstantBufferPreviewer</class>
<widget class="QFrame" name="ConstantBufferPreviewer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Constant Buffer</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="toolbar">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QLabel" name="slotLabel">
<property name="text">
<string>Subresource</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="nameLabel">
<property name="text">
<string>Mip</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="setFormat">
<property name="text">
<string>{}</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextOnly</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="saveCSV">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/Resources/save.png</normaloff>:/Resources/save.png</iconset>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTreeWidget" name="variables">
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ContiguousSelection</enum>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
<column>
<property name="text">
<string>Type</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="BufferFormatSpecifier" name="formatSpecifier" native="true"/>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>BufferFormatSpecifier</class>
<extends>QWidget</extends>
<header>Widgets/BufferFormatSpecifier.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections/>
</ui>
+1
View File
@@ -36,6 +36,7 @@
#include "Windows/Dialogs/CaptureDialog.h"
#include "Windows/Dialogs/LiveCapture.h"
#include "APIInspector.h"
#include "ConstantBufferPreviewer.h"
#include "EventBrowser.h"
#include "TextureViewer.h"
#include "ui_MainWindow.h"
@@ -25,6 +25,9 @@
#include "VulkanPipelineStateViewer.h"
#include <float.h>
#include <QScrollBar>
#include "3rdparty/toolwindowmanager/ToolWindowManager.h"
#include "Windows/ConstantBufferPreviewer.h"
#include "Windows/MainWindow.h"
#include "Windows/TextureViewer.h"
#include "ui_VulkanPipelineStateViewer.h"
@@ -134,6 +137,10 @@ VulkanPipelineStateViewer::VulkanPipelineStateViewer(CaptureContext *ctx, QWidge
QObject::connect(res, &RDTreeWidget::itemActivated, this,
&VulkanPipelineStateViewer::resource_itemActivated);
for(RDTreeWidget *ubo : ubos)
QObject::connect(ubo, &RDTreeWidget::itemActivated, this,
&VulkanPipelineStateViewer::ubo_itemActivated);
addGridLines(ui->rasterizerGridLayout);
addGridLines(ui->MSAAGridLayout);
addGridLines(ui->blendStateGridLayout);
@@ -422,28 +429,6 @@ void VulkanPipelineStateViewer::setViewDetails(QTreeWidgetItem *node, const bind
}
}
QTreeWidgetItem *VulkanPipelineStateViewer::makeNode(const std::initializer_list<QVariant> &values)
{
QTreeWidgetItem *ret = new QTreeWidgetItem();
int i = 0;
for(const QVariant &v : values)
ret->setData(i++, Qt::DisplayRole, v);
return ret;
}
QTreeWidgetItem *VulkanPipelineStateViewer::makeNode(const QVariantList &values)
{
QTreeWidgetItem *ret = new QTreeWidgetItem();
int i = 0;
for(const QVariant &v : values)
ret->setData(i++, Qt::DisplayRole, v);
return ret;
}
bool VulkanPipelineStateViewer::showNode(bool usedSlot, bool filledSlot)
{
const bool showDisabled = ui->showDisabled->isChecked();
@@ -762,7 +747,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
if(arrayLength > 1)
{
QTreeWidgetItem *node =
makeNode({"", setname, slotname, tr("Array[%1]").arg(arrayLength), "", "", "", ""});
makeTreeNode({"", setname, slotname, tr("Array[%1]").arg(arrayLength), "", "", "", ""});
if(!filledSlot)
setEmptyRow(node);
@@ -864,7 +849,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
{
if(!isbuf)
{
node = makeNode({
node = makeTreeNode({
"", bindset, slotname, ToQStr(bindType), "-", "-", "",
});
@@ -876,7 +861,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
if(descriptorBind != NULL)
range = QString("%1 - %2").arg(descriptorBind->offset).arg(descriptorBind->size);
node = makeNode({
node = makeTreeNode({
"", bindset, slotname, ToQStr(bindType), name, QString("%1 bytes").arg(len), range,
});
@@ -895,7 +880,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
{
if(descriptorBind == NULL || descriptorBind->sampler == ResourceId())
{
node = makeNode({
node = makeTreeNode({
"", bindset, slotname, ToQStr(bindType), "-", "-", "",
});
@@ -903,7 +888,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
}
else
{
node = makeNode(makeSampler(QString::number(bindset), slotname, *descriptorBind));
node = makeTreeNode(makeSampler(QString::number(bindset), slotname, *descriptorBind));
if(!filledSlot)
setEmptyRow(node);
@@ -923,7 +908,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
{
if(descriptorBind == NULL || descriptorBind->res == ResourceId())
{
node = makeNode({
node = makeTreeNode({
"", bindset, slotname, ToQStr(bindType), "-", "-", "",
});
@@ -963,7 +948,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
if(restype == eResType_Texture2DMS || restype == eResType_Texture2DMSArray)
dim += QString(", %1x MSAA").arg(samples);
node = makeNode({
node = makeTreeNode({
"", bindset, slotname, typeName, name, dim, format,
});
@@ -982,7 +967,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
{
if(descriptorBind == NULL || descriptorBind->sampler == ResourceId())
{
samplerNode = makeNode({
samplerNode = makeTreeNode({
"", bindset, slotname, bindType, "-", "-", "",
});
@@ -992,7 +977,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
{
if(!samplers.contains(descriptorBind->sampler))
{
samplerNode = makeNode(makeSampler("", "", *descriptorBind));
samplerNode = makeTreeNode(makeSampler("", "", *descriptorBind));
if(!filledSlot)
setEmptyRow(samplerNode);
@@ -1111,7 +1096,7 @@ void VulkanPipelineStateViewer::addConstantBlockRow(ShaderReflection *shaderDeta
if(arrayLength > 1)
{
QTreeWidgetItem *node =
makeNode({"", setname, slotname, tr("Array[%1]").arg(arrayLength), "", ""});
makeTreeNode({"", setname, slotname, tr("Array[%1]").arg(arrayLength), "", ""});
if(!filledSlot)
setEmptyRow(node);
@@ -1192,7 +1177,7 @@ void VulkanPipelineStateViewer::addConstantBlockRow(ShaderReflection *shaderDeta
filledSlot = false;
}
QTreeWidgetItem *node = makeNode({"", setname, slotname, name, vecrange, sizestr});
QTreeWidgetItem *node = makeTreeNode({"", setname, slotname, name, vecrange, sizestr});
ubos->setHoverIcons(node, action, action_hover);
@@ -1393,8 +1378,8 @@ void VulkanPipelineStateViewer::setShaderState(const VulkanPipelineState::Shader
// could maybe get range from ShaderVariable.reg if it's filled out
// from SPIR-V side.
QTreeWidgetItem *node = makeNode({"", "", ToQStr(cblock.name), "Push constants", "",
tr("%1 Variable(s)", "", cblock.variables.count)});
QTreeWidgetItem *node = makeTreeNode({"", "", ToQStr(cblock.name), "Push constants", "",
tr("%1 Variable(s)", "", cblock.variables.count)});
ubos->setHoverIcons(node, action, action_hover);
node->setData(0, Qt::UserRole, QVariant::fromValue(CBufferTag(cb, 0)));
@@ -1465,7 +1450,7 @@ void VulkanPipelineStateViewer::setState()
if(showNode(usedSlot, filledSlot))
{
QTreeWidgetItem *node =
makeNode({i, name, a.location, a.binding, ToQStr(a.format.strname), a.byteoffset});
makeTreeNode({i, name, a.location, a.binding, ToQStr(a.format.strname), a.byteoffset});
usedBindings[a.binding] = true;
@@ -1569,8 +1554,8 @@ void VulkanPipelineStateViewer::setState()
length = buf->length;
}
QTreeWidgetItem *node = makeNode({"Index", name, "Index", (qulonglong)state.IA.ibuffer.offs,
draw->indexByteWidth, (qulonglong)length, ""});
QTreeWidgetItem *node = makeTreeNode({"Index", name, "Index", (qulonglong)state.IA.ibuffer.offs,
draw->indexByteWidth, (qulonglong)length, ""});
ui->viBuffers->setHoverIcons(node, action, action_hover);
@@ -1591,7 +1576,8 @@ void VulkanPipelineStateViewer::setState()
{
if(ibufferUsed || showEmpty)
{
QTreeWidgetItem *node = makeNode({"Index", tr("No Buffer Set"), "Index", "-", "-", "-", ""});
QTreeWidgetItem *node =
makeTreeNode({"Index", tr("No Buffer Set"), "Index", "-", "-", "-", ""});
ui->viBuffers->setHoverIcons(node, action, action_hover);
@@ -1661,9 +1647,9 @@ void VulkanPipelineStateViewer::setState()
QTreeWidgetItem *node = NULL;
if(filledSlot)
node = makeNode({i, name, rate, (qulonglong)offset, stride, (qulonglong)length, ""});
node = makeTreeNode({i, name, rate, (qulonglong)offset, stride, (qulonglong)length, ""});
else
node = makeNode({i, tr("No Binding"), "-", "-", "-", "-", ""});
node = makeTreeNode({i, tr("No Binding"), "-", "-", "-", "-", ""});
ui->viBuffers->setHoverIcons(node, action, action_hover);
@@ -1687,7 +1673,7 @@ void VulkanPipelineStateViewer::setState()
{
if(usedBindings[i])
{
QTreeWidgetItem *node = makeNode({i, tr("No Binding"), "-", "-", "-", "-", ""});
QTreeWidgetItem *node = makeTreeNode({i, tr("No Binding"), "-", "-", "-", "-", ""});
ui->viBuffers->setHoverIcons(node, action, action_hover);
@@ -1728,8 +1714,8 @@ void VulkanPipelineStateViewer::setState()
if(state.Pass.renderpass.obj != ResourceId())
{
ui->scissors->addTopLevelItem(
makeNode({"Render Area", state.Pass.renderArea.x, state.Pass.renderArea.y,
state.Pass.renderArea.width, state.Pass.renderArea.height}));
makeTreeNode({"Render Area", state.Pass.renderArea.x, state.Pass.renderArea.y,
state.Pass.renderArea.width, state.Pass.renderArea.height}));
}
{
@@ -1737,13 +1723,13 @@ void VulkanPipelineStateViewer::setState()
for(const VulkanPipelineState::ViewState::ViewportScissor &v : state.VP.viewportScissors)
{
QTreeWidgetItem *node =
makeNode({i, v.vp.x, v.vp.y, v.vp.width, v.vp.height, v.vp.minDepth, v.vp.maxDepth});
makeTreeNode({i, v.vp.x, v.vp.y, v.vp.width, v.vp.height, v.vp.minDepth, v.vp.maxDepth});
ui->viewports->addTopLevelItem(node);
if(v.vp.width == 0 || v.vp.height == 0)
setEmptyRow(node);
node = makeNode({i, v.scissor.x, v.scissor.y, v.scissor.width, v.scissor.height});
node = makeTreeNode({i, v.scissor.x, v.scissor.y, v.scissor.width, v.scissor.height});
ui->scissors->addTopLevelItem(node);
if(v.scissor.width == 0 || v.scissor.height == 0)
@@ -1854,7 +1840,7 @@ void VulkanPipelineStateViewer::setState()
.arg(ToQStr(p.swizzle[3]));
}
QTreeWidgetItem *node = makeNode({i, name, typeName, w, h, d, a, format, ""});
QTreeWidgetItem *node = makeTreeNode({i, name, typeName, w, h, d, a, format, ""});
ui->framebuffer->setHoverIcons(node, action, action_hover);
@@ -1900,19 +1886,19 @@ void VulkanPipelineStateViewer::setState()
if(showNode(usedSlot, filledSlot))
{
QTreeWidgetItem *node =
makeNode({i, blend.blendEnable,
makeTreeNode({i, blend.blendEnable,
ToQStr(blend.blend.Source), ToQStr(blend.blend.Destination),
ToQStr(blend.blend.Operation),
ToQStr(blend.blend.Source), ToQStr(blend.blend.Destination),
ToQStr(blend.blend.Operation),
ToQStr(blend.alphaBlend.Source), ToQStr(blend.alphaBlend.Destination),
ToQStr(blend.alphaBlend.Operation),
ToQStr(blend.alphaBlend.Source), ToQStr(blend.alphaBlend.Destination),
ToQStr(blend.alphaBlend.Operation),
QString("%1%2%3%4")
.arg((blend.writeMask & 0x1) == 0 ? "_" : "R")
.arg((blend.writeMask & 0x2) == 0 ? "_" : "G")
.arg((blend.writeMask & 0x4) == 0 ? "_" : "B")
.arg((blend.writeMask & 0x8) == 0 ? "_" : "A")});
QString("%1%2%3%4")
.arg((blend.writeMask & 0x1) == 0 ? "_" : "R")
.arg((blend.writeMask & 0x2) == 0 ? "_" : "G")
.arg((blend.writeMask & 0x4) == 0 ? "_" : "B")
.arg((blend.writeMask & 0x8) == 0 ? "_" : "A")});
if(!filledSlot)
setEmptyRow(node);
@@ -1959,21 +1945,21 @@ void VulkanPipelineStateViewer::setState()
if(state.DS.stencilTestEnable)
{
ui->stencils->addTopLevelItems(
{makeNode({"Front", ToQStr(state.DS.front.func), ToQStr(state.DS.front.failOp),
ToQStr(state.DS.front.depthFailOp), ToQStr(state.DS.front.passOp),
QString("%1").arg(state.DS.front.writeMask, 2, 16, QChar('0')),
QString("%1").arg(state.DS.front.compareMask, 2, 16, QChar('0')),
QString("%1").arg(state.DS.front.ref, 2, 16, QChar('0'))}),
makeNode({"Back", ToQStr(state.DS.back.func), ToQStr(state.DS.back.failOp),
ToQStr(state.DS.back.depthFailOp), ToQStr(state.DS.back.passOp),
QString("%1").arg(state.DS.back.writeMask, 2, 16, QChar('0')),
QString("%1").arg(state.DS.back.compareMask, 2, 16, QChar('0')),
QString("%1").arg(state.DS.back.ref, 2, 16, QChar('0'))})});
{makeTreeNode({"Front", ToQStr(state.DS.front.func), ToQStr(state.DS.front.failOp),
ToQStr(state.DS.front.depthFailOp), ToQStr(state.DS.front.passOp),
QString("%1").arg(state.DS.front.writeMask, 2, 16, QChar('0')),
QString("%1").arg(state.DS.front.compareMask, 2, 16, QChar('0')),
QString("%1").arg(state.DS.front.ref, 2, 16, QChar('0'))}),
makeTreeNode({"Back", ToQStr(state.DS.back.func), ToQStr(state.DS.back.failOp),
ToQStr(state.DS.back.depthFailOp), ToQStr(state.DS.back.passOp),
QString("%1").arg(state.DS.back.writeMask, 2, 16, QChar('0')),
QString("%1").arg(state.DS.back.compareMask, 2, 16, QChar('0')),
QString("%1").arg(state.DS.back.ref, 2, 16, QChar('0'))})});
}
else
{
ui->stencils->addTopLevelItems({makeNode({"Front", "-", "-", "-", "-", "-", "-", "-"}),
makeNode({"Back", "-", "-", "-", "-", "-", "-", "-"})});
ui->stencils->addTopLevelItems({makeTreeNode({"Front", "-", "-", "-", "-", "-", "-", "-"}),
makeTreeNode({"Back", "-", "-", "-", "-", "-", "-", "-"})});
}
ui->stencils->clearSelection();
ui->stencils->setUpdatesEnabled(true);
@@ -2134,6 +2120,37 @@ void VulkanPipelineStateViewer::resource_itemActivated(QTreeWidgetItem *item, in
}
}
void VulkanPipelineStateViewer::ubo_itemActivated(QTreeWidgetItem *item, int column)
{
const VulkanPipelineState::ShaderStage *stage = stageForSender(item->treeWidget());
if(stage == NULL)
return;
QVariant tag = item->data(0, Qt::UserRole);
if(!tag.canConvert<CBufferTag>())
return;
CBufferTag cb = tag.value<CBufferTag>();
ConstantBufferPreviewer *existing =
ConstantBufferPreviewer::has(stage->stage, cb.slotIdx, cb.arrayIdx);
if(existing != NULL)
{
ToolWindowManager::raiseToolWindow(existing);
return;
}
ConstantBufferPreviewer *prev =
new ConstantBufferPreviewer(m_Ctx, stage->stage, cb.slotIdx, cb.arrayIdx, m_Ctx->mainWindow());
ToolWindowManager *manager = ToolWindowManager::managerOf(this);
ToolWindowManager::AreaReference ref(ToolWindowManager::RightOf, manager->areaOf(this), 0.3f);
manager->addToolWindow(prev, ref);
}
void VulkanPipelineStateViewer::on_viAttrs_itemActivated(QTreeWidgetItem *item, int column)
{
// TODO Buffer Viewer
@@ -70,6 +70,7 @@ private slots:
void shaderEdit_clicked();
void shaderSave_clicked();
void resource_itemActivated(QTreeWidgetItem *item, int column);
void ubo_itemActivated(QTreeWidgetItem *item, int column);
void vertex_leave(QEvent *e);
private:
@@ -107,8 +108,6 @@ private:
template <typename viewType>
void setViewDetails(QTreeWidgetItem *node, const viewType &view, FetchBuffer *buf);
QTreeWidgetItem *makeNode(const std::initializer_list<QVariant> &values);
QTreeWidgetItem *makeNode(const QVariantList &values);
bool showNode(bool usedSlot, bool filledSlot);
// keep track of the VB nodes (we want to be able to highlight them easily on hover)
+10 -3
View File
@@ -117,7 +117,10 @@ SOURCES += 3rdparty/toolwindowmanager/ToolWindowManager.cpp \
Windows/PipelineState/D3D11PipelineStateViewer.cpp \
Windows/PipelineState/D3D12PipelineStateViewer.cpp \
Windows/PipelineState/GLPipelineStateViewer.cpp \
Widgets/Extended/RDTreeWidget.cpp
Widgets/Extended/RDTreeWidget.cpp \
Windows/ConstantBufferPreviewer.cpp \
Widgets/BufferFormatSpecifier.cpp \
Code/FormatElement.cpp
HEADERS += 3rdparty/toolwindowmanager/ToolWindowManager.h \
3rdparty/toolwindowmanager/ToolWindowManagerArea.h \
@@ -152,7 +155,9 @@ HEADERS += 3rdparty/toolwindowmanager/ToolWindowManager.h \
Windows/PipelineState/D3D11PipelineStateViewer.h \
Windows/PipelineState/D3D12PipelineStateViewer.h \
Windows/PipelineState/GLPipelineStateViewer.h \
Widgets/Extended/RDTreeWidget.h
Widgets/Extended/RDTreeWidget.h \
Windows/ConstantBufferPreviewer.h \
Widgets/BufferFormatSpecifier.h
FORMS += Windows/Dialogs/AboutDialog.ui \
Windows/MainWindow.ui \
@@ -168,7 +173,9 @@ FORMS += Windows/Dialogs/AboutDialog.ui \
Windows/PipelineState/VulkanPipelineStateViewer.ui \
Windows/PipelineState/D3D11PipelineStateViewer.ui \
Windows/PipelineState/D3D12PipelineStateViewer.ui \
Windows/PipelineState/GLPipelineStateViewer.ui
Windows/PipelineState/GLPipelineStateViewer.ui \
Windows/ConstantBufferPreviewer.ui \
Widgets/BufferFormatSpecifier.ui
RESOURCES += \
resources.qrc
+11
View File
@@ -281,12 +281,15 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Code\CommonPipelineState.cpp" />
<ClCompile Include="Code\FormatElement.cpp" />
<ClCompile Include="Code\PersistantConfig.cpp" />
<ClCompile Include="Code\qprocessinfo.cpp" />
<ClCompile Include="Code\QRDUtils.cpp" />
<ClCompile Include="generated\moc_AboutDialog.cpp" />
<ClCompile Include="generated\moc_APIInspector.cpp" />
<ClCompile Include="generated\moc_BufferFormatSpecifier.cpp" />
<ClCompile Include="generated\moc_CaptureDialog.cpp" />
<ClCompile Include="generated\moc_ConstantBufferPreviewer.cpp" />
<ClCompile Include="generated\moc_CustomPaintWidget.cpp" />
<ClCompile Include="generated\moc_D3D11PipelineStateViewer.cpp" />
<ClCompile Include="generated\moc_D3D12PipelineStateViewer.cpp" />
@@ -313,6 +316,7 @@
<ClCompile Include="generated\moc_ToolWindowManagerWrapper.cpp" />
<ClCompile Include="generated\moc_VulkanPipelineStateViewer.cpp" />
<ClCompile Include="generated\qrc_resources.cpp" />
<ClCompile Include="Widgets\BufferFormatSpecifier.cpp" />
<ClCompile Include="Widgets\Extended\RDListWidget.cpp" />
<ClCompile Include="Widgets\Extended\RDTreeWidget.cpp" />
<ClCompile Include="Widgets\RangeHistogram.cpp" />
@@ -325,6 +329,7 @@
<ClCompile Include="Code\CaptureContext.cpp" />
<ClCompile Include="Widgets\CustomPaintWidget.cpp" />
<ClCompile Include="Windows\APIInspector.cpp" />
<ClCompile Include="Windows\ConstantBufferPreviewer.cpp" />
<ClCompile Include="Windows\Dialogs\AboutDialog.cpp" />
<ClCompile Include="Windows\Dialogs\CaptureDialog.cpp" />
<ClCompile Include="Windows\Dialogs\LiveCapture.cpp" />
@@ -360,7 +365,9 @@
<ClInclude Include="Code\QRDUtils.h" />
<ClInclude Include="generated\ui_AboutDialog.h" />
<ClInclude Include="generated\ui_APIInspector.h" />
<ClInclude Include="generated\ui_BufferFormatSpecifier.h" />
<ClInclude Include="generated\ui_CaptureDialog.h" />
<ClInclude Include="generated\ui_ConstantBufferPreviewer.h" />
<ClInclude Include="generated\ui_D3D11PipelineStateViewer.h" />
<ClInclude Include="generated\ui_D3D12PipelineStateViewer.h" />
<ClInclude Include="generated\ui_EventBrowser.h" />
@@ -374,6 +381,7 @@
<ClInclude Include="generated\ui_ThumbnailStrip.h" />
<ClInclude Include="generated\ui_VulkanPipelineStateViewer.h" />
<ClInclude Include="Resources\resource.h" />
<ClInclude Include="Widgets\BufferFormatSpecifier.h" />
<ClInclude Include="Widgets\Extended\RDListWidget.h" />
<ClInclude Include="Widgets\Extended\RDTreeWidget.h" />
<ClInclude Include="Widgets\RangeHistogram.h" />
@@ -386,6 +394,7 @@
<ClInclude Include="Code\CaptureContext.h" />
<ClInclude Include="Widgets\CustomPaintWidget.h" />
<ClInclude Include="Windows\APIInspector.h" />
<ClInclude Include="Windows\ConstantBufferPreviewer.h" />
<ClInclude Include="Windows\Dialogs\AboutDialog.h" />
<ClInclude Include="Windows\Dialogs\CaptureDialog.h" />
<ClInclude Include="Windows\Dialogs\LiveCapture.h" />
@@ -406,9 +415,11 @@
<ClInclude Include="3rdparty\toolwindowmanager\ToolWindowManagerWrapper.h" />
</ItemGroup>
<ItemGroup>
<None Include="Widgets\BufferFormatSpecifier.ui" />
<None Include="Widgets\ResourcePreview.ui" />
<None Include="Widgets\ThumbnailStrip.ui" />
<None Include="Windows\APIInspector.ui" />
<None Include="Windows\ConstantBufferPreviewer.ui" />
<None Include="Windows\Dialogs\AboutDialog.ui" />
<None Include="Windows\Dialogs\CaptureDialog.ui" />
<None Include="Windows\Dialogs\LiveCapture.ui" />
@@ -238,6 +238,21 @@
<ClCompile Include="generated\moc_RDTreeWidget.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="Windows\ConstantBufferPreviewer.cpp">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="Widgets\BufferFormatSpecifier.cpp">
<Filter>Widgets</Filter>
</ClCompile>
<ClCompile Include="generated\moc_BufferFormatSpecifier.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="generated\moc_ConstantBufferPreviewer.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="Code\FormatElement.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="3rdparty\flowlayout\FlowLayout.h">
@@ -378,6 +393,18 @@
<ClInclude Include="Widgets\Extended\RDTreeWidget.h">
<Filter>Widgets\Extended</Filter>
</ClInclude>
<ClInclude Include="Windows\ConstantBufferPreviewer.h">
<Filter>Windows</Filter>
</ClInclude>
<ClInclude Include="Widgets\BufferFormatSpecifier.h">
<Filter>Widgets</Filter>
</ClInclude>
<ClInclude Include="generated\ui_ConstantBufferPreviewer.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="generated\ui_BufferFormatSpecifier.h">
<Filter>Generated Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="resources.qrc">
@@ -602,6 +629,12 @@
<None Include="Resources\action.png">
<Filter>Resources\Files</Filter>
</None>
<None Include="Windows\ConstantBufferPreviewer.ui">
<Filter>Windows</Filter>
</None>
<None Include="Widgets\BufferFormatSpecifier.ui">
<Filter>Widgets</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="generated\ui_AboutDialog.h">