Skip to content

Commit e205054

Browse files
committed
Add UI support for GPU typed pointers in buffers
1 parent b397926 commit e205054

28 files changed

+722
-249
lines changed

qrenderdoc/Code/BufferFormatter.cpp

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
struct StructFormatData
3131
{
3232
ShaderConstant structDef;
33+
uint32_t pointerTypeId = 0;
3334
uint32_t offset = 0;
3435
};
3536

@@ -86,6 +87,7 @@ ShaderConstant BufferFormatter::ParseFormatString(const QString &formatString, u
8687
QRegularExpression structUseRegex(
8788
lit("^" // start of the line
8889
"([A-Za-z_][A-Za-z0-9_]*)" // struct type name
90+
"(\\*)?" // maybe a pointer
8991
"\\s+([A-Za-z@_][A-Za-z0-9@_]*)" // variable name
9092
"(\\s*\\[[0-9]+\\])?" // optional array dimension
9193
"$"));
@@ -119,6 +121,8 @@ ShaderConstant BufferFormatter::ParseFormatString(const QString &formatString, u
119121
if(!tightPacking)
120122
cur->structDef.type.descriptor.arrayByteStride = (cur->offset + 0xFU) & (~0xFU);
121123

124+
cur->pointerTypeId = PointerTypeRegistry::GetTypeID(cur->structDef.type);
125+
122126
cur = &root;
123127
continue;
124128
}
@@ -140,6 +144,7 @@ ShaderConstant BufferFormatter::ParseFormatString(const QString &formatString, u
140144
}
141145

142146
cur = &structelems[lastStruct];
147+
cur->structDef.type.descriptor.name = lastStruct;
143148
continue;
144149
}
145150
}
@@ -152,34 +157,55 @@ ShaderConstant BufferFormatter::ParseFormatString(const QString &formatString, u
152157
{
153158
StructFormatData &structContext = structelems[structMatch.captured(1)];
154159

155-
QString varName = structMatch.captured(2);
160+
bool isPointer = !structMatch.captured(2).trimmed().isEmpty();
161+
162+
QString varName = structMatch.captured(3);
156163

157-
QString arrayDim = structMatch.captured(3).trimmed();
158-
uint32_t arrayCount = 1;
159-
if(!arrayDim.isEmpty())
164+
if(isPointer)
160165
{
161-
arrayDim = arrayDim.mid(1, arrayDim.count() - 2);
162-
bool ok = false;
163-
arrayCount = arrayDim.toUInt(&ok);
164-
if(!ok)
165-
arrayCount = 1;
166+
// if not tight packing, align up to pointer size
167+
if(!tightPacking)
168+
cur->offset = (cur->offset + 0x7) & (~0x7);
169+
170+
el.name = varName;
171+
el.byteOffset = cur->offset;
172+
el.type.descriptor.pointerTypeID = structContext.pointerTypeId;
173+
el.type.descriptor.type = VarType::ULong;
174+
el.type.descriptor.displayAsHex = true;
175+
el.type.descriptor.arrayByteStride = 8;
176+
177+
cur->offset += 8;
178+
cur->structDef.type.members.push_back(el);
166179
}
180+
else
181+
{
182+
QString arrayDim = structMatch.captured(4).trimmed();
183+
uint32_t arrayCount = 1;
184+
if(!arrayDim.isEmpty())
185+
{
186+
arrayDim = arrayDim.mid(1, arrayDim.count() - 2);
187+
bool ok = false;
188+
arrayCount = arrayDim.toUInt(&ok);
189+
if(!ok)
190+
arrayCount = 1;
191+
}
167192

168-
// cbuffer packing rules, structs are always float4 base aligned
169-
if(!tightPacking)
170-
cur->offset = (cur->offset + 0xFU) & (~0xFU);
193+
// cbuffer packing rules, structs are always float4 base aligned
194+
if(!tightPacking)
195+
cur->offset = (cur->offset + 0xFU) & (~0xFU);
171196

172-
el = structContext.structDef;
173-
el.name = varName;
174-
el.byteOffset = cur->offset;
175-
el.type.descriptor.elements = arrayCount;
197+
el = structContext.structDef;
198+
el.name = varName;
199+
el.byteOffset = cur->offset;
200+
el.type.descriptor.elements = arrayCount;
176201

177-
cur->structDef.type.members.push_back(el);
202+
cur->structDef.type.members.push_back(el);
178203

179-
// undo the padding after the last struct
180-
uint32_t padding = el.type.descriptor.arrayByteStride - structContext.offset;
204+
// undo the padding after the last struct
205+
uint32_t padding = el.type.descriptor.arrayByteStride - structContext.offset;
181206

182-
cur->offset += el.type.descriptor.elements * el.type.descriptor.arrayByteStride - padding;
207+
cur->offset += el.type.descriptor.elements * el.type.descriptor.arrayByteStride - padding;
208+
}
183209

184210
continue;
185211
}
@@ -760,7 +786,24 @@ QString BufferFormatter::DeclareStruct(QList<QString> &declaredStructs, const QS
760786

761787
QString varTypeName = members[i].type.descriptor.name;
762788

763-
if(!members[i].type.members.isEmpty())
789+
if(members[i].type.descriptor.pointerTypeID != ~0U)
790+
{
791+
const ShaderVariableType &pointeeType =
792+
PointerTypeRegistry::GetTypeDescriptor(members[i].type.descriptor.pointerTypeID);
793+
794+
varTypeName = pointeeType.descriptor.name;
795+
796+
if(!declaredStructs.contains(varTypeName))
797+
{
798+
declaredStructs.push_back(varTypeName);
799+
ret = DeclareStruct(declaredStructs, varTypeName, pointeeType.members,
800+
pointeeType.descriptor.arrayByteStride) +
801+
lit("\n") + ret;
802+
}
803+
804+
varTypeName += lit("*");
805+
}
806+
else if(!members[i].type.members.isEmpty())
764807
{
765808
// GL structs don't give us typenames (boo!) so give them unique names. This will mean some
766809
// structs get duplicated if they're used in multiple places, but not much we can do about
@@ -1453,6 +1496,9 @@ QString TypeString(const ShaderVariable &v)
14531496
return QFormatStr("%1[%2]").arg(TypeString(v.members[0])).arg(v.members.count());
14541497
}
14551498

1499+
if(v.isPointer)
1500+
return PointerTypeRegistry::GetTypeDescriptor(v.GetPointer()).descriptor.name + "*";
1501+
14561502
QString typeStr = ToQStr(v.type);
14571503

14581504
if(v.displayAsHex)
@@ -1504,6 +1550,9 @@ QString RowString(const ShaderVariable &v, uint32_t row, VarType type)
15041550
if(type == VarType::Unknown)
15051551
type = v.type;
15061552

1553+
if(v.isPointer)
1554+
return ToQStr(v.GetPointer());
1555+
15071556
if(type == VarType::Double)
15081557
return RowValuesToString((int)v.columns, v.displayAsHex, v.value.dv[row * v.columns + 0],
15091558
v.value.dv[row * v.columns + 1], v.value.dv[row * v.columns + 2],
@@ -1562,6 +1611,9 @@ QString RowTypeString(const ShaderVariable &v)
15621611
if(v.rows == 0 && v.columns == 0)
15631612
return lit("-");
15641613

1614+
if(v.isPointer)
1615+
return PointerTypeRegistry::GetTypeDescriptor(v.GetPointer()).descriptor.name + "*";
1616+
15651617
QString typeStr = ToQStr(v.type);
15661618

15671619
if(v.displayAsHex)

qrenderdoc/Code/CaptureContext.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,8 @@ void CaptureContext::LoadCapture(const rdcstr &captureFile, const ReplayOptions
686686
{
687687
CloseCapture();
688688

689+
PointerTypeRegistry::Init();
690+
689691
m_LoadInProgress = true;
690692

691693
if(local)
@@ -1450,6 +1452,15 @@ void CaptureContext::SetRemoteHost(int hostIdx)
14501452
void CaptureContext::RefreshUIStatus(const rdcarray<ICaptureViewer *> &exclude,
14511453
bool updateSelectedEvent, bool updateEvent)
14521454
{
1455+
// cache and assign pointer type IDs for any known pointer types in current shaders
1456+
for(ShaderStage stage : {ShaderStage::Vertex, ShaderStage::Hull, ShaderStage::Domain,
1457+
ShaderStage::Geometry, ShaderStage::Pixel, ShaderStage::Compute})
1458+
{
1459+
const ShaderReflection *refl = m_CurPipelineState->GetShaderReflection(stage);
1460+
if(refl)
1461+
PointerTypeRegistry::CacheShader(refl);
1462+
}
1463+
14531464
for(ICaptureViewer *viewer : m_CaptureViewers)
14541465
{
14551466
if(exclude.contains(viewer))

0 commit comments

Comments
 (0)