mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 17:40:39 +00:00
* This is supported currently in the API inspector, constant buffer previewer, and resource inspector. * The saved expansions are only saved while the capture is open, and will be reset each time.
This commit is contained in:
@@ -243,6 +243,11 @@ void RDTreeView::saveInternalExpansion(uint key, int keyColumn, int role)
|
||||
saveExpansionExternal(state, key, keyColumn, role);
|
||||
}
|
||||
|
||||
bool RDTreeView::hasInternalExpansion(uint key)
|
||||
{
|
||||
return m_Expansions.contains(key);
|
||||
}
|
||||
|
||||
void RDTreeView::applyInternalExpansion(uint key, int keyColumn, int role)
|
||||
{
|
||||
RDTreeViewExpansionState &state = m_Expansions[key];
|
||||
|
||||
@@ -97,6 +97,7 @@ public:
|
||||
QAbstractItemDelegate *itemDelegate() const;
|
||||
|
||||
void saveInternalExpansion(uint key, int keyColumn, int role = Qt::DisplayRole);
|
||||
bool hasInternalExpansion(uint key);
|
||||
void applyInternalExpansion(uint key, int keyColumn, int role = Qt::DisplayRole);
|
||||
void clearInternalExpansions();
|
||||
|
||||
@@ -111,6 +112,7 @@ public:
|
||||
saveInternalExpansion(qHash(keystring), keyColumn, role);
|
||||
}
|
||||
|
||||
bool hasInternalExpansion(QString keystring) { return hasInternalExpansion(qHash(keystring)); }
|
||||
void applyInternalExpansion(QString keystring, int keyColumn, int role = Qt::DisplayRole)
|
||||
{
|
||||
applyInternalExpansion(qHash(keystring), keyColumn, role);
|
||||
|
||||
@@ -64,13 +64,20 @@ void APIInspector::OnCaptureClosed()
|
||||
{
|
||||
ui->apiEvents->clear();
|
||||
ui->callstack->clear();
|
||||
ui->apiEvents->clearInternalExpansions();
|
||||
m_EventID = 0;
|
||||
}
|
||||
|
||||
void APIInspector::OnSelectedEventChanged(uint32_t eventId)
|
||||
{
|
||||
ui->apiEvents->saveInternalExpansion(m_EventID, 0);
|
||||
|
||||
ui->apiEvents->clearSelection();
|
||||
|
||||
fillAPIView();
|
||||
|
||||
m_EventID = eventId;
|
||||
ui->apiEvents->applyInternalExpansion(m_EventID, 0);
|
||||
}
|
||||
|
||||
void APIInspector::addCallstack(rdcarray<rdcstr> calls)
|
||||
|
||||
@@ -57,6 +57,8 @@ private:
|
||||
Ui::APIInspector *ui;
|
||||
ICaptureContext &m_Ctx;
|
||||
|
||||
uint32_t m_EventID;
|
||||
|
||||
void addCallstack(rdcarray<rdcstr> calls);
|
||||
void fillAPIView();
|
||||
};
|
||||
|
||||
@@ -88,6 +88,7 @@ void ConstantBufferPreviewer::OnCaptureLoaded()
|
||||
void ConstantBufferPreviewer::OnCaptureClosed()
|
||||
{
|
||||
ui->variables->clear();
|
||||
ui->variables->clearInternalExpansions();
|
||||
|
||||
ui->saveCSV->setEnabled(false);
|
||||
|
||||
@@ -101,6 +102,8 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
|
||||
uint64_t offs = cb.byteOffset;
|
||||
uint64_t size = cb.byteSize;
|
||||
|
||||
ResourceId prevShader = m_shader;
|
||||
|
||||
m_shader = m_Ctx.CurPipelineState().GetShader(m_stage);
|
||||
QString entryPoint = m_Ctx.CurPipelineState().GetShaderEntryPoint(m_stage);
|
||||
const ShaderReflection *reflection = m_Ctx.CurPipelineState().GetShaderReflection(m_stage);
|
||||
@@ -109,6 +112,13 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
|
||||
|
||||
updateLabels();
|
||||
|
||||
if(m_formatOverride.empty())
|
||||
{
|
||||
// stage, slot, and array index are all invariant across a given ConstantBufferPreviewer
|
||||
// instance. We only need to use the actual bound shader as a key.
|
||||
ui->variables->saveInternalExpansion(ToQStr(prevShader), 0);
|
||||
}
|
||||
|
||||
if(reflection == NULL || m_slot >= reflection->constantBlocks.size())
|
||||
{
|
||||
setVariables({});
|
||||
@@ -121,27 +131,43 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
|
||||
bytebuf data = r->GetBufferData(m_cbuffer, offs, size);
|
||||
rdcarray<ShaderVariable> vars = applyFormatOverride(data);
|
||||
GUIInvoke::call(this, [this, vars, wasEmpty] {
|
||||
RDTreeViewExpansionState state;
|
||||
ui->variables->saveExpansionExternal(state, 0, 0);
|
||||
setVariables(vars);
|
||||
if(wasEmpty)
|
||||
{
|
||||
for(int i = 0; i < 3; i++)
|
||||
ui->variables->resizeColumnToContents(i);
|
||||
}
|
||||
ui->variables->applyExternalExpansion(state, 0, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Ctx.Replay().AsyncInvoke([this, entryPoint, offs, wasEmpty](IReplayController *r) {
|
||||
m_Ctx.Replay().AsyncInvoke([this, entryPoint, offs, prevShader, wasEmpty](IReplayController *r) {
|
||||
rdcarray<ShaderVariable> vars = r->GetCBufferVariableContents(
|
||||
m_shader, entryPoint.toUtf8().data(), m_slot, m_cbuffer, offs);
|
||||
GUIInvoke::call(this, [this, vars, wasEmpty] {
|
||||
GUIInvoke::call(this, [this, vars, prevShader, wasEmpty] {
|
||||
|
||||
// save this state to reapply if we don't already have an internal expansion for the new
|
||||
// shader, since this means two shaders with the same or similar constants will preserve
|
||||
// expansion across selections.
|
||||
RDTreeViewExpansionState state;
|
||||
if(!ui->variables->hasInternalExpansion(ToQStr(m_shader)))
|
||||
ui->variables->saveExpansionExternal(state, 0, 0);
|
||||
|
||||
setVariables(vars);
|
||||
if(wasEmpty)
|
||||
{
|
||||
for(int i = 0; i < 3; i++)
|
||||
ui->variables->resizeColumnToContents(i);
|
||||
}
|
||||
|
||||
if(ui->variables->hasInternalExpansion(ToQStr(m_shader)))
|
||||
ui->variables->applyInternalExpansion(ToQStr(m_shader), 0);
|
||||
else
|
||||
ui->variables->applyExternalExpansion(state, 0, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -262,72 +288,10 @@ void ConstantBufferPreviewer::addVariables(RDTreeWidgetItem *root,
|
||||
}
|
||||
}
|
||||
|
||||
bool ConstantBufferPreviewer::updateVariables(RDTreeWidgetItem *root,
|
||||
const rdcarray<ShaderVariable> &prevVars,
|
||||
const rdcarray<ShaderVariable> &newVars)
|
||||
{
|
||||
// mismatched child count? can't update
|
||||
if(prevVars.size() != newVars.size())
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < prevVars.count(); i++)
|
||||
{
|
||||
const ShaderVariable &a = prevVars[i];
|
||||
const ShaderVariable &b = newVars[i];
|
||||
|
||||
// different names? can't update
|
||||
if(strcmp(a.name.c_str(), b.name.c_str()))
|
||||
return false;
|
||||
|
||||
// different size or type? can't update
|
||||
if(a.rows != b.rows || a.columns != b.columns || a.displayAsHex != b.displayAsHex ||
|
||||
a.isStruct != b.isStruct || a.rowMajor != b.rowMajor || a.type != b.type)
|
||||
return false;
|
||||
|
||||
// update this node's value column
|
||||
RDTreeWidgetItem *node = root->child(i);
|
||||
|
||||
node->setText(1, VarString(b));
|
||||
|
||||
if(a.rows > 1)
|
||||
{
|
||||
for(uint32_t r = 0; r < a.rows; r++)
|
||||
node->child(r)->setText(1, RowString(b, r));
|
||||
}
|
||||
|
||||
if(!a.members.isEmpty())
|
||||
{
|
||||
// recurse to update child members. This handles a and b having different number of variables
|
||||
bool updated = updateVariables(node, a.members, b.members);
|
||||
|
||||
if(!updated)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// got this far without bailing? we updated!
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConstantBufferPreviewer::setVariables(const rdcarray<ShaderVariable> &vars)
|
||||
{
|
||||
ui->variables->beginUpdate();
|
||||
|
||||
// try to update the variables in-place by only changing their values, if the set of variables
|
||||
// matches *exactly* to what we had before.
|
||||
//
|
||||
// This keeps things like expanded structs and matrices when moving between drawcalls
|
||||
bool updated = updateVariables(ui->variables->invisibleRootItem(), m_Vars, vars);
|
||||
|
||||
// update the variables either way
|
||||
m_Vars = vars;
|
||||
|
||||
if(updated)
|
||||
{
|
||||
ui->variables->endUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
ui->variables->clear();
|
||||
|
||||
ui->saveCSV->setEnabled(false);
|
||||
|
||||
@@ -81,11 +81,6 @@ private:
|
||||
void addVariables(RDTreeWidgetItem *root, const rdcarray<ShaderVariable> &vars);
|
||||
void setVariables(const rdcarray<ShaderVariable> &vars);
|
||||
|
||||
rdcarray<ShaderVariable> m_Vars;
|
||||
|
||||
bool updateVariables(RDTreeWidgetItem *root, const rdcarray<ShaderVariable> &prevVars,
|
||||
const rdcarray<ShaderVariable> &newVars);
|
||||
|
||||
void updateLabels();
|
||||
|
||||
static QList<ConstantBufferPreviewer *> m_Previews;
|
||||
|
||||
@@ -201,6 +201,9 @@ void ResourceInspector::Inspect(ResourceId id)
|
||||
if(m_Resource == id)
|
||||
return;
|
||||
|
||||
if(m_Resource != ResourceId())
|
||||
ui->initChunks->saveInternalExpansion(ToQStr(m_Resource), 0);
|
||||
|
||||
m_Resource = id;
|
||||
|
||||
ui->viewContents->setVisible(m_Ctx.GetTexture(id) || m_Ctx.GetBuffer(id));
|
||||
@@ -325,6 +328,9 @@ void ResourceInspector::Inspect(ResourceId id)
|
||||
}
|
||||
|
||||
ui->initChunks->setUpdatesEnabled(true);
|
||||
|
||||
if(m_Resource != ResourceId())
|
||||
ui->initChunks->applyInternalExpansion(ToQStr(m_Resource), 0);
|
||||
}
|
||||
|
||||
void ResourceInspector::OnCaptureLoaded()
|
||||
@@ -347,6 +353,7 @@ void ResourceInspector::OnCaptureClosed()
|
||||
m_ResourceModel->reset();
|
||||
|
||||
ui->initChunks->clear();
|
||||
ui->initChunks->clearInternalExpansions();
|
||||
ui->relatedResources->clear();
|
||||
ui->resourceUsage->clear();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user