diff --git a/docs/how/how_edit_shader.rst b/docs/how/how_edit_shader.rst index 00ed02fb7..77bbd3fe0 100644 --- a/docs/how/how_edit_shader.rst +++ b/docs/how/how_edit_shader.rst @@ -42,7 +42,7 @@ Using the built-in shader editor When you have launched the shader editor, the main window will be filled with the source of your shader. In here you can make edits and changes with the basic controls and syntax highlighting available with the Scintilla editor. -To compile the shader and apply your changes, either click the refresh button in the toolbar or press :kbd:`F5`. This will compile the shader and apply it, any warnings and errors will be added to the errors panel below the main source. +To compile the shader and apply your changes, either click the Apply changes button in the toolbar or press :kbd:`F5`. This will compile the shader and apply it, any warnings and errors will be added to the errors panel below the main source. You can choose the tool used to compile in the lower section, as well as configure any parameters to it. See above for more information about shader processing tools. diff --git a/qrenderdoc/Code/CaptureContext.cpp b/qrenderdoc/Code/CaptureContext.cpp index 35d85c619..d2f5053d7 100644 --- a/qrenderdoc/Code/CaptureContext.cpp +++ b/qrenderdoc/Code/CaptureContext.cpp @@ -1973,14 +1973,14 @@ void CaptureContext::LoadEdits(const QString &data) ApplyShaderEdit(viewer, id, stage, shaderEncoding, flags, entryFunc, shaderBytes); }; - auto replaceCloseCallback = [this](ICaptureContext *ctx, IShaderViewer *view, ResourceId id) { + auto replaceRevertCallback = [this](ICaptureContext *ctx, IShaderViewer *view, ResourceId id) { RevertShaderEdit(view, id); }; for(QVariant e : editors) { ShaderViewer *edit = - ShaderViewer::LoadEditor(*this, e.toMap(), replaceSaveCallback, replaceCloseCallback, + ShaderViewer::LoadEditor(*this, e.toMap(), replaceSaveCallback, replaceRevertCallback, [this](ShaderViewer *view, bool closed) { SetModification(CaptureModifications::EditedShaders); if(closed) @@ -2457,7 +2457,7 @@ IShaderViewer *CaptureContext::EditShader(ResourceId id, ShaderStage stage, const rdcstr &entryPoint, const rdcstrpairs &files, ShaderEncoding shaderEncoding, ShaderCompileFlags flags, IShaderViewer::SaveCallback saveCallback, - IShaderViewer::CloseCallback closeCallback) + IShaderViewer::RevertCallback revertCallback) { ShaderViewer *viewer = NULL; @@ -2474,16 +2474,16 @@ IShaderViewer *CaptureContext::EditShader(ResourceId id, ShaderStage stage, saveCallback(ctx, viewer, id, stage, shaderEncoding, flags, entryFunc, shaderBytes); }; - auto replaceCloseCallback = [this, closeCallback](ICaptureContext *ctx, IShaderViewer *view, - ResourceId id) { + auto replaceRevertCallback = [this, revertCallback](ICaptureContext *ctx, IShaderViewer *view, + ResourceId id) { RevertShaderEdit(view, id); - if(closeCallback) - closeCallback(ctx, view, id); + if(revertCallback) + revertCallback(ctx, view, id); }; viewer = ShaderViewer::EditShader(*this, id, stage, entryPoint, files, shaderEncoding, flags, - replaceSaveCallback, replaceCloseCallback, + replaceSaveCallback, replaceRevertCallback, [this](ShaderViewer *view, bool closed) { SetModification(CaptureModifications::EditedShaders); if(closed) @@ -2497,7 +2497,7 @@ IShaderViewer *CaptureContext::EditShader(ResourceId id, ShaderStage stage, else { viewer = ShaderViewer::EditShader(*this, id, stage, entryPoint, files, shaderEncoding, flags, - saveCallback, closeCallback, NULL, m_MainWindow->Widget()); + saveCallback, revertCallback, NULL, m_MainWindow->Widget()); } return viewer; @@ -2546,12 +2546,18 @@ void CaptureContext::ApplyShaderEdit(IShaderViewer *viewer, ResourceId id, Shade void CaptureContext::RevertShaderEdit(IShaderViewer *viewer, ResourceId id) { + QPointer ptr(viewer->Widget()); + // 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) { + Replay().AsyncInvoke([this, viewer, id, ptr](IReplayController *r) { if(IsCaptureLoaded()) r->RemoveReplacement(id); - GUIInvoke::call(GetMainWindow()->Widget(), [this, id] { UnregisterReplacement(id); }); + GUIInvoke::call(GetMainWindow()->Widget(), [this, viewer, id, ptr] { + UnregisterReplacement(id); + if(ptr) + viewer->ShowErrors(rdcstr()); + }); }); } diff --git a/qrenderdoc/Code/CaptureContext.h b/qrenderdoc/Code/CaptureContext.h index 731396e16..13cf5332e 100644 --- a/qrenderdoc/Code/CaptureContext.h +++ b/qrenderdoc/Code/CaptureContext.h @@ -245,7 +245,7 @@ public: IShaderViewer *EditShader(ResourceId id, ShaderStage stage, const rdcstr &entryPoint, const rdcstrpairs &files, ShaderEncoding shaderEncoding, ShaderCompileFlags flags, IShaderViewer::SaveCallback saveCallback, - IShaderViewer::CloseCallback closeCallback) override; + IShaderViewer::RevertCallback revertCallback) override; void ApplyShaderEdit(IShaderViewer *viewer, ResourceId id, ShaderStage stage, ShaderEncoding shaderEncoding, ShaderCompileFlags flags, diff --git a/qrenderdoc/Code/Interface/QRDInterface.h b/qrenderdoc/Code/Interface/QRDInterface.h index 9acc46f48..32af8b2fd 100644 --- a/qrenderdoc/Code/Interface/QRDInterface.h +++ b/qrenderdoc/Code/Interface/QRDInterface.h @@ -1096,9 +1096,9 @@ DOCUMENT(R"(A shader window used for viewing, editing, or debugging. :param bytes source: The byte buffer containing the source - may just be text depending on the encoding. -.. function:: CloseCallback(context) +.. function:: RevertCallback(context) - Not a member function - the signature for any ``CloseCallback`` callbacks. + Not a member function - the signature for any ``RevertCallback`` callbacks. Called whenever a shader viewer that was open for editing is closed. @@ -1111,7 +1111,7 @@ struct IShaderViewer typedef std::function SaveCallback; - typedef std::function CloseCallback; + typedef std::function RevertCallback; DOCUMENT(R"(Retrieves the PySide2 QWidget for this :class:`ShaderViewer` if PySide2 is available, or otherwise returns a unique opaque pointer that can be passed back to any RenderDoc functions expecting a @@ -2483,8 +2483,8 @@ place if needed. :param renderdoc.ShaderCompileFlags flags: The flags originally used to compile the shader. :param ShaderViewer.SaveCallback saveCallback: The callback function to call when a save/update is triggered. -:param ShaderViewer.CloseCallback closeCallback: The callback function to call when the shader - viewer is closed. +:param ShaderViewer.RevertCallback revertCallback: The callback function to call when the shader + is to be reverted - either by user request or because the shader viewer was closed. :return: The new :class:`ShaderViewer` window opened but not shown for editing. :rtype: ShaderViewer )"); @@ -2492,7 +2492,7 @@ place if needed. const rdcstrpairs &files, ShaderEncoding shaderEncoding, ShaderCompileFlags flags, IShaderViewer::SaveCallback saveCallback, - IShaderViewer::CloseCallback closeCallback) = 0; + IShaderViewer::RevertCallback revertCallback) = 0; DOCUMENT(R"(Show a new :class:`ShaderViewer` window, showing a read-only view of a debug trace through the execution of a given shader. diff --git a/qrenderdoc/Windows/PythonShell.cpp b/qrenderdoc/Windows/PythonShell.cpp index f0c8a33bb..e103faa9c 100644 --- a/qrenderdoc/Windows/PythonShell.cpp +++ b/qrenderdoc/Windows/PythonShell.cpp @@ -747,11 +747,11 @@ struct CaptureContextInvoker : ObjectForwarder const rdcstrpairs &files, ShaderEncoding shaderEncoding, ShaderCompileFlags flags, IShaderViewer::SaveCallback saveCallback, - IShaderViewer::CloseCallback closeCallback) override + IShaderViewer::RevertCallback revertCallback) override { return InvokeRetFunction(&ICaptureContext::EditShader, id, stage, entryPoint, files, shaderEncoding, flags, saveCallback, - closeCallback); + revertCallback); } virtual IShaderViewer *DebugShader(const ShaderBindpointMapping *bind, diff --git a/qrenderdoc/Windows/ShaderViewer.cpp b/qrenderdoc/Windows/ShaderViewer.cpp index cb06c8264..ff94e2cf1 100644 --- a/qrenderdoc/Windows/ShaderViewer.cpp +++ b/qrenderdoc/Windows/ShaderViewer.cpp @@ -322,6 +322,7 @@ void ShaderViewer::editShader(ResourceId id, ShaderStage stage, const QString &e QWidget *w = (QWidget *)scintilla; w->setProperty("filename", kv.first); + w->setProperty("origText", kv.second); if(text.contains(entryPoint)) sel = scintilla; @@ -526,6 +527,9 @@ void ShaderViewer::debugShader(const ShaderBindpointMapping *bind, const ShaderR // hide edit buttons ui->refresh->hide(); + ui->unrefresh->hide(); + ui->resetEdits->hide(); + ui->editStatusLabel->hide(); ui->snippets->hide(); ui->editSep->hide(); @@ -1130,7 +1134,7 @@ void ShaderViewer::gotoDisassemblyDebugging() ShaderViewer *ShaderViewer::LoadEditor(ICaptureContext &ctx, QVariantMap data, IShaderViewer::SaveCallback saveCallback, - IShaderViewer::CloseCallback closeCallback, + IShaderViewer::RevertCallback revertCallback, ModifyCallback modifyCallback, QWidget *parent) { if(data.isEmpty()) @@ -1181,7 +1185,7 @@ ShaderViewer *ShaderViewer::LoadEditor(ICaptureContext &ctx, QVariantMap data, } ShaderViewer *view = EditShader(ctx, id, stage, entryPoint, files, encoding, flags, saveCallback, - closeCallback, modifyCallback, parent); + revertCallback, modifyCallback, parent); int toolIndex = -1; @@ -1266,8 +1270,8 @@ ShaderViewer::~ShaderViewer() m_Ctx.Replay().AsyncInvoke([trace](IReplayController *r) { r->FreeTrace(trace); }); - if(m_CloseCallback) - m_CloseCallback(&m_Ctx, this, m_EditingShader); + if(m_RevertCallback) + m_RevertCallback(&m_Ctx, this, m_EditingShader); if(m_ModifyCallback) m_ModifyCallback(this, true); @@ -2645,12 +2649,35 @@ bool ShaderViewer::getVar(RDTreeWidgetItem *item, ShaderVariable *var, QString * } } -void ShaderViewer::setEditorWindowTitle() +void ShaderViewer::updateEditState() { if(m_EditingShader != ResourceId()) { - if(!m_Ctx.IsResourceReplaced(m_EditingShader)) - m_Modified = true; + QString statusString, statusTooltip; + + // check if the shader is replaced and update the status + if(m_Ctx.IsResourceReplaced(m_EditingShader)) + { + statusString = tr("Status: Edited Shader Active"); + statusTooltip = tr("The replay currently has the original shader active"); + } + else + { + statusString = tr("Status: Original Shader Active"); + statusTooltip = tr("The replay currently has an edited version of the shader active"); + + // if we expected it to be saved something went wrong + if(m_Saved) + { + // we're still 'modified' as in have unsaved changes + m_Modified = true; + + statusTooltip.append(tr("\n\nSomething went wrong applying changes.")); + } + } + + ui->editStatusLabel->setText(statusString); + ui->editStatusLabel->setToolTip(statusTooltip); if(m_Modified) { @@ -4257,7 +4284,7 @@ void ShaderViewer::ShowErrors(const rdcstr &errors) ToolWindowManager::raiseToolWindow(m_Errors); } - setEditorWindowTitle(); + updateEditState(); } void ShaderViewer::AddWatch(const rdcstr &variable) @@ -4760,7 +4787,7 @@ void ShaderViewer::MarkModification() m_Modified = true; - setEditorWindowTitle(); + updateEditState(); } void ShaderViewer::disasm_tooltipShow(int x, int y) @@ -5095,6 +5122,41 @@ bool ShaderViewer::ProcessIncludeDirectives(QString &source, const rdcstrpairs & return true; } +void ShaderViewer::on_resetEdits_clicked() +{ + QMessageBox::StandardButton res = RDDialog::question( + this, tr("Are you sure?"), tr("Are you sure you want to reset all edits and restore the " + "shader source back to the original?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + + if(res != QMessageBox::Yes) + return; + + for(ScintillaEdit *s : m_Scintillas) + { + QWidget *w = (QWidget *)s; + s->selectAll(); + s->replaceSel(w->property("origText").toString().toUtf8().data()); + } + + m_RevertCallback(&m_Ctx, this, m_EditingShader); + + m_Modified = false; + m_Saved = false; + + updateEditState(); +} + +void ShaderViewer::on_unrefresh_clicked() +{ + m_RevertCallback(&m_Ctx, this, m_EditingShader); + + m_Modified = true; + m_Saved = false; + + updateEditState(); +} + void ShaderViewer::on_refresh_clicked() { if(m_Trace) @@ -5134,6 +5196,8 @@ void ShaderViewer::on_refresh_clicked() return; } + m_Saved = true; + bytebuf shaderBytes(source.toUtf8()); rdcarray accepted = m_Ctx.TargetShaderEncodings(); diff --git a/qrenderdoc/Windows/ShaderViewer.h b/qrenderdoc/Windows/ShaderViewer.h index e90417e15..cc63a7b34 100644 --- a/qrenderdoc/Windows/ShaderViewer.h +++ b/qrenderdoc/Windows/ShaderViewer.h @@ -78,7 +78,7 @@ public: static ShaderViewer *LoadEditor(ICaptureContext &ctx, QVariantMap data, IShaderViewer::SaveCallback saveCallback, - IShaderViewer::CloseCallback closeCallback, + IShaderViewer::RevertCallback revertCallback, ModifyCallback modifyCallback, QWidget *parent); QVariantMap SaveEditor(); @@ -86,12 +86,12 @@ public: const QString &entryPoint, const rdcstrpairs &files, ShaderEncoding shaderEncoding, ShaderCompileFlags flags, IShaderViewer::SaveCallback saveCallback, - IShaderViewer::CloseCallback closeCallback, + IShaderViewer::RevertCallback revertCallback, ModifyCallback modifyCallback, QWidget *parent) { ShaderViewer *ret = new ShaderViewer(ctx, parent); ret->m_SaveCallback = saveCallback; - ret->m_CloseCallback = closeCallback; + ret->m_RevertCallback = revertCallback; ret->m_ModifyCallback = modifyCallback; ret->editShader(id, stage, entryPoint, files, shaderEncoding, flags); return ret; @@ -140,6 +140,8 @@ private slots: // automatic slots void on_findReplace_clicked(); void on_refresh_clicked(); + void on_unrefresh_clicked(); + void on_resetEdits_clicked(); void on_intView_clicked(); void on_floatView_clicked(); void on_debugToggle_clicked(); @@ -261,10 +263,11 @@ private: } m_FindState; SaveCallback m_SaveCallback; - CloseCallback m_CloseCallback; + RevertCallback m_RevertCallback; ModifyCallback m_ModifyCallback; bool m_Modified = true; + bool m_Saved = false; ShaderDebugTrace *m_Trace = NULL; rdcarray m_States; @@ -338,7 +341,7 @@ private: void find(bool down); - void setEditorWindowTitle(); + void updateEditState(); enum StepMode { diff --git a/qrenderdoc/Windows/ShaderViewer.ui b/qrenderdoc/Windows/ShaderViewer.ui index ad49456bb..b0c740eb5 100644 --- a/qrenderdoc/Windows/ShaderViewer.ui +++ b/qrenderdoc/Windows/ShaderViewer.ui @@ -327,12 +327,32 @@ - + - Compile Shader & Refresh changes + Remove all source edits and restore original shader - Refresh + Reset + + + + :/del.png:/del.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Compile shader & apply changes + + + Apply changes @@ -346,6 +366,36 @@ + + + + Use original shader + + + Remove changes + + + + :/arrow_undo.png:/arrow_undo.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Status: Original Shader Active + + + The replay currently has the original shader active + + +