PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/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

Large files files are truncated, but you can click here to view the full file

  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

Large files files are truncated, but you can click here to view the full file