mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-11-15 02:11:22 +00:00
In VK pipeline view, look up FB from RP attachments. Closes #2756
* Doing this lets us more consistently reference the color attachments in the correct indices and makes it easier to match for blends. It also allows the user to show unused/empty attachments
This commit is contained in:
1 file changed
+228
-194
@@ -2624,8 +2624,6 @@ void VulkanPipelineStateViewer::setState()
|
||||
////////////////////////////////////////////////
|
||||
// Output Merger
|
||||
|
||||
bool targets[32] = {};
|
||||
|
||||
if(state.currentPass.renderpass.dynamic)
|
||||
{
|
||||
QString dynamic = tr("Dynamic", "Dynamic rendering renderpass name");
|
||||
@@ -2650,204 +2648,235 @@ void VulkanPipelineStateViewer::setState()
|
||||
vs = ui->fbAttach->verticalScrollBar()->value();
|
||||
ui->fbAttach->beginUpdate();
|
||||
ui->fbAttach->clear();
|
||||
{
|
||||
int i = 0;
|
||||
for(const VKPipe::Attachment &p : state.currentPass.framebuffer.attachments)
|
||||
{
|
||||
int colIdx = -1;
|
||||
for(int c = 0; c < state.currentPass.renderpass.colorAttachments.count(); c++)
|
||||
{
|
||||
if(state.currentPass.renderpass.colorAttachments[c] == (uint)i)
|
||||
{
|
||||
colIdx = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int resIdx = -1;
|
||||
for(int c = 0; c < state.currentPass.renderpass.resolveAttachments.count(); c++)
|
||||
{
|
||||
if(state.currentPass.renderpass.resolveAttachments[c] == (uint)i)
|
||||
{
|
||||
resIdx = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool filledSlot = (p.imageResourceId != ResourceId());
|
||||
bool usedSlot =
|
||||
(colIdx >= 0 || resIdx >= 0 || state.currentPass.renderpass.depthstencilAttachment == i ||
|
||||
state.currentPass.renderpass.fragmentDensityAttachment == i ||
|
||||
state.currentPass.renderpass.shadingRateAttachment == i ||
|
||||
state.currentPass.renderpass.depthstencilResolveAttachment == i);
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString format;
|
||||
QString typeName;
|
||||
QString dimensions;
|
||||
QString samples;
|
||||
bool tooltipOffsets = false;
|
||||
|
||||
if(p.imageResourceId != ResourceId())
|
||||
{
|
||||
format = p.viewFormat.Name();
|
||||
typeName = tr("Unknown");
|
||||
}
|
||||
else
|
||||
{
|
||||
format = lit("-");
|
||||
typeName = lit("-");
|
||||
dimensions = lit("-");
|
||||
samples = lit("-");
|
||||
}
|
||||
|
||||
TextureDescription *tex = m_Ctx.GetTexture(p.imageResourceId);
|
||||
if(tex)
|
||||
{
|
||||
dimensions += tr("%1x%2").arg(tex->width).arg(tex->height);
|
||||
if(tex->depth > 1)
|
||||
dimensions += tr("x%1").arg(tex->depth);
|
||||
if(tex->arraysize > 1)
|
||||
dimensions += tr("[%1]").arg(tex->arraysize);
|
||||
|
||||
typeName = ToQStr(tex->type);
|
||||
}
|
||||
samples = getTextureRenderSamples(tex, state.currentPass.renderpass);
|
||||
|
||||
if(p.swizzle.red != TextureSwizzle::Red || p.swizzle.green != TextureSwizzle::Green ||
|
||||
p.swizzle.blue != TextureSwizzle::Blue || p.swizzle.alpha != TextureSwizzle::Alpha)
|
||||
{
|
||||
format += tr(" swizzle[%1%2%3%4]")
|
||||
.arg(ToQStr(p.swizzle.red))
|
||||
.arg(ToQStr(p.swizzle.green))
|
||||
.arg(ToQStr(p.swizzle.blue))
|
||||
.arg(ToQStr(p.swizzle.alpha));
|
||||
}
|
||||
|
||||
rdcpair<uint32_t, uint32_t> shadingRateTexelSize = {0, 0};
|
||||
QString slotname;
|
||||
|
||||
if(colIdx >= 0)
|
||||
{
|
||||
slotname = QFormatStr("Color %1").arg(colIdx);
|
||||
}
|
||||
else if(resIdx >= 0)
|
||||
{
|
||||
slotname = QFormatStr("Resolve %1").arg(resIdx);
|
||||
}
|
||||
else if(state.currentPass.renderpass.depthstencilResolveAttachment == i)
|
||||
{
|
||||
slotname = lit("Depth/Stencil Resolve");
|
||||
}
|
||||
else if(state.currentPass.renderpass.fragmentDensityAttachment == i)
|
||||
{
|
||||
slotname = lit("Fragment Density Map");
|
||||
if(state.currentPass.renderpass.fragmentDensityOffsets.size() > 2)
|
||||
{
|
||||
tooltipOffsets = true;
|
||||
}
|
||||
else if(state.currentPass.renderpass.fragmentDensityOffsets.size() > 0)
|
||||
{
|
||||
dimensions += tr(" : offsets");
|
||||
for(uint32_t j = 0; j < state.currentPass.renderpass.fragmentDensityOffsets.size(); j++)
|
||||
{
|
||||
const Offset &o = state.currentPass.renderpass.fragmentDensityOffsets[j];
|
||||
if(j > 0)
|
||||
dimensions += tr(", ");
|
||||
|
||||
dimensions += tr(" %1x%2").arg(o.x).arg(o.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(state.currentPass.renderpass.shadingRateAttachment == i)
|
||||
{
|
||||
slotname = lit("Fragment Shading Rate Map");
|
||||
shadingRateTexelSize = state.currentPass.renderpass.shadingRateTexelSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
slotname = lit("Depth");
|
||||
|
||||
if(p.viewFormat.type == ResourceFormatType::D16S8 ||
|
||||
p.viewFormat.type == ResourceFormatType::D24S8 ||
|
||||
p.viewFormat.type == ResourceFormatType::D32S8)
|
||||
{
|
||||
slotname = lit("Depth/Stencil");
|
||||
}
|
||||
else if(p.viewFormat.type == ResourceFormatType::S8)
|
||||
{
|
||||
slotname = lit("Stencil");
|
||||
}
|
||||
}
|
||||
|
||||
if(state.fragmentShader.reflection != NULL)
|
||||
{
|
||||
for(int s = 0; s < state.fragmentShader.reflection->outputSignature.count(); s++)
|
||||
{
|
||||
if(state.fragmentShader.reflection->outputSignature[s].regIndex == (uint32_t)colIdx &&
|
||||
(state.fragmentShader.reflection->outputSignature[s].systemValue ==
|
||||
ShaderBuiltin::Undefined ||
|
||||
state.fragmentShader.reflection->outputSignature[s].systemValue ==
|
||||
ShaderBuiltin::ColorOutput))
|
||||
{
|
||||
slotname +=
|
||||
QFormatStr(": %1").arg(state.fragmentShader.reflection->outputSignature[s].varName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString resName = ToQStr(p.imageResourceId);
|
||||
|
||||
if(shadingRateTexelSize.first > 0)
|
||||
resName +=
|
||||
tr(" (%1x%2 texels)").arg(shadingRateTexelSize.first).arg(shadingRateTexelSize.second);
|
||||
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem(
|
||||
{slotname, resName, typeName, dimensions, format, samples, QString()});
|
||||
|
||||
if(tex)
|
||||
node->setTag(
|
||||
QVariant::fromValue(VulkanTextureTag(p.imageResourceId, p.viewFormat.compType)));
|
||||
|
||||
if(p.imageResourceId == ResourceId())
|
||||
{
|
||||
setEmptyRow(node);
|
||||
}
|
||||
else if(!usedSlot)
|
||||
{
|
||||
setInactiveRow(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
targets[i] = true;
|
||||
}
|
||||
|
||||
bool hasViewDetails =
|
||||
setViewDetails(node, p, tex, true, QString(), resIdx < 0, tooltipOffsets);
|
||||
|
||||
if(hasViewDetails)
|
||||
node->setText(
|
||||
1, tr("%1 viewed by %2").arg(ToQStr(p.imageResourceId)).arg(ToQStr(p.viewResourceId)));
|
||||
|
||||
ui->fbAttach->addTopLevelItem(node);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
ui->fbAttach->clearSelection();
|
||||
ui->fbAttach->endUpdate();
|
||||
ui->fbAttach->verticalScrollBar()->setValue(vs);
|
||||
|
||||
vs = ui->blends->verticalScrollBar()->value();
|
||||
vs2 = ui->blends->verticalScrollBar()->value();
|
||||
ui->blends->beginUpdate();
|
||||
ui->blends->clear();
|
||||
{
|
||||
const VKPipe::Framebuffer &fb = state.currentPass.framebuffer;
|
||||
const VKPipe::RenderPass &rp = state.currentPass.renderpass;
|
||||
|
||||
enum class AttType
|
||||
{
|
||||
Color,
|
||||
Resolve,
|
||||
Depth,
|
||||
DepthResolve,
|
||||
Density,
|
||||
ShadingRate
|
||||
};
|
||||
|
||||
struct AttachRef
|
||||
{
|
||||
int32_t fbIdx;
|
||||
int32_t localIdx;
|
||||
AttType type;
|
||||
};
|
||||
|
||||
rdcarray<AttachRef> attachs;
|
||||
|
||||
// iterate the attachments in logical order, checking each index into the framebuffer
|
||||
|
||||
for(int c = 0; c < rp.colorAttachments.count(); c++)
|
||||
attachs.push_back({int32_t(rp.colorAttachments[c]), c, AttType::Color});
|
||||
|
||||
for(int c = 0; c < rp.resolveAttachments.count(); c++)
|
||||
attachs.push_back({int32_t(rp.resolveAttachments[c]), c, AttType::Resolve});
|
||||
|
||||
attachs.push_back({rp.depthstencilAttachment, 0, AttType::Depth});
|
||||
attachs.push_back({rp.depthstencilResolveAttachment, 0, AttType::DepthResolve});
|
||||
attachs.push_back({rp.fragmentDensityAttachment, 0, AttType::Density});
|
||||
attachs.push_back({rp.shadingRateAttachment, 0, AttType::ShadingRate});
|
||||
|
||||
for(const AttachRef &a : attachs)
|
||||
{
|
||||
int32_t attIdx = a.fbIdx;
|
||||
|
||||
// negative index means unused
|
||||
bool usedSlot = (attIdx >= 0);
|
||||
|
||||
bool filledSlot = false;
|
||||
if(usedSlot && attIdx < fb.attachments.count())
|
||||
filledSlot = fb.attachments[attIdx].imageResourceId != ResourceId();
|
||||
|
||||
if(showNode(usedSlot, filledSlot))
|
||||
{
|
||||
QString slotname;
|
||||
|
||||
if(a.type == AttType::Color)
|
||||
{
|
||||
slotname = QFormatStr("Color %1").arg(a.localIdx);
|
||||
|
||||
if(state.fragmentShader.reflection != NULL)
|
||||
{
|
||||
const rdcarray<SigParameter> &outSig = state.fragmentShader.reflection->outputSignature;
|
||||
for(int s = 0; s < outSig.count(); s++)
|
||||
{
|
||||
if(outSig[s].regIndex == (uint32_t)a.localIdx &&
|
||||
(outSig[s].systemValue == ShaderBuiltin::Undefined ||
|
||||
outSig[s].systemValue == ShaderBuiltin::ColorOutput))
|
||||
{
|
||||
slotname += QFormatStr(": %1").arg(outSig[s].varName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(a.type == AttType::Resolve)
|
||||
{
|
||||
slotname = QFormatStr("Resolve %1").arg(a.localIdx);
|
||||
}
|
||||
else if(a.type == AttType::Depth)
|
||||
{
|
||||
slotname = lit("Depth/Stencil");
|
||||
|
||||
if(filledSlot)
|
||||
{
|
||||
const VKPipe::Attachment &p = fb.attachments[attIdx];
|
||||
|
||||
slotname = lit("Depth");
|
||||
|
||||
if(p.viewFormat.type == ResourceFormatType::D16S8 ||
|
||||
p.viewFormat.type == ResourceFormatType::D24S8 ||
|
||||
p.viewFormat.type == ResourceFormatType::D32S8)
|
||||
slotname = lit("Depth/Stencil");
|
||||
else if(p.viewFormat.type == ResourceFormatType::S8)
|
||||
slotname = lit("Stencil");
|
||||
}
|
||||
}
|
||||
else if(a.type == AttType::DepthResolve)
|
||||
{
|
||||
slotname = lit("Depth/Stencil Resolve");
|
||||
}
|
||||
else if(a.type == AttType::Density)
|
||||
{
|
||||
slotname = lit("Fragment Density Map");
|
||||
}
|
||||
else if(a.type == AttType::ShadingRate)
|
||||
{
|
||||
slotname = lit("Fragment Shading Rate Map");
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *node;
|
||||
|
||||
if(filledSlot)
|
||||
{
|
||||
const VKPipe::Attachment &p = fb.attachments[attIdx];
|
||||
|
||||
QString format;
|
||||
QString typeName;
|
||||
QString dimensions;
|
||||
QString samples;
|
||||
bool tooltipOffsets = false;
|
||||
|
||||
if(p.imageResourceId != ResourceId())
|
||||
{
|
||||
format = p.viewFormat.Name();
|
||||
typeName = tr("Unknown");
|
||||
}
|
||||
else
|
||||
{
|
||||
format = lit("-");
|
||||
typeName = lit("-");
|
||||
dimensions = lit("-");
|
||||
samples = lit("-");
|
||||
}
|
||||
|
||||
TextureDescription *tex = m_Ctx.GetTexture(p.imageResourceId);
|
||||
if(tex)
|
||||
{
|
||||
dimensions += tr("%1x%2").arg(tex->width).arg(tex->height);
|
||||
if(tex->depth > 1)
|
||||
dimensions += tr("x%1").arg(tex->depth);
|
||||
if(tex->arraysize > 1)
|
||||
dimensions += tr("[%1]").arg(tex->arraysize);
|
||||
|
||||
typeName = ToQStr(tex->type);
|
||||
}
|
||||
samples = getTextureRenderSamples(tex, state.currentPass.renderpass);
|
||||
|
||||
if(p.swizzle.red != TextureSwizzle::Red || p.swizzle.green != TextureSwizzle::Green ||
|
||||
p.swizzle.blue != TextureSwizzle::Blue || p.swizzle.alpha != TextureSwizzle::Alpha)
|
||||
{
|
||||
format += tr(" swizzle[%1%2%3%4]")
|
||||
.arg(ToQStr(p.swizzle.red))
|
||||
.arg(ToQStr(p.swizzle.green))
|
||||
.arg(ToQStr(p.swizzle.blue))
|
||||
.arg(ToQStr(p.swizzle.alpha));
|
||||
}
|
||||
|
||||
rdcpair<uint32_t, uint32_t> shadingRateTexelSize = {0, 0};
|
||||
|
||||
if(a.type == AttType::Density)
|
||||
{
|
||||
if(state.currentPass.renderpass.fragmentDensityOffsets.size() > 2)
|
||||
{
|
||||
tooltipOffsets = true;
|
||||
}
|
||||
else if(state.currentPass.renderpass.fragmentDensityOffsets.size() > 0)
|
||||
{
|
||||
dimensions += tr(" : offsets");
|
||||
for(uint32_t j = 0; j < state.currentPass.renderpass.fragmentDensityOffsets.size(); j++)
|
||||
{
|
||||
const Offset &o = state.currentPass.renderpass.fragmentDensityOffsets[j];
|
||||
if(j > 0)
|
||||
dimensions += tr(", ");
|
||||
|
||||
dimensions += tr(" %1x%2").arg(o.x).arg(o.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(a.type == AttType::ShadingRate)
|
||||
{
|
||||
shadingRateTexelSize = state.currentPass.renderpass.shadingRateTexelSize;
|
||||
}
|
||||
|
||||
QString resName = ToQStr(p.imageResourceId);
|
||||
|
||||
if(shadingRateTexelSize.first > 0)
|
||||
resName +=
|
||||
tr(" (%1x%2 texels)").arg(shadingRateTexelSize.first).arg(shadingRateTexelSize.second);
|
||||
|
||||
node = new RDTreeWidgetItem(
|
||||
{slotname, resName, typeName, dimensions, format, samples, QString()});
|
||||
|
||||
if(tex)
|
||||
node->setTag(
|
||||
QVariant::fromValue(VulkanTextureTag(p.imageResourceId, p.viewFormat.compType)));
|
||||
|
||||
if(p.imageResourceId == ResourceId())
|
||||
setEmptyRow(node);
|
||||
else if(!usedSlot)
|
||||
setInactiveRow(node);
|
||||
|
||||
bool hasViewDetails = setViewDetails(
|
||||
node, p, tex, true, QString(),
|
||||
a.type == AttType::Resolve || a.type == AttType::DepthResolve, tooltipOffsets);
|
||||
|
||||
if(hasViewDetails)
|
||||
node->setText(
|
||||
1,
|
||||
tr("%1 viewed by %2").arg(ToQStr(p.imageResourceId)).arg(ToQStr(p.viewResourceId)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// special simple case for an attachment that's not used. No framebuffer to look up so
|
||||
// just display the name and empty contents.
|
||||
|
||||
node = new RDTreeWidgetItem({slotname, usedSlot ? ToQStr(ResourceId()) : tr("Unused"),
|
||||
QString(), QString(), QString(), QString(), QString()});
|
||||
|
||||
setEmptyRow(node);
|
||||
}
|
||||
|
||||
ui->fbAttach->addTopLevelItem(node);
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for(const ColorBlend &blend : state.colorBlend.blends)
|
||||
{
|
||||
bool usedSlot = (targets[i]);
|
||||
bool usedSlot =
|
||||
(i < rp.colorAttachments.count() && rp.colorAttachments[i] < fb.attachments.size());
|
||||
|
||||
if(showNode(usedSlot, /*filledSlot*/ true))
|
||||
{
|
||||
@@ -2875,9 +2904,14 @@ void VulkanPipelineStateViewer::setState()
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
ui->fbAttach->clearSelection();
|
||||
ui->fbAttach->endUpdate();
|
||||
ui->fbAttach->verticalScrollBar()->setValue(vs);
|
||||
|
||||
ui->blends->clearSelection();
|
||||
ui->blends->endUpdate();
|
||||
ui->blends->verticalScrollBar()->setValue(vs);
|
||||
ui->blends->verticalScrollBar()->setValue(vs2);
|
||||
|
||||
ui->blendFactor->setText(QFormatStr("%1, %2, %3, %4")
|
||||
.arg(state.colorBlend.blendFactor[0], 0, 'f', 2)
|
||||
|
||||
Reference in new issue
Block a user