Save and load edited shaders as capture modifications

* When a shader edit is loaded with a capture, it's loaded as "pending" and not
  immediately applied.
This commit is contained in:
baldurk
2020-10-21 14:14:20 +01:00
parent 31bf9f4593
commit 806187f613
11 changed files with 429 additions and 71 deletions
+172 -2
View File
@@ -978,6 +978,16 @@ void CaptureContext::LoadCaptureThreaded(const QString &captureFile, const Repla
bytebuf buf = access->GetSectionContents(idx);
LoadNotes(QString::fromUtf8((const char *)buf.data(), buf.count()));
}
idx = access->FindSectionByType(SectionType::EditedShaders);
if(idx >= 0)
{
bytebuf buf = access->GetSectionContents(idx);
GUIInvoke::call(m_MainWindow, [this, buf]() {
LoadEdits(QString::fromUtf8((const char *)buf.data(), buf.count()));
});
}
QString driver = access->DriverName();
if(driver == lit("Image"))
{
@@ -1480,6 +1490,11 @@ void CaptureContext::SetRemoteHost(int hostIdx)
m_MainWindow->setRemoteHost(hostIdx);
}
bool CaptureContext::IsResourceReplaced(ResourceId id)
{
return m_ReplacedResources.contains(id);
}
void CaptureContext::RegisterReplacement(ResourceId id)
{
if(!m_ReplacedResources.contains(id))
@@ -1596,6 +1611,9 @@ void CaptureContext::SaveChanges()
if(m_CaptureMods & CaptureModifications::Notes)
success &= SaveNotes();
if(m_CaptureMods & CaptureModifications::EditedShaders)
success &= SaveEdits();
if(!success)
{
RDDialog::critical(m_MainWindow, tr("Can't save file"),
@@ -1729,6 +1747,66 @@ void CaptureContext::LoadNotes(const QString &data)
}
}
bool CaptureContext::SaveEdits()
{
// make sure this format matches SetCaptureFileComments in app_api.cpp if it changes
QVariantList editors;
for(ShaderViewer *e : m_ShaderEditors)
{
QVariantMap editor = e->SaveEditor();
if(!editor.isEmpty())
editors.push_back(e->SaveEditor());
}
QVariantMap root;
root[lit("editors")] = editors;
QString json = VariantToJSON(root);
SectionProperties props;
props.type = SectionType::EditedShaders;
props.version = 1;
return Replay().GetCaptureAccess()->WriteSection(props, json.toUtf8());
}
void CaptureContext::LoadEdits(const QString &data)
{
QVariantMap root = JSONToVariant(data);
QVariantList editors = root[lit("editors")].toList();
auto replaceSaveCallback = [this](ICaptureContext *ctx, IShaderViewer *viewer, ResourceId id,
ShaderStage stage, ShaderEncoding shaderEncoding,
ShaderCompileFlags flags, rdcstr entryFunc, bytebuf shaderBytes) {
ApplyShaderEdit(viewer, id, stage, shaderEncoding, flags, entryFunc, shaderBytes);
};
auto replaceCloseCallback = [this](ICaptureContext *ctx, IShaderViewer *view, ResourceId id) {
RevertShaderEdit(view, id);
};
for(QVariant e : editors)
{
ShaderViewer *edit =
ShaderViewer::LoadEditor(*this, e.toMap(), replaceSaveCallback, replaceCloseCallback,
[this](ShaderViewer *view, bool closed) {
m_CaptureMods |= CaptureModifications::EditedShaders;
if(closed)
m_ShaderEditors.removeOne(view);
},
m_MainWindow->Widget());
if(edit)
{
AddDockWindow(edit->Widget(), DockReference::MainToolArea, NULL);
m_ShaderEditors.push_back(edit);
}
}
}
bool CaptureContext::OpenRGPProfile(const rdcstr &filename)
{
delete m_RGP;
@@ -2195,8 +2273,100 @@ IShaderViewer *CaptureContext::EditShader(ResourceId id, ShaderStage stage,
IShaderViewer::SaveCallback saveCallback,
IShaderViewer::CloseCallback closeCallback)
{
return ShaderViewer::EditShader(*this, id, stage, entryPoint, files, shaderEncoding, flags,
saveCallback, closeCallback, m_MainWindow->Widget());
ShaderViewer *viewer = NULL;
if(id != ResourceId())
{
auto replaceSaveCallback = [this, saveCallback](
ICaptureContext *ctx, IShaderViewer *viewer, ResourceId id, ShaderStage stage,
ShaderEncoding shaderEncoding, ShaderCompileFlags flags, rdcstr entryFunc,
bytebuf shaderBytes) {
ApplyShaderEdit(viewer, id, stage, shaderEncoding, flags, entryFunc, shaderBytes);
if(saveCallback)
saveCallback(ctx, viewer, id, stage, shaderEncoding, flags, entryFunc, shaderBytes);
};
auto replaceCloseCallback = [this, closeCallback](ICaptureContext *ctx, IShaderViewer *view,
ResourceId id) {
RevertShaderEdit(view, id);
if(closeCallback)
closeCallback(ctx, view, id);
};
viewer = ShaderViewer::EditShader(*this, id, stage, entryPoint, files, shaderEncoding, flags,
replaceSaveCallback, replaceCloseCallback,
[this](ShaderViewer *view, bool closed) {
m_CaptureMods |= CaptureModifications::EditedShaders;
if(closed)
m_ShaderEditors.removeOne(view);
},
m_MainWindow->Widget());
m_ShaderEditors.push_back(viewer);
m_CaptureMods |= CaptureModifications::EditedShaders;
}
else
{
viewer = ShaderViewer::EditShader(*this, id, stage, entryPoint, files, shaderEncoding, flags,
saveCallback, closeCallback, NULL, m_MainWindow->Widget());
}
return viewer;
}
void CaptureContext::ApplyShaderEdit(IShaderViewer *viewer, ResourceId id, ShaderStage stage,
ShaderEncoding shaderEncoding, ShaderCompileFlags flags,
const rdcstr &entryFunc, const bytebuf &shaderBytes)
{
if(shaderBytes.isEmpty())
return;
ANALYTIC_SET(UIFeatures.ShaderEditing, true);
QPointer<QObject> ptr(viewer->Widget());
// invoke off to the ReplayController to replace the capture's shader
// with our edited one
Replay().AsyncInvoke([this, entryFunc, shaderBytes, shaderEncoding, flags, stage, id, ptr,
viewer](IReplayController *r) {
rdcstr errs;
ResourceId from = id;
ResourceId to;
rdctie(to, errs) =
r->BuildTargetShader(entryFunc.c_str(), shaderEncoding, shaderBytes, flags, stage);
if(to == ResourceId())
{
r->RemoveReplacement(from);
// this GUIInvoke call always needs to go through even if the viewer has been closed.
GUIInvoke::call(GetMainWindow()->Widget(), [this, from]() { UnregisterReplacement(from); });
}
else
{
r->ReplaceResource(from, to);
GUIInvoke::call(GetMainWindow()->Widget(), [this, from]() { RegisterReplacement(from); });
}
if(ptr)
GUIInvoke::call(ptr, [viewer, errs]() { viewer->ShowErrors(errs); });
});
}
void CaptureContext::RevertShaderEdit(IShaderViewer *viewer, ResourceId id)
{
// remove the replacement on close (we could make this more sophisticated if there
// was a place to control replaced resources/shaders).
Replay().AsyncInvoke([this, id](IReplayController *r) {
if(IsCaptureLoaded())
r->RemoveReplacement(id);
GUIInvoke::call(GetMainWindow()->Widget(), [this, id] { UnregisterReplacement(id); });
});
}
IShaderViewer *CaptureContext::DebugShader(const ShaderBindpointMapping *bind,
+12
View File
@@ -52,6 +52,7 @@ class StatisticsViewer;
class TimelineBar;
class PythonShell;
class ResourceInspector;
class ShaderViewer;
class CaptureContext : public ICaptureContext, IExtensionManager
{
@@ -114,6 +115,7 @@ public:
uint32_t eventId, bool force = false) override;
void SetRemoteHost(int hostIndex);
void RefreshStatus() override { SetEventID({}, m_SelectedEventID, m_EventID, true); }
bool IsResourceReplaced(ResourceId id) override;
void RegisterReplacement(ResourceId id) override;
void UnregisterReplacement(ResourceId id) override;
void RefreshUIStatus(const rdcarray<ICaptureViewer *> &exclude, bool updateSelectedEvent,
@@ -241,6 +243,11 @@ public:
ShaderCompileFlags flags, IShaderViewer::SaveCallback saveCallback,
IShaderViewer::CloseCallback closeCallback) override;
void ApplyShaderEdit(IShaderViewer *viewer, ResourceId id, ShaderStage stage,
ShaderEncoding shaderEncoding, ShaderCompileFlags flags,
const rdcstr &entryFunc, const bytebuf &shaderBytes);
void RevertShaderEdit(IShaderViewer *viewer, ResourceId id);
IShaderViewer *DebugShader(const ShaderBindpointMapping *bind, const ShaderReflection *shader,
ResourceId pipeline, ShaderDebugTrace *trace,
const rdcstr &debugContext) override;
@@ -303,6 +310,9 @@ private:
bool SaveNotes();
void LoadNotes(const QString &data);
bool SaveEdits();
void LoadEdits(const QString &data);
void CacheResources();
rdcstr GetResourceNameUnsuffixed(const ResourceDescription *desc);
@@ -386,6 +396,8 @@ private:
QList<QPointer<RegisteredMenuItem>> m_RegisteredMenuItems;
QList<ShaderViewer *> m_ShaderEditors;
// Windows
MainWindow *m_MainWindow = NULL;
EventBrowser *m_EventBrowser = NULL;
+18 -3
View File
@@ -564,6 +564,8 @@ DOCUMENT(R"(A shader window used for viewing, editing, or debugging.
:param CaptureContext context: The current capture context.
:param ShaderViewer viewer: The open shader viewer.
:param ResourceId id: The id of the shader being replaced.
:param ShaderStage stage: The shader stage of the shader being replaced.
:param ShaderEncoding encoding: The encoding of the files being passed.
:param ShaderCompileFlags flags: The flags to use during compilation.
:param str entryFunc: The name of the entry point.
@@ -577,13 +579,15 @@ DOCUMENT(R"(A shader window used for viewing, editing, or debugging.
Called whenever a shader viewer that was open for editing is closed.
:param CaptureContext context: The current capture context.
:param ShaderViewer viewer: The open shader viewer.
:param ResourceId id: The id of the shader being replaced.
)");
struct IShaderViewer
{
typedef std::function<void(ICaptureContext *ctx, IShaderViewer *, ShaderEncoding,
ShaderCompileFlags, rdcstr, bytebuf)>
typedef std::function<void(ICaptureContext *, IShaderViewer *, ResourceId, ShaderStage,
ShaderEncoding, ShaderCompileFlags, rdcstr, bytebuf)>
SaveCallback;
typedef std::function<void(ICaptureContext *ctx)> CloseCallback;
typedef std::function<void(ICaptureContext *, IShaderViewer *, ResourceId)> CloseCallback;
DOCUMENT(
"Retrieves the QWidget for this :class:`ShaderViewer` if PySide2 is available, or otherwise "
@@ -1011,6 +1015,10 @@ This is a bitmask, so several values can be present at once.
The general notes field has been changed.
.. data:: EditedShaders
There are shader editing changes (new edits or reverts).
.. data:: All
Fixed value with all bits set, indication all modifications have been made.
@@ -1021,6 +1029,7 @@ enum class CaptureModifications : uint32_t
Renames = 0x0001,
Bookmarks = 0x0002,
Notes = 0x0004,
EditedShaders = 0x0008,
All = 0xffffffff,
};
@@ -1162,6 +1171,12 @@ been made.
)");
virtual void RefreshStatus() = 0;
DOCUMENT(R"(Determine if a resource has been replaced. See :meth:`RegisterReplacement`.
:param ResourceId id: The id of the resource to check.
)");
virtual bool IsResourceReplaced(ResourceId id) = 0;
DOCUMENT(R"(Register that a resource has replaced, so that the UI can be updated to reflect the
change.
+2
View File
@@ -1071,6 +1071,8 @@ bool MainWindow::PromptCloseCapture()
text += tr("Bookmarks have been changed.\n");
if(mods & CaptureModifications::Notes)
text += tr("Capture notes have been changed.\n");
if(mods & CaptureModifications::EditedShaders)
text += tr("Edited shaders have been changed.\n");
bool saveas = false;
@@ -837,60 +837,8 @@ IShaderViewer *PipelineStateViewer::EditShader(ResourceId id, ShaderStage shader
const rdcstr &entry, ShaderCompileFlags compileFlags,
ShaderEncoding encoding, const rdcstrpairs &files)
{
auto saveCallback = [shaderType, id](ICaptureContext *ctx, IShaderViewer *viewer,
ShaderEncoding shaderEncoding, ShaderCompileFlags flags,
rdcstr entryFunc, bytebuf shaderBytes) {
if(shaderBytes.isEmpty())
return;
ANALYTIC_SET(UIFeatures.ShaderEditing, true);
QPointer<QObject> ptr(viewer->Widget());
// invoke off to the ReplayController to replace the capture's shader
// with our edited one
ctx->Replay().AsyncInvoke([ctx, entryFunc, shaderBytes, shaderEncoding, flags, shaderType, id,
ptr, viewer](IReplayController *r) {
rdcstr errs;
ResourceId from = id;
ResourceId to;
rdctie(to, errs) =
r->BuildTargetShader(entryFunc.c_str(), shaderEncoding, shaderBytes, flags, shaderType);
if(ptr)
GUIInvoke::call(ptr, [viewer, errs]() { viewer->ShowErrors(errs); });
if(to == ResourceId())
{
r->RemoveReplacement(from);
// this GUIInvoke call always needs to go through even if the viewer has been closed.
GUIInvoke::call(ctx->GetMainWindow()->Widget(),
[ctx, from]() { ctx->UnregisterReplacement(from); });
}
else
{
r->ReplaceResource(from, to);
GUIInvoke::call(ctx->GetMainWindow()->Widget(),
[ctx, from]() { ctx->RegisterReplacement(from); });
}
});
};
auto closeCallback = [id](ICaptureContext *ctx) {
// remove the replacement on close (we could make this more sophisticated if there
// was a place to control replaced resources/shaders).
ctx->Replay().AsyncInvoke([ctx, id](IReplayController *r) {
if(ctx->IsCaptureLoaded())
r->RemoveReplacement(id);
GUIInvoke::call(ctx->GetMainWindow()->Widget(), [ctx, id] { ctx->UnregisterReplacement(id); });
});
};
IShaderViewer *sv = m_Ctx.EditShader(id, shaderType, entry, files, encoding, compileFlags,
saveCallback, closeCallback);
IShaderViewer *sv =
m_Ctx.EditShader(id, shaderType, entry, files, encoding, compileFlags, NULL, NULL);
m_Ctx.AddDockWindow(sv->Widget(), DockReference::AddTo, this);
+4
View File
@@ -210,6 +210,10 @@ struct CaptureContextInvoker : ICaptureContext
InvokeVoidFunction(&ICaptureContext::SetEventID, exclude, selectedEventID, eventId, force);
}
virtual void RefreshStatus() override { InvokeVoidFunction(&ICaptureContext::RefreshStatus); }
virtual bool IsResourceReplaced(ResourceId id) override
{
return InvokeRetFunction<bool>(&ICaptureContext::IsResourceReplaced, id);
}
virtual void RegisterReplacement(ResourceId id) override
{
InvokeVoidFunction(&ICaptureContext::RegisterReplacement, id);
+184 -4
View File
@@ -215,6 +215,7 @@ void ShaderViewer::editShader(ResourceId id, ShaderStage stage, const QString &e
m_Flags = flags;
m_CustomShader = (id == ResourceId());
m_EditingShader = id;
// set up compilation parameters
for(ShaderEncoding i : values<ShaderEncoding>())
@@ -230,12 +231,22 @@ void ShaderViewer::editShader(ResourceId id, ShaderStage stage, const QString &e
ui->encoding->setCurrentIndex(m_Encodings.indexOf(shaderEncoding));
ui->entryFunc->setText(entryPoint);
QObject::connect(ui->entryFunc, &QLineEdit::textChanged,
[this](const QString &) { MarkModification(); });
QObject::connect(ui->toolCommandLine, &QTextEdit::textChanged, [this]() { MarkModification(); });
PopulateCompileTools();
QObject::connect(ui->encoding, OverloadedSlot<int>::of(&QComboBox::currentIndexChanged),
[this](int) { PopulateCompileTools(); });
[this](int) {
PopulateCompileTools();
MarkModification();
});
QObject::connect(ui->compileTool, OverloadedSlot<int>::of(&QComboBox::currentIndexChanged),
[this](int) { PopulateCompileToolParameters(); });
[this](int) {
PopulateCompileToolParameters();
MarkModification();
});
// if it's a custom shader, hide the group entirely (don't allow customisation of compile
// parameters). We can still use it to store the parameters passed in. When visible we collapse it
@@ -289,6 +300,8 @@ void ShaderViewer::editShader(ResourceId id, ShaderStage stage, const QString &e
const QByteArray &, int, int, int) {
if(type & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT | SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE))
m_FindState = FindState();
MarkModification();
});
m_Ctx.GetMainWindow()->RegisterShortcut(QKeySequence(QKeySequence::Refresh).toString(), this,
@@ -961,6 +974,131 @@ void ShaderViewer::gotoDisassemblyDebugging()
m_DisassemblyFrame->setFocus(Qt::MouseFocusReason);
}
ShaderViewer *ShaderViewer::LoadEditor(ICaptureContext &ctx, QVariantMap data,
IShaderViewer::SaveCallback saveCallback,
IShaderViewer::CloseCallback closeCallback,
ModifyCallback modifyCallback, QWidget *parent)
{
if(data.isEmpty())
return NULL;
ResourceId id;
{
QVariant v = data[lit("id")];
RichResourceTextInitialise(v);
id = v.value<ResourceId>();
}
ShaderStage stage = (ShaderStage)data[lit("stage")].toUInt();
rdcstr entryPoint = data[lit("entryPoint")].toString();
ShaderEncoding encoding = (ShaderEncoding)data[lit("encoding")].toUInt();
QString commandLine = data[lit("commandLine")].toString();
QString toolName = data[lit("tool")].toString();
ShaderCompileFlags flags;
{
QVariantMap v = data[lit("flags")].toMap();
for(const QString &str : v.keys())
flags.flags.push_back({(rdcstr)str, (rdcstr)v[str].toString()});
}
rdcstrpairs files;
{
QVariantList v = data[lit("files")].toList();
for(QVariant f : v)
{
QVariantMap file = f.toMap();
files.push_back(
{(rdcstr)file[lit("name")].toString(), (rdcstr)file[lit("contents")].toString()});
}
}
rdcstr errors;
if((uint32_t)encoding >= (uint32_t)ShaderEncoding::Count)
{
errors += tr("Unrecognised shader encoding '%1'").arg(ToStr(encoding));
// with no other information let's guess HLSL as the most likely
encoding = ShaderEncoding::HLSL;
}
ShaderViewer *view = EditShader(ctx, id, stage, entryPoint, files, encoding, flags, saveCallback,
closeCallback, modifyCallback, parent);
int toolIndex = -1;
for(int i = 0; i < view->ui->compileTool->count(); i++)
{
QString tool = view->ui->compileTool->itemText(i);
if(tool == toolName)
{
toolIndex = i;
break;
}
}
if(toolIndex == -1)
{
errors += tr("Unknown shader tool '%1'").arg(toolName);
// let's pick the highest priority tool for the current encoding
toolIndex = 0;
}
view->ui->encoding->setCurrentIndex(view->m_Encodings.indexOf(encoding));
view->ui->compileTool->setCurrentIndex(toolIndex);
view->ui->entryFunc->setText(entryPoint);
view->ui->toolCommandLine->setText(commandLine);
return view;
}
QVariantMap ShaderViewer::SaveEditor()
{
QVariantMap ret;
if(m_EditingShader != ResourceId())
{
ret[lit("id")] = m_EditingShader;
ret[lit("stage")] = (uint32_t)m_Stage;
ret[lit("entryPoint")] = ui->entryFunc->text();
ret[lit("encoding")] = (uint32_t)currentEncoding();
ret[lit("commandLine")] = ui->toolCommandLine->toPlainText();
ret[lit("tool")] = ui->compileTool->currentText();
{
QVariantMap v;
for(const ShaderCompileFlag &flag : m_Flags.flags)
v[flag.name] = QString(flag.value);
ret[lit("flags")] = v;
}
{
QVariantList v;
for(ScintillaEdit *edit : m_Scintillas)
{
QWidget *w = (QWidget *)edit;
QVariantMap f;
f[lit("name")] = w->property("filename").toString();
f[lit("contents")] = QString::fromUtf8(edit->getText(edit->textLength() + 1));
v.push_back(f);
}
ret[lit("files")] = v;
}
}
return ret;
}
ShaderViewer::~ShaderViewer()
{
delete m_FindResults;
@@ -975,7 +1113,10 @@ ShaderViewer::~ShaderViewer()
m_Ctx.Replay().AsyncInvoke([trace](IReplayController *r) { r->FreeTrace(trace); });
if(m_CloseCallback)
m_CloseCallback(&m_Ctx);
m_CloseCallback(&m_Ctx, this, m_EditingShader);
if(m_ModifyCallback)
m_ModifyCallback(this, true);
m_Ctx.RemoveCaptureViewer(this);
delete ui;
@@ -2309,6 +2450,30 @@ bool ShaderViewer::getVar(RDTreeWidgetItem *item, ShaderVariable *var, QString *
}
}
void ShaderViewer::setEditorWindowTitle()
{
if(m_EditingShader != ResourceId())
{
if(!m_Ctx.IsResourceReplaced(m_EditingShader))
m_Modified = true;
if(m_Modified)
{
QString title = windowTitle();
if(title[0] != QLatin1Char('*'))
title.prepend(lit("* "));
setWindowTitle(title);
}
else
{
QString title = windowTitle();
if(title[0] == QLatin1Char('*'))
title.remove(0, 2);
setWindowTitle(title);
}
}
}
void ShaderViewer::highlightMatchingVars(RDTreeWidgetItem *root, const QString varName,
const QColor highlightColor)
{
@@ -3872,6 +4037,8 @@ void ShaderViewer::ShowErrors(const rdcstr &errors)
if(!errors.isEmpty())
ToolWindowManager::raiseToolWindow(m_Errors);
}
setEditorWindowTitle();
}
void ShaderViewer::AddWatch(const rdcstr &variable)
@@ -4340,6 +4507,16 @@ bool ShaderViewer::eventFilter(QObject *watched, QEvent *event)
return QFrame::eventFilter(watched, event);
}
void ShaderViewer::MarkModification()
{
if(m_ModifyCallback)
m_ModifyCallback(this, false);
m_Modified = true;
setEditorWindowTitle();
}
void ShaderViewer::disasm_tooltipShow(int x, int y)
{
// do nothing if there's no trace
@@ -4757,7 +4934,10 @@ void ShaderViewer::on_refresh_clicked()
if(!found)
flags.flags.push_back({"@cmdline", ui->toolCommandLine->toPlainText()});
m_SaveCallback(&m_Ctx, this, encoding, flags, ui->entryFunc->text(), shaderBytes);
m_Modified = false;
m_SaveCallback(&m_Ctx, this, m_EditingShader, m_Stage, encoding, flags, ui->entryFunc->text(),
shaderBytes);
}
}
+23 -5
View File
@@ -74,15 +74,25 @@ class ShaderViewer : public QFrame, public IShaderViewer, public ICaptureViewer
Q_OBJECT
public:
static IShaderViewer *EditShader(ICaptureContext &ctx, ResourceId id, ShaderStage stage,
const QString &entryPoint, const rdcstrpairs &files,
ShaderEncoding shaderEncoding, ShaderCompileFlags flags,
IShaderViewer::SaveCallback saveCallback,
IShaderViewer::CloseCallback closeCallback, QWidget *parent)
typedef std::function<void(ShaderViewer *viewer, bool closed)> ModifyCallback;
static ShaderViewer *LoadEditor(ICaptureContext &ctx, QVariantMap data,
IShaderViewer::SaveCallback saveCallback,
IShaderViewer::CloseCallback closeCallback,
ModifyCallback modifyCallback, QWidget *parent);
QVariantMap SaveEditor();
static ShaderViewer *EditShader(ICaptureContext &ctx, ResourceId id, ShaderStage stage,
const QString &entryPoint, const rdcstrpairs &files,
ShaderEncoding shaderEncoding, ShaderCompileFlags flags,
IShaderViewer::SaveCallback saveCallback,
IShaderViewer::CloseCallback closeCallback,
ModifyCallback modifyCallback, QWidget *parent)
{
ShaderViewer *ret = new ShaderViewer(ctx, parent);
ret->m_SaveCallback = saveCallback;
ret->m_CloseCallback = closeCallback;
ret->m_ModifyCallback = modifyCallback;
ret->editShader(id, stage, entryPoint, files, shaderEncoding, flags);
return ret;
}
@@ -177,6 +187,8 @@ private:
ResourceId pipeline, ShaderDebugTrace *trace, const QString &debugContext);
bool eventFilter(QObject *watched, QEvent *event) override;
void MarkModification();
void PopulateCompileTools();
void PopulateCompileToolParameters();
bool ProcessIncludeDirectives(QString &source, const rdcstrpairs &files);
@@ -207,6 +219,7 @@ private:
ShaderBindpointMapping m_Mapping;
const ShaderReflection *m_ShaderDetails = NULL;
bool m_CustomShader = false;
ResourceId m_EditingShader;
ShaderCompileFlags m_Flags;
QList<ShaderEncoding> m_Encodings;
ShaderStage m_Stage;
@@ -250,6 +263,9 @@ private:
SaveCallback m_SaveCallback;
CloseCallback m_CloseCallback;
ModifyCallback m_ModifyCallback;
bool m_Modified = true;
ShaderDebugTrace *m_Trace = NULL;
rdcarray<ShaderDebugState> m_States;
@@ -315,6 +331,8 @@ private:
void find(bool down);
void setEditorWindowTitle();
void runTo(QVector<size_t> runToInstructions, bool forward,
ShaderEvents condition = ShaderEvents::NoEvent);
+4 -3
View File
@@ -4368,8 +4368,9 @@ void TextureViewer::on_customEdit_clicked()
ResourceId(), ShaderStage::Fragment, lit("main"), files,
encodingExtensions[QFileInfo(filename).completeSuffix()], ShaderCompileFlags(),
// Save Callback
[thisPointer, key, filename, path](ICaptureContext *ctx, IShaderViewer *viewer,
ShaderEncoding, ShaderCompileFlags, rdcstr, bytebuf bytes) {
[thisPointer, key, filename, path](ICaptureContext *ctx, IShaderViewer *viewer, ResourceId,
ShaderStage, ShaderEncoding, ShaderCompileFlags, rdcstr,
bytebuf bytes) {
{
// don't trigger a full refresh
if(thisPointer)
@@ -4397,7 +4398,7 @@ void TextureViewer::on_customEdit_clicked()
}
},
[thisPointer, key](ICaptureContext *ctx) {
[thisPointer, key](ICaptureContext *, IShaderViewer *, ResourceId) {
if(thisPointer)
thisPointer->m_CustomShaderEditor.remove(key);
});
+1
View File
@@ -1014,6 +1014,7 @@ rdcstr DoStringise(const SectionType &el)
STRINGISE_ENUM_CLASS_NAMED(AMDRGPProfile, "amd/rgp/profile");
STRINGISE_ENUM_CLASS_NAMED(ExtendedThumbnail, "renderdoc/internal/exthumb");
STRINGISE_ENUM_CLASS_NAMED(EmbeddedLogfile, "renderdoc/internal/logfile");
STRINGISE_ENUM_CLASS_NAMED(EditedShaders, "renderdoc/ui/edits");
}
END_ENUM_STRINGISE();
}
+7
View File
@@ -92,6 +92,12 @@ version of RenderDoc that addes a new section type. They should be considered eq
This section contains the log file at the time of capture, for debugging.
The name for this section will be "renderdoc/internal/logfile".
.. data:: EditedShaders
This section contains any edited shaders.
The name for this section will be "renderdoc/ui/edits".
)");
enum class SectionType : uint32_t
{
@@ -105,6 +111,7 @@ enum class SectionType : uint32_t
AMDRGPProfile,
ExtendedThumbnail,
EmbeddedLogfile,
EditedShaders,
Count,
};