mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-11-14 01:41:10 +00:00
Centralise generation of buffer format strings for struct buffers
* We also fix a number of issues that could cause incorrect formats to be generated. * Test cases added for D3D11/GL/Vulkan to test different struct types. These aren't automated at the moment because most of the code they're testing is in the UI itself.
This commit is contained in:
18 files changed
+1134
-547
No files matched your search
@@ -484,13 +484,49 @@ QString FormatElement::GenerateTextureBufferFormat(const TextureDescription &tex
|
||||
case ResourceFormatType::Regular:
|
||||
{
|
||||
if(tex.format.compByteWidth == 1)
|
||||
baseType = lit("byte");
|
||||
{
|
||||
if(tex.format.compType == CompType::UNorm)
|
||||
baseType = lit("unormb");
|
||||
else if(tex.format.compType == CompType::SNorm)
|
||||
baseType = lit("snormb");
|
||||
else if(tex.format.compType == CompType::SInt)
|
||||
baseType = lit("byte");
|
||||
else
|
||||
baseType = lit("ubyte");
|
||||
}
|
||||
else if(tex.format.compByteWidth == 2)
|
||||
baseType = lit("short");
|
||||
{
|
||||
if(tex.format.compType == CompType::UNorm)
|
||||
baseType = lit("unormh");
|
||||
else if(tex.format.compType == CompType::SNorm)
|
||||
baseType = lit("snormh");
|
||||
else if(tex.format.compType == CompType::Float)
|
||||
baseType = lit("half");
|
||||
else if(tex.format.compType == CompType::SInt)
|
||||
baseType = lit("short");
|
||||
else
|
||||
baseType = lit("ushort");
|
||||
}
|
||||
else if(tex.format.compByteWidth == 4)
|
||||
{
|
||||
if(tex.format.compType == CompType::Float)
|
||||
baseType = lit("float");
|
||||
else if(tex.format.compType == CompType::SInt)
|
||||
baseType = lit("int");
|
||||
else
|
||||
baseType = lit("uint");
|
||||
}
|
||||
else
|
||||
baseType = lit("int");
|
||||
{
|
||||
if(tex.format.compType == CompType::Float || tex.format.compType == CompType::Double)
|
||||
baseType = lit("double");
|
||||
else if(tex.format.compType == CompType::SInt)
|
||||
baseType = lit("long");
|
||||
else
|
||||
baseType = lit("ulong");
|
||||
}
|
||||
|
||||
baseType = QFormatStr("rgb x%1%2").arg(baseType).arg(tex.format.compCount);
|
||||
baseType = QFormatStr("rgb %1%2").arg(baseType).arg(tex.format.compCount);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1923,46 +1923,6 @@ void D3D11PipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
|
||||
QString D3D11PipelineStateViewer::formatMembers(int indent, const QString &nameprefix,
|
||||
const rdcarray<ShaderConstant> &vars)
|
||||
{
|
||||
QString indentstr(indent * 4, QLatin1Char(' '));
|
||||
|
||||
QString ret;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(const ShaderConstant &v : vars)
|
||||
{
|
||||
if(!v.type.members.empty())
|
||||
{
|
||||
if(i > 0)
|
||||
ret += lit("\n");
|
||||
ret += indentstr + lit("// struct %1\n").arg(v.type.descriptor.name);
|
||||
ret += indentstr + lit("{\n") + formatMembers(indent + 1, v.name + lit("_"), v.type.members) +
|
||||
indentstr + lit("}\n");
|
||||
if(i < vars.count() - 1)
|
||||
ret += lit("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
QString arr;
|
||||
if(v.type.descriptor.elements > 1)
|
||||
arr = QFormatStr("[%1]").arg(v.type.descriptor.elements);
|
||||
ret += QFormatStr("%1%2 %3%4%5;\n")
|
||||
.arg(indentstr)
|
||||
.arg(v.type.descriptor.name)
|
||||
.arg(nameprefix)
|
||||
.arg(v.name)
|
||||
.arg(arr);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3D11PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int column)
|
||||
{
|
||||
const D3D11Pipe::Shader *stage = stageForSender(item->treeWidget());
|
||||
@@ -2102,103 +2062,10 @@ void D3D11PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
|
||||
|
||||
if(shaderRes)
|
||||
{
|
||||
const ShaderResource &res = *shaderRes;
|
||||
format = m_Common.GenerateBufferFormatter(*shaderRes, view.res.viewFormat, offs);
|
||||
|
||||
if(!res.variableType.members.empty())
|
||||
{
|
||||
format = lit("// struct %1\n{\n%2}")
|
||||
.arg(res.variableType.descriptor.name)
|
||||
.arg(formatMembers(1, QString(), res.variableType.members));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &desc = res.variableType.descriptor;
|
||||
|
||||
if(view.res.viewFormat.type == ResourceFormatType::Undefined)
|
||||
{
|
||||
format = QString();
|
||||
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
|
||||
{
|
||||
const ResourceFormat &fmt = view.res.viewFormat;
|
||||
if(fmt.type == ResourceFormatType::R10G10B10A2)
|
||||
{
|
||||
if(fmt.compType == CompType::UInt)
|
||||
format = lit("uintten");
|
||||
if(fmt.compType == CompType::UNorm)
|
||||
format = lit("unormten");
|
||||
}
|
||||
else if(fmt.type == ResourceFormatType::R11G11B10)
|
||||
{
|
||||
format = lit("floateleven");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(fmt.compByteWidth)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if(fmt.compType == CompType::UNorm)
|
||||
format = lit("unormb");
|
||||
if(fmt.compType == CompType::SNorm)
|
||||
format = lit("snormb");
|
||||
if(fmt.compType == CompType::UInt)
|
||||
format = lit("ubyte");
|
||||
if(fmt.compType == CompType::SInt)
|
||||
format = lit("byte");
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if(fmt.compType == CompType::UNorm)
|
||||
format = lit("unormh");
|
||||
if(fmt.compType == CompType::SNorm)
|
||||
format = lit("snormh");
|
||||
if(fmt.compType == CompType::UInt)
|
||||
format = lit("ushort");
|
||||
if(fmt.compType == CompType::SInt)
|
||||
format = lit("short");
|
||||
if(fmt.compType == CompType::Float)
|
||||
format = lit("half");
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
if(fmt.compType == CompType::UNorm)
|
||||
format = lit("unormf");
|
||||
if(fmt.compType == CompType::SNorm)
|
||||
format = lit("snormf");
|
||||
if(fmt.compType == CompType::UInt)
|
||||
format = lit("uint");
|
||||
if(fmt.compType == CompType::SInt)
|
||||
format = lit("int");
|
||||
if(fmt.compType == CompType::Float)
|
||||
format = lit("float");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(view.res.bufferFlags & D3DBufferViewFlags::Raw)
|
||||
format = lit("xint");
|
||||
|
||||
format += QString::number(fmt.compCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(view.res.bufferFlags & D3DBufferViewFlags::Raw)
|
||||
format = lit("xint");
|
||||
}
|
||||
|
||||
IBufferViewer *viewer = m_Ctx.ViewBuffer(offs, size, view.res.resourceResourceId, format);
|
||||
|
||||
@@ -104,7 +104,6 @@ private:
|
||||
void setEmptyRow(RDTreeWidgetItem *node);
|
||||
void highlightIABind(int slot);
|
||||
|
||||
QString formatMembers(int indent, const QString &nameprefix, const rdcarray<ShaderConstant> &vars);
|
||||
const D3D11Pipe::Shader *stageForSender(QWidget *widget);
|
||||
|
||||
bool HasImportantViewParams(const D3D11Pipe::View &view, TextureDescription *tex);
|
||||
|
||||
@@ -1809,46 +1809,6 @@ void D3D12PipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
|
||||
QString D3D12PipelineStateViewer::formatMembers(int indent, const QString &nameprefix,
|
||||
const rdcarray<ShaderConstant> &vars)
|
||||
{
|
||||
QString indentstr(indent * 4, QLatin1Char(' '));
|
||||
|
||||
QString ret;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(const ShaderConstant &v : vars)
|
||||
{
|
||||
if(!v.type.members.empty())
|
||||
{
|
||||
if(i > 0)
|
||||
ret += lit("\n");
|
||||
ret += indentstr + lit("// struct %1\n").arg(v.type.descriptor.name);
|
||||
ret += indentstr + lit("{\n") + formatMembers(indent + 1, v.name + lit("_"), v.type.members) +
|
||||
indentstr + lit("}\n");
|
||||
if(i < vars.count() - 1)
|
||||
ret += lit("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
QString arr;
|
||||
if(v.type.descriptor.elements > 1)
|
||||
arr = QFormatStr("[%1]").arg(v.type.descriptor.elements);
|
||||
ret += QFormatStr("%1%2 %3%4%5;\n")
|
||||
.arg(indentstr)
|
||||
.arg(v.type.descriptor.name)
|
||||
.arg(nameprefix)
|
||||
.arg(v.name)
|
||||
.arg(arr);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void D3D12PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int column)
|
||||
{
|
||||
const D3D12Pipe::Shader *stage = stageForSender(item->treeWidget());
|
||||
@@ -1954,103 +1914,10 @@ void D3D12PipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, in
|
||||
|
||||
if(shaderRes)
|
||||
{
|
||||
const ShaderResource &res = *shaderRes;
|
||||
format = m_Common.GenerateBufferFormatter(*shaderRes, view.res.viewFormat, offs);
|
||||
|
||||
if(!res.variableType.members.empty())
|
||||
{
|
||||
format = QFormatStr("// struct %1\n{\n%2}")
|
||||
.arg(res.variableType.descriptor.name)
|
||||
.arg(formatMembers(1, QString(), res.variableType.members));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &desc = res.variableType.descriptor;
|
||||
|
||||
if(view.res.viewFormat.type == ResourceFormatType::Undefined)
|
||||
{
|
||||
format = QString();
|
||||
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
|
||||
{
|
||||
const ResourceFormat &fmt = view.res.viewFormat;
|
||||
if(fmt.type == ResourceFormatType::R10G10B10A2)
|
||||
{
|
||||
if(fmt.compType == CompType::UInt)
|
||||
format = lit("uintten");
|
||||
if(fmt.compType == CompType::UNorm)
|
||||
format = lit("unormten");
|
||||
}
|
||||
else if(fmt.type == ResourceFormatType::R11G11B10)
|
||||
{
|
||||
format = lit("floateleven");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(fmt.compByteWidth)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if(fmt.compType == CompType::UNorm)
|
||||
format = lit("unormb");
|
||||
if(fmt.compType == CompType::SNorm)
|
||||
format = lit("snormb");
|
||||
if(fmt.compType == CompType::UInt)
|
||||
format = lit("ubyte");
|
||||
if(fmt.compType == CompType::SInt)
|
||||
format = lit("byte");
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if(fmt.compType == CompType::UNorm)
|
||||
format = lit("unormh");
|
||||
if(fmt.compType == CompType::SNorm)
|
||||
format = lit("snormh");
|
||||
if(fmt.compType == CompType::UInt)
|
||||
format = lit("ushort");
|
||||
if(fmt.compType == CompType::SInt)
|
||||
format = lit("short");
|
||||
if(fmt.compType == CompType::Float)
|
||||
format = lit("half");
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
if(fmt.compType == CompType::UNorm)
|
||||
format = lit("unormf");
|
||||
if(fmt.compType == CompType::SNorm)
|
||||
format = lit("snormf");
|
||||
if(fmt.compType == CompType::UInt)
|
||||
format = lit("uint");
|
||||
if(fmt.compType == CompType::SInt)
|
||||
format = lit("int");
|
||||
if(fmt.compType == CompType::Float)
|
||||
format = lit("float");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(view.res.bufferFlags & D3DBufferViewFlags::Raw)
|
||||
format = lit("xint");
|
||||
|
||||
format += QString::number(fmt.compCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(view.res.bufferFlags & D3DBufferViewFlags::Raw)
|
||||
format = lit("xint");
|
||||
}
|
||||
|
||||
IBufferViewer *viewer = m_Ctx.ViewBuffer(offs, size, view.res.resourceId, format);
|
||||
|
||||
@@ -2117,46 +2117,6 @@ void GLPipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
|
||||
QString GLPipelineStateViewer::formatMembers(int indent, const QString &nameprefix,
|
||||
const rdcarray<ShaderConstant> &vars)
|
||||
{
|
||||
QString indentstr(indent * 4, QLatin1Char(' '));
|
||||
|
||||
QString ret;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(const ShaderConstant &v : vars)
|
||||
{
|
||||
if(!v.type.members.empty())
|
||||
{
|
||||
if(i > 0)
|
||||
ret += lit("\n");
|
||||
ret += indentstr + QFormatStr("// struct %1\n").arg(v.type.descriptor.name);
|
||||
ret += indentstr + lit("{\n") + formatMembers(indent + 1, v.name + lit("_"), v.type.members) +
|
||||
indentstr + lit("}\n");
|
||||
if(i < vars.count() - 1)
|
||||
ret += lit("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
QString arr;
|
||||
if(v.type.descriptor.elements > 1)
|
||||
arr = QFormatStr("[%1]").arg(v.type.descriptor.elements);
|
||||
ret += QFormatStr("%1%2 %3%4%5;\n")
|
||||
.arg(indentstr)
|
||||
.arg(v.type.descriptor.name)
|
||||
.arg(nameprefix)
|
||||
.arg(v.name)
|
||||
.arg(arr);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void GLPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int column)
|
||||
{
|
||||
const GLPipe::Shader *stage = stageForSender(item->treeWidget());
|
||||
@@ -2196,43 +2156,7 @@ void GLPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int c
|
||||
|
||||
const ShaderResource &shaderRes = stage->reflection->readWriteResources[buf.bindPoint];
|
||||
|
||||
QString format = lit("// struct %1\n").arg(shaderRes.variableType.descriptor.name);
|
||||
|
||||
if(shaderRes.variableType.members.count() > 1)
|
||||
{
|
||||
format += tr("// members skipped as they are fixed size:\n");
|
||||
for(int i = 0; i < shaderRes.variableType.members.count() - 1; i++)
|
||||
format += QFormatStr("// %1 %2;\n")
|
||||
.arg(shaderRes.variableType.members[i].type.descriptor.name)
|
||||
.arg(shaderRes.variableType.members[i].name);
|
||||
}
|
||||
|
||||
if(!shaderRes.variableType.members.empty())
|
||||
{
|
||||
format += lit("{\n") +
|
||||
formatMembers(1, QString(), shaderRes.variableType.members.back().type.members) +
|
||||
lit("}");
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &desc = shaderRes.variableType.descriptor;
|
||||
|
||||
format = QString();
|
||||
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);
|
||||
}
|
||||
QString format = m_Common.GenerateBufferFormatter(shaderRes, ResourceFormat(), buf.offset);
|
||||
|
||||
if(buf.ID != ResourceId())
|
||||
{
|
||||
|
||||
@@ -39,6 +39,71 @@
|
||||
#include "VulkanPipelineStateViewer.h"
|
||||
#include "ui_PipelineStateViewer.h"
|
||||
|
||||
static uint32_t byteSize(const ResourceFormat &fmt)
|
||||
{
|
||||
if(fmt.Special())
|
||||
{
|
||||
switch(fmt.type)
|
||||
{
|
||||
default:
|
||||
case ResourceFormatType::R9G9B9E5:
|
||||
case ResourceFormatType::R5G6B5:
|
||||
case ResourceFormatType::R5G5B5A1:
|
||||
case ResourceFormatType::R4G4B4A4:
|
||||
case ResourceFormatType::R4G4:
|
||||
case ResourceFormatType::BC1:
|
||||
case ResourceFormatType::BC2:
|
||||
case ResourceFormatType::BC3:
|
||||
case ResourceFormatType::BC4:
|
||||
case ResourceFormatType::BC5:
|
||||
case ResourceFormatType::BC6:
|
||||
case ResourceFormatType::BC7:
|
||||
case ResourceFormatType::ETC2:
|
||||
case ResourceFormatType::EAC:
|
||||
case ResourceFormatType::ASTC:
|
||||
case ResourceFormatType::D16S8:
|
||||
case ResourceFormatType::D24S8:
|
||||
case ResourceFormatType::D32S8:
|
||||
case ResourceFormatType::S8:
|
||||
case ResourceFormatType::YUV8:
|
||||
case ResourceFormatType::YUV10:
|
||||
case ResourceFormatType::YUV12:
|
||||
case ResourceFormatType::YUV16:
|
||||
case ResourceFormatType::PVRTC: return ~0U;
|
||||
case ResourceFormatType::R10G10B10A2:
|
||||
case ResourceFormatType::R11G11B10: return 4;
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.compByteWidth * fmt.compCount;
|
||||
}
|
||||
|
||||
static QString padding(uint32_t bytes)
|
||||
{
|
||||
if(bytes == 0)
|
||||
return QString();
|
||||
|
||||
QString ret;
|
||||
|
||||
if(bytes > 4)
|
||||
{
|
||||
ret += lit("xint pad[%1];").arg(bytes / 4);
|
||||
|
||||
bytes = bytes % 4;
|
||||
}
|
||||
|
||||
if(bytes == 4)
|
||||
ret += lit("xint pad;");
|
||||
else if(bytes == 3)
|
||||
ret += lit("xshort pad; xbyte pad;");
|
||||
else if(bytes == 2)
|
||||
ret += lit("xshort pad;");
|
||||
else if(bytes == 1)
|
||||
ret += lit("xbyte pad;");
|
||||
|
||||
return ret + lit("\n");
|
||||
}
|
||||
|
||||
PipelineStateViewer::PipelineStateViewer(ICaptureContext &ctx, QWidget *parent)
|
||||
: QFrame(parent), ui(new Ui::PipelineStateViewer), m_Ctx(ctx)
|
||||
{
|
||||
@@ -549,6 +614,241 @@ void PipelineStateViewer::setMeshViewPixmap(RDLabel *meshView)
|
||||
});
|
||||
}
|
||||
|
||||
QString PipelineStateViewer::formatMembers(int indent, int requiredByteStride,
|
||||
const QString &nameprefix,
|
||||
const rdcarray<ShaderConstant> &vars)
|
||||
{
|
||||
QString indentstr(indent * 4, QLatin1Char(' '));
|
||||
|
||||
QString ret;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(const ShaderConstant &v : vars)
|
||||
{
|
||||
if(!v.type.members.empty())
|
||||
{
|
||||
if(i > 0)
|
||||
ret += lit("\n");
|
||||
|
||||
if(v.type.descriptor.name == "struct")
|
||||
ret += indentstr + lit("// struct\n");
|
||||
else
|
||||
ret += indentstr + lit("// struct %1\n").arg(v.type.descriptor.name);
|
||||
|
||||
ret += indentstr + lit("{\n") + formatMembers(indent + 1, v.type.descriptor.arrayByteStride,
|
||||
v.name + lit("_"), v.type.members) +
|
||||
indentstr + lit("}\n");
|
||||
if(i < vars.count() - 1)
|
||||
ret += lit("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
QString arr;
|
||||
if(v.type.descriptor.elements > 1)
|
||||
arr = QFormatStr("[%1]").arg(v.type.descriptor.elements);
|
||||
ret += QFormatStr("%1%2 %3%4%5;\n")
|
||||
.arg(indentstr)
|
||||
.arg(v.type.descriptor.name)
|
||||
.arg(nameprefix)
|
||||
.arg(v.name)
|
||||
.arg(arr);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if(requiredByteStride > 0)
|
||||
{
|
||||
uint32_t structStart = 0;
|
||||
|
||||
const ShaderConstant *lastChild = &vars.back();
|
||||
|
||||
structStart += lastChild->byteOffset;
|
||||
while(!lastChild->type.members.isEmpty())
|
||||
{
|
||||
lastChild = &lastChild->type.members.back();
|
||||
structStart += lastChild->byteOffset;
|
||||
}
|
||||
|
||||
uint32_t size = lastChild->type.descriptor.rows * lastChild->type.descriptor.columns;
|
||||
if(lastChild->type.descriptor.type == VarType::Double ||
|
||||
lastChild->type.descriptor.type == VarType::ULong ||
|
||||
lastChild->type.descriptor.type == VarType::SLong)
|
||||
size *= 8;
|
||||
else if(lastChild->type.descriptor.type == VarType::Float ||
|
||||
lastChild->type.descriptor.type == VarType::UInt ||
|
||||
lastChild->type.descriptor.type == VarType::SInt)
|
||||
size *= 4;
|
||||
else if(lastChild->type.descriptor.type == VarType::Half ||
|
||||
lastChild->type.descriptor.type == VarType::UShort ||
|
||||
lastChild->type.descriptor.type == VarType::SShort)
|
||||
size *= 2;
|
||||
|
||||
if(lastChild->type.descriptor.elements > 1)
|
||||
size *= lastChild->type.descriptor.elements;
|
||||
|
||||
uint32_t padBytes = requiredByteStride - (lastChild->byteOffset + size);
|
||||
|
||||
if(padBytes > 0)
|
||||
ret += indentstr + padding(padBytes);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString PipelineStateViewer::GenerateBufferFormatter(const ShaderResource &res,
|
||||
const ResourceFormat &viewFormat,
|
||||
uint64_t &baseByteOffset)
|
||||
{
|
||||
QString format;
|
||||
|
||||
if(!res.variableType.members.empty())
|
||||
{
|
||||
const rdcarray<ShaderConstant> *members = &res.variableType.members;
|
||||
|
||||
uint32_t requiredStride = 0;
|
||||
|
||||
if(m_Ctx.APIProps().pipelineType == GraphicsAPI::Vulkan ||
|
||||
m_Ctx.APIProps().pipelineType == GraphicsAPI::OpenGL)
|
||||
{
|
||||
// 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 += lit("// %1 members skipped as they are fixed size:\n").arg(res.name);
|
||||
for(int i = 0; i < members->count() - 1; i++)
|
||||
{
|
||||
QString arraySize;
|
||||
if(members->at(i).type.descriptor.elements > 1)
|
||||
arraySize = QFormatStr("[%1]").arg(members->at(i).type.descriptor.elements);
|
||||
format += QFormatStr("// %1 %2%3;\n")
|
||||
.arg(members->at(i).type.descriptor.name)
|
||||
.arg(members->at(i).name)
|
||||
.arg(arraySize);
|
||||
}
|
||||
|
||||
format += lit("// final array struct @ byte offset %1\n{\n").arg(members->back().byteOffset);
|
||||
|
||||
baseByteOffset += members->back().byteOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
format += lit("// struct %1\n{\n").arg(res.name);
|
||||
}
|
||||
|
||||
// if the last member is a struct, remove one level of indirection before declaring the
|
||||
// repeated structure
|
||||
if(!members->back().type.members.isEmpty())
|
||||
{
|
||||
requiredStride = members->back().type.descriptor.arrayByteStride;
|
||||
|
||||
members = &members->back().type.members;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
format = lit("// struct %1\n{\n").arg(res.variableType.descriptor.name);
|
||||
}
|
||||
|
||||
format += formatMembers(1, requiredStride, QString(), *members);
|
||||
format += lit("}");
|
||||
}
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
@@ -920,69 +1220,6 @@ void PipelineStateViewer::SetupShaderEditButton(QToolButton *button, ResourceId
|
||||
button->setMenu(menu);
|
||||
}
|
||||
|
||||
static uint32_t byteSize(const ResourceFormat &fmt)
|
||||
{
|
||||
if(fmt.Special())
|
||||
{
|
||||
switch(fmt.type)
|
||||
{
|
||||
default:
|
||||
case ResourceFormatType::R9G9B9E5:
|
||||
case ResourceFormatType::R5G6B5:
|
||||
case ResourceFormatType::R5G5B5A1:
|
||||
case ResourceFormatType::R4G4B4A4:
|
||||
case ResourceFormatType::R4G4:
|
||||
case ResourceFormatType::BC1:
|
||||
case ResourceFormatType::BC2:
|
||||
case ResourceFormatType::BC3:
|
||||
case ResourceFormatType::BC4:
|
||||
case ResourceFormatType::BC5:
|
||||
case ResourceFormatType::BC6:
|
||||
case ResourceFormatType::BC7:
|
||||
case ResourceFormatType::ETC2:
|
||||
case ResourceFormatType::EAC:
|
||||
case ResourceFormatType::ASTC:
|
||||
case ResourceFormatType::D16S8:
|
||||
case ResourceFormatType::D24S8:
|
||||
case ResourceFormatType::D32S8:
|
||||
case ResourceFormatType::S8:
|
||||
case ResourceFormatType::YUV8:
|
||||
case ResourceFormatType::YUV10:
|
||||
case ResourceFormatType::YUV12:
|
||||
case ResourceFormatType::YUV16:
|
||||
case ResourceFormatType::PVRTC: return ~0U;
|
||||
case ResourceFormatType::R10G10B10A2:
|
||||
case ResourceFormatType::R11G11B10: return 4;
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.compByteWidth * fmt.compCount;
|
||||
}
|
||||
|
||||
static QString padding(uint32_t bytes)
|
||||
{
|
||||
if(bytes == 0)
|
||||
return QString();
|
||||
|
||||
QString ret;
|
||||
|
||||
if(bytes > 4)
|
||||
{
|
||||
ret += lit("xint pad[%1];").arg(bytes / 4);
|
||||
|
||||
bytes = bytes % 4;
|
||||
}
|
||||
|
||||
if(bytes == 3)
|
||||
ret += lit("xshort pad; xbyte pad;");
|
||||
else if(bytes == 2)
|
||||
ret += lit("xshort pad;");
|
||||
else if(bytes == 1)
|
||||
ret += lit("xbyte pad;");
|
||||
|
||||
return ret + lit("\n");
|
||||
}
|
||||
|
||||
QString PipelineStateViewer::GetVBufferFormatString(uint32_t slot)
|
||||
{
|
||||
rdcarray<BoundVBuffer> vbs = m_Ctx.CurPipelineState().GetVBuffers();
|
||||
|
||||
@@ -70,6 +70,9 @@ public:
|
||||
void SetupShaderEditButton(QToolButton *button, ResourceId pipelineId, ResourceId shaderId,
|
||||
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);
|
||||
@@ -90,6 +93,9 @@ private:
|
||||
|
||||
QMenu *editMenus[6] = {};
|
||||
|
||||
QString formatMembers(int indent, int requiredByteStride, const QString &nameprefix,
|
||||
const rdcarray<ShaderConstant> &vars);
|
||||
|
||||
QString GenerateHLSLStub(const ShaderReflection *shaderDetails, const QString &entryFunc);
|
||||
IShaderViewer *EditShader(ResourceId id, ShaderStage shaderType, const rdcstr &entry,
|
||||
ShaderCompileFlags compileFlags, ShaderEncoding encoding,
|
||||
|
||||
@@ -75,16 +75,18 @@ struct VulkanBufferTag
|
||||
bindPoint = 0;
|
||||
offset = size = 0;
|
||||
}
|
||||
VulkanBufferTag(bool rw, uint32_t b, ResourceId id, uint64_t offs, uint64_t sz)
|
||||
VulkanBufferTag(bool rw, uint32_t b, ResourceFormat f, ResourceId id, uint64_t offs, uint64_t sz)
|
||||
{
|
||||
rwRes = rw;
|
||||
bindPoint = b;
|
||||
ID = id;
|
||||
fmt = f;
|
||||
offset = offs;
|
||||
size = sz;
|
||||
}
|
||||
bool rwRes;
|
||||
uint32_t bindPoint;
|
||||
ResourceFormat fmt;
|
||||
ResourceId ID;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
@@ -1056,8 +1058,9 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
if(descriptorLen == UINT64_MAX)
|
||||
descriptorLen = len - descriptorBind->byteOffset;
|
||||
|
||||
tag = QVariant::fromValue(VulkanBufferTag(isrw, bindPoint, buf->resourceId,
|
||||
descriptorBind->byteOffset, descriptorLen));
|
||||
tag = QVariant::fromValue(VulkanBufferTag(isrw, bindPoint, descriptorBind->viewFormat,
|
||||
buf->resourceId, descriptorBind->byteOffset,
|
||||
descriptorLen));
|
||||
|
||||
isbuf = true;
|
||||
}
|
||||
@@ -1973,7 +1976,7 @@ void VulkanPipelineStateViewer::setState()
|
||||
length, s.counterBufferResourceId, (qulonglong)s.counterBufferOffset, QString()});
|
||||
|
||||
node->setTag(QVariant::fromValue(
|
||||
VulkanBufferTag(false, ~0U, s.bufferResourceId, s.byteOffset, length)));
|
||||
VulkanBufferTag(false, ~0U, ResourceFormat(), s.bufferResourceId, s.byteOffset, length)));
|
||||
|
||||
if(!filledSlot)
|
||||
setEmptyRow(node);
|
||||
@@ -2391,46 +2394,6 @@ void VulkanPipelineStateViewer::setState()
|
||||
}
|
||||
}
|
||||
|
||||
QString VulkanPipelineStateViewer::formatMembers(int indent, const QString &nameprefix,
|
||||
const rdcarray<ShaderConstant> &vars)
|
||||
{
|
||||
QString indentstr(indent * 4, QLatin1Char(' '));
|
||||
|
||||
QString ret = QString();
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(const ShaderConstant &v : vars)
|
||||
{
|
||||
if(!v.type.members.isEmpty())
|
||||
{
|
||||
if(i > 0)
|
||||
ret += lit("\n");
|
||||
ret += indentstr + lit("// struct %1\n").arg(v.type.descriptor.name);
|
||||
ret += indentstr + lit("{\n") + formatMembers(indent + 1, v.name + lit("_"), v.type.members) +
|
||||
indentstr + lit("}\n");
|
||||
if(i < vars.count() - 1)
|
||||
ret += lit("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
QString arr = QString();
|
||||
if(v.type.descriptor.elements > 1)
|
||||
arr = QFormatStr("[%1]").arg(v.type.descriptor.elements);
|
||||
ret += QFormatStr("%1%2 %3%4%5;\n")
|
||||
.arg(indentstr)
|
||||
.arg(v.type.descriptor.name)
|
||||
.arg(nameprefix)
|
||||
.arg(v.name)
|
||||
.arg(arr);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void VulkanPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, int column)
|
||||
{
|
||||
const VKPipe::Shader *stage = stageForSender(item->treeWidget());
|
||||
@@ -2478,41 +2441,7 @@ void VulkanPipelineStateViewer::resource_itemActivated(RDTreeWidgetItem *item, i
|
||||
? stage->reflection->readWriteResources[buf.bindPoint]
|
||||
: stage->reflection->readOnlyResources[buf.bindPoint];
|
||||
|
||||
format = lit("// struct %1\n").arg(shaderRes.variableType.descriptor.name);
|
||||
|
||||
if(shaderRes.variableType.members.count() > 1)
|
||||
{
|
||||
format += lit("// members skipped as they are fixed size:\n");
|
||||
for(int i = 0; i < shaderRes.variableType.members.count() - 1; i++)
|
||||
format += QFormatStr("// %1 %2;\n")
|
||||
.arg(shaderRes.variableType.members[i].type.descriptor.name)
|
||||
.arg(shaderRes.variableType.members[i].name);
|
||||
}
|
||||
|
||||
if(!shaderRes.variableType.members.isEmpty())
|
||||
{
|
||||
format += lit("{\n") + formatMembers(1, QString(), shaderRes.variableType.members) + lit("}");
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &desc = shaderRes.variableType.descriptor;
|
||||
|
||||
format = QString();
|
||||
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.isEmpty())
|
||||
format += lit(" ") + desc.name;
|
||||
|
||||
if(desc.elements > 1)
|
||||
format += QFormatStr("[%1]").arg(desc.elements);
|
||||
}
|
||||
format = m_Common.GenerateBufferFormatter(shaderRes, buf.fmt, buf.offset);
|
||||
}
|
||||
|
||||
if(buf.ID != ResourceId())
|
||||
|
||||
Reference in new issue
Block a user