PageRenderTime 60ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/renderdocui/Windows/PipelineState/D3D11PipelineStateViewer.cs

https://github.com/tgAncel/renderdoc
C# | 2139 lines | 1672 code | 391 blank | 76 comment | 530 complexity | 31845932758885b56cef523fa4637610 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause
  1. /******************************************************************************
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2014 Crytek
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. ******************************************************************************/
  24. using System;
  25. using System.Collections.Generic;
  26. using System.ComponentModel;
  27. using System.Drawing;
  28. using System.Linq;
  29. using System.Text;
  30. using System.IO;
  31. using System.Windows.Forms;
  32. using WeifenLuo.WinFormsUI.Docking;
  33. using renderdocui.Code;
  34. using renderdocui.Controls;
  35. using renderdoc;
  36. namespace renderdocui.Windows.PipelineState
  37. {
  38. public partial class D3D11PipelineStateViewer : UserControl, ILogViewerForm
  39. {
  40. private Core m_Core;
  41. private DockContent m_DockContent;
  42. // keep track of the VB nodes (we want to be able to highlight them easily on hover)
  43. private List<TreelistView.Node> m_VBNodes = new List<TreelistView.Node>();
  44. public D3D11PipelineStateViewer(Core core, DockContent c)
  45. {
  46. InitializeComponent();
  47. m_DockContent = c;
  48. pipeFlow.SetStages(new KeyValuePair<string, string>[] {
  49. new KeyValuePair<string,string>("IA", "Input Assembler"),
  50. new KeyValuePair<string,string>("VS", "Vertex Shader"),
  51. new KeyValuePair<string,string>("HS", "Hull Shader"),
  52. new KeyValuePair<string,string>("DS", "Domain Shader"),
  53. new KeyValuePair<string,string>("GS", "Geometry Shader"),
  54. new KeyValuePair<string,string>("RS", "Rasterizer"),
  55. new KeyValuePair<string,string>("PS", "Pixel Shader"),
  56. new KeyValuePair<string,string>("OM", "Output Merger"),
  57. new KeyValuePair<string,string>("CS", "Compute Shader"),
  58. });
  59. pipeFlow.IsolateStage(8); // compute shader isolated
  60. pipeFlow.SetStagesEnabled(new bool[] { true, true, true, true, true, true, true, true, true });
  61. //Icon = global::renderdocui.Properties.Resources.icon;
  62. SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
  63. iaBytecodeMismatch.Text = "";
  64. iaBytecodeMismatch.Visible = false;
  65. toolTip.SetToolTip(vsShaderCog, "Open Shader Source");
  66. toolTip.SetToolTip(dsShaderCog, "Open Shader Source");
  67. toolTip.SetToolTip(hsShaderCog, "Open Shader Source");
  68. toolTip.SetToolTip(gsShaderCog, "Open Shader Source");
  69. toolTip.SetToolTip(psShaderCog, "Open Shader Source");
  70. toolTip.SetToolTip(csShaderCog, "Open Shader Source");
  71. toolTip.SetToolTip(vsShader, "Open Shader Source");
  72. toolTip.SetToolTip(dsShader, "Open Shader Source");
  73. toolTip.SetToolTip(hsShader, "Open Shader Source");
  74. toolTip.SetToolTip(gsShader, "Open Shader Source");
  75. toolTip.SetToolTip(psShader, "Open Shader Source");
  76. toolTip.SetToolTip(csShader, "Open Shader Source");
  77. OnLogfileClosed();
  78. m_Core = core;
  79. }
  80. public void OnLogfileClosed()
  81. {
  82. inputLayouts.Nodes.Clear();
  83. iabuffers.Nodes.Clear();
  84. topology.Text = "";
  85. topologyDiagram.Image = null;
  86. iaBytecodeMismatch.Text = "";
  87. iaBytecodeMismatch.Visible = false;
  88. iaBytecode.Text = "";
  89. ClearShaderState(vsShader, vsResources, vsSamplers, vsCBuffers, vsClasses);
  90. ClearShaderState(gsShader, gsResources, gsSamplers, gsCBuffers, gsClasses);
  91. ClearShaderState(hsShader, hsResources, hsSamplers, hsCBuffers, hsClasses);
  92. ClearShaderState(dsShader, dsResources, dsSamplers, dsCBuffers, dsClasses);
  93. ClearShaderState(psShader, psResources, psSamplers, psCBuffers, psClasses);
  94. ClearShaderState(csShader, csResources, csSamplers, csCBuffers, csClasses);
  95. csUAVs.Nodes.Clear();
  96. gsStreams.Nodes.Clear();
  97. var tick = global::renderdocui.Properties.Resources.tick;
  98. var cross = global::renderdocui.Properties.Resources.cross;
  99. fillMode.Text = "Solid";
  100. cullMode.Text = "Front";
  101. frontCCW.Image = tick;
  102. scissorEnable.Image = tick;
  103. lineAAEnable.Image = tick;
  104. multisampleEnable.Image = tick;
  105. depthClip.Image = tick;
  106. depthBias.Text = "0";
  107. depthBiasClamp.Text = "0.0";
  108. slopeScaledBias.Text = "0.0";
  109. viewports.Nodes.Clear();
  110. scissors.Nodes.Clear();
  111. targetOutputs.Nodes.Clear();
  112. blendOperations.Nodes.Clear();
  113. alphaToCoverage.Image = tick;
  114. independentBlend.Image = tick;
  115. blendFactor.Text = "0.00, 0.00, 0.00, 0.00";
  116. sampleMask.Text = "FFFFFFFF";
  117. depthEnable.Image = tick;
  118. depthFunc.Text = "GREATER_EQUAL";
  119. depthWrite.Image = tick;
  120. stencilEnable.Image = tick;
  121. stencilReadMask.Text = "FF";
  122. stencilWriteMask.Text = "FF";
  123. stencilRef.Text = "FF";
  124. pipeFlow.SetStagesEnabled(new bool[] { true, true, true, true, true, true, true, true, true });
  125. }
  126. public void OnLogfileLoaded()
  127. {
  128. OnEventSelected(m_Core.CurFrame, m_Core.CurEvent);
  129. }
  130. private void EmptyRow(TreelistView.Node node)
  131. {
  132. node.BackColor = Color.Firebrick;
  133. }
  134. private void InactiveRow(TreelistView.Node node)
  135. {
  136. node.Italic = true;
  137. }
  138. private void ClearShaderState(Label shader, TreelistView.TreeListView resources, TreelistView.TreeListView samplers,
  139. TreelistView.TreeListView cbuffers, TreelistView.TreeListView classes)
  140. {
  141. shader.Text = "Unbound";
  142. resources.Nodes.Clear();
  143. samplers.Nodes.Clear();
  144. cbuffers.Nodes.Clear();
  145. classes.Nodes.Clear();
  146. }
  147. // Set a shader stage's resources and values
  148. private void SetShaderState(FetchTexture[] texs, FetchBuffer[] bufs,
  149. D3D11PipelineState.ShaderStage stage,
  150. Label shader, TreelistView.TreeListView resources, TreelistView.TreeListView samplers,
  151. TreelistView.TreeListView cbuffers, TreelistView.TreeListView classes)
  152. {
  153. ShaderReflection shaderDetails = stage.ShaderDetails;
  154. if (stage.Shader == ResourceId.Null)
  155. shader.Text = "Unbound";
  156. else
  157. shader.Text = "Shader " + stage.Shader.ToString();
  158. if (shaderDetails != null && shaderDetails.DebugInfo.entryFunc != "" && shaderDetails.DebugInfo.files.Length > 0)
  159. shader.Text = shaderDetails.DebugInfo.entryFunc + "()" + " - " +
  160. Path.GetFileName(shaderDetails.DebugInfo.files[0].filename);
  161. resources.BeginUpdate();
  162. resources.Nodes.Clear();
  163. if (stage.SRVs != null)
  164. {
  165. int i = 0;
  166. foreach (var r in stage.SRVs)
  167. {
  168. ShaderResource shaderInput = null;
  169. if (shaderDetails != null)
  170. {
  171. foreach (var bind in shaderDetails.Resources)
  172. {
  173. if (bind.IsSRV && bind.bindPoint == i)
  174. shaderInput = bind;
  175. }
  176. }
  177. bool filledSlot = (r.Resource != ResourceId.Null);
  178. bool usedSlot = (shaderInput != null);
  179. // show if
  180. if (usedSlot || // it's referenced by the shader - regardless of empty or not
  181. (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled"
  182. (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty"
  183. )
  184. {
  185. string slotname = i.ToString();
  186. if (shaderInput != null && shaderInput.name != "")
  187. slotname += ": " + shaderInput.name;
  188. UInt32 w = 1, h = 1, d = 1;
  189. UInt32 a = 1;
  190. string format = "Unknown";
  191. string name = "Shader Resource " + r.Resource.ToString();
  192. string typename = "Unknown";
  193. object tag = null;
  194. if (!filledSlot)
  195. {
  196. name = "Empty";
  197. format = "-";
  198. typename = "-";
  199. w = h = d = a = 0;
  200. }
  201. // check to see if it's a texture
  202. for (int t = 0; t < texs.Length; t++)
  203. {
  204. if (texs[t].ID == r.Resource)
  205. {
  206. w = texs[t].width;
  207. h = texs[t].height;
  208. d = texs[t].depth;
  209. a = texs[t].arraysize;
  210. format = texs[t].format.ToString();
  211. name = texs[t].name;
  212. typename = string.Format("Texture{0}D", texs[t].dimension);
  213. if(texs[t].cubemap)
  214. typename = "TexCube";
  215. tag = texs[t];
  216. }
  217. }
  218. // if not a texture, it must be a buffer
  219. for (int t = 0; t < bufs.Length; t++)
  220. {
  221. if (bufs[t].ID == r.Resource)
  222. {
  223. w = bufs[t].length;
  224. h = 0;
  225. d = 0;
  226. a = 0;
  227. format = "";
  228. name = bufs[t].name;
  229. typename = "Buffer";
  230. // for structured buffers, display how many 'elements' there are in the buffer
  231. if (bufs[t].structureSize > 0)
  232. typename = "StructuredBuffer[" + (bufs[t].length / bufs[t].structureSize) + "]";
  233. // get the buffer type, whether it's just a basic type or a complex struct
  234. if (shaderInput != null && !shaderInput.IsTexture)
  235. {
  236. if (r.Format.compType == FormatComponentType.None)
  237. {
  238. if (shaderInput.variableType.members.Length > 0)
  239. format = "struct " + shaderInput.variableType.Name;
  240. else
  241. format = shaderInput.variableType.Name;
  242. }
  243. else
  244. {
  245. format = r.Format.ToString();
  246. }
  247. }
  248. tag = bufs[t];
  249. }
  250. }
  251. var node = resources.Nodes.Add(new object[] { slotname, name, typename, w, h, d, a, format });
  252. node.Image = global::renderdocui.Properties.Resources.action;
  253. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  254. node.Tag = tag;
  255. if (!filledSlot)
  256. EmptyRow(node);
  257. if (!usedSlot)
  258. InactiveRow(node);
  259. }
  260. i++;
  261. }
  262. }
  263. resources.EndUpdate();
  264. resources.NodesSelection.Clear();
  265. samplers.BeginUpdate();
  266. samplers.Nodes.Clear();
  267. if (stage.Samplers != null)
  268. {
  269. int i = 0;
  270. foreach (var s in stage.Samplers)
  271. {
  272. ShaderResource shaderInput = null;
  273. if (shaderDetails != null)
  274. {
  275. foreach (var bind in shaderDetails.Resources)
  276. {
  277. if (bind.IsSampler && bind.bindPoint == i)
  278. shaderInput = bind;
  279. }
  280. }
  281. bool filledSlot = (s.AddressU != "");
  282. bool usedSlot = (shaderInput != null);
  283. // show if
  284. if (usedSlot || // it's referenced by the shader - regardless of empty or not
  285. (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled"
  286. (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty"
  287. )
  288. {
  289. string slotname = i.ToString();
  290. if (shaderInput != null && shaderInput.name != "")
  291. slotname += ": " + shaderInput.name;
  292. string borderColor = s.BorderColor[0].ToString() + ", " +
  293. s.BorderColor[1].ToString() + ", " +
  294. s.BorderColor[2].ToString() + ", " +
  295. s.BorderColor[3].ToString();
  296. string addressing = "";
  297. string addPrefix = "";
  298. string addVal = "";
  299. string[] addr = { s.AddressU, s.AddressV, s.AddressW };
  300. // arrange like either UVW: WRAP or UV: WRAP, W: CLAMP
  301. for (int a = 0; a < 3; a++)
  302. {
  303. string prefix = "" + "UVW"[a];
  304. if (a == 0 || addr[a] == addr[a - 1])
  305. {
  306. addPrefix += prefix;
  307. }
  308. else
  309. {
  310. addressing += addPrefix + ": " + addVal + ", ";
  311. addPrefix = prefix;
  312. }
  313. addVal = addr[a];
  314. }
  315. addressing += addPrefix + ": " + addVal;
  316. var node = samplers.Nodes.Add(new object[] { slotname, addressing, borderColor,
  317. s.Comparison, s.Filter, s.MaxAniso.ToString(),
  318. s.MinLOD == -float.MaxValue ? "-FLT_MAX" : s.MinLOD.ToString(),
  319. s.MaxLOD == float.MaxValue ? "FLT_MAX" : s.MaxLOD.ToString(),
  320. s.MipLODBias.ToString() });
  321. if (!filledSlot)
  322. EmptyRow(node);
  323. if (!usedSlot)
  324. InactiveRow(node);
  325. }
  326. i++;
  327. }
  328. }
  329. samplers.EndUpdate();
  330. samplers.NodesSelection.Clear();
  331. cbuffers.BeginUpdate();
  332. cbuffers.Nodes.Clear();
  333. if (stage.ConstantBuffers != null)
  334. {
  335. UInt32 i = 0;
  336. foreach (var b in stage.ConstantBuffers)
  337. {
  338. ConstantBlock shaderCBuf = null;
  339. if (shaderDetails != null && i < shaderDetails.ConstantBlocks.Length && shaderDetails.ConstantBlocks[i].name != "")
  340. shaderCBuf = shaderDetails.ConstantBlocks[i];
  341. bool filledSlot = (b.Buffer != ResourceId.Null);
  342. bool usedSlot = (shaderCBuf != null);
  343. // show if
  344. if (usedSlot || // it's referenced by the shader - regardless of empty or not
  345. (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled"
  346. (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty"
  347. )
  348. {
  349. string name = "Constant Buffer " + b.Buffer.ToString();
  350. UInt32 length = 1;
  351. int numvars = shaderCBuf != null ? shaderCBuf.variables.Length : 0;
  352. if (!filledSlot)
  353. {
  354. name = "Empty";
  355. length = 0;
  356. }
  357. for (int t = 0; t < bufs.Length; t++)
  358. {
  359. if (bufs[t].ID == b.Buffer)
  360. {
  361. name = bufs[t].name;
  362. length = bufs[t].length;
  363. }
  364. }
  365. string slotname = i.ToString();
  366. if (shaderCBuf != null && shaderCBuf.name != "")
  367. slotname += ": " + shaderCBuf.name;
  368. var node = cbuffers.Nodes.Add(new object[] { slotname, name, b.VecOffset, b.VecCount, numvars, length });
  369. node.Image = global::renderdocui.Properties.Resources.action;
  370. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  371. node.Tag = i;
  372. if (!filledSlot)
  373. EmptyRow(node);
  374. if (!usedSlot)
  375. InactiveRow(node);
  376. }
  377. i++;
  378. }
  379. }
  380. cbuffers.EndUpdate();
  381. cbuffers.NodesSelection.Clear();
  382. classes.BeginUpdate();
  383. classes.Nodes.Clear();
  384. {
  385. UInt32 i = 0;
  386. foreach (var inst in stage.ClassInstances)
  387. {
  388. string interfaceName = String.Format("Interface {0}", i);
  389. if (shaderDetails != null && i < shaderDetails.Interfaces.Length)
  390. interfaceName = shaderDetails.Interfaces[i].Name;
  391. classes.Nodes.Add(new object[] { i.ToString(), interfaceName, inst });
  392. i++;
  393. }
  394. }
  395. classes.EndUpdate();
  396. classes.NodesSelection.Clear();
  397. }
  398. // from https://gist.github.com/mjijackson/5311256
  399. private float CalcHue(float p, float q, float t)
  400. {
  401. if (t < 0) t += 1;
  402. if (t > 1) t -= 1;
  403. if (t < 1.0f / 6.0f)
  404. return p + (q - p) * 6.0f * t;
  405. if (t < 0.5f)
  406. return q;
  407. if (t < 2.0f / 3.0f)
  408. return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
  409. return p;
  410. }
  411. private Color HSLColor(float h, float s, float l)
  412. {
  413. float r, g, b;
  414. if (s == 0)
  415. {
  416. r = g = b = l; // achromatic
  417. }
  418. else
  419. {
  420. var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  421. var p = 2 * l - q;
  422. r = CalcHue(p, q, h + 1.0f / 3.0f);
  423. g = CalcHue(p, q, h);
  424. b = CalcHue(p, q, h - 1.0f / 3.0f);
  425. }
  426. return Color.FromArgb(255, (int)(r * 255), (int)(g * 255), (int)(b * 255));
  427. }
  428. private void UpdateState()
  429. {
  430. if (!m_Core.LogLoaded)
  431. return;
  432. FetchTexture[] texs = m_Core.CurTextures;
  433. FetchBuffer[] bufs = m_Core.CurBuffers;
  434. D3D11PipelineState state = m_Core.CurD3D11PipelineState;
  435. FetchDrawcall draw = m_Core.CurDrawcall;
  436. var tick = global::renderdocui.Properties.Resources.tick;
  437. var cross = global::renderdocui.Properties.Resources.cross;
  438. bool[] usedVBuffers = new bool[128];
  439. UInt32[] layoutOffs = new UInt32[128];
  440. for (int i = 0; i < 128; i++)
  441. {
  442. usedVBuffers[i] = false;
  443. layoutOffs[i] = 0;
  444. }
  445. ////////////////////////////////////////////////
  446. // Input Assembler
  447. if(state.m_IA.Bytecode == null)
  448. iaBytecode.Text = "None";
  449. else if(state.m_IA.Bytecode.DebugInfo == null || state.m_IA.Bytecode.DebugInfo.entryFunc == "")
  450. iaBytecode.Text = "Layout " + state.m_IA.layout.ToString();
  451. else
  452. iaBytecode.Text = state.m_IA.Bytecode.DebugInfo.entryFunc;
  453. iaBytecodeMismatch.Text = "";
  454. iaBytecodeMismatch.Visible = false;
  455. // check for IA-VS mismatches here.
  456. // This should be moved to a "Render Doctor" window reporting problems
  457. if (state.m_IA.Bytecode != null && state.m_VS.ShaderDetails != null)
  458. {
  459. string mismatchDetails = "";
  460. // VS wants more elements
  461. if (state.m_IA.Bytecode.InputSig.Length < state.m_VS.ShaderDetails.InputSig.Length)
  462. mismatchDetails += "IA bytecode provides fewer elements than VS wants.\n";
  463. {
  464. var IA = state.m_IA.Bytecode.InputSig;
  465. var VS = state.m_VS.ShaderDetails.InputSig;
  466. int count = Math.Min(IA.Length, VS.Length);
  467. for (int i = 0; i < count; i++)
  468. {
  469. // misorder or misnamed semantics
  470. if (IA[i].semanticIdxName.ToLowerInvariant() != VS[i].semanticIdxName.ToLowerInvariant())
  471. mismatchDetails += String.Format("IA bytecode semantic {0}: {1} != VS bytecode semantic {0}: {2}\n", i,
  472. IA[i].semanticIdxName, VS[i].semanticIdxName);
  473. // VS wants more components
  474. if (IA[i].compCount < VS[i].compCount)
  475. mismatchDetails += String.Format("IA bytecode semantic {0} ({1}) is {3}-wide, VS bytecode semantic {0} ({1}) {2} is {4}-wide\n", i,
  476. IA[i].semanticIdxName, VS[i].semanticIdxName,
  477. IA[i].compCount, VS[i].compCount);
  478. // VS wants different types
  479. if (IA[i].compType != VS[i].compType)
  480. mismatchDetails += String.Format("IA bytecode semantic {0} ({1}) is {3}, VS bytecode semantic {0} ({2}) is {4}\n", i,
  481. IA[i].semanticIdxName, VS[i].semanticIdxName,
  482. IA[i].compType, VS[i].compType);
  483. }
  484. }
  485. if (mismatchDetails.Length != 0)
  486. {
  487. iaBytecodeMismatch.Text = "Warning: Mismatch detected between bytecode used to create IA and currently bound VS inputs";
  488. toolTip.SetToolTip(iaBytecodeMismatch, mismatchDetails.Trim());
  489. iaBytecodeMismatch.Visible = true;
  490. }
  491. }
  492. inputLayouts.Nodes.Clear();
  493. inputLayouts.BeginUpdate();
  494. if (state.m_IA.layouts != null)
  495. {
  496. int i = 0;
  497. foreach (var l in state.m_IA.layouts)
  498. {
  499. string byteOffs = l.ByteOffset.ToString();
  500. // D3D11 specific value
  501. if (l.ByteOffset == uint.MaxValue)
  502. {
  503. byteOffs = String.Format("APPEND_ALIGNED ({0})", layoutOffs[l.InputSlot]);
  504. }
  505. else
  506. {
  507. layoutOffs[l.InputSlot] = l.ByteOffset;
  508. }
  509. layoutOffs[l.InputSlot] += l.Format.compByteWidth * l.Format.compCount;
  510. var node = inputLayouts.Nodes.Add(new object[] {
  511. i, l.SemanticName, l.SemanticIndex.ToString(), l.Format, l.InputSlot.ToString(), byteOffs,
  512. l.PerInstance ? "PER_INSTANCE" : "PER_VERTEX", l.InstanceDataStepRate.ToString() });
  513. usedVBuffers[l.InputSlot] = true;
  514. node.Image = global::renderdocui.Properties.Resources.action;
  515. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  516. i++;
  517. }
  518. }
  519. inputLayouts.NodesSelection.Clear();
  520. inputLayouts.EndUpdate();
  521. topology.Text = state.m_IA.Topology.ToString();
  522. if (state.m_IA.Topology > PrimitiveTopology.PatchList)
  523. {
  524. int numCPs = (int)state.m_IA.Topology - (int)PrimitiveTopology.PatchList + 1;
  525. topology.Text = string.Format("PatchList ({0} Control Points)", numCPs);
  526. }
  527. switch (state.m_IA.Topology)
  528. {
  529. case PrimitiveTopology.PointList:
  530. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_pointlist;
  531. break;
  532. case PrimitiveTopology.LineList:
  533. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_linelist;
  534. break;
  535. case PrimitiveTopology.LineStrip:
  536. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_linestrip;
  537. break;
  538. case PrimitiveTopology.TriangleList:
  539. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_trilist;
  540. break;
  541. case PrimitiveTopology.TriangleStrip:
  542. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_tristrip;
  543. break;
  544. case PrimitiveTopology.LineList_Adj:
  545. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_linelist_adj;
  546. break;
  547. case PrimitiveTopology.LineStrip_Adj:
  548. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_linestrip_adj;
  549. break;
  550. case PrimitiveTopology.TriangleList_Adj:
  551. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_trilist_adj;
  552. break;
  553. case PrimitiveTopology.TriangleStrip_Adj:
  554. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_tristrip_adj;
  555. break;
  556. default:
  557. topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_patch;
  558. break;
  559. }
  560. iabuffers.Nodes.Clear();
  561. iabuffers.BeginUpdate();
  562. bool ibufferUsed = draw != null && (draw.flags & DrawcallFlags.UseIBuffer) != 0;
  563. if (state.m_IA.ibuffer != null)
  564. {
  565. if (ibufferUsed || showDisabled.Checked)
  566. {
  567. string ptr = "Buffer " + state.m_IA.ibuffer.Buffer.ToString();
  568. string name = ptr;
  569. UInt32 length = 1;
  570. if (!ibufferUsed)
  571. {
  572. length = 0;
  573. }
  574. for (int t = 0; t < bufs.Length; t++)
  575. {
  576. if (bufs[t].ID == state.m_IA.ibuffer.Buffer)
  577. {
  578. name = bufs[t].name;
  579. length = bufs[t].length;
  580. }
  581. }
  582. var node = iabuffers.Nodes.Add(new object[] { "Index", name, state.m_IA.ibuffer.Format.compByteWidth, state.m_IA.ibuffer.Offset, length });
  583. node.Image = global::renderdocui.Properties.Resources.action;
  584. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  585. node.Tag = state.m_IA.ibuffer.Buffer;
  586. if (!ibufferUsed)
  587. InactiveRow(node);
  588. if (state.m_IA.ibuffer.Buffer == ResourceId.Null)
  589. EmptyRow(node);
  590. }
  591. }
  592. else
  593. {
  594. if (showEmpty.Checked &&
  595. (ibufferUsed || showDisabled.Checked))
  596. {
  597. var node = iabuffers.Nodes.Add(new object[] { "Index", "-", "-", "-", "-" });
  598. node.Image = global::renderdocui.Properties.Resources.action;
  599. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  600. node.Tag = state.m_IA.ibuffer.Buffer;
  601. EmptyRow(node);
  602. if (!ibufferUsed)
  603. InactiveRow(node);
  604. }
  605. }
  606. m_VBNodes.Clear();
  607. if (state.m_IA.vbuffers != null)
  608. {
  609. int i = 0;
  610. foreach (var v in state.m_IA.vbuffers)
  611. {
  612. bool filledSlot = (v.Buffer != ResourceId.Null);
  613. bool usedSlot = (usedVBuffers[i]);
  614. // show if
  615. if (usedSlot || // it's referenced by the shader - regardless of empty or not
  616. (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled"
  617. (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty"
  618. )
  619. {
  620. string name = "Buffer " + v.Buffer.ToString();
  621. UInt32 length = 1;
  622. if (!filledSlot)
  623. {
  624. name = "Empty";
  625. length = 0;
  626. }
  627. for (int t = 0; t < bufs.Length; t++)
  628. {
  629. if (bufs[t].ID == v.Buffer)
  630. {
  631. name = bufs[t].name;
  632. length = bufs[t].length;
  633. }
  634. }
  635. var node = iabuffers.Nodes.Add(new object[] { i, name, v.Stride, v.Offset, length });
  636. node.Image = global::renderdocui.Properties.Resources.action;
  637. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  638. node.Tag = v.Buffer;
  639. if (!filledSlot)
  640. EmptyRow(node);
  641. if (!usedSlot)
  642. InactiveRow(node);
  643. m_VBNodes.Add(node);
  644. }
  645. i++;
  646. }
  647. }
  648. iabuffers.NodesSelection.Clear();
  649. iabuffers.EndUpdate();
  650. SetShaderState(texs, bufs, state.m_VS, vsShader, vsResources, vsSamplers, vsCBuffers, vsClasses);
  651. SetShaderState(texs, bufs, state.m_GS, gsShader, gsResources, gsSamplers, gsCBuffers, gsClasses);
  652. SetShaderState(texs, bufs, state.m_HS, hsShader, hsResources, hsSamplers, hsCBuffers, hsClasses);
  653. SetShaderState(texs, bufs, state.m_DS, dsShader, dsResources, dsSamplers, dsCBuffers, dsClasses);
  654. SetShaderState(texs, bufs, state.m_PS, psShader, psResources, psSamplers, psCBuffers, psClasses);
  655. SetShaderState(texs, bufs, state.m_CS, csShader, csResources, csSamplers, csCBuffers, csClasses);
  656. csUAVs.Nodes.Clear();
  657. csUAVs.BeginUpdate();
  658. if (state.m_CS.UAVs != null)
  659. {
  660. int i = 0;
  661. foreach (var r in state.m_CS.UAVs)
  662. {
  663. ShaderResource shaderInput = null;
  664. if (state.m_CS.ShaderDetails != null)
  665. {
  666. foreach (var bind in state.m_CS.ShaderDetails.Resources)
  667. {
  668. if (bind.IsUAV && bind.bindPoint == i)
  669. shaderInput = bind;
  670. }
  671. }
  672. bool filledSlot = (r.Resource != ResourceId.Null);
  673. bool usedSlot = (shaderInput != null);
  674. // show if
  675. if (usedSlot || // it's referenced by the shader - regardless of empty or not
  676. (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled"
  677. (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty"
  678. )
  679. {
  680. UInt32 w = 1, h = 1, d = 1;
  681. UInt32 a = 1;
  682. string format = "Unknown";
  683. string name = "UAV " + r.Resource.ToString();
  684. string typename = "Unknown";
  685. object tag = null;
  686. if (!filledSlot)
  687. {
  688. name = "Empty";
  689. format = "-";
  690. typename = "-";
  691. w = h = d = a = 0;
  692. }
  693. for (int t = 0; t < texs.Length; t++)
  694. {
  695. if (texs[t].ID == r.Resource)
  696. {
  697. w = texs[t].width;
  698. h = texs[t].height;
  699. d = texs[t].depth;
  700. a = texs[t].arraysize;
  701. format = texs[t].format.ToString();
  702. name = texs[t].name;
  703. typename = string.Format("Texture{0}D", texs[t].dimension);
  704. if (texs[t].cubemap)
  705. typename = "TexCube";
  706. tag = texs[t];
  707. }
  708. }
  709. for (int t = 0; t < bufs.Length; t++)
  710. {
  711. if (bufs[t].ID == r.Resource)
  712. {
  713. w = bufs[t].length;
  714. h = 0;
  715. d = 0;
  716. a = 0;
  717. format = "";
  718. name = bufs[t].name;
  719. typename = "Buffer";
  720. if (bufs[t].structureSize > 0)
  721. typename = "StructuredBuffer[" + (bufs[t].length / bufs[t].structureSize) + "]";
  722. if (r.Structured)
  723. {
  724. typename += " (Count: " + r.BufferStructCount + ")";
  725. }
  726. if (shaderInput != null && !shaderInput.IsTexture)
  727. {
  728. if (r.Format.compType == FormatComponentType.None)
  729. {
  730. if (shaderInput.variableType.members.Length > 0)
  731. format = "struct " + shaderInput.variableType.Name;
  732. else
  733. format = shaderInput.variableType.Name;
  734. }
  735. else
  736. {
  737. format = r.Format.ToString();
  738. }
  739. }
  740. tag = bufs[t];
  741. }
  742. }
  743. var node = csUAVs.Nodes.Add(new object[] { i, name, typename, w, h, d, a, format });
  744. node.Tag = tag;
  745. node.Image = global::renderdocui.Properties.Resources.action;
  746. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  747. if (!filledSlot)
  748. EmptyRow(node);
  749. if (!usedSlot)
  750. InactiveRow(node);
  751. }
  752. i++;
  753. }
  754. }
  755. csUAVs.NodesSelection.Clear();
  756. csUAVs.EndUpdate();
  757. gsStreams.BeginUpdate();
  758. gsStreams.Nodes.Clear();
  759. if (state.m_SO.Outputs != null)
  760. {
  761. int i = 0;
  762. foreach (var s in state.m_SO.Outputs)
  763. {
  764. bool filledSlot = (s.Buffer != ResourceId.Null);
  765. bool usedSlot = (filledSlot);
  766. // show if
  767. if (usedSlot || // it's referenced by the shader - regardless of empty or not
  768. (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled"
  769. (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty"
  770. )
  771. {
  772. string name = "Buffer " + s.Buffer.ToString();
  773. uint length = 0;
  774. if (!filledSlot)
  775. {
  776. name = "Empty";
  777. }
  778. FetchBuffer fetch = null;
  779. for (int t = 0; t < bufs.Length; t++)
  780. {
  781. if (bufs[t].ID == s.Buffer)
  782. {
  783. name = bufs[t].name;
  784. length = bufs[t].length;
  785. fetch = bufs[t];
  786. }
  787. }
  788. var node = gsStreams.Nodes.Add(new object[] { i, name, length, s.Offset });
  789. node.Image = global::renderdocui.Properties.Resources.action;
  790. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  791. node.Tag = fetch;
  792. if (!filledSlot)
  793. EmptyRow(node);
  794. if (!usedSlot)
  795. InactiveRow(node);
  796. }
  797. i++;
  798. }
  799. }
  800. gsStreams.EndUpdate();
  801. gsStreams.NodesSelection.Clear();
  802. ////////////////////////////////////////////////
  803. // Rasterizer
  804. viewports.BeginUpdate();
  805. viewports.Nodes.Clear();
  806. if (state.m_RS.Viewports != null)
  807. {
  808. int i = 0;
  809. foreach (var v in state.m_RS.Viewports)
  810. {
  811. if (v.Width != v.Height || v.Width != 0 || v.Height != 0 || showEmpty.Checked)
  812. {
  813. var node = viewports.Nodes.Add(new object[] { i, v.TopLeft[0], v.TopLeft[1], v.Width, v.Height, v.MinDepth, v.MaxDepth });
  814. if (v.Width == v.Height && v.Width == 0 && v.Height == 0)
  815. EmptyRow(node);
  816. }
  817. i++;
  818. }
  819. }
  820. viewports.NodesSelection.Clear();
  821. viewports.EndUpdate();
  822. scissors.BeginUpdate();
  823. scissors.Nodes.Clear();
  824. if (state.m_RS.Scissors != null)
  825. {
  826. int i = 0;
  827. foreach (var s in state.m_RS.Scissors)
  828. {
  829. if (s.right != 0 || s.bottom != 0 || showEmpty.Checked)
  830. {
  831. var node = scissors.Nodes.Add(new object[] { i, s.left, s.top, s.right - s.left, s.bottom - s.top });
  832. if (s.right == 0 && s.bottom == 0)
  833. EmptyRow(node);
  834. }
  835. i++;
  836. }
  837. }
  838. scissors.NodesSelection.Clear();
  839. scissors.EndUpdate();
  840. fillMode.Text = state.m_RS.m_State.FillMode.ToString();
  841. cullMode.Text = state.m_RS.m_State.CullMode.ToString();
  842. frontCCW.Image = state.m_RS.m_State.FrontCCW ? tick : cross;
  843. scissorEnable.Image = state.m_RS.m_State.ScissorEnable ? tick : cross;
  844. lineAAEnable.Image = state.m_RS.m_State.AntialiasedLineEnable ? tick : cross;
  845. multisampleEnable.Image = state.m_RS.m_State.MultisampleEnable ? tick : cross;
  846. depthClip.Image = state.m_RS.m_State.DepthClip ? tick : cross;
  847. depthBias.Text = state.m_RS.m_State.DepthBias.ToString();
  848. depthBiasClamp.Text = Formatter.Format(state.m_RS.m_State.DepthBiasClamp);
  849. slopeScaledBias.Text = Formatter.Format(state.m_RS.m_State.SlopeScaledDepthBias);
  850. forcedSampleCount.Text = state.m_RS.m_State.ForcedSampleCount.ToString();
  851. ////////////////////////////////////////////////
  852. // Output Merger
  853. bool[] targets = new bool[8];
  854. for (int i = 0; i < 8; i++)
  855. targets[i] = false;
  856. targetOutputs.BeginUpdate();
  857. targetOutputs.Nodes.Clear();
  858. if (state.m_OM.RenderTargets != null)
  859. {
  860. int i = 0;
  861. foreach (var p in state.m_OM.RenderTargets)
  862. {
  863. if (p.Resource != ResourceId.Null || showEmpty.Checked)
  864. {
  865. UInt32 w = 1, h = 1, d = 1;
  866. UInt32 a = 1;
  867. string format = "Unknown";
  868. string name = "Texture " + p.ToString();
  869. string typename = "Unknown";
  870. object tag = null;
  871. if (p.Resource == ResourceId.Null)
  872. {
  873. name = "Empty";
  874. format = "-";
  875. typename = "-";
  876. w = h = d = a = 0;
  877. }
  878. for (int t = 0; t < texs.Length; t++)
  879. {
  880. if (texs[t].ID == p.Resource)
  881. {
  882. w = texs[t].width;
  883. h = texs[t].height;
  884. d = texs[t].depth;
  885. a = texs[t].arraysize;
  886. format = texs[t].format.ToString();
  887. name = texs[t].name;
  888. typename = string.Format("Texture{0}D", texs[t].dimension);
  889. if (texs[t].cubemap)
  890. typename = "TexCube";
  891. tag = texs[t];
  892. }
  893. }
  894. var node = targetOutputs.Nodes.Add(new object[] { i, name, typename, w, h, d, a, format });
  895. node.Image = global::renderdocui.Properties.Resources.action;
  896. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  897. node.Tag = tag;
  898. if (p.Resource == ResourceId.Null)
  899. {
  900. EmptyRow(node);
  901. }
  902. else
  903. {
  904. targets[i] = true;
  905. }
  906. }
  907. i++;
  908. }
  909. }
  910. if (state.m_OM.UAVs != null)
  911. {
  912. int i = 0;
  913. foreach (var r in state.m_OM.UAVs)
  914. {
  915. ShaderResource shaderInput = null;
  916. if (state.m_PS.ShaderDetails != null)
  917. {
  918. foreach (var bind in state.m_PS.ShaderDetails.Resources)
  919. {
  920. if (bind.IsUAV && bind.bindPoint == i + state.m_OM.UAVStartSlot)
  921. shaderInput = bind;
  922. }
  923. }
  924. bool filledSlot = (r.Resource != ResourceId.Null);
  925. bool usedSlot = (shaderInput != null);
  926. // note: we don't show empty UAVs as these "slots" are already showed as empty RTs.
  927. // show if
  928. if (usedSlot || // it's referenced by the shader - regardless of empty or not
  929. (showDisabled.Checked && !usedSlot && filledSlot) // it's bound, but not referenced, and we have "show disabled"
  930. )
  931. {
  932. UInt32 w = 1, h = 1, d = 1;
  933. UInt32 a = 1;
  934. string format = "Unknown";
  935. string name = "UAV " + r.Resource.ToString();
  936. string typename = "Unknown";
  937. object tag = null;
  938. if (!filledSlot)
  939. {
  940. name = "Empty";
  941. format = "-";
  942. typename = "-";
  943. w = h = d = a = 0;
  944. }
  945. for (int t = 0; t < texs.Length; t++)
  946. {
  947. if (texs[t].ID == r.Resource)
  948. {
  949. w = texs[t].width;
  950. h = texs[t].height;
  951. d = texs[t].depth;
  952. a = texs[t].arraysize;
  953. format = texs[t].format.ToString();
  954. name = texs[t].name;
  955. typename = string.Format("Texture{0}D", texs[t].dimension);
  956. if (texs[t].cubemap)
  957. typename = "TexCube";
  958. tag = texs[t];
  959. }
  960. }
  961. for (int t = 0; t < bufs.Length; t++)
  962. {
  963. if (bufs[t].ID == r.Resource)
  964. {
  965. w = bufs[t].length;
  966. h = 0;
  967. d = 0;
  968. a = 0;
  969. format = "";
  970. name = bufs[t].name;
  971. typename = "Buffer";
  972. if (bufs[t].structureSize > 0)
  973. typename = "StructuredBuffer[" + (bufs[t].length / bufs[t].structureSize) + "]";
  974. if (r.Structured)
  975. {
  976. typename += " (Count: " + r.BufferStructCount + ")";
  977. }
  978. if (shaderInput != null && !shaderInput.IsTexture)
  979. {
  980. if (r.Format.compType == FormatComponentType.None)
  981. {
  982. if (shaderInput.variableType.members.Length > 0)
  983. format = "struct " + shaderInput.variableType.Name;
  984. else
  985. format = shaderInput.variableType.Name;
  986. }
  987. else
  988. {
  989. format = r.Format.ToString();
  990. }
  991. }
  992. tag = bufs[t];
  993. }
  994. }
  995. var node = targetOutputs.Nodes.Add(new object[] { i + state.m_OM.UAVStartSlot, name, typename, w, h, d, a, format });
  996. node.Image = global::renderdocui.Properties.Resources.action;
  997. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  998. node.Tag = tag;
  999. if (r.Resource == ResourceId.Null)
  1000. EmptyRow(node);
  1001. }
  1002. i++;
  1003. }
  1004. }
  1005. if (state.m_OM.DepthTarget.Resource != ResourceId.Null || showEmpty.Checked)
  1006. {
  1007. UInt32 w = 1, h = 1, d = 1;
  1008. UInt32 a = 1;
  1009. string format = "Unknown";
  1010. string name = "Depth Target " + state.m_OM.DepthTarget.Resource.ToString();
  1011. string typename = "Unknown";
  1012. object tag = null;
  1013. if (state.m_OM.DepthTarget.Resource == ResourceId.Null)
  1014. {
  1015. name = "Empty";
  1016. format = "-";
  1017. typename = "-";
  1018. w = h = d = a = 0;
  1019. }
  1020. for (int t = 0; t < texs.Length; t++)
  1021. {
  1022. if (texs[t].ID == state.m_OM.DepthTarget.Resource)
  1023. {
  1024. w = texs[t].width;
  1025. h = texs[t].height;
  1026. d = texs[t].depth;
  1027. a = texs[t].arraysize;
  1028. format = texs[t].format.ToString();
  1029. name = texs[t].name;
  1030. typename = string.Format("Texture{0}D", texs[t].dimension);
  1031. if (texs[t].cubemap)
  1032. typename = "TexCube";
  1033. tag = texs[t];
  1034. }
  1035. }
  1036. var node = targetOutputs.Nodes.Add(new object[] { "Depth", name, typename, w, h, d, a, format });
  1037. node.Image = global::renderdocui.Properties.Resources.action;
  1038. node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
  1039. node.Tag = tag;
  1040. if (state.m_OM.DepthTarget.Resource == ResourceId.Null)
  1041. EmptyRow(node);
  1042. }
  1043. targetOutputs.EndUpdate();
  1044. targetOutputs.NodesSelection.Clear();
  1045. blendOperations.BeginUpdate();
  1046. blendOperations.Nodes.Clear();
  1047. {
  1048. int i = 0;
  1049. foreach(var blend in state.m_OM.m_BlendState.Blends)
  1050. {
  1051. bool filledSlot = (blend.Enabled == true || targets[i]);
  1052. bool usedSlot = (targets[i]);
  1053. // show if
  1054. if (usedSlot || // it's referenced by the shader - regardless of empty or not
  1055. (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled"
  1056. (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty"
  1057. )
  1058. {
  1059. var node = blendOperations.Nodes.Add(new object[] { i,
  1060. blend.Enabled,
  1061. blend.LogicEnabled,
  1062. blend.m_Blend.Source,
  1063. blend.m_Blend.Destination,
  1064. blend.m_Blend.Operation,
  1065. blend.m_AlphaBlend.Source,
  1066. blend.m_AlphaBlend.Destination,
  1067. blend.m_AlphaBlend.Operation,
  1068. blend.LogicOp,
  1069. ((blend.WriteMask & 0x1) == 0 ? "_" : "R") +
  1070. ((blend.WriteMask & 0x2) == 0 ? "_" : "G") +
  1071. ((blend.WriteMask & 0x4) == 0 ? "_" : "B") +
  1072. ((blend.WriteMask & 0x8) == 0 ? "_" : "A")
  1073. });
  1074. if (!filledSlot)
  1075. EmptyRow(node);
  1076. if (!usedSlot)
  1077. InactiveRow(node);
  1078. }
  1079. i++;
  1080. }
  1081. }
  1082. blendOperations.NodesSelection.Clear();
  1083. blendOperations.EndUpdate();
  1084. alphaToCoverage.Image = state.m_OM.m_BlendState.AlphaToCoverage ? tick : cross;
  1085. independentBlend.Image = state.m_OM.m_BlendState.IndependentBlend ? tick : cross;
  1086. blendFactor.Text = state.m_OM.m_BlendState.BlendFactor[0].ToString("F2") + ", " +
  1087. state.m_OM.m_BlendState.BlendFactor[1].ToString("F2") + ", " +
  1088. state.m_OM.m_BlendState.BlendFactor[2].ToString("F2") + ", " +
  1089. state.m_OM.m_BlendState.BlendFactor[3].ToString("F2");
  1090. sampleMask.Text = state.m_OM.m_BlendState.SampleMask.ToString("X8");
  1091. depthEnable.Image = state.m_OM.m_State.DepthEnable ? tick : cross;
  1092. depthFunc.Text = state.m_OM.m_State.DepthFunc;
  1093. depthWrite.Image = state.m_OM.m_State.DepthWrites ? tick : cross;
  1094. stencilEnable.Image = state.m_OM.m_State.StencilEnable ? tick : cross;
  1095. stencilReadMask.Text = state.m_OM.m_State.StencilReadMask.ToString("X2");
  1096. stencilWriteMask.Text = state.m_OM.m_State.StencilWriteMask.ToString("X2");
  1097. stencilRef.Text = state.m_OM.m_State.StencilRef.ToString("X2");
  1098. stencilFuncs.BeginUpdate();
  1099. stencilFuncs.Nodes.Clear();
  1100. stencilFuncs.Nodes.Add(new object[] { "Front", state.m_OM.m_State.m_FrontFace.Func, state.m_OM.m_State.m_FrontFace.FailOp,
  1101. state.m_OM.m_State.m_FrontFace.DepthFailOp, state.m_OM.m_State.m_FrontFace.PassOp });
  1102. stencilFuncs.Nodes.Add(new object[] { "Back", state.m_OM.m_State.m_BackFace.Func, state.m_OM.m_State.m_BackFace.FailOp,
  1103. state.m_OM.m_State.m_BackFace.DepthFailOp, state.m_OM.m_State.m_BackFace.PassOp });
  1104. stencilFuncs.EndUpdate();
  1105. stencilFuncs.NodesSelection.Clear();
  1106. // highlight the appropriate stages in the flowchart
  1107. if (draw == null)
  1108. {
  1109. pipeFlow.SetStagesEnabled(new bool[] { true, true, true, true, true, true, true, true, true });
  1110. }
  1111. else if ((draw.flags & DrawcallFlags.Dispatch) != 0)
  1112. {
  1113. pipeFlow.SetStagesEnabled(new bool[] { false, false, false, false, false, false, false, false, true });
  1114. }
  1115. else
  1116. {
  1117. pipeFlow.SetStagesEnabled(new bool[] {
  1118. true,
  1119. true,
  1120. state.m_HS.Shader != ResourceId.Null,
  1121. state.m_DS.Shader != ResourceId.Null,
  1122. state.m_GS.Shader != ResourceId.Null,
  1123. true,
  1124. state.m_PS.Shader != ResourceId.Null,
  1125. true,
  1126. false
  1127. });
  1128. // if(streamout only)
  1129. //{
  1130. // pipeFlow.Rasterizer = false;
  1131. // pipeFlow.OutputMerger = false;
  1132. //}
  1133. }
  1134. }
  1135. public void OnEventSelected(UInt32 frameID, UInt32 eventID)
  1136. {
  1137. UpdateState();
  1138. }
  1139. private void hideDisabledEmpty_MouseClick(object sender, MouseEventArgs e)
  1140. {
  1141. if (e.Button == MouseButtons.Right)
  1142. {
  1143. rightclickMenu.Show((Control)sender, new Point(e.X, e.Y));
  1144. }
  1145. }
  1146. private void hideDisabled_Click(object sender, EventArgs e)
  1147. {
  1148. showDisabled.Checked = !showDisabled.Checked;
  1149. showDisabledToolitem.Checked = showDisabled.Checked;
  1150. UpdateState();
  1151. }
  1152. private void hideEmpty_Click(object sender, EventArgs e)
  1153. {
  1154. showEmpty.Checked = !showEmpty.Checked;
  1155. showEmptyToolitem.Checked = showEmpty.Checked;
  1156. UpdateState();
  1157. }
  1158. // launch the appropriate kind of viewer, depending on the type of resource that's in this node
  1159. private void textureCell_CellDoubleClick(TreelistView.Node node)
  1160. {
  1161. object tag = node.Tag;
  1162. D3D11PipelineState.ShaderStage stage = GetStageForSender(node.OwnerView);
  1163. if (stage == null) return;
  1164. if (tag is FetchTexture)
  1165. {
  1166. FetchTexture tex = (FetchTexture)tag;
  1167. var viewer = m_Core.GetTextureViewer();
  1168. viewer.Show(m_DockContent.DockPanel);
  1169. if (!viewer.IsDisposed)
  1170. viewer.ViewTexture(tex.ID, true);
  1171. }
  1172. else if(tag is FetchBuffer)
  1173. {
  1174. FetchBuffer buf = (FetchBuffer)tag;
  1175. string format = "";
  1176. var deets = stage.ShaderDetails;
  1177. int bind = -1;
  1178. bool uav = false;
  1179. for (int i = 0; i < stage.SRVs.Length; i++)
  1180. {
  1181. if (stage.SRVs[i].Resource == buf.ID)
  1182. {
  1183. bind = i;
  1184. break;
  1185. }
  1186. }
  1187. for (int i = 0; i < stage.UAVs.Length; i++)
  1188. {
  1189. if (stage.UAVs[i].Resource == buf.ID)
  1190. {
  1191. bind = i;
  1192. uav = true;
  1193. break;
  1194. }
  1195. if (stage == m_Core.CurD3D11PipelineState.m_PS &&
  1196. m_Core.CurD3D11PipelineState.m_OM.UAVs[i].Resource == buf.ID)
  1197. {
  1198. bind = i + (int)m_Core.CurD3D11PipelineState.m_OM.UAVStartSlot;
  1199. uav = true;
  1200. break;
  1201. }
  1202. }
  1203. if (deets != null)
  1204. {
  1205. foreach (var r in deets.Resources)
  1206. {
  1207. if(r.IsTexture)
  1208. continue;
  1209. if ( (r.IsSRV && !uav) || (r.IsUAV && uav) )
  1210. {
  1211. if (r.bindPoint == bind)
  1212. {
  1213. if (r.variableType.members.Length == 0)
  1214. {
  1215. if (r.variableType.Name != "")
  1216. format = r.variableType.Name + " " + r.name + ";";
  1217. }
  1218. else
  1219. {
  1220. format = "// struct " + r.variableType.Name + Environment.NewLine +
  1221. "{" + Environment.NewLine + FormatMembers(1, "", r.variableType.members) + "}";
  1222. }
  1223. break;
  1224. }
  1225. }
  1226. }
  1227. }
  1228. if (buf.ID != ResourceId.Null)
  1229. {
  1230. var viewer = new BufferViewer(m_Core, false);
  1231. if (format == "")
  1232. viewer.ViewRawBuffer(buf.ID);
  1233. else
  1234. viewer.ViewRawBuffer(buf.ID, format);
  1235. viewer.Show(m_DockContent.DockPanel);
  1236. }
  1237. }
  1238. }
  1239. private void disableSelection_Leave(object sender, EventArgs e)
  1240. {
  1241. if (sender is DataGridView)
  1242. ((DataGridView)sender).ClearSelection();
  1243. else if (sender is TreelistView.TreeListView)
  1244. {
  1245. ((TreelistView.TreeListView)sender).NodesSelection.Clear();
  1246. ((TreelistView.TreeListView)sender).FocusedNode = null;
  1247. }
  1248. }
  1249. private void disableSelection_VisibleChanged(object sender, EventArgs e)
  1250. {
  1251. ((DataGridView)sender).ClearSelection();
  1252. ((DataGridView)sender).AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
  1253. }
  1254. private void iabuffers_NodeDoubleClicked(TreelistView.Node node)
  1255. {
  1256. if (node.Tag is ResourceId)
  1257. {
  1258. ResourceId id = (ResourceId)node.Tag;
  1259. if (id != ResourceId.Null)
  1260. {
  1261. var viewer = new BufferViewer(m_Core, false);
  1262. viewer.ViewRawBuffer(id);
  1263. viewer.Show(m_DockContent.DockPanel);
  1264. }
  1265. }
  1266. }
  1267. private void inputLayouts_NodeDoubleClick(TreelistView.Node node)
  1268. {
  1269. (new BufferViewer(m_Core, true)).Show(m_DockContent.DockPanel);
  1270. }
  1271. private D3D11PipelineState.ShaderStage GetStageForSender(object sender)
  1272. {
  1273. D3D11PipelineState.ShaderStage stage = null;
  1274. if (!m_Core.LogLoaded)
  1275. return null;
  1276. object cur = sender;
  1277. while (cur is Control)
  1278. {
  1279. if (cur == tabVS)
  1280. stage = m_Core.CurD3D11PipelineState.m_VS;
  1281. else if (cur == tabGS)
  1282. stage = m_Core.CurD3D11PipelineState.m_GS;
  1283. else if (cur == tabHS)
  1284. stage = m_Core.CurD3D11PipelineState.m_HS;
  1285. else if (cur == tabDS)
  1286. stage = m_Core.CurD3D11PipelineState.m_DS;
  1287. else if (cur == tabPS)
  1288. stage = m_Core.CurD3D11PipelineState.m_PS;
  1289. else if (cur == tabCS)
  1290. stage = m_Core.CurD3D11PipelineState.m_CS;
  1291. else if (cur == tabOM)
  1292. stage = m_Core.CurD3D11PipelineState.m_PS;
  1293. if (stage != null)
  1294. return stage;
  1295. Control c = (Control)cur;
  1296. if(c.Parent == null)
  1297. break;
  1298. cur = ((Control)cur).Parent;
  1299. }
  1300. System.Diagnostics.Debug.Fail("Unrecognised control calling event handler");
  1301. return null;
  1302. }
  1303. private void shader_Click(object sender, EventArgs e)
  1304. {
  1305. if (sender == iaBytecode || sender == iaBytecodeCog)
  1306. {
  1307. if(m_Core.CurD3D11PipelineState != null &&
  1308. m_Core.CurD3D11PipelineState.m_IA.Bytecode != null)
  1309. {
  1310. (new ShaderViewer(m_Core, m_Core.CurD3D11PipelineState.m_IA.Bytecode, ShaderStageType.Vertex, null))
  1311. .Show(m_DockContent.DockPanel);
  1312. }
  1313. return;
  1314. }
  1315. D3D11PipelineState.ShaderStage stage = GetStageForSender(sender);
  1316. if (stage == null) return;
  1317. ShaderReflection shaderDetails = stage.ShaderDetails;
  1318. if (stage.Shader == ResourceId.Null) return;
  1319. ShaderViewer s = new ShaderViewer(m_Core, shaderDetails, stage.stage, null);
  1320. s.Show(m_DockContent.DockPanel);
  1321. }
  1322. private void MakeShaderVariablesHLSL(bool cbufferContents, ShaderConstant[] vars, ref string struct_contents, ref string struct_defs)
  1323. {
  1324. var nl = Environment.NewLine;
  1325. var nl2 = Environment.NewLine + Environment.NewLine;
  1326. foreach (var v in vars)
  1327. {
  1328. if (v.type.members.Length > 0)
  1329. {
  1330. string def = "struct " + v.type.descriptor.name + " {" + nl;
  1331. if(!struct_defs.Contains(def))
  1332. {
  1333. string contents = "";
  1334. MakeShaderVariablesHLSL(false, v.type.members, ref contents, ref struct_defs);
  1335. struct_defs += def + contents + "};" + nl2;
  1336. }
  1337. }
  1338. struct_contents += "\t" + v.type.descriptor.name + " " + v.name;
  1339. char comp = 'x';
  1340. if (v.reg.comp == 1) comp = 'y';
  1341. if (v.reg.comp == 2) comp = 'z';
  1342. if (v.reg.comp == 3) comp = 'w';
  1343. if (cbufferContents) struct_contents += String.Format(" : packoffset(c{0}.{1});", v.reg.vec, comp);
  1344. else struct_contents += ";";
  1345. struct_contents += nl;
  1346. }
  1347. }
  1348. // start a shaderviewer to edit this shader, optionally generating stub HLSL if there isn't
  1349. // HLSL source available for this shader.
  1350. private void shaderedit_Click(object sender, EventArgs e)
  1351. {
  1352. D3D11PipelineState.ShaderStage stage = GetStageForSender(sender);
  1353. if (stage == null) return;
  1354. ShaderReflection shaderDetails = stage.ShaderDetails;
  1355. if (stage.Shader == ResourceId.Null || shaderDetails == null) return;
  1356. var entryFunc = String.Format("EditedShader{0}S", stage.stage.ToString()[0]);
  1357. string mainfile = "";
  1358. var files = new Dictionary<string, string>();
  1359. if (shaderDetails.DebugInfo.entryFunc != "" && shaderDetails.DebugInfo.files.Length > 0)
  1360. {
  1361. entryFunc = shaderDetails.DebugInfo.entryFunc;
  1362. foreach (var s in shaderDetails.DebugInfo.files)
  1363. files.Add(Path.GetFileName(s.filename), s.filetext);
  1364. mainfile = Path.GetFileName(shaderDetails.DebugInfo.files[0].filename);
  1365. }
  1366. else
  1367. {
  1368. var nl = Environment.NewLine;
  1369. var nl2 = Environment.NewLine + Environment.NewLine;
  1370. string hlsl = "// No HLSL available - function stub generated" + nl2;
  1371. var shType = String.Format("{0}S", stage.stage.ToString()[0]);
  1372. foreach (var res in shaderDetails.Resources)
  1373. {
  1374. if (res.IsSampler)
  1375. {
  1376. hlsl += String.Format("//SamplerComparisonState {0} : register(s{1}); // can't disambiguate", res.name, res.bindPoint) + nl;
  1377. hlsl += String.Format("SamplerState {0} : register(s{1}); // can't disambiguate", res.name, res.bindPoint) + nl;
  1378. }
  1379. else
  1380. {
  1381. char regChar = 't';
  1382. if (res.IsUAV)
  1383. {
  1384. hlsl += "RW";
  1385. regChar = 'u';
  1386. }
  1387. if (res.IsTexture)
  1388. {
  1389. hlsl += String.Format("{0}<{1}> {2} : register({3}{4});", res.resType.ToString(), res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl;
  1390. }
  1391. else
  1392. {
  1393. if (res.variableType.descriptor.rows == 1)
  1394. hlsl += String.Format("Buffer<{0}> {1} : register({2}{3});", res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl;
  1395. else
  1396. hlsl += String.Format("StructuredBuffer<{0}> {1} : register({2}{3});", res.variableType.descriptor.name, res.name, regChar, res.bindPoint) + nl;
  1397. }
  1398. }
  1399. }
  1400. hlsl += nl2;
  1401. string cbuffers = "";
  1402. int cbufIdx = 0;
  1403. foreach (var cbuf in shaderDetails.ConstantBlocks)
  1404. {
  1405. if (cbuf.name != "" && cbuf.variables.Length > 0)
  1406. {
  1407. cbuffers += String.Format("cbuffer {0} : register(b{1}) {{", cbuf.name, cbufIdx) + nl;
  1408. MakeShaderVariablesHLSL(true, cbuf.variables, ref cbuffers, ref hlsl);
  1409. cbuffers += "};" + nl2;
  1410. }
  1411. cbufIdx++;
  1412. }
  1413. hlsl += cbuffers + nl2;
  1414. hlsl += String.Format("struct {0}Input{1}{{{1}", shType, nl);
  1415. foreach(var sig in shaderDetails.InputSig)
  1416. hlsl += String.Format("\t{0} {1} : {2};" + nl, sig.TypeString, sig.varName != "" ? sig.varName : "param" + sig.regIndex, sig.D3D11SemanticString);
  1417. hlsl += "};" + nl2;
  1418. hlsl += String.Format("struct {0}Output{1}{{{1}", shType, nl);
  1419. foreach (var sig in shaderDetails.OutputSig)
  1420. hlsl += String.Format("\t{0} {1} : {2};" + nl, sig.TypeString, sig.varName != "" ? sig.varName : "param" + sig.regIndex, sig.D3D11SemanticString);
  1421. hlsl += "};" + nl2;
  1422. hlsl += String.Format("{0}Output {1}(in {0}Input IN){2}{{{2}\t{0}Output OUT = ({0}Output)0;{2}{2}\t// ...{2}{2}\treturn OUT;{2}}}{2}", shType, entryFunc, nl);
  1423. mainfile = "generated.hlsl";
  1424. files.Add(mainfile, hlsl);
  1425. }
  1426. if (files.Count == 0)
  1427. return;
  1428. ShaderViewer sv = new ShaderViewer(m_Core, false, entryFunc, files,
  1429. // Save Callback
  1430. (ShaderViewer viewer, Dictionary<string, string> updatedfiles) =>
  1431. {
  1432. string compileSource = updatedfiles.First().Value;
  1433. // try and match up #includes against the files that we have. This isn't always
  1434. // possible as fxc only seems to include the source for files if something in
  1435. // that file was included in the compiled output. So you might end up with
  1436. // dangling #includes - we just have to ignore them
  1437. int offs = compileSource.IndexOf("#include");
  1438. while(offs >= 0)
  1439. {
  1440. // search back to ensure this is a valid #include (ie. not in a comment).
  1441. // Must only see whitespace before, then a newline.
  1442. int ws = offs-1;
  1443. while (ws >= 0 && (compileSource[ws] == ' ' || compileSource[ws] == '\t'))
  1444. ws--;
  1445. // not valid? jump to next.
  1446. if (compileSource[ws] != '\n')
  1447. {
  1448. offs = compileSource.IndexOf("#include", offs + 1);
  1449. continue;
  1450. }
  1451. int start = ws+1;
  1452. bool tail = true;
  1453. int lineEnd = compileSource.IndexOf("\n", start+1);
  1454. if(lineEnd == -1)
  1455. {
  1456. lineEnd = compileSource.Length;
  1457. tail = false;
  1458. }
  1459. ws = offs + "#include".Length;
  1460. while (compileSource[ws] == ' ' || compileSource[ws] == '\t')
  1461. ws++;
  1462. string line = compileSource.Substring(offs, lineEnd-offs+1);
  1463. if (compileSource[ws] != '<' && compileSource[ws] != '"')
  1464. {
  1465. viewer.ShowErrors("Invalid #include directive found:\r\n" + line);
  1466. return;
  1467. }
  1468. // find matching char, either <> or "";
  1469. int end = compileSource.IndexOf(compileSource[ws] == '"' ? '"' : '>', ws + 1);
  1470. if (end == -1)
  1471. {
  1472. viewer.ShowErrors("Invalid #include directive found:\r\n" + line);
  1473. return;
  1474. }
  1475. string fname = compileSource.Substring(ws + 1, end - ws - 1);
  1476. string fileText = "";
  1477. if (updatedfiles.ContainsKey(fname))
  1478. fileText = updatedfiles[fname];
  1479. else
  1480. fileText = "// Can't find file " + fname + "\n";
  1481. compileSource = compileSource.Substring(0, offs) + "\n\n" + fileText + "\n\n" + (tail ? compileSource.Substring(lineEnd + 1) : "");
  1482. offs = compileSource.IndexOf("#include", offs);
  1483. }
  1484. // invoke off to the ReplayRenderer to replace the log's shader
  1485. // with our edited one
  1486. m_Core.Renderer.BeginInvoke((ReplayRenderer r) =>
  1487. {
  1488. string errs = "";
  1489. uint flags = shaderDetails.DebugInfo.compileFlags;
  1490. ResourceId from = stage.Shader;
  1491. ResourceId to = r.BuildTargetShader(entryFunc, compileSource, flags, stage.stage, out errs);
  1492. viewer.BeginInvoke((MethodInvoker)delegate { viewer.ShowErrors(errs); });
  1493. if (to == ResourceId.Null)
  1494. {
  1495. r.RemoveReplacement(from);
  1496. }
  1497. else
  1498. {
  1499. r.ReplaceResource(from, to);
  1500. }
  1501. });
  1502. },
  1503. // Close Callback
  1504. () =>
  1505. {
  1506. // remove the replacement on close (we could make this more sophisticated if there
  1507. // was a place to control replaced resources/shaders).
  1508. m_Core.Renderer.BeginInvoke((ReplayRenderer r) =>
  1509. {
  1510. r.RemoveReplacement(stage.Shader);
  1511. });
  1512. });
  1513. sv.Show(m_DockContent.DockPanel);
  1514. }
  1515. private void ShowCBuffer(D3D11PipelineState.ShaderStage stage, UInt32 slot)
  1516. {
  1517. var existing = ConstantBufferPreviewer.Has(stage.stage, slot);
  1518. if (existing != null)
  1519. {
  1520. existing.Show();
  1521. return;
  1522. }
  1523. var prev = new ConstantBufferPreviewer(m_Core, stage.stage, slot);
  1524. var dock = Helpers.WrapDockContent(m_DockContent.DockPanel, prev);
  1525. dock.DockState = DockState.DockRight;
  1526. dock.DockAreas |= DockAreas.Float;
  1527. ConstantBufferPreviewer.ShowDock(dock, m_DockContent.Pane, DockAlignment.Right, 0.3);
  1528. }
  1529. private void cbuffers_NodeDoubleClicked(TreelistView.Node node)
  1530. {
  1531. D3D11PipelineState.ShaderStage stage = GetStageForSender(node.OwnerView);
  1532. if (stage != null && node.Tag is UInt32)
  1533. {
  1534. ShowCBuffer(stage, (UInt32)node.Tag);
  1535. }
  1536. }
  1537. private void CBuffers_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
  1538. {
  1539. D3D11PipelineState.ShaderStage stage = GetStageForSender(sender);
  1540. object tag = ((DataGridView)sender).Rows[e.RowIndex].Tag;
  1541. if (stage != null && tag is UInt32)
  1542. {
  1543. ShowCBuffer(stage, (UInt32)tag);
  1544. }
  1545. }
  1546. private string FormatMembers(int indent, string nameprefix, ShaderConstant[] vars)
  1547. {
  1548. string indentstr = new string(' ', indent*4);
  1549. string ret = "";
  1550. int i = 0;
  1551. foreach (var v in vars)
  1552. {
  1553. if (v.type.members.Length > 0)
  1554. {
  1555. if (i > 0)
  1556. ret += "\n";
  1557. ret += indentstr + "// struct " + v.type.Name + Environment.NewLine;
  1558. ret += indentstr + "{" + Environment.NewLine +
  1559. FormatMembers(indent + 1, v.name + "_", v.type.members) +
  1560. indentstr + "}" + Environment.NewLine;
  1561. if (i < vars.Length-1)
  1562. ret += Environment.NewLine;
  1563. }
  1564. else
  1565. {
  1566. string arr = "";
  1567. if (v.type.descriptor.elements > 1)
  1568. arr = String.Format("[{0}]", v.type.descriptor.elements);
  1569. ret += indentstr + v.type.Name + " " + nameprefix + v.name + arr + ";" + Environment.NewLine;
  1570. }
  1571. i++;
  1572. }
  1573. return ret;
  1574. }
  1575. private void shaderCog_MouseEnter(object sender, EventArgs e)
  1576. {
  1577. if (sender == iaBytecode || sender == iaBytecodeCog)
  1578. {
  1579. if (m_Core.CurD3D11PipelineState != null &&
  1580. m_Core.CurD3D11PipelineState.m_IA.Bytecode != null)
  1581. iaBytecodeCog.Image = global::renderdocui.Properties.Resources.action_hover;
  1582. return;
  1583. }
  1584. if (sender is PictureBox)
  1585. {
  1586. D3D11PipelineState.ShaderStage stage = GetStageForSender(sender);
  1587. if (stage != null && stage.Shader != ResourceId.Null)
  1588. (sender as PictureBox).Image = global::renderdocui.Properties.Resources.action_hover;
  1589. }
  1590. if (sender is Label)
  1591. {
  1592. D3D11PipelineState.ShaderStage stage = GetStageForSender(sender);
  1593. if (stage == null) return;
  1594. if (stage.stage == ShaderStageType.Vertex) shaderCog_MouseEnter(vsShaderCog, e);
  1595. if (stage.stage == ShaderStageType.Domain) shaderCog_MouseEnter(dsShaderCog, e);
  1596. if (stage.stage == ShaderStageType.Hull) shaderCog_MouseEnter(hsShaderCog, e);
  1597. if (stage.stage == ShaderStageType.Geometry) shaderCog_MouseEnter(gsShaderCog, e);
  1598. if (stage.stage == ShaderStageType.Pixel) shaderCog_MouseEnter(psShaderCog, e);
  1599. if (stage.stage == ShaderStageType.Compute) shaderCog_MouseEnter(csShaderCog, e);
  1600. }
  1601. }
  1602. private void shaderCog_MouseLeave(object sender, EventArgs e)
  1603. {
  1604. if (sender == iaBytecode || sender == iaBytecodeCog)
  1605. {
  1606. iaBytecodeCog.Image = global::renderdocui.Properties.Resources.action;
  1607. return;
  1608. }
  1609. if (sender is PictureBox)
  1610. {
  1611. (sender as PictureBox).Image = global::renderdocui.Properties.Resources.action;
  1612. }
  1613. if (sender is Label)
  1614. {
  1615. D3D11PipelineState.ShaderStage stage = GetStageForSender(sender);
  1616. if (stage == null) return;
  1617. if (stage.stage == ShaderStageType.Vertex) shaderCog_MouseLeave(vsShaderCog, e);
  1618. if (stage.stage == ShaderStageType.Domain) shaderCog_MouseLeave(dsShaderCog, e);
  1619. if (stage.stage == ShaderStageType.Hull) shaderCog_MouseLeave(hsShaderCog, e);
  1620. if (stage.stage == ShaderStageType.Geometry) shaderCog_MouseLeave(gsShaderCog, e);
  1621. if (stage.stage == ShaderStageType.Pixel) shaderCog_MouseLeave(psShaderCog, e);
  1622. if (stage.stage == ShaderStageType.Compute) shaderCog_MouseLeave(csShaderCog, e);
  1623. }
  1624. }
  1625. private void pipeFlow_SelectedStageChanged(object sender, EventArgs e)
  1626. {
  1627. stageTabControl.SelectedIndex = pipeFlow.SelectedStage;
  1628. }
  1629. private void csDebug_Click(object sender, EventArgs e)
  1630. {
  1631. uint gx = 0, gy = 0, gz = 0;
  1632. uint tx = 0, ty = 0, tz = 0;
  1633. if (m_Core.CurD3D11PipelineState == null ||
  1634. m_Core.CurD3D11PipelineState.m_CS.Shader == ResourceId.Null ||
  1635. m_Core.CurD3D11PipelineState.m_CS.ShaderDetails == null)
  1636. return;
  1637. if (uint.TryParse(groupX.Text, out gx) &&
  1638. uint.TryParse(groupY.Text, out gy) &&
  1639. uint.TryParse(groupZ.Text, out gz) &&
  1640. uint.TryParse(threadX.Text, out tx) &&
  1641. uint.TryParse(threadY.Text, out ty) &&
  1642. uint.TryParse(threadZ.Text, out tz))
  1643. {
  1644. ShaderDebugTrace trace = null;
  1645. ShaderReflection shaderDetails = m_Core.CurD3D11PipelineState.m_CS.ShaderDetails;
  1646. m_Core.Renderer.Invoke((ReplayRenderer r) =>
  1647. {
  1648. trace = r.CSGetDebugStates(new uint[] { gx, gy, gz }, new uint[] { tx, ty, tz });
  1649. });
  1650. if (trace == null || trace.states.Length == 0)
  1651. {
  1652. MessageBox.Show("Couldn't debug compute shader.", "Uh Oh!",
  1653. MessageBoxButtons.OK, MessageBoxIcon.Information);
  1654. return;
  1655. }
  1656. this.BeginInvoke(new Action(() =>
  1657. {
  1658. ShaderViewer s = new ShaderViewer(m_Core, shaderDetails, ShaderStageType.Compute, trace);
  1659. s.Show(m_DockContent.DockPanel);
  1660. }));
  1661. }
  1662. else
  1663. {
  1664. MessageBox.Show("Enter numbers for group and thread ID.", "Invalid thread", MessageBoxButtons.OK, MessageBoxIcon.Error);
  1665. }
  1666. }
  1667. private void meshView_MouseEnter(object sender, EventArgs e)
  1668. {
  1669. meshView.BackColor = Color.LightGray;
  1670. }
  1671. private void meshView_MouseLeave(object sender, EventArgs e)
  1672. {
  1673. meshView.BackColor = SystemColors.Control;
  1674. }
  1675. private void meshView_Click(object sender, EventArgs e)
  1676. {
  1677. (new BufferViewer(m_Core, true)).Show(m_DockContent.DockPanel);
  1678. }
  1679. private float GetHueForVB(int i)
  1680. {
  1681. int idx = ((i+1) * 21) % 32; // space neighbouring colours reasonably distinctly
  1682. return (float)(idx) / 32.0f;
  1683. }
  1684. private void inputLayouts_MouseMove(object sender, MouseEventArgs e)
  1685. {
  1686. if (m_Core.CurD3D11PipelineState == null) return;
  1687. Point mousePoint = inputLayouts.PointToClient(Cursor.Position);
  1688. var hoverNode = inputLayouts.CalcHitNode(mousePoint);
  1689. ia_MouseLeave(sender, e);
  1690. var IA = m_Core.CurD3D11PipelineState.m_IA;
  1691. if (hoverNode != null)
  1692. {
  1693. int index = inputLayouts.Nodes.GetNodeIndex(hoverNode);
  1694. if (index >= 0 && index < IA.layouts.Length)
  1695. {
  1696. uint slot = IA.layouts[index].InputSlot;
  1697. HighlightIASlot(slot);
  1698. }
  1699. }
  1700. }
  1701. private void HighlightIASlot(uint slot)
  1702. {
  1703. var IA = m_Core.CurD3D11PipelineState.m_IA;
  1704. Color c = HSLColor(GetHueForVB((int)slot), 1.0f, 0.95f);
  1705. if (slot < m_VBNodes.Count)
  1706. m_VBNodes[(int)slot].DefaultBackColor = c;
  1707. for (int i = 0; i < inputLayouts.Nodes.Count; i++)
  1708. {
  1709. var n = inputLayouts.Nodes[i];
  1710. if (IA.layouts[i].InputSlot == slot)
  1711. n.DefaultBackColor = c;
  1712. else
  1713. n.DefaultBackColor = Color.Transparent;
  1714. }
  1715. inputLayouts.Invalidate();
  1716. iabuffers.Invalidate();
  1717. }
  1718. private void ia_MouseLeave(object sender, EventArgs e)
  1719. {
  1720. foreach (var n in iabuffers.Nodes)
  1721. n.DefaultBackColor = Color.Transparent;
  1722. foreach (var n in inputLayouts.Nodes)
  1723. n.DefaultBackColor = Color.Transparent;
  1724. inputLayouts.Invalidate();
  1725. iabuffers.Invalidate();
  1726. }
  1727. private void iabuffers_MouseMove(object sender, MouseEventArgs e)
  1728. {
  1729. if (m_Core.CurD3D11PipelineState == null) return;
  1730. Point mousePoint = iabuffers.PointToClient(Cursor.Position);
  1731. var hoverNode = iabuffers.CalcHitNode(mousePoint);
  1732. ia_MouseLeave(sender, e);
  1733. if (hoverNode != null)
  1734. {
  1735. int idx = m_VBNodes.IndexOf(hoverNode);
  1736. if (idx >= 0)
  1737. HighlightIASlot((uint)idx);
  1738. else
  1739. hoverNode.DefaultBackColor = SystemColors.ControlLight;
  1740. }
  1741. }
  1742. }
  1743. }