fgviewer: add info in panel for render passes (#9618)
- Add plumbing to add more information about rendertargets (including discard flags and pass id) to the fgviewer pass struct. - Add UI to display information about a selected pass - Highlight a selected resource or pass
This commit is contained in:
@@ -522,8 +522,8 @@ fgviewer::FrameGraphInfo FrameGraph::getFrameGraphInfo(const char *viewName) con
|
||||
continue;
|
||||
writes.push_back(resourceNode->resourceHandle.index);
|
||||
}
|
||||
passes.emplace_back(utils::CString(pass->getName()),
|
||||
std::move(reads), std::move(writes));
|
||||
passes.emplace_back(pass->getId(), utils::CString(pass->getName()),
|
||||
std::move(reads), std::move(writes), pass->getRenderTargetInfo());
|
||||
}
|
||||
|
||||
std::unordered_map<fgviewer::ResourceId, fgviewer::FrameGraphInfo::Resource> resources;
|
||||
|
||||
@@ -64,6 +64,8 @@ public:
|
||||
|
||||
bool isInitialized() const noexcept { return index != UNINITIALIZED; }
|
||||
|
||||
uint16_t getIndex() const noexcept { return index; }
|
||||
|
||||
operator bool() const noexcept { return isInitialized(); }
|
||||
|
||||
void clear() noexcept { index = UNINITIALIZED; version = 0; }
|
||||
|
||||
@@ -39,6 +39,11 @@ struct FrameGraphRenderPass {
|
||||
FrameGraphId<FrameGraphTexture> stencil;
|
||||
|
||||
FrameGraphId<FrameGraphTexture>& operator[](size_t index) noexcept {
|
||||
return const_cast<FrameGraphId<FrameGraphTexture>&>(
|
||||
static_cast<const Attachments*>(this)->operator[](index));
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> const& operator[](size_t index) const noexcept {
|
||||
assert_invariant(index < ATTACHMENT_COUNT);
|
||||
if (index < backend::MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT) {
|
||||
return color[index];
|
||||
|
||||
@@ -175,7 +175,8 @@ void RenderPassNode::resolve() noexcept {
|
||||
rt.backend.params.flags.discardStart |= target;
|
||||
}
|
||||
VirtualResource* pResource = mFrameGraph.getResource(rt.descriptor.attachments[i]);
|
||||
Resource<FrameGraphTexture>* pTextureResource = static_cast<Resource<FrameGraphTexture>*>(pResource);
|
||||
Resource<FrameGraphTexture>* pTextureResource =
|
||||
static_cast<Resource<FrameGraphTexture>*>(pResource);
|
||||
|
||||
pImportedRenderTarget = pImportedRenderTarget ?
|
||||
pImportedRenderTarget : pResource->asImportedRenderTarget();
|
||||
@@ -332,6 +333,52 @@ utils::CString RenderPassNode::graphvizify() const noexcept {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
using RenderTargetInfo = fgviewer::FrameGraphInfo::Pass::RenderTargetInfo;
|
||||
using AttachmentInfo = fgviewer::FrameGraphInfo::Pass::AttachmentInfo;
|
||||
std::vector<RenderTargetInfo> RenderPassNode::getRenderTargetInfo() const noexcept {
|
||||
using namespace backend;
|
||||
std::vector<RenderTargetInfo> info;
|
||||
info.reserve(mRenderTargetData.size());
|
||||
|
||||
for (auto const& rt: mRenderTargetData) {
|
||||
RenderTargetInfo rtInfo;
|
||||
|
||||
auto extractAttachmentInfo = [&](TargetBufferFlags flags,
|
||||
std::vector<AttachmentInfo>& list) {
|
||||
for (size_t i = 0; i < RenderPassData::ATTACHMENT_COUNT; ++i) {
|
||||
TargetBufferFlags mask = getTargetBufferFlagsAt(i);
|
||||
if (any(flags & mask)) {
|
||||
FrameGraphHandle handle = rt.descriptor.attachments[i];
|
||||
if (handle) {
|
||||
const char* name = nullptr;
|
||||
if (i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT) name = "color";
|
||||
else if (i == MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT)
|
||||
name = "depth";
|
||||
else if (i == MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + 1)
|
||||
name = "stencil";
|
||||
|
||||
utils::CString slotName(name);
|
||||
if (i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT) {
|
||||
slotName += utils::to_string(i);
|
||||
}
|
||||
|
||||
list.push_back({ slotName, handle.getIndex() });
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extractAttachmentInfo(rt.backend.params.flags.discardStart, rtInfo.discardStart);
|
||||
extractAttachmentInfo(rt.backend.params.flags.discardEnd, rtInfo.discardEnd);
|
||||
extractAttachmentInfo(rt.backend.params.flags.clear, rtInfo.clear);
|
||||
|
||||
info.push_back(std::move(rtInfo));
|
||||
}
|
||||
return info;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
PresentPassNode::PresentPassNode(FrameGraph& fg) noexcept
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
#include "fg/FrameGraphRenderPass.h"
|
||||
|
||||
#include "backend/DriverApiForward.h"
|
||||
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
#include <fgviewer/FrameGraphInfo.h>
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@@ -60,6 +63,12 @@ public:
|
||||
virtual void resolve() noexcept = 0;
|
||||
utils::CString graphvizifyEdgeColor() const noexcept override;
|
||||
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
virtual std::vector<fgviewer::FrameGraphInfo::Pass::RenderTargetInfo>
|
||||
getRenderTargetInfo() const noexcept {
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
Vector<VirtualResource*> devirtualize; // resources we need to create before executing
|
||||
Vector<VirtualResource*> destroy; // resources we need to destroy after executing
|
||||
};
|
||||
@@ -93,6 +102,7 @@ public:
|
||||
utils::StaticString name, FrameGraphRenderPass::Descriptor const& descriptor);
|
||||
|
||||
RenderPassData const* getRenderPassData(uint32_t id) const noexcept;
|
||||
size_t getRenderTargetCount() const noexcept { return mRenderTargetData.size(); }
|
||||
|
||||
private:
|
||||
// virtuals from DependencyGraph::Node
|
||||
@@ -100,6 +110,10 @@ private:
|
||||
utils::CString graphvizify() const noexcept override;
|
||||
void execute(FrameGraphResources const& resources, backend::DriverApi& driver) noexcept override;
|
||||
void resolve() noexcept override;
|
||||
#if FILAMENT_ENABLE_FGVIEWER
|
||||
std::vector<fgviewer::FrameGraphInfo::Pass::RenderTargetInfo>
|
||||
getRenderTargetInfo() const noexcept override;
|
||||
#endif
|
||||
|
||||
// constants
|
||||
const char* const mName = nullptr;
|
||||
|
||||
@@ -39,14 +39,29 @@ public:
|
||||
bool operator==(const FrameGraphInfo& rhs) const;
|
||||
|
||||
struct Pass {
|
||||
Pass(utils::CString name, std::vector<ResourceId> reads,
|
||||
std::vector<ResourceId> writes);
|
||||
struct AttachmentInfo {
|
||||
utils::CString name;
|
||||
ResourceId id;
|
||||
bool operator==(const AttachmentInfo& rhs) const;
|
||||
};
|
||||
|
||||
struct RenderTargetInfo {
|
||||
std::vector<AttachmentInfo> discardStart;
|
||||
std::vector<AttachmentInfo> discardEnd;
|
||||
std::vector<AttachmentInfo> clear;
|
||||
bool operator==(const RenderTargetInfo& rhs) const;
|
||||
};
|
||||
|
||||
Pass(uint32_t id, utils::CString name, std::vector<ResourceId> reads,
|
||||
std::vector<ResourceId> writes, std::vector<RenderTargetInfo> renderTargets = {});
|
||||
|
||||
bool operator==(const Pass& rhs) const;
|
||||
|
||||
uint32_t id;
|
||||
utils::CString name;
|
||||
std::vector<ResourceId> reads;
|
||||
std::vector<ResourceId> writes;
|
||||
std::vector<RenderTargetInfo> renderTargets;
|
||||
};
|
||||
|
||||
struct Resource {
|
||||
|
||||
@@ -37,13 +37,25 @@ bool FrameGraphInfo::operator==(const FrameGraphInfo& rhs) const {
|
||||
&& resources == rhs.resources;
|
||||
}
|
||||
|
||||
FrameGraphInfo::Pass::Pass(utils::CString name, std::vector<ResourceId> reads,
|
||||
std::vector<ResourceId> writes): name(std::move(name)),
|
||||
FrameGraphInfo::Pass::Pass(uint32_t id, utils::CString name, std::vector<ResourceId> reads,
|
||||
std::vector<ResourceId> writes, std::vector<RenderTargetInfo> renderTargets):
|
||||
id(id),
|
||||
name(std::move(name)),
|
||||
reads(std::move(reads)),
|
||||
writes(std::move(writes)) {}
|
||||
writes(std::move(writes)),
|
||||
renderTargets(std::move(renderTargets)) {}
|
||||
|
||||
bool FrameGraphInfo::Pass::operator==(const Pass& rhs) const {
|
||||
return name == rhs.name && reads == rhs.reads && writes == rhs.writes;
|
||||
return id == rhs.id && name == rhs.name && reads == rhs.reads && writes == rhs.writes &&
|
||||
renderTargets == rhs.renderTargets;
|
||||
}
|
||||
|
||||
bool FrameGraphInfo::Pass::AttachmentInfo::operator==(const AttachmentInfo& rhs) const {
|
||||
return name == rhs.name && id == rhs.id;
|
||||
}
|
||||
|
||||
bool FrameGraphInfo::Pass::RenderTargetInfo::operator==(const RenderTargetInfo& rhs) const {
|
||||
return discardStart == rhs.discardStart && discardEnd == rhs.discardEnd && clear == rhs.clear;
|
||||
}
|
||||
|
||||
FrameGraphInfo::Resource::Resource(ResourceId id, utils::CString name,
|
||||
|
||||
@@ -57,12 +57,49 @@ void writeResourceIds(std::ostream& os, const std::vector<ResourceId>& resources
|
||||
}
|
||||
}
|
||||
|
||||
void writeRenderTargetInfo(std::ostream& os,
|
||||
const std::vector<FrameGraphInfo::Pass::RenderTargetInfo>& renderTargets) {
|
||||
os << " \"renderTargets\": [\n";
|
||||
for (size_t i = 0; i < renderTargets.size(); ++i) {
|
||||
const auto& rt = renderTargets[i];
|
||||
os << " {\n";
|
||||
|
||||
auto writeAttachmentInfo =
|
||||
[&](const char* label,
|
||||
const std::vector<FrameGraphInfo::Pass::AttachmentInfo>& attachments) {
|
||||
os << " \"" << label << "\": [\n";
|
||||
for (size_t k = 0; k < attachments.size(); ++k) {
|
||||
const auto& att = attachments[k];
|
||||
os << " { \"name\": ";
|
||||
writeJSONString(os, att.name.c_str());
|
||||
os << ", \"id\": " << att.id << " }";
|
||||
if (k + 1 < attachments.size()) os << ",";
|
||||
os << "\n";
|
||||
}
|
||||
os << " ]";
|
||||
};
|
||||
|
||||
writeAttachmentInfo("discardStart", rt.discardStart);
|
||||
os << ",\n";
|
||||
writeAttachmentInfo("discardEnd", rt.discardEnd);
|
||||
os << ",\n";
|
||||
writeAttachmentInfo("clear", rt.clear);
|
||||
os << "\n";
|
||||
|
||||
os << " }";
|
||||
if (i + 1 < renderTargets.size()) os << ",";
|
||||
os << "\n";
|
||||
}
|
||||
os << " ]\n";
|
||||
}
|
||||
|
||||
void writePasses(std::ostream& os, const FrameGraphInfo& frameGraph) {
|
||||
os << " \"passes\": [\n";
|
||||
auto& passes = frameGraph.getPasses();
|
||||
for (size_t i = 0; i < passes.size(); ++i) {
|
||||
const FrameGraphInfo::Pass& pass = passes[i];
|
||||
os << " {\n";
|
||||
os << " \"id\": " << pass.id << ",\n";
|
||||
os << " \"name\": ";
|
||||
writeJSONString(os, pass.name.c_str());
|
||||
os << ",\n";
|
||||
@@ -75,7 +112,10 @@ void writePasses(std::ostream& os, const FrameGraphInfo& frameGraph) {
|
||||
const std::vector<ResourceId>& writes = pass.writes;
|
||||
os << " \"writes\": [";
|
||||
writeResourceIds(os, writes);
|
||||
os << "]\n";
|
||||
os << "],\n";
|
||||
|
||||
writeRenderTargetInfo(os, pass.renderTargets);
|
||||
os << "\n";
|
||||
|
||||
os << " }";
|
||||
if (i + 1 < passes.size()) os << ",";
|
||||
|
||||
@@ -28,11 +28,13 @@ const REGULAR_FONT_SIZE = 12;
|
||||
// Constants for color operations
|
||||
const READ_COLOR = '#aee1a6';
|
||||
const WRITE_COLOR = '#df8e8e';
|
||||
const NO_ACCESS_COLOR = '#d8dde754';
|
||||
const NO_ACCESS_COLOR = '#bcbcbc';
|
||||
const READ_WRITE_COLOR = '#ffeb99';
|
||||
const DEFAULT_COLOR = '#ffffff';
|
||||
const SUBRESOURCE_COLOR = '#d3d3d3';
|
||||
|
||||
const SELECTED_ROW_COLUMN_COLOR = "rgba(180,210,240,.35)";
|
||||
|
||||
// Constants for view mode toggle
|
||||
const VIEW_TOGGLE_INACTIVE_COLOR = '#292929';
|
||||
const VIEW_TOGGLE_UNSELECTED_COLOR = '#3f4cbe';
|
||||
@@ -200,6 +202,13 @@ class FrameGraphSidePanel extends LitElement {
|
||||
background-color: ${this.connected ? VIEW_TOGGLE_SELECTED_COLOR:VIEW_TOGGLE_INACTIVE_COLOR};
|
||||
font-weight: bold;
|
||||
}
|
||||
.resource-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.render-target-resource {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -208,6 +217,7 @@ class FrameGraphSidePanel extends LitElement {
|
||||
connected: {type: Boolean, attribute: 'connected'},
|
||||
selectedFrameGraph: {type: String, attribute: 'selected-framegraph'},
|
||||
selectedResourceId: {type: Number, attribute: 'selected-resource'},
|
||||
selectedPassIndex: {type: Number, attribute: 'selected-pass'},
|
||||
viewMode: {type: String, attribute: 'view-mode'},
|
||||
|
||||
database: {type: Object, state: true},
|
||||
@@ -222,6 +232,7 @@ class FrameGraphSidePanel extends LitElement {
|
||||
this.database = {};
|
||||
this.viewMode = VIEW_MODE_TABLE;
|
||||
this.selectedFrameGraph = '';
|
||||
this.selectedPassIndex = -1;
|
||||
}
|
||||
|
||||
updated(props) {
|
||||
@@ -274,6 +285,32 @@ class FrameGraphSidePanel extends LitElement {
|
||||
return null;
|
||||
}
|
||||
|
||||
_findCurrentPass() {
|
||||
if (!this.selectedFrameGraph || this.selectedPassIndex === -1 ||
|
||||
this.selectedPassIndex === undefined) {
|
||||
return null;
|
||||
}
|
||||
const passes = this.database[this.selectedFrameGraph]?.passes;
|
||||
return passes ? passes[this.selectedPassIndex] : null;
|
||||
}
|
||||
|
||||
_handleResourceLinkClick(ev, id) {
|
||||
ev.stopPropagation();
|
||||
this.dispatchEvent(new CustomEvent('select-resource', {
|
||||
detail: id,
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}));
|
||||
}
|
||||
|
||||
_formatResourceId(id) {
|
||||
const resources = this.database[this.selectedFrameGraph]?.resources;
|
||||
const resource = resources ? resources[id] : null;
|
||||
const label = resource ? `${resource.name} [${id}]` : `[${id}]`;
|
||||
return html`<span class="resource-link" style="cursor: pointer;"
|
||||
@click="${(e) => this._handleResourceLinkClick(e, id)}">${label}</span>`;
|
||||
}
|
||||
|
||||
render() {
|
||||
const renderFrameGraphs = (title) => {
|
||||
if (!this.framegraphs.length)
|
||||
@@ -316,10 +353,8 @@ class FrameGraphSidePanel extends LitElement {
|
||||
return html`
|
||||
<menu-section title="${title}">
|
||||
<div class="resource-content">
|
||||
<div><b>Name:</b> ${currentResource.name}</div>
|
||||
</div>
|
||||
<div class="resource-content">
|
||||
<div><b>ID:</b> ${currentResource.id}</div>
|
||||
<div><b>Name:</b> ${currentResource.name}
|
||||
<b>[ID=${currentResource.id}]</b></div>
|
||||
</div>
|
||||
${currentResource.properties.length > 0 ? html`
|
||||
<div class="resource-content">
|
||||
@@ -335,12 +370,76 @@ class FrameGraphSidePanel extends LitElement {
|
||||
`;
|
||||
};
|
||||
|
||||
const renderPassDetails = (title) => {
|
||||
const currentPass = this._findCurrentPass();
|
||||
if (!currentPass) return nothing;
|
||||
|
||||
const renderRenderTarget = (rt, index) => {
|
||||
const resourceFlags = {}; // id -> { name, flags: [] }
|
||||
|
||||
const processList = (list, flagName) => {
|
||||
if (!list) return;
|
||||
for (const att of list) {
|
||||
if (!resourceFlags[att.id]) {
|
||||
resourceFlags[att.id] = { name: att.name, id: att.id, flags: [] };
|
||||
}
|
||||
resourceFlags[att.id].flags.push(flagName);
|
||||
}
|
||||
};
|
||||
|
||||
processList(rt.discardStart, "Discard Start");
|
||||
processList(rt.discardEnd, "Discard End");
|
||||
processList(rt.clear, "Clear");
|
||||
|
||||
const resources = Object.values(resourceFlags);
|
||||
if (resources.length === 0) return nothing;
|
||||
|
||||
return html`
|
||||
<div class="resource-content render-target-resource"
|
||||
style="margin-top: 5px; border-top: 1px dashed #6f6f6f;">
|
||||
<div>(${index})</div>
|
||||
<ul style="margin:0;padding-inline-start:25px">
|
||||
${resources.map(res => html`
|
||||
<li>
|
||||
${this._formatResourceId(res.id)}: ${res.flags.join(", ")}
|
||||
</li>
|
||||
`)}
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
|
||||
const joinResources = (ids) => {
|
||||
return ids.map((id, i) => html`
|
||||
<li>${this._formatResourceId(id)}</li>`);
|
||||
};
|
||||
|
||||
return html`
|
||||
<menu-section title="${title}">
|
||||
<div class="resource-content">
|
||||
<div><b>Name:</b> ${currentPass.name} <b>[ID=${currentPass.id}]</b></div>
|
||||
</div>
|
||||
${currentPass.reads.length > 0 ? html`
|
||||
<div class="resource-content">
|
||||
<div><b>Reads:</b> </div>
|
||||
<ul style="margin: 4px 0;">
|
||||
${joinResources(currentPass.reads)}
|
||||
</ul>
|
||||
</div>` : nothing}
|
||||
${currentPass.renderTargets && currentPass.renderTargets.length > 0 ?
|
||||
html`<div><b>Writes (Render Targets):</b></div>
|
||||
${currentPass.renderTargets.map((rt, i) => renderRenderTarget(rt, i))}` : nothing}
|
||||
</menu-section>
|
||||
`;
|
||||
};
|
||||
|
||||
return html`
|
||||
<style>${this.dynamicStyle()}</style>
|
||||
<div class="container">
|
||||
<div class="title">fgviewer</div>
|
||||
${renderFrameGraphs("Views") ?? nothing}
|
||||
${renderResourceDetails("Resource Details") ?? nothing}
|
||||
${renderPassDetails("Pass Details") ?? nothing}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -439,6 +538,7 @@ class FrameGraphTable extends LitElement {
|
||||
}
|
||||
.selected {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
}
|
||||
.sticky-col {
|
||||
text-align: right;
|
||||
@@ -457,6 +557,7 @@ class FrameGraphTable extends LitElement {
|
||||
return {
|
||||
frameGraphData: {type: Object, state: true}, // Expecting a JSON frame graph structure
|
||||
selectedResourceId: {type: Number, attribute: 'selected-resource'},
|
||||
selectedPassIndex: {type: Number, attribute: 'selected-pass'},
|
||||
tooltipText: {type: String, state: true},
|
||||
tooltipVisible: {type: Boolean, state: true},
|
||||
tooltipX: {type: Number, state: true},
|
||||
@@ -468,6 +569,7 @@ class FrameGraphTable extends LitElement {
|
||||
super();
|
||||
this.frameGraphData = null;
|
||||
this.selectedResourceId = -1;
|
||||
this.selectedPassIndex = -1;
|
||||
this.expandedResourceSet = new Set();
|
||||
this.subresourceToParent = {};
|
||||
this._hoverTimeout = null;
|
||||
@@ -494,7 +596,7 @@ class FrameGraphTable extends LitElement {
|
||||
}
|
||||
|
||||
_getRowGridTemplateColumnsStyle(numColumns) {
|
||||
let out = '165px ';
|
||||
let out = '185px ';
|
||||
const oneCol = '35px ';
|
||||
for (let i = 0; i < numColumns; i++) {
|
||||
out += oneCol;
|
||||
@@ -517,15 +619,23 @@ class FrameGraphTable extends LitElement {
|
||||
}
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
if (props.has('selectedResourceId')) {
|
||||
const parentId = this.subresourceToParent[this.selectedResourceId];
|
||||
if (parentId && !this.expandedResourceSet.has(parentId)) {
|
||||
this.expandedResourceSet.add(parentId);
|
||||
this.requestUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_getCellColor(type) {
|
||||
_getCellColor(type, defaultColor) {
|
||||
return {
|
||||
[RESOURCE_USAGE_TYPE_READ]: READ_COLOR,
|
||||
[RESOURCE_USAGE_TYPE_WRITE]: WRITE_COLOR,
|
||||
[RESOURCE_USAGE_TYPE_NO_ACCESS]: NO_ACCESS_COLOR,
|
||||
[RESOURCE_USAGE_TYPE_READ_WRITE]: READ_WRITE_COLOR
|
||||
}[type] || DEFAULT_COLOR;
|
||||
}[type] || defaultColor;
|
||||
}
|
||||
|
||||
_toggleCollapse(resourceId) {
|
||||
@@ -549,9 +659,10 @@ class FrameGraphTable extends LitElement {
|
||||
_renderResourceUsage(allPasses, resourceIds, defaultColor, lastRow) {
|
||||
const passLen = allPasses.length;
|
||||
return allPasses.map((passData, index) => {
|
||||
const isSelectedPass = index === this.selectedPassIndex;
|
||||
const isRead = resourceIds.some(resourceId => passData?.reads.includes(resourceId));
|
||||
const isWrite = resourceIds.some(resourceId => passData?.writes.includes(resourceId));
|
||||
let type = null;
|
||||
let restype = null;
|
||||
|
||||
const hasUsed = (passData) => {
|
||||
return resourceIds.some(resourceId =>
|
||||
@@ -561,24 +672,25 @@ class FrameGraphTable extends LitElement {
|
||||
const hasBeenUsedBefore = allPasses.slice(0, index).some(hasUsed);
|
||||
const willBeUsedLater = allPasses.slice(index + 1).some(hasUsed);
|
||||
|
||||
if (isRead && isWrite) type = RESOURCE_USAGE_TYPE_READ_WRITE;
|
||||
else if (isRead) type = RESOURCE_USAGE_TYPE_READ;
|
||||
else if (isWrite) type = RESOURCE_USAGE_TYPE_WRITE;
|
||||
else if (hasBeenUsedBefore && willBeUsedLater) type = RESOURCE_USAGE_TYPE_NO_ACCESS;
|
||||
if (isRead && isWrite) restype = RESOURCE_USAGE_TYPE_READ_WRITE;
|
||||
else if (isRead) restype = RESOURCE_USAGE_TYPE_READ;
|
||||
else if (isWrite) restype = RESOURCE_USAGE_TYPE_WRITE;
|
||||
else if (hasBeenUsedBefore && willBeUsedLater) restype = RESOURCE_USAGE_TYPE_NO_ACCESS;
|
||||
|
||||
const lastPass = index == passLen - 1;
|
||||
const borderStyle = '1px solid #a5a5a5';
|
||||
const bgColor = this._getCellColor(type, defaultColor);
|
||||
const bgColor = isSelectedPass ? this._getCellColor(restype, SELECTED_ROW_COLUMN_COLOR)
|
||||
: this._getCellColor(restype, defaultColor);
|
||||
const style = `background-color:${bgColor};` +
|
||||
`border-left:${borderStyle};border-top:${borderStyle};` +
|
||||
(lastPass ? `border-right:${borderStyle};` : '') +
|
||||
(lastRow ? `border-bottom:${borderStyle};` : '');
|
||||
`border-left:${borderStyle};border-top:${borderStyle};` +
|
||||
(lastPass ? `border-right:${borderStyle};` : '') +
|
||||
(lastRow ? `border-bottom:${borderStyle};` : '');
|
||||
|
||||
let tooltip = '';
|
||||
if (type === RESOURCE_USAGE_TYPE_READ) tooltip = 'Read';
|
||||
else if (type === RESOURCE_USAGE_TYPE_WRITE) tooltip = 'Write';
|
||||
else if (type === RESOURCE_USAGE_TYPE_READ_WRITE) tooltip = 'Read-Write';
|
||||
else if (type === RESOURCE_USAGE_TYPE_NO_ACCESS) tooltip = 'No Access';
|
||||
if (restype === RESOURCE_USAGE_TYPE_READ) tooltip = 'Read';
|
||||
else if (restype === RESOURCE_USAGE_TYPE_WRITE) tooltip = 'Write';
|
||||
else if (restype === RESOURCE_USAGE_TYPE_READ_WRITE) tooltip = 'Read-Write';
|
||||
else if (restype === RESOURCE_USAGE_TYPE_NO_ACCESS) tooltip = 'No Access';
|
||||
|
||||
return html`
|
||||
<div class="grid-cell" style="${style}"
|
||||
@@ -635,9 +747,11 @@ class FrameGraphTable extends LitElement {
|
||||
groupColorStyle = "border-right:5px solid " + COLORS[colorIndex];
|
||||
}
|
||||
|
||||
const isSelectedResource = resource.id === this.selectedResourceId;
|
||||
const onClickResource = () => this._handleResourceClick(resource.id);
|
||||
const selectedStyle = resource.id === this.selectedResourceId ? "selected" : "";
|
||||
const selectedStyle = isSelectedResource ? "selected" : "";
|
||||
const rowStyle = this._getRowGridTemplateColumnsStyle(allPasses.length);
|
||||
const defaultColor = isSelectedResource ? SELECTED_ROW_COLUMN_COLOR : DEFAULT_COLOR;
|
||||
return html`
|
||||
<div class="grid-row" id="resource-${resource.id}" style="${rowStyle}">
|
||||
<div class="grid-cell sticky-col resource ${selectedStyle}" style="${groupColorStyle}"
|
||||
@@ -652,11 +766,19 @@ class FrameGraphTable extends LitElement {
|
||||
${resource.name}
|
||||
${hasSubresources && !isExpanded ? html`(${subresourceIds.length})` : nothing}
|
||||
</div>
|
||||
${this._renderResourceUsage(allPasses, resourceIds, DEFAULT_COLOR, lastRow)}
|
||||
${this._renderResourceUsage(allPasses, resourceIds, defaultColor, lastRow)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
_handlePassClick(index) {
|
||||
this.dispatchEvent(new CustomEvent('select-pass', {
|
||||
detail: index,
|
||||
bubbles: true,
|
||||
composed: true
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.frameGraphData?.passes || !this.frameGraphData?.resources)
|
||||
return nothing;
|
||||
@@ -670,8 +792,14 @@ class FrameGraphTable extends LitElement {
|
||||
<div class="grid-row" style="${rowStyle}">
|
||||
<div class="grid-cell" style="${colStyle}">
|
||||
</div>
|
||||
${allPasses.map(pass => html`<div class="grid-cell" style="border:1px solid rgba(0,0,0,0)">
|
||||
<div class="pass-cell">${pass.name}</div></div>`)}
|
||||
${allPasses.map((pass, index) => {
|
||||
const isSelected = index === this.selectedPassIndex;
|
||||
const gclass = isSelected ? "grid-cell selected" : "grid-cell";
|
||||
const pclass = isSelected ? "pass-cell selected" : "pass-cell";
|
||||
return html`<div class="${gclass}" style="border:1px solid rgba(0,0,0,0); cursor: pointer;"
|
||||
@click="${() => this._handlePassClick(index)}">
|
||||
<div class="${pclass}">${pass.name}</div></div>`;
|
||||
})}
|
||||
</div>
|
||||
${this._renderResourceRows(resources, allPasses)}
|
||||
</div>
|
||||
@@ -819,6 +947,7 @@ class FrameGraphViewer extends LitElement {
|
||||
this.database = {};
|
||||
this.selectedFrameGraph = null;
|
||||
this.selectedResourceId = -1;
|
||||
this.selectedPassIndex = -1;
|
||||
this.viewMode = VIEW_MODE_TABLE;
|
||||
this.init();
|
||||
|
||||
@@ -830,7 +959,13 @@ class FrameGraphViewer extends LitElement {
|
||||
|
||||
this.addEventListener('select-resource',
|
||||
(ev) => {
|
||||
this.selectedResourceId = ev.detail;
|
||||
this.selectedResourceId = this.selectedResourceId === ev.detail ? -1 : ev.detail;
|
||||
}
|
||||
);
|
||||
|
||||
this.addEventListener('select-pass',
|
||||
(ev) => {
|
||||
this.selectedPassIndex = this.selectedPassIndex === ev.detail ? -1 : ev.detail;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -847,6 +982,7 @@ class FrameGraphViewer extends LitElement {
|
||||
database: {type: Object, state: true},
|
||||
selectedFrameGraph: {type: String, state: true},
|
||||
selectedResourceId: {type: Number, state: true},
|
||||
selectedPassIndex: {type: Number, state: true},
|
||||
viewMode: {type: String, state: true},
|
||||
}
|
||||
}
|
||||
@@ -867,6 +1003,7 @@ class FrameGraphViewer extends LitElement {
|
||||
?connected="${this.connected}"
|
||||
selected-framegraph="${this.selectedFrameGraph}"
|
||||
selected-resource="${this.selectedResourceId}"
|
||||
selected-pass="${this.selectedPassIndex}"
|
||||
view-mode="${this.viewMode}">
|
||||
</framegraph-sidepanel>
|
||||
|
||||
@@ -874,7 +1011,8 @@ class FrameGraphViewer extends LitElement {
|
||||
style="display: ${this.viewMode === VIEW_MODE_TABLE ? 'block' : 'none'};"
|
||||
?connected="${this.connected}"
|
||||
selected-framegraph="${this.selectedFrameGraph}"
|
||||
selected-resource="${this.selectedResourceId}">
|
||||
selected-resource="${this.selectedResourceId}"
|
||||
selected-pass="${this.selectedPassIndex}">
|
||||
</framegraph-table>
|
||||
|
||||
<graphviz-view id="graphviz"
|
||||
|
||||
Reference in New Issue
Block a user