diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index af8c66089..6aab99f1c 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -345,6 +345,12 @@ enum ShaderStageBits eStageBits_Compute, }; +enum ShaderDebugStateFlags +{ + eShaderDebugStateFlags_SampleLoadGather = 0x1, + eShaderDebugStateFlags_GeneratedNanOrInf = 0x2, +}; + enum DebugMessageCategory { eDbgCategory_Application_Defined = 0, diff --git a/renderdoc/api/replay/shader_types.h b/renderdoc/api/replay/shader_types.h index 9b0752e09..8042da529 100644 --- a/renderdoc/api/replay/shader_types.h +++ b/renderdoc/api/replay/shader_types.h @@ -133,6 +133,7 @@ struct ShaderDebugState rdctype::array > indexableTemps; uint32_t nextInstruction; + uint32_t flags; }; struct ShaderDebugTrace diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index f652eb90b..92fd5de7f 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -260,6 +260,7 @@ void Serialiser::Serialise(const char *name, ShaderDebugState &el) Serialise("", el.registers); Serialise("", el.outputs); Serialise("", el.nextInstruction); + Serialise("", el.flags); vector > indexableTemps; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index 7983b42d4..ee5fb048f 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -276,6 +276,8 @@ ShaderVariable sat(const ShaderVariable &v, const VarType type) type); } + r.type = type; + return r; } @@ -319,6 +321,8 @@ ShaderVariable abs(const ShaderVariable &v, const VarType type) type); } + r.type = type; + return r; } @@ -362,6 +366,8 @@ ShaderVariable neg(const ShaderVariable &v, const VarType type) type); } + r.type = type; + return r; } @@ -410,6 +416,8 @@ ShaderVariable mul(const ShaderVariable &a, const ShaderVariable &b, const VarTy type); } + r.type = type; + return r; } @@ -458,6 +466,8 @@ ShaderVariable div(const ShaderVariable &a, const ShaderVariable &b, const VarTy type); } + r.type = type; + return r; } @@ -506,6 +516,8 @@ ShaderVariable add(const ShaderVariable &a, const ShaderVariable &b, const VarTy type); } + r.type = type; + return r; } @@ -573,6 +585,25 @@ bool State::Finished() const return dxbc && (done || nextInstruction >= (int)dxbc->GetNumInstructions()); } +void State::AssignValue(ShaderVariable &dst, uint32_t dstIndex, const ShaderVariable &src, + uint32_t srcIndex) +{ + if(src.type == eVar_Float) + { + float ft = src.value.fv[srcIndex]; + if(isinf(ft) || isnan(ft)) + flags |= eShaderDebugStateFlags_GeneratedNanOrInf; + } + else if(src.type == eVar_Double) + { + double dt = src.value.dv[srcIndex]; + if(isinf(dt) || isnan(dt)) + flags |= eShaderDebugStateFlags_GeneratedNanOrInf; + } + + dst.value.uv[dstIndex] = src.value.uv[srcIndex]; +} + void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const ShaderVariable &val) { ShaderVariable *v = NULL; @@ -689,7 +720,7 @@ void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const Shad { RDCASSERT(dstoper.comps[0] != 0xff); - v->value.uv[dstoper.comps[0]] = right.value.u.x; + AssignValue(*v, dstoper.comps[0], right, 0); } else { @@ -700,13 +731,13 @@ void State::SetDst(const ASMOperand &dstoper, const ASMOperation &op, const Shad if(dstoper.comps[i] != 0xff) { RDCASSERT(dstoper.comps[i] < v->columns); - v->value.uv[dstoper.comps[i]] = right.value.uv[dstoper.comps[i]]; + AssignValue(*v, dstoper.comps[i], right, dstoper.comps[i]); compsWritten++; } } if(compsWritten == 0) - v->value.uv[0] = right.value.uv[0]; + AssignValue(*v, 0, right, 0); } } } @@ -1070,6 +1101,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const const ASMOperation &op = s.dxbc->GetInstruction((size_t)s.nextInstruction); s.nextInstruction++; + s.flags = 0; vector srcOpers; @@ -2334,6 +2366,9 @@ State State::GetNext(GlobalState &global, State quad[4]) const load = false; } + if(load) + s.flags = eShaderDebugStateFlags_SampleLoadGather; + if(op.operation == OPCODE_LD_STRUCTURED || op.operation == OPCODE_STORE_STRUCTURED) { if(load) @@ -3396,6 +3431,11 @@ State State::GetNext(GlobalState &global, State quad[4]) const string funcRet = ""; DXGI_FORMAT retFmt = DXGI_FORMAT_UNKNOWN; + if(op.operation != OPCODE_LOD) + { + s.flags = eShaderDebugStateFlags_SampleLoadGather; + } + if(op.operation == OPCODE_SAMPLE_C || op.operation == OPCODE_SAMPLE_C_LZ || op.operation == OPCODE_GATHER4_C || op.operation == OPCODE_GATHER4_PO_C || op.operation == OPCODE_LOD) diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.h b/renderdoc/driver/shaders/dxbc/dxbc_debug.h index 41583140a..0ac836a6d 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.h @@ -121,6 +121,7 @@ public: { quadIndex = 0; nextInstruction = 0; + flags = 0; done = false; trace = NULL; dxbc = NULL; @@ -131,6 +132,7 @@ public: { quadIndex = quadIdx; nextInstruction = 0; + flags = 0; done = false; trace = t; dxbc = f; @@ -165,6 +167,9 @@ private: bool done; + // validates assignment for generation of non-normal values + void AssignValue(ShaderVariable &dst, uint32_t dstIndex, const ShaderVariable &src, + uint32_t srcIndex); // sets the destination operand by looking up in the register // file and applying any masking or swizzling void SetDst(const DXBC::ASMOperand &dstoper, const DXBC::ASMOperation &op, diff --git a/renderdocui/Interop/Enums.cs b/renderdocui/Interop/Enums.cs index 39d9090d7..d97b3b344 100644 --- a/renderdocui/Interop/Enums.cs +++ b/renderdocui/Interop/Enums.cs @@ -350,6 +350,13 @@ namespace renderdoc All = (Vertex | Hull | Domain | Geometry | Pixel | Fragment | Compute), }; + [Flags] + public enum ShaderDebugStateFlags + { + SampleLoadGather = 0x1, + GeneratedNanOrInf = 0x2, + }; + public enum DebugMessageSource { API = 0, diff --git a/renderdocui/Interop/Shader.cs b/renderdocui/Interop/Shader.cs index 1f5fee988..d55385c3c 100644 --- a/renderdocui/Interop/Shader.cs +++ b/renderdocui/Interop/Shader.cs @@ -192,6 +192,7 @@ namespace renderdoc public IndexableTempArray[] indexableTemps; public UInt32 nextInstruction; + public ShaderDebugStateFlags flags; }; [StructLayout(LayoutKind.Sequential)] diff --git a/renderdocui/Properties/Resources.Designer.cs b/renderdocui/Properties/Resources.Designer.cs index 03a609fe6..3a5239ea4 100644 --- a/renderdocui/Properties/Resources.Designer.cs +++ b/renderdocui/Properties/Resources.Designer.cs @@ -460,6 +460,26 @@ namespace renderdocui.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap runnaninf { + get { + object obj = ResourceManager.GetObject("runnaninf", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap runsample { + get { + object obj = ResourceManager.GetObject("runsample", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/renderdocui/Properties/Resources.resx b/renderdocui/Properties/Resources.resx index 972fd251f..edfbd9a66 100644 --- a/renderdocui/Properties/Resources.resx +++ b/renderdocui/Properties/Resources.resx @@ -304,4 +304,10 @@ ..\Resources\upfolder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\runsample.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\runnaninf.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/renderdocui/Resources/runnaninf.png b/renderdocui/Resources/runnaninf.png new file mode 100644 index 000000000..e99310424 Binary files /dev/null and b/renderdocui/Resources/runnaninf.png differ diff --git a/renderdocui/Resources/runsample.png b/renderdocui/Resources/runsample.png new file mode 100644 index 000000000..99d324fca Binary files /dev/null and b/renderdocui/Resources/runsample.png differ diff --git a/renderdocui/Windows/ShaderViewer.Designer.cs b/renderdocui/Windows/ShaderViewer.Designer.cs index 5c8a825c7..8d107099f 100644 --- a/renderdocui/Windows/ShaderViewer.Designer.cs +++ b/renderdocui/Windows/ShaderViewer.Designer.cs @@ -78,6 +78,8 @@ this.stepBack = new System.Windows.Forms.ToolStripButton(); this.stepNext = new System.Windows.Forms.ToolStripButton(); this.runToCursor = new System.Windows.Forms.ToolStripButton(); + this.runToSample = new System.Windows.Forms.ToolStripButton(); + this.runToNanOrInf = new System.Windows.Forms.ToolStripButton(); this.runBack = new System.Windows.Forms.ToolStripButton(); this.run = new System.Windows.Forms.ToolStripButton(); this.displayInts = new System.Windows.Forms.ToolStripButton(); @@ -299,6 +301,8 @@ this.stepBack, this.stepNext, this.runToCursor, + this.runToSample, + this.runToNanOrInf, this.runBack, this.run, this.showWindows, @@ -344,6 +348,28 @@ this.runToCursor.ToolTipText = "Run to Cursor (Ctrl-F10)"; this.runToCursor.Click += new System.EventHandler(this.runToCursor_Click); // + // runToSample + // + this.runToSample.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.runToSample.Image = global::renderdocui.Properties.Resources.runsample; + this.runToSample.ImageTransparentColor = System.Drawing.Color.Magenta; + this.runToSample.Name = "runToSample"; + this.runToSample.Size = new System.Drawing.Size(23, 22); + this.runToSample.Text = "Run to Sample/Load/Gather"; + this.runToSample.ToolTipText = "Run to Sample/Load/Gather"; + this.runToSample.Click += new System.EventHandler(this.runToSample_Click); + // + // runToNanOrInf + // + this.runToNanOrInf.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.runToNanOrInf.Image = global::renderdocui.Properties.Resources.runnaninf; + this.runToNanOrInf.ImageTransparentColor = System.Drawing.Color.Magenta; + this.runToNanOrInf.Name = "runToNanOrInf"; + this.runToNanOrInf.Size = new System.Drawing.Size(23, 22); + this.runToNanOrInf.Text = "Run to NaN or Inf"; + this.runToNanOrInf.ToolTipText = "Run to NaN or Inf"; + this.runToNanOrInf.Click += new System.EventHandler(this.runToNanOrInf_Click); + // // runBack // this.runBack.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; @@ -766,6 +792,8 @@ private System.Windows.Forms.ToolStripButton stepBack; private System.Windows.Forms.ToolStripButton stepNext; private System.Windows.Forms.ToolStripButton runToCursor; + private System.Windows.Forms.ToolStripButton runToSample; + private System.Windows.Forms.ToolStripButton runToNanOrInf; private System.Windows.Forms.ToolStripButton runBack; private System.Windows.Forms.ToolStripButton run; private System.Windows.Forms.ToolStripDropDownButton showWindows; diff --git a/renderdocui/Windows/ShaderViewer.cs b/renderdocui/Windows/ShaderViewer.cs index 5b1d3e73a..763a246df 100644 --- a/renderdocui/Windows/ShaderViewer.cs +++ b/renderdocui/Windows/ShaderViewer.cs @@ -1864,6 +1864,22 @@ namespace renderdocui.Windows RunToCursor(); } + private void runToSample_Click(object sender, EventArgs e) + { + if (m_Trace == null || m_Trace.states == null) + return; + + RunToSample(); + } + + private void runToNanOrInf_Click(object sender, EventArgs e) + { + if (m_Trace == null || m_Trace.states == null) + return; + + RunToNanOrInf(); + } + private bool StepBack() { if (m_Trace == null || m_Trace.states == null) @@ -1966,6 +1982,46 @@ namespace renderdocui.Windows } } + private void RunToCondition(ShaderDebugStateFlags condition) + { + if (m_Trace == null || m_Trace.states == null) + return; + + int step = CurrentStep; + + bool firstStep = true; + + while (step < m_Trace.states.Length) + { + int nextStep = step + 1; + + if (nextStep >= m_Trace.states.Length) + break; + + if (!firstStep && m_Trace.states[nextStep].flags.HasFlag(condition)) + break; + + if (!firstStep && m_Breakpoints.Contains((int)m_Trace.states[step].nextInstruction)) + break; + + firstStep = false; + + step = nextStep; + } + + CurrentStep = step; + } + + private void RunToSample() + { + RunToCondition(ShaderDebugStateFlags.SampleLoadGather); + } + + private void RunToNanOrInf() + { + RunToCondition(ShaderDebugStateFlags.GeneratedNanOrInf); + } + private void autosToolStripMenuItem_Click(object sender, EventArgs e) { ShowConstants(); diff --git a/renderdocui/renderdocui.csproj b/renderdocui/renderdocui.csproj index c21dd55c4..c52ca1753 100644 --- a/renderdocui/renderdocui.csproj +++ b/renderdocui/renderdocui.csproj @@ -607,6 +607,8 @@ + +