mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Add HTML export for D3D11 pipeline state viewer. Closes #92
This commit is contained in:
@@ -281,6 +281,7 @@
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.showDisabledToolitem = new System.Windows.Forms.ToolStripButton();
|
||||
this.showEmptyToolitem = new System.Windows.Forms.ToolStripButton();
|
||||
this.export = new System.Windows.Forms.ToolStripButton();
|
||||
this.stageTabControl = new renderdocui.Controls.TablessControl();
|
||||
this.tabIA = new System.Windows.Forms.TabPage();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
@@ -473,6 +474,7 @@
|
||||
this.showDisabled = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.showEmpty = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.exportDialog = new System.Windows.Forms.SaveFileDialog();
|
||||
toolStripLabel1 = new System.Windows.Forms.ToolStripLabel();
|
||||
toolstripTable = new System.Windows.Forms.TableLayoutPanel();
|
||||
groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
@@ -677,7 +679,7 @@
|
||||
this.flowLayoutPanel6.Controls.Add(this.toolStrip1);
|
||||
this.flowLayoutPanel6.Location = new System.Drawing.Point(3, 3);
|
||||
this.flowLayoutPanel6.Name = "flowLayoutPanel6";
|
||||
this.flowLayoutPanel6.Size = new System.Drawing.Size(335, 25);
|
||||
this.flowLayoutPanel6.Size = new System.Drawing.Size(394, 25);
|
||||
this.flowLayoutPanel6.TabIndex = 1;
|
||||
//
|
||||
// toolStrip1
|
||||
@@ -687,10 +689,11 @@
|
||||
toolStripLabel1,
|
||||
this.toolStripSeparator2,
|
||||
this.showDisabledToolitem,
|
||||
this.showEmptyToolitem});
|
||||
this.showEmptyToolitem,
|
||||
this.export});
|
||||
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.toolStrip1.Name = "toolStrip1";
|
||||
this.toolStrip1.Size = new System.Drawing.Size(335, 25);
|
||||
this.toolStrip1.Size = new System.Drawing.Size(394, 25);
|
||||
this.toolStrip1.TabIndex = 0;
|
||||
this.toolStrip1.Text = "toolStrip1";
|
||||
//
|
||||
@@ -719,6 +722,15 @@
|
||||
this.showEmptyToolitem.Text = "Show Empty Items";
|
||||
this.showEmptyToolitem.Click += new System.EventHandler(this.hideEmpty_Click);
|
||||
//
|
||||
// export
|
||||
//
|
||||
this.export.Image = global::renderdocui.Properties.Resources.save;
|
||||
this.export.ImageTransparentColor = System.Drawing.Color.Magenta;
|
||||
this.export.Name = "export";
|
||||
this.export.Size = new System.Drawing.Size(59, 22);
|
||||
this.export.Text = "Export";
|
||||
this.export.Click += new System.EventHandler(this.export_Click);
|
||||
//
|
||||
// stageTabControl
|
||||
//
|
||||
this.stageTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
@@ -869,7 +881,7 @@
|
||||
treeListColumn4,
|
||||
treeListColumn5,
|
||||
treeListColumn6});
|
||||
this.iabuffers.Cursor = System.Windows.Forms.Cursors.Arrow;
|
||||
this.iabuffers.Cursor = System.Windows.Forms.Cursors.VSplit;
|
||||
this.iabuffers.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.iabuffers.GridLineColour = System.Drawing.SystemColors.ControlDark;
|
||||
this.iabuffers.Location = new System.Drawing.Point(3, 16);
|
||||
@@ -2517,7 +2529,7 @@
|
||||
this.tableLayoutPanel8.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel8.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel8.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel8.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 598F));
|
||||
this.tableLayoutPanel8.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 599F));
|
||||
this.tableLayoutPanel8.Controls.Add(this.forcedSampleCount, 7, 1);
|
||||
this.tableLayoutPanel8.Controls.Add(this.label14, 6, 1);
|
||||
this.tableLayoutPanel8.Controls.Add(this.frontCCW, 5, 0);
|
||||
@@ -4354,6 +4366,12 @@
|
||||
this.showEmpty.Text = "Show Empty";
|
||||
this.showEmpty.Click += new System.EventHandler(this.hideEmpty_Click);
|
||||
//
|
||||
// exportDialog
|
||||
//
|
||||
this.exportDialog.DefaultExt = "html";
|
||||
this.exportDialog.Filter = "HTML Files (*.html)|*.html";
|
||||
this.exportDialog.Title = "Export pipeline state as HTML";
|
||||
//
|
||||
// D3D11PipelineStateViewer
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
@@ -4735,5 +4753,7 @@
|
||||
private System.Windows.Forms.PictureBox iaBytecodeCog;
|
||||
private System.Windows.Forms.PictureBox meshView;
|
||||
private System.Windows.Forms.Label iaBytecodeMismatch;
|
||||
private System.Windows.Forms.ToolStripButton export;
|
||||
private System.Windows.Forms.SaveFileDialog exportDialog;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Windows.Forms;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
using renderdocui.Code;
|
||||
@@ -2193,5 +2194,934 @@ namespace renderdocui.Windows.PipelineState
|
||||
hoverNode.DefaultBackColor = SystemColors.ControlLight;
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportHTMLTable(XmlTextWriter writer, string[] cols, object[][] rows)
|
||||
{
|
||||
writer.WriteStartElement("table");
|
||||
|
||||
{
|
||||
writer.WriteStartElement("thead");
|
||||
writer.WriteStartElement("tr");
|
||||
|
||||
foreach (var col in cols)
|
||||
{
|
||||
writer.WriteStartElement("th");
|
||||
writer.WriteString(col);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("tbody");
|
||||
|
||||
if (rows.Length == 0)
|
||||
{
|
||||
writer.WriteStartElement("tr");
|
||||
|
||||
for (int i = 0; i < cols.Length; i++)
|
||||
{
|
||||
writer.WriteStartElement("td");
|
||||
writer.WriteString("-");
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var row in rows)
|
||||
{
|
||||
writer.WriteStartElement("tr");
|
||||
|
||||
foreach (var el in row)
|
||||
{
|
||||
writer.WriteStartElement("td");
|
||||
writer.WriteString(el.ToString());
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
private void ExportHTMLTable(XmlTextWriter writer, string[] cols, object[] rows)
|
||||
{
|
||||
ExportHTMLTable(writer, cols, new object[][] { rows });
|
||||
}
|
||||
|
||||
private object[] ExportViewHTML(D3D11PipelineState.ShaderStage.ResourceView view, int i, ShaderReflection refl, string extraParams)
|
||||
{
|
||||
FetchTexture[] texs = m_Core.CurTextures;
|
||||
FetchBuffer[] bufs = m_Core.CurBuffers;
|
||||
|
||||
ShaderResource shaderInput = null;
|
||||
|
||||
if (refl != null)
|
||||
{
|
||||
foreach (var bind in refl.Resources)
|
||||
{
|
||||
if (bind.IsUAV && bind.bindPoint == i)
|
||||
shaderInput = bind;
|
||||
}
|
||||
}
|
||||
|
||||
string name = "Empty";
|
||||
string typename = "Unknown";
|
||||
string format = "Unknown";
|
||||
uint w = 0, h = 0, d = 0, a = 0;
|
||||
|
||||
FetchTexture tex = null;
|
||||
FetchBuffer buf = null;
|
||||
|
||||
// check to see if it's a texture
|
||||
for (int t = 0; t < texs.Length; t++)
|
||||
{
|
||||
if (texs[t].ID == view.Resource)
|
||||
{
|
||||
w = texs[t].width;
|
||||
h = texs[t].height;
|
||||
d = texs[t].depth;
|
||||
a = texs[t].arraysize;
|
||||
format = texs[t].format.ToString();
|
||||
name = texs[t].name;
|
||||
typename = string.Format("Texture{0}D", texs[t].dimension);
|
||||
if (texs[t].cubemap)
|
||||
typename = "TexCube";
|
||||
|
||||
tex = texs[t];
|
||||
}
|
||||
}
|
||||
|
||||
// if not a texture, it must be a buffer
|
||||
for (int t = 0; t < bufs.Length; t++)
|
||||
{
|
||||
if (bufs[t].ID == view.Resource)
|
||||
{
|
||||
w = bufs[t].length;
|
||||
h = 0;
|
||||
d = 0;
|
||||
a = 0;
|
||||
format = view.Format.ToString();
|
||||
name = bufs[t].name;
|
||||
typename = "Buffer";
|
||||
|
||||
// for structured buffers, display how many 'elements' there are in the buffer
|
||||
if (bufs[t].structureSize > 0)
|
||||
typename = "StructuredBuffer[" + (bufs[t].length / bufs[t].structureSize) + "]";
|
||||
|
||||
if (view.Structured)
|
||||
{
|
||||
typename += " (Count: " + view.BufferStructCount + ")";
|
||||
}
|
||||
|
||||
if (shaderInput != null && !shaderInput.IsTexture)
|
||||
{
|
||||
if (view.Format.compType == FormatComponentType.None)
|
||||
{
|
||||
if (shaderInput.variableType.members.Length > 0)
|
||||
format = "struct " + shaderInput.variableType.Name;
|
||||
else
|
||||
format = shaderInput.variableType.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
format = view.Format.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
buf = bufs[t];
|
||||
}
|
||||
}
|
||||
|
||||
string viewParams = "";
|
||||
|
||||
if(buf != null)
|
||||
{
|
||||
viewParams = String.Format("First Element: {0}, Num Elements {1}, Flags {2}", view.FirstElement, view.NumElements, view.Flags);
|
||||
}
|
||||
|
||||
if (tex != null)
|
||||
{
|
||||
if(tex.mips > 1)
|
||||
viewParams = String.Format("Highest Mip: {0}, Num Mips: {1}", view.HighestMip, view.NumMipLevels);
|
||||
|
||||
if (tex.arraysize > 1)
|
||||
{
|
||||
if (viewParams.Length > 0)
|
||||
viewParams += ", ";
|
||||
viewParams += String.Format("First Slice: {0}, Array Size: {1}", view.FirstArraySlice, view.ArraySize);
|
||||
}
|
||||
}
|
||||
|
||||
if (viewParams == "")
|
||||
viewParams = extraParams;
|
||||
else
|
||||
viewParams += ", " + extraParams;
|
||||
|
||||
return new object[] {
|
||||
i, name,
|
||||
view.Type, typename,
|
||||
w, h, d, a,
|
||||
view.Format, format,
|
||||
viewParams };
|
||||
}
|
||||
|
||||
private void ExportHTML(XmlTextWriter writer, D3D11PipelineState.InputAssembler ia)
|
||||
{
|
||||
FetchBuffer[] bufs = m_Core.CurBuffers;
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Input Layouts");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
int i = 0;
|
||||
foreach (var l in ia.layouts)
|
||||
{
|
||||
rows.Add(new object[] { i, l.SemanticName, l.SemanticIndex, l.Format, l.InputSlot, l.ByteOffset, l.PerInstance, l.InstanceDataStepRate });
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer, new string[] { "Slot", "Semantic Name", "Semantic Index", "Format", "Input Slot", "Byte Offset", "Per Instance", "Instance Data Step Rate" }, rows.ToArray());
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Vertex Buffers");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
int i = 0;
|
||||
foreach (var vb in ia.vbuffers)
|
||||
{
|
||||
string name = "Buffer " + vb.Buffer.ToString();
|
||||
UInt32 length = 0;
|
||||
|
||||
if (vb.Buffer == ResourceId.Null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int t = 0; t < bufs.Length; t++)
|
||||
{
|
||||
if (bufs[t].ID == vb.Buffer)
|
||||
{
|
||||
name = bufs[t].name;
|
||||
length = bufs[t].length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rows.Add(new object[] { i, name, vb.Stride, vb.Offset, length });
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer, new string[] { "Slot", "Buffer", "Stride", "Offset", "Byte Length" }, rows.ToArray());
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Index Buffer");
|
||||
writer.WriteEndElement();
|
||||
|
||||
string name = "Buffer " + ia.ibuffer.Buffer.ToString();
|
||||
UInt32 length = 0;
|
||||
|
||||
if (ia.ibuffer.Buffer == ResourceId.Null)
|
||||
{
|
||||
name = "Empty";
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int t = 0; t < bufs.Length; t++)
|
||||
{
|
||||
if (bufs[t].ID == ia.ibuffer.Buffer)
|
||||
{
|
||||
name = bufs[t].name;
|
||||
length = bufs[t].length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer, new string[] { "Buffer", "Format", "Offset", "Byte Length" },
|
||||
new object[] { name, ia.ibuffer.Format.ToString(), ia.ibuffer.Offset.ToString(), length.ToString() });
|
||||
}
|
||||
|
||||
writer.WriteStartElement("p");
|
||||
writer.WriteEndElement();
|
||||
|
||||
ExportHTMLTable(writer, new string[] { "Primitive Topology" }, new object[] { ia.Topology.Str() });
|
||||
}
|
||||
|
||||
private void ExportHTML(XmlTextWriter writer, D3D11PipelineState.ShaderStage sh)
|
||||
{
|
||||
FetchBuffer[] bufs = m_Core.CurBuffers;
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Shader");
|
||||
writer.WriteEndElement();
|
||||
|
||||
ShaderReflection shaderDetails = sh.ShaderDetails;
|
||||
|
||||
string shadername = "Unknown";
|
||||
|
||||
if (sh.Shader == ResourceId.Null)
|
||||
shadername = "Unbound";
|
||||
else
|
||||
shadername = sh.ShaderName;
|
||||
|
||||
if (shaderDetails != null && shaderDetails.DebugInfo.entryFunc.Length > 0 && shaderDetails.DebugInfo.files.Length > 0)
|
||||
shadername = shaderDetails.DebugInfo.entryFunc + "()" + " - " +
|
||||
Path.GetFileName(shaderDetails.DebugInfo.files[0].filename);
|
||||
|
||||
writer.WriteStartElement("p");
|
||||
writer.WriteString(shadername);
|
||||
writer.WriteEndElement();
|
||||
|
||||
if (sh.Shader == ResourceId.Null)
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Resources");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
for (int i = 0; i < sh.SRVs.Length; i++)
|
||||
{
|
||||
if (sh.SRVs[i].View == ResourceId.Null) continue;
|
||||
|
||||
rows.Add(ExportViewHTML(sh.SRVs[i], i, null, ""));
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] {
|
||||
"Slot", "Name",
|
||||
"View Type", "Resource Type",
|
||||
"Width", "Height", "Depth", "Array Size",
|
||||
"View Format", "Resource Format",
|
||||
"View Parameters",
|
||||
},
|
||||
rows.ToArray());
|
||||
}
|
||||
|
||||
if (sh.stage == ShaderStageType.Compute)
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Unordered Access Views");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
for (int i = 0; i < sh.UAVs.Length; i++)
|
||||
{
|
||||
if (sh.UAVs[i].View == ResourceId.Null) continue;
|
||||
|
||||
rows.Add(ExportViewHTML(sh.UAVs[i], i, null, ""));
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] {
|
||||
"Slot", "Name",
|
||||
"View Type", "Resource Type",
|
||||
"Width", "Height", "Depth", "Array Size",
|
||||
"View Format", "Resource Format",
|
||||
"View Parameters",
|
||||
},
|
||||
rows.ToArray());
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Samplers");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
for (int i = 0; i < sh.Samplers.Length; i++)
|
||||
{
|
||||
D3D11PipelineState.ShaderStage.Sampler s = sh.Samplers[i];
|
||||
|
||||
if (s.Samp == ResourceId.Null) continue;
|
||||
|
||||
string borderColor = s.BorderColor[0].ToString() + ", " +
|
||||
s.BorderColor[1].ToString() + ", " +
|
||||
s.BorderColor[2].ToString() + ", " +
|
||||
s.BorderColor[3].ToString();
|
||||
|
||||
string addressing = "";
|
||||
|
||||
string addPrefix = "";
|
||||
string addVal = "";
|
||||
|
||||
string[] addr = { s.AddressU, s.AddressV, s.AddressW };
|
||||
|
||||
// arrange like either UVW: WRAP or UV: WRAP, W: CLAMP
|
||||
for (int a = 0; a < 3; a++)
|
||||
{
|
||||
string prefix = "" + "UVW"[a];
|
||||
|
||||
if (a == 0 || addr[a] == addr[a - 1])
|
||||
{
|
||||
addPrefix += prefix;
|
||||
}
|
||||
else
|
||||
{
|
||||
addressing += addPrefix + ": " + addVal + ", ";
|
||||
|
||||
addPrefix = prefix;
|
||||
}
|
||||
addVal = addr[a];
|
||||
}
|
||||
|
||||
addressing += addPrefix + ": " + addVal;
|
||||
|
||||
rows.Add(new object[] { i, addressing, borderColor,
|
||||
s.Comparison, s.Filter, s.MaxAniso.ToString(),
|
||||
s.MinLOD == -float.MaxValue ? "-FLT_MAX" : s.MinLOD.ToString(),
|
||||
s.MaxLOD == float.MaxValue ? "FLT_MAX" : s.MaxLOD.ToString(),
|
||||
s.MipLODBias.ToString() });
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] {
|
||||
"Slot", "Addressing", "Border Colour",
|
||||
"Comparison", "Filter", "Max Anisotropy",
|
||||
"Min LOD", "Max LOD", "Mip Bias",
|
||||
},
|
||||
rows.ToArray());
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Constant Buffers");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
for (int i = 0; i < sh.ConstantBuffers.Length; i++)
|
||||
{
|
||||
ConstantBlock shaderCBuf = null;
|
||||
|
||||
if (sh.ConstantBuffers[i].Buffer == ResourceId.Null) continue;
|
||||
|
||||
if (sh.ShaderDetails != null && i < sh.ShaderDetails.ConstantBlocks.Length &&
|
||||
sh.ShaderDetails.ConstantBlocks[i].name.Length > 0)
|
||||
shaderCBuf = sh.ShaderDetails.ConstantBlocks[i];
|
||||
|
||||
string name = "Constant Buffer " + sh.ConstantBuffers[i].Buffer.ToString();
|
||||
UInt32 length = 1;
|
||||
int numvars = shaderCBuf != null ? shaderCBuf.variables.Length : 0;
|
||||
|
||||
if (sh.ConstantBuffers[i].Buffer == ResourceId.Null)
|
||||
{
|
||||
name = "Empty";
|
||||
length = 0;
|
||||
}
|
||||
|
||||
for (int t = 0; t < bufs.Length; t++)
|
||||
{
|
||||
if (bufs[t].ID == sh.ConstantBuffers[i].Buffer)
|
||||
{
|
||||
name = bufs[t].name;
|
||||
length = bufs[t].length;
|
||||
}
|
||||
}
|
||||
|
||||
rows.Add(new object[] { i, name, sh.ConstantBuffers[i].VecOffset, sh.ConstantBuffers[i].VecCount, numvars, length });
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer, new string[] { "Slot", "Buffer", "Vector Offset", "Vector Count", "Number of Variables", "Byte Length", }, rows.ToArray());
|
||||
}
|
||||
|
||||
if (sh.ClassInstances.Length > 0)
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Class Instances");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
for (int i = 0; i < sh.ClassInstances.Length; i++)
|
||||
{
|
||||
string interfaceName = String.Format("Interface {0}", i);
|
||||
|
||||
if (sh.ShaderDetails != null && i < sh.ShaderDetails.Interfaces.Length)
|
||||
interfaceName = sh.ShaderDetails.Interfaces[i].Name;
|
||||
|
||||
rows.Add(new object[] { i, interfaceName, sh.ClassInstances[i] });
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer, new string[] { "Slot", "Interface Name", "Instance Name", }, rows.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportHTML(XmlTextWriter writer, D3D11PipelineState.Streamout so)
|
||||
{
|
||||
FetchBuffer[] bufs = m_Core.CurBuffers;
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Stream Out Targets");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
int i = 0;
|
||||
foreach (var o in so.Outputs)
|
||||
{
|
||||
string name = "Buffer " + o.Buffer.ToString();
|
||||
UInt32 length = 0;
|
||||
|
||||
if (o.Buffer == ResourceId.Null)
|
||||
{
|
||||
name = "Empty";
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int t = 0; t < bufs.Length; t++)
|
||||
{
|
||||
if (bufs[t].ID == o.Buffer)
|
||||
{
|
||||
name = bufs[t].name;
|
||||
length = bufs[t].length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rows.Add(new object[] { i, name, o.Offset, length });
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer, new string[] { "Slot", "Buffer", "Offset", "Byte Length" }, rows.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportHTML(XmlTextWriter writer, D3D11PipelineState.Rasterizer rs)
|
||||
{
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("States");
|
||||
writer.WriteEndElement();
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] { "Fill Mode", "Cull Mode", "Front CCW" },
|
||||
new object[] { rs.m_State.FillMode, rs.m_State.CullMode, rs.m_State.FrontCCW ? "Yes" : "No" });
|
||||
|
||||
writer.WriteStartElement("p");
|
||||
writer.WriteEndElement();
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] { "Scissor Enable", "Line AA Enable", "Multisample Enable", "Forced Sample Count" },
|
||||
new object[] { rs.m_State.ScissorEnable ? "Yes" : "No", rs.m_State.AntialiasedLineEnable ? "Yes" : "No",
|
||||
rs.m_State.MultisampleEnable ? "Yes" : "No", rs.m_State.ForcedSampleCount });
|
||||
|
||||
writer.WriteStartElement("p");
|
||||
writer.WriteEndElement();
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] { "Depth Clip", "Depth Bias", "Depth Bias Clamp", "Slope Scaled Bias" },
|
||||
new object[] { rs.m_State.DepthClip ? "Yes" : "No", rs.m_State.DepthBias,
|
||||
Formatter.Format(rs.m_State.DepthBiasClamp), Formatter.Format(rs.m_State.SlopeScaledDepthBias)});
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Viewports");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
int i = 0;
|
||||
foreach (var v in rs.Viewports)
|
||||
{
|
||||
if (v.Width == v.Height && v.Width == 0 && v.Height == 0) continue;
|
||||
|
||||
rows.Add(new object[] { i, v.TopLeft[0], v.TopLeft[1], v.Width, v.Height, v.MinDepth, v.MaxDepth });
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer, new string[] { "Slot", "X", "Y", "Width", "Height", "Min Depth", "Max Depth" }, rows.ToArray());
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Scissors");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
int i = 0;
|
||||
foreach (var s in rs.Scissors)
|
||||
{
|
||||
if (s.right == 0 && s.bottom == 0) continue;
|
||||
|
||||
rows.Add(new object[] { i, s.left, s.top, s.right - s.left, s.bottom - s.top });
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer, new string[] { "Slot", "X", "Y", "Width", "Height" }, rows.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportHTML(XmlTextWriter writer, D3D11PipelineState.OutputMerger om)
|
||||
{
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Blend State");
|
||||
writer.WriteEndElement();
|
||||
|
||||
var blendFactor = om.m_BlendState.BlendFactor[0].ToString("F2") + ", " +
|
||||
om.m_BlendState.BlendFactor[1].ToString("F2") + ", " +
|
||||
om.m_BlendState.BlendFactor[2].ToString("F2") + ", " +
|
||||
om.m_BlendState.BlendFactor[3].ToString("F2");
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] { "Independent Blend Enable", "Alpha to Coverage", "Sample Mask", "Blend Factor" },
|
||||
new object[] { om.m_BlendState.IndependentBlend ? "Yes" : "No", om.m_BlendState.AlphaToCoverage ? "Yes" : "No",
|
||||
om.m_BlendState.SampleMask.ToString("X8"), blendFactor, });
|
||||
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Target Blends");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
int i = 0;
|
||||
foreach (var b in om.m_BlendState.Blends)
|
||||
{
|
||||
if (!b.Enabled) continue;
|
||||
|
||||
rows.Add(new object[] {
|
||||
i,
|
||||
b.Enabled ? "Yes" : "No", b.LogicEnabled ? "Yes" : "No",
|
||||
b.m_Blend.Source, b.m_Blend.Destination, b.m_Blend.Operation,
|
||||
b.m_AlphaBlend.Source, b.m_AlphaBlend.Destination, b.m_AlphaBlend.Operation,
|
||||
b.LogicOp, b.WriteMask });
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] {
|
||||
"Slot",
|
||||
"Blend Enable", "Logic Enable",
|
||||
"Blend Source", "Blend Destination", "Blend Operation",
|
||||
"Alpha Blend Source", "Alpha Blend Destination", "Alpha Blend Operation",
|
||||
"Logic Operation", "Write Mask",
|
||||
},
|
||||
rows.ToArray());
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Depth State");
|
||||
writer.WriteEndElement();
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] { "Depth Test Enable", "Depth Writes Enable", "Depth Function" },
|
||||
new object[] { om.m_State.DepthEnable ? "Yes" : "No", om.m_State.DepthWrites ? "Yes" : "No", om.m_State.DepthFunc });
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Render targets");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
for (int i = 0; i < om.RenderTargets.Length; i++)
|
||||
{
|
||||
if (om.RenderTargets[i].View == ResourceId.Null) continue;
|
||||
|
||||
rows.Add(ExportViewHTML(om.RenderTargets[i], i, null, ""));
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] {
|
||||
"Slot", "Name",
|
||||
"View Type", "Resource Type",
|
||||
"Width", "Height", "Depth", "Array Size",
|
||||
"View Format", "Resource Format",
|
||||
"View Parameters",
|
||||
},
|
||||
rows.ToArray());
|
||||
}
|
||||
|
||||
if(om.UAVs.Length > 0 && om.UAVs[0].View != ResourceId.Null)
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Unordered Access Views");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (; i < om.UAVStartSlot; i++)
|
||||
rows.Add(new object[] { i, "Empty", "", "", "", "", 0, 0, 0, 0, "", "", "" });
|
||||
|
||||
for (; i < om.RenderTargets.Length; i++)
|
||||
{
|
||||
if (om.UAVs[i - om.UAVStartSlot].View == ResourceId.Null) continue;
|
||||
|
||||
rows.Add(ExportViewHTML(om.UAVs[i - om.UAVStartSlot], i, m_Core.CurD3D11PipelineState.m_PS.ShaderDetails, ""));
|
||||
}
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] {
|
||||
"Slot", "Name",
|
||||
"View Type", "Resource Type",
|
||||
"Width", "Height", "Depth", "Array Size",
|
||||
"View Format", "Resource Format",
|
||||
"View Parameters",
|
||||
},
|
||||
rows.ToArray());
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("h3");
|
||||
writer.WriteString("Depth target");
|
||||
writer.WriteEndElement();
|
||||
|
||||
List<object[]> rows = new List<object[]>();
|
||||
|
||||
string extra = "";
|
||||
|
||||
if(om.DepthReadOnly && om.StencilReadOnly)
|
||||
extra = "Depth & Stencil Read-Only";
|
||||
else if (om.DepthReadOnly)
|
||||
extra = "Depth Read-Only";
|
||||
else if (om.StencilReadOnly)
|
||||
extra = "Stencil Read-Only";
|
||||
|
||||
rows.Add(ExportViewHTML(om.DepthTarget, 0, null, extra));
|
||||
|
||||
ExportHTMLTable(writer,
|
||||
new string[] {
|
||||
"Slot", "Name",
|
||||
"View Type", "Resource Type",
|
||||
"Width", "Height", "Depth", "Array Size",
|
||||
"View Format", "Resource Format",
|
||||
"View Parameters",
|
||||
},
|
||||
rows.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportHTML(string filename)
|
||||
{
|
||||
using (Stream s = new FileStream(filename, FileMode.Create))
|
||||
{
|
||||
StreamWriter sw = new StreamWriter(s);
|
||||
|
||||
sw.WriteLine("<!DOCTYPE html>");
|
||||
|
||||
using (XmlTextWriter writer = new XmlTextWriter(sw))
|
||||
{
|
||||
writer.Formatting = Formatting.Indented;
|
||||
writer.Indentation = 4;
|
||||
|
||||
writer.WriteStartElement("html");
|
||||
writer.WriteAttributeString("lang", "en");
|
||||
|
||||
var title = String.Format("{0} EID {1} - D3D11 Pipeline export", Path.GetFileName(m_Core.LogFileName), m_Core.CurEvent);
|
||||
|
||||
var css = @"
|
||||
/* If you think this css is ugly/bad, open a pull request! */
|
||||
body { margin: 20px; }
|
||||
div.stage { border: 1px solid #BBBBBB; border-radius: 5px; padding: 16px; margin-bottom: 32px; }
|
||||
div.stage h1 { text-decoration: underline; margin-top: 0px; }
|
||||
div.stage table { border: 1px solid #AAAAAA; border-collapse: collapse; }
|
||||
div.stage table thead tr { border-bottom: 1px solid #AAAAAA; background-color: #EEEEFF; }
|
||||
div.stage table tr th { border-right: 1px solid #AAAAAA; padding: 6px; }
|
||||
div.stage table tr td { border-right: 1px solid #AAAAAA; background-color: #EEEEEE; padding: 3px; }
|
||||
";
|
||||
|
||||
{
|
||||
writer.WriteStartElement("head");
|
||||
|
||||
writer.WriteStartElement("meta");
|
||||
writer.WriteAttributeString("charset", "utf-8");
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("meta");
|
||||
writer.WriteAttributeString("http-equiv", "X-UA-Compatible");
|
||||
writer.WriteAttributeString("content", "IE=edge");
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("meta");
|
||||
writer.WriteAttributeString("name", "viewport");
|
||||
writer.WriteAttributeString("content", "width=device-width, initial-scale=1");
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("meta");
|
||||
writer.WriteAttributeString("name", "description");
|
||||
writer.WriteAttributeString("content", "");
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("meta");
|
||||
writer.WriteAttributeString("name", "author");
|
||||
writer.WriteAttributeString("content", "");
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("meta");
|
||||
writer.WriteAttributeString("http-equiv", "Content-Type");
|
||||
writer.WriteAttributeString("content", "text/html;charset=utf-8");
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("title");
|
||||
writer.WriteString(title);
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("style");
|
||||
writer.WriteComment(css);
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteEndElement(); // head
|
||||
}
|
||||
|
||||
{
|
||||
writer.WriteStartElement("body");
|
||||
|
||||
writer.WriteStartElement("h1");
|
||||
writer.WriteString(title);
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("h3");
|
||||
{
|
||||
var context = String.Format("Frame {0}", m_Core.FrameInfo[m_Core.CurFrame].frameNumber);
|
||||
|
||||
FetchDrawcall draw = m_Core.CurDrawcall;
|
||||
|
||||
var drawstack = new List<FetchDrawcall>();
|
||||
var parent = draw.parent;
|
||||
while (parent != null)
|
||||
{
|
||||
drawstack.Add(parent);
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
drawstack.Reverse();
|
||||
|
||||
foreach (var d in drawstack)
|
||||
{
|
||||
context += String.Format(" > {0}", d.name);
|
||||
}
|
||||
|
||||
FetchDrawcall prev = null;
|
||||
|
||||
for (uint i = draw.events[0].eventID; i <= draw.events.Last().eventID; i++)
|
||||
{
|
||||
prev = m_Core.GetDrawcall(m_Core.CurFrame, i);
|
||||
if (prev != null)
|
||||
break;
|
||||
}
|
||||
|
||||
if (prev != null)
|
||||
context += String.Format(" => {0}, {1}", prev.name, draw.name);
|
||||
else
|
||||
context += String.Format(" => {0}", draw.name);
|
||||
|
||||
writer.WriteString(context);
|
||||
}
|
||||
writer.WriteEndElement(); // h2 context
|
||||
|
||||
string[] stageNames = new string[]{
|
||||
"Input Assembler",
|
||||
"Vertex Shader",
|
||||
"Hull Shader",
|
||||
"Domain Shader",
|
||||
"Geometry Shader",
|
||||
"Stream Out",
|
||||
"Rasterizer",
|
||||
"Pixel Shader",
|
||||
"Output Merger",
|
||||
"Compute Shader",
|
||||
};
|
||||
|
||||
string[] stageAbbrevs = new string[]{
|
||||
"IA", "VS", "HS", "DS", "GS", "SO", "RS", "PS", "OM", "CS"
|
||||
};
|
||||
|
||||
int stage=0;
|
||||
foreach(var sn in stageNames)
|
||||
{
|
||||
writer.WriteStartElement("div");
|
||||
writer.WriteStartElement("a");
|
||||
writer.WriteAttributeString("name", stageAbbrevs[stage]);
|
||||
writer.WriteEndElement();
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("div");
|
||||
writer.WriteAttributeString("class", "stage");
|
||||
|
||||
writer.WriteStartElement("h1");
|
||||
writer.WriteString(sn);
|
||||
writer.WriteEndElement();
|
||||
|
||||
switch(stage)
|
||||
{
|
||||
case 0: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_IA); break;
|
||||
case 1: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_VS); break;
|
||||
case 2: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_HS); break;
|
||||
case 3: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_DS); break;
|
||||
case 4: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_GS); break;
|
||||
case 5: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_SO); break;
|
||||
case 6: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_RS); break;
|
||||
case 7: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_PS); break;
|
||||
case 8: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_OM); break;
|
||||
case 9: ExportHTML(writer, m_Core.CurD3D11PipelineState.m_CS); break;
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
|
||||
stage++;
|
||||
}
|
||||
|
||||
writer.WriteEndElement(); // body
|
||||
}
|
||||
|
||||
writer.WriteEndElement(); // html
|
||||
|
||||
writer.Close();
|
||||
}
|
||||
|
||||
sw.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void export_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!m_Core.LogLoaded) return;
|
||||
|
||||
DialogResult res = exportDialog.ShowDialog();
|
||||
|
||||
if (res == DialogResult.OK)
|
||||
{
|
||||
ExportHTML(exportDialog.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,4 +300,7 @@
|
||||
<metadata name="rightclickMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="exportDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>324, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
Reference in New Issue
Block a user