public D3D11PipelineState GetD3D11PipelineState() { IntPtr mem = CustomMarshal.Alloc(typeof(D3D11PipelineState)); bool success = ReplayRenderer_GetD3D11PipelineState(m_Real, mem); D3D11PipelineState ret = null; if (success) { ret = (D3D11PipelineState)CustomMarshal.PtrToStructure(mem, typeof(D3D11PipelineState), true); } CustomMarshal.Free(mem); return(ret); }
private bool HasImportantViewParams(D3D11PipelineState.ShaderStage.ResourceView view, FetchTexture tex) { // we don't count 'upgrade typeless to typed' as important, we just display the typed format // in the row since there's no real hidden important information there. The formats can't be // different for any other reason (if the SRV format differs from the texture format, the // texture must have been typeless. if (view.HighestMip > 0 || view.FirstArraySlice > 0 || (view.NumMipLevels < tex.mips && tex.mips > 1) || (view.ArraySize < tex.arraysize && tex.arraysize > 1)) return true; // in the case of the swapchain case, types can be different and it won't have shown // up as taking the view's format because the swapchain already has one. Make sure to mark it // as important if (view.Format.compType != FormatComponentType.None && view.Format != tex.format) return true; return false; }
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; bool rw = false; if (refl != null) { foreach (var bind in refl.ReadOnlyResources) { if (bind.bindPoint == i) { shaderInput = bind; break; } } foreach (var bind in refl.ReadWriteResources) { if (bind.bindPoint == i) { shaderInput = bind; rw = true; break; } } } string name = "Empty"; string typename = "Unknown"; string format = "Unknown"; UInt64 w = 1; UInt32 h = 1, d = 1; UInt32 a = 0; string viewFormat = view.Format.ToString(); 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 = texs[t].resType.ToString(); 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 (view.ElementSize > 0) { typename = (rw ? "RWStructuredBuffer" : "StructuredBuffer") + "[" + (bufs[t].length / view.ElementSize) + "]"; } else if (view.Flags.HasFlag(D3D11BufferViewFlags.Raw)) { typename = rw ? "RWByteAddressBuffer" : "ByteAddressBuffer"; } if (view.Flags.HasFlag(D3D11BufferViewFlags.Append) || view.Flags.HasFlag(D3D11BufferViewFlags.Counter)) { typename += " (Count: " + view.BufferStructCount + ")"; } if (shaderInput != null && !shaderInput.IsTexture) { if (view.Format.compType == FormatComponentType.None) { if (shaderInput.variableType.members.Length > 0) viewFormat = format = "struct " + shaderInput.variableType.Name; else viewFormat = 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, viewFormat, format, viewParams }; }
private void ShowCBuffer(D3D11PipelineState.ShaderStage stage, UInt32 slot) { var existing = ConstantBufferPreviewer.Has(stage.stage, slot); if (existing != null) { existing.Show(); return; } var prev = new ConstantBufferPreviewer(m_Core, stage.stage, slot); var dock = Helpers.WrapDockContent(m_DockContent.DockPanel, prev); dock.DockState = DockState.DockRight; dock.DockAreas |= DockAreas.Float; ConstantBufferPreviewer.ShowDock(dock, m_DockContent.Pane, DockAlignment.Right, 0.3); }
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", "Conservative Raster" }, new object[] { rs.m_State.ScissorEnable ? "Yes" : "No", rs.m_State.AntialiasedLineEnable ? "Yes" : "No", rs.m_State.MultisampleEnable ? "Yes" : "No", rs.m_State.ForcedSampleCount, rs.m_State.ConservativeRasterization ? "Yes" : "No" }); 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.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 + "()" + " - " + shaderDetails.DebugInfo.files[0].BaseFilename; 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, sh.ShaderDetails, "")); } 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, sh.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("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(); UInt64 length = 1; int numvars = shaderCBuf != null ? shaderCBuf.variables.Length : 0; UInt32 byteSize = shaderCBuf != null ? shaderCBuf.byteSize : 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, byteSize, length }); } ExportHTMLTable(writer, new string[] { "Slot", "Buffer", "Vector Offset", "Vector Count", "Number of Variables", "Bytes Needed", "Bytes Provided" }, 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()); } }
public ViewTexTag(D3D11PipelineState.ShaderStage.ResourceView v, FetchTexture t) { view = v; tex = t; }
private void ShowCBuffer(D3D11PipelineState.ShaderStage stage, UInt32 slot) { if (stage.ShaderDetails != null && (stage.ShaderDetails.ConstantBlocks.Length <= slot || stage.ShaderDetails.ConstantBlocks[slot].name.Length == 0) ) { // unused cbuffer, open regular buffer viewer var viewer = new BufferViewer(m_Core, false); if (stage.ConstantBuffers.Length < slot) return; var buf = stage.ConstantBuffers[slot]; viewer.ViewRawBuffer(true, buf.VecOffset * 4 * sizeof(float), buf.VecCount * 4 * sizeof(float), buf.Buffer); viewer.Show(m_DockContent.DockPanel); return; } var existing = ConstantBufferPreviewer.Has(stage.stage, slot, 0); if (existing != null) { existing.Show(); return; } var prev = new ConstantBufferPreviewer(m_Core, stage.stage, slot, 0); prev.ShowDock(m_DockContent.Pane, DockAlignment.Right, 0.3); }
public ViewTexTag(D3D11PipelineState.ShaderStage.ResourceView v, FetchTexture t) { view = v; tex = t; DepthReadOnly = false; StencilReadOnly = false; }
private void ShowCBuffer(D3D11PipelineState.ShaderStage stage, UInt32 bindPoint) { bool found = false; UInt32 slot = UInt32.MaxValue; if (stage.ShaderDetails != null) { UInt32 i = 0; foreach (var cb in stage.ShaderDetails.ConstantBlocks) { if (cb.bindPoint == bindPoint) { slot = i; found = true; break; } i++; } } if (!found) { // unused cbuffer, open regular buffer viewer var viewer = new BufferViewer(m_Core, false); if (stage.ConstantBuffers.Length < bindPoint) return; var buf = stage.ConstantBuffers[bindPoint]; viewer.ViewRawBuffer(true, buf.VecOffset * 4 * sizeof(float), buf.VecCount * 4 * sizeof(float), buf.Buffer); viewer.Show(m_DockContent.DockPanel); return; } var existing = ConstantBufferPreviewer.Has(stage.stage, slot, 0); if (existing != null) { existing.Show(); return; } var prev = new ConstantBufferPreviewer(m_Core, stage.stage, slot, 0); prev.ShowDock(m_DockContent.Pane, DockAlignment.Right, 0.3); }
private void SetEventID(ILogViewerForm exclude, UInt32 eventID, bool force) { m_EventID = eventID; m_Renderer.Invoke((ReplayRenderer r) => { r.SetFrameEvent(m_EventID, force); m_D3D11PipelineState = r.GetD3D11PipelineState(); m_D3D12PipelineState = r.GetD3D12PipelineState(); m_GLPipelineState = r.GetGLPipelineState(); m_VulkanPipelineState = r.GetVulkanPipelineState(); m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_D3D12PipelineState, m_GLPipelineState, m_VulkanPipelineState); }); foreach (var logviewer in m_LogViewers) { if(logviewer == exclude) continue; Control c = (Control)logviewer; if (c.InvokeRequired) c.Invoke(new Action(() => logviewer.OnEventSelected(eventID))); else logviewer.OnEventSelected(eventID); } }
// generally logFile == origFilename, but if the log was transferred remotely then origFilename // is the log locally before being copied we can present to the user in dialogs, etc. public void LoadLogfile(string logFile, string origFilename, bool temporary, bool local) { m_LogFile = origFilename; m_LogLocal = local; m_LogLoadingInProgress = true; if (File.Exists(Core.ConfigFilename)) m_Config.Serialize(Core.ConfigFilename); float postloadProgress = 0.0f; bool progressThread = true; // start a modal dialog to prevent the user interacting with the form while the log is loading. // We'll close it down when log loading finishes (whether it succeeds or fails) ProgressPopup modal = new ProgressPopup(LogLoadCallback, true); Thread modalThread = Helpers.NewThread(new ThreadStart(() => { modal.SetModalText(string.Format("Loading Log: {0}", origFilename)); AppWindow.BeginInvoke(new Action(() => { modal.ShowDialog(AppWindow); })); })); modalThread.Start(); // this thread continually ticks and notifies any threads of the progress, through a float // that is updated by the main loading code Thread thread = Helpers.NewThread(new ThreadStart(() => { modal.LogfileProgressBegin(); foreach (var p in m_ProgressListeners) p.LogfileProgressBegin(); while (progressThread) { Thread.Sleep(2); float progress = 0.8f * m_Renderer.LoadProgress + 0.19f * postloadProgress + 0.01f; modal.LogfileProgress(progress); foreach (var p in m_ProgressListeners) p.LogfileProgress(progress); } })); thread.Start(); // this function call will block until the log is either loaded, or there's some failure m_Renderer.OpenCapture(logFile); // if the renderer isn't running, we hit a failure case so display an error message if (!m_Renderer.Running) { string errmsg = m_Renderer.InitException.Status.Str(); MessageBox.Show(String.Format("{0}\nFailed to open file for replay: {1}.\n\n" + "Check diagnostic log in Help menu for more details.", origFilename, errmsg), "Error opening log", MessageBoxButtons.OK, MessageBoxIcon.Error); progressThread = false; thread.Join(); m_LogLoadingInProgress = false; modal.LogfileProgress(-1.0f); foreach (var p in m_ProgressListeners) p.LogfileProgress(-1.0f); return; } if (!temporary) { m_Config.AddRecentFile(m_Config.RecentLogFiles, origFilename, 10); if (File.Exists(Core.ConfigFilename)) m_Config.Serialize(Core.ConfigFilename); } m_EventID = 0; m_FrameInfo = null; m_APIProperties = null; // fetch initial data like drawcalls, textures and buffers m_Renderer.Invoke((ReplayRenderer r) => { m_FrameInfo = r.GetFrameInfo(); m_APIProperties = r.GetAPIProperties(); postloadProgress = 0.2f; m_DrawCalls = FakeProfileMarkers(r.GetDrawcalls()); bool valid = HasValidMarkerColors(m_DrawCalls); if (!valid) RemoveMarkerColors(m_DrawCalls); postloadProgress = 0.4f; m_Buffers = r.GetBuffers(); postloadProgress = 0.7f; var texs = new List<FetchTexture>(r.GetTextures()); m_Textures = texs.OrderBy(o => o.name).ToArray(); postloadProgress = 0.9f; m_D3D11PipelineState = r.GetD3D11PipelineState(); m_D3D12PipelineState = r.GetD3D12PipelineState(); m_GLPipelineState = r.GetGLPipelineState(); m_VulkanPipelineState = r.GetVulkanPipelineState(); m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_D3D12PipelineState, m_GLPipelineState, m_VulkanPipelineState); UnreadMessageCount = 0; AddMessages(m_FrameInfo.debugMessages); postloadProgress = 1.0f; }); Thread.Sleep(20); DateTime today = DateTime.Now; DateTime compare = today.AddDays(-21); if (compare.CompareTo(Config.DegradedLog_LastUpdate) >= 0 && m_APIProperties.degraded) { Config.DegradedLog_LastUpdate = today; MessageBox.Show(String.Format("{0}\nThis log opened with degraded support - " + "this could mean missing hardware support caused a fallback to software rendering.\n\n" + "This warning will not appear every time this happens, " + "check debug errors/warnings window for more details.", origFilename), "Degraded support of log", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } m_LogLoaded = true; progressThread = false; if (local) { m_LogWatcher = new FileSystemWatcher(Path.GetDirectoryName(m_LogFile), Path.GetFileName(m_LogFile)); m_LogWatcher.EnableRaisingEvents = true; m_LogWatcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite; m_LogWatcher.Created += new FileSystemEventHandler(OnLogfileChanged); m_LogWatcher.Changed += new FileSystemEventHandler(OnLogfileChanged); m_LogWatcher.SynchronizingObject = m_MainWindow; // callbacks on UI thread please } List<ILogViewerForm> logviewers = new List<ILogViewerForm>(); logviewers.AddRange(m_LogViewers); // notify all the registers log viewers that a log has been loaded foreach (var logviewer in logviewers) { if (logviewer == null || !(logviewer is Control)) continue; Control c = (Control)logviewer; if (c.InvokeRequired) { if (!c.IsDisposed) { c.Invoke(new Action(() => { try { logviewer.OnLogfileLoaded(); } catch (Exception ex) { throw new AccessViolationException("Rethrown from Invoke:\n" + ex.ToString()); } })); } } else if (!c.IsDisposed) logviewer.OnLogfileLoaded(); } m_LogLoadingInProgress = false; modal.LogfileProgress(1.0f); foreach (var p in m_ProgressListeners) p.LogfileProgress(1.0f); }
public void SetStates(APIProperties props, D3D11PipelineState d3d11, GLPipelineState gl) { m_APIProps = props; m_D3D11 = d3d11; m_GL = gl; }
private void AddResourceRegister(ShaderResource slot, D3D11PipelineState.ShaderStage.ResourceView res) { bool found = false; var name = slot.bindPoint + " (" + slot.name + ")"; foreach (var tex in m_Core.CurTextures) { if (tex.ID == res.Resource) { var node = new TreelistView.Node(new object[] { "t" + name, "Texture", tex.width + "x" + tex.height + "x" + (tex.depth > 1 ? tex.depth : tex.arraysize) + "[" + tex.mips + "] @ " + tex.format + " - " + tex.name }); node.Tag = null; constantRegs.Nodes.Add(node); found = true; break; } } if (!found) { foreach (var buf in m_Core.CurBuffers) { if (buf.ID == res.Resource) { string prefix = "u"; if (slot.IsSRV) prefix = "t"; var node = new TreelistView.Node(new object[] { prefix + name, "Buffer", buf.length + " - " + buf.name }); node.Tag = null; constantRegs.Nodes.Add(node); found = true; break; } } } if (!found) { string prefix = "u"; if (slot.IsSRV) prefix = "t"; var node = new TreelistView.Node(new object[] { prefix + name, "Resource", "unknown" }); node.Tag = null; constantRegs.Nodes.Add(node); } }
public void SetStates(APIProperties props, D3D11PipelineState d3d11, GLPipelineState gl, VulkanPipelineState vk) { m_APIProps = props; m_D3D11 = d3d11; m_GL = gl; m_Vulkan = vk; }
private bool HasImportantViewParams(D3D11PipelineState.ShaderStage.ResourceView view, FetchBuffer buf) { if (view.FirstElement > 0 || view.NumElements*view.ElementSize < buf.length) return true; return false; }
// Set a shader stage's resources and values private void SetShaderState(FetchTexture[] texs, FetchBuffer[] bufs, D3D11PipelineState.ShaderStage stage, Label shader, TreelistView.TreeListView resources, TreelistView.TreeListView samplers, TreelistView.TreeListView cbuffers, TreelistView.TreeListView classes) { ShaderReflection shaderDetails = stage.ShaderDetails; if (stage.Shader == ResourceId.Null) shader.Text = "Unbound"; else shader.Text = stage.ShaderName; if (shaderDetails != null && shaderDetails.DebugInfo.entryFunc.Length > 0 && shaderDetails.DebugInfo.files.Length > 0) { string shaderfn = ""; int entryFile = shaderDetails.DebugInfo.entryFile; if (entryFile < 0 || entryFile >= shaderDetails.DebugInfo.files.Length) entryFile = 0; shaderfn = shaderDetails.DebugInfo.files[entryFile].BaseFilename; shader.Text = shaderDetails.DebugInfo.entryFunc + "()" + " - " + shaderfn; } int vs = 0; vs = resources.VScrollValue(); resources.BeginUpdate(); resources.Nodes.Clear(); if (stage.SRVs != null) { int i = 0; foreach (var r in stage.SRVs) { ShaderResource shaderInput = null; if (shaderDetails != null) { foreach (var bind in shaderDetails.ReadOnlyResources) { if (bind.IsSRV && bind.bindPoint == i) { shaderInput = bind; break; } } } bool filledSlot = (r.Resource != ResourceId.Null); bool usedSlot = (shaderInput != null); // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled" (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { string slotname = i.ToString(); if (shaderInput != null && shaderInput.name.Length > 0) slotname += ": " + shaderInput.name; UInt64 w = 1; UInt32 h = 1, d = 1; UInt32 a = 1; string format = "Unknown"; string name = "Shader Resource " + r.Resource.ToString(); string typename = "Unknown"; object tag = null; bool viewDetails = false; if (!filledSlot) { name = "Empty"; format = "-"; typename = "-"; w = h = d = a = 0; } // check to see if it's a texture for (int t = 0; t < texs.Length; t++) { if (texs[t].ID == r.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 = texs[t].resType.Str(); if (texs[t].resType == ShaderResourceType.Texture2DMS || texs[t].resType == ShaderResourceType.Texture2DMSArray) { typename += String.Format(" {0}x", texs[t].msSamp); } // if it's a typeless format, show the format of the view if (texs[t].format != r.Format) { format = "Viewed as " + r.Format.ToString(); } tag = new ViewTexTag(r, texs[t]); if (HasImportantViewParams(r, texs[t])) viewDetails = true; } } // if not a texture, it must be a buffer for (int t = 0; t < bufs.Length; t++) { if (bufs[t].ID == r.Resource) { w = bufs[t].length; h = 0; d = 0; a = 0; format = ""; name = bufs[t].name; typename = "Buffer"; // for structured buffers, display how many 'elements' there are in the buffer if (r.ElementSize > 0) { typename = "StructuredBuffer[" + (bufs[t].length / r.ElementSize) + "]"; } else if (r.Flags.HasFlag(D3D11BufferViewFlags.Raw)) { typename = "ByteAddressBuffer"; } if (r.Flags.HasFlag(D3D11BufferViewFlags.Append) || r.Flags.HasFlag(D3D11BufferViewFlags.Counter)) { typename += " (Count: " + r.BufferStructCount + ")"; } // get the buffer type, whether it's just a basic type or a complex struct if (shaderInput != null && !shaderInput.IsTexture) { if (r.Format.compType == FormatComponentType.None) { if (shaderInput.variableType.members.Length > 0) format = "struct " + shaderInput.variableType.Name; else format = shaderInput.variableType.Name; } else { format = r.Format.ToString(); } } tag = new ViewBufTag(r, bufs[t]); if (HasImportantViewParams(r, bufs[t])) viewDetails = true; } } var node = resources.Nodes.Add(new object[] { slotname, name, typename, w, h, d, a, format }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = tag; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); if (viewDetails) ViewDetailsRow(node); } i++; } } resources.EndUpdate(); resources.NodesSelection.Clear(); resources.SetVScrollValue(vs); vs = samplers.VScrollValue(); samplers.BeginUpdate(); samplers.Nodes.Clear(); if (stage.Samplers != null) { int i = 0; foreach (var s in stage.Samplers) { ShaderResource shaderInput = null; if (shaderDetails != null) { foreach (var bind in shaderDetails.ReadOnlyResources) { if (bind.IsSampler && bind.bindPoint == i) { shaderInput = bind; break; } } } bool filledSlot = (s.AddressU.Length > 0); bool usedSlot = (shaderInput != null); // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled" (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { string slotname = i.ToString(); if (shaderInput != null && shaderInput.name.Length > 0) slotname += ": " + shaderInput.name; if (s.customSamplerName) slotname += "(" + s.SamplerName + ")"; 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; if(s.UseBorder) addressing += String.Format("<{0}>", borderColor); string filter = s.Filter; if (s.MaxAniso > 0) filter += String.Format(" {0}x", s.MaxAniso); if (s.UseComparison) filter += String.Format(" ({0})", s.Comparison); var node = samplers.Nodes.Add(new object[] { slotname, addressing, filter, (s.MinLOD == -float.MaxValue ? "0" : s.MinLOD.ToString()) + " - " + (s.MaxLOD == float.MaxValue ? "FLT_MAX" : s.MaxLOD.ToString()), s.MipLODBias.ToString() }); if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); } i++; } } samplers.EndUpdate(); samplers.NodesSelection.Clear(); samplers.SetVScrollValue(vs); vs = cbuffers.VScrollValue(); cbuffers.BeginUpdate(); cbuffers.Nodes.Clear(); if (stage.ConstantBuffers != null) { UInt32 i = 0; foreach (var b in stage.ConstantBuffers) { ConstantBlock shaderCBuf = null; if (shaderDetails != null && i < shaderDetails.ConstantBlocks.Length && shaderDetails.ConstantBlocks[i].name.Length > 0) shaderCBuf = shaderDetails.ConstantBlocks[i]; bool filledSlot = (b.Buffer != ResourceId.Null); bool usedSlot = (shaderCBuf != null); // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled" (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { string name = "Constant Buffer " + b.Buffer.ToString(); UInt64 length = 1; int numvars = shaderCBuf != null ? shaderCBuf.variables.Length : 0; UInt32 byteSize = shaderCBuf != null ? shaderCBuf.byteSize : 0; if (!filledSlot) { name = "Empty"; length = 0; } for (int t = 0; t < bufs.Length; t++) { if (bufs[t].ID == b.Buffer) { name = bufs[t].name; length = bufs[t].length; } } string slotname = i.ToString(); if (shaderCBuf != null && shaderCBuf.name.Length > 0) slotname += ": " + shaderCBuf.name; string sizestr; if (byteSize == length) sizestr = String.Format("{0} Variables, {1} bytes", numvars, length); else sizestr = String.Format("{0} Variables, {1} bytes needed, {2} provided", numvars, byteSize, length); if (length < byteSize) filledSlot = false; string vecrange = String.Format("{0} - {1}", b.VecOffset, b.VecOffset + b.VecCount); var node = cbuffers.Nodes.Add(new object[] { slotname, name, vecrange, sizestr }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = i; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); } i++; } } cbuffers.EndUpdate(); cbuffers.NodesSelection.Clear(); cbuffers.SetVScrollValue(vs); vs = classes.VScrollValue(); classes.BeginUpdate(); classes.Nodes.Clear(); { UInt32 i = 0; foreach (var inst in stage.ClassInstances) { string interfaceName = String.Format("Interface {0}", i); if (shaderDetails != null && i < shaderDetails.Interfaces.Length) interfaceName = shaderDetails.Interfaces[i].Name; classes.Nodes.Add(new object[] { i.ToString(), interfaceName, inst }); i++; } } classes.EndUpdate(); classes.NodesSelection.Clear(); classes.SetVScrollValue(vs); classes.Visible = classes.Parent.Visible = (stage.ClassInstances.Length > 0); }
// Set a shader stage's resources and values private void SetShaderState(FetchTexture[] texs, FetchBuffer[] bufs, D3D11PipelineState.ShaderStage stage, Label shader, TreelistView.TreeListView resources, TreelistView.TreeListView samplers, TreelistView.TreeListView cbuffers, TreelistView.TreeListView classes) { ShaderReflection shaderDetails = stage.ShaderDetails; if (stage.Shader == ResourceId.Null) shader.Text = "Unbound"; else shader.Text = stage.ShaderName; if (shaderDetails != null && shaderDetails.DebugInfo.entryFunc != "" && shaderDetails.DebugInfo.files.Length > 0) shader.Text = shaderDetails.DebugInfo.entryFunc + "()" + " - " + Path.GetFileName(shaderDetails.DebugInfo.files[0].filename); resources.BeginUpdate(); resources.Nodes.Clear(); if (stage.SRVs != null) { int i = 0; foreach (var r in stage.SRVs) { ShaderResource shaderInput = null; if (shaderDetails != null) { foreach (var bind in shaderDetails.Resources) { if (bind.IsSRV && bind.bindPoint == i) shaderInput = bind; } } bool filledSlot = (r.Resource != ResourceId.Null); bool usedSlot = (shaderInput != null); // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled" (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { string slotname = i.ToString(); if (shaderInput != null && shaderInput.name != "") slotname += ": " + shaderInput.name; UInt32 w = 1, h = 1, d = 1; UInt32 a = 1; string format = "Unknown"; string name = "Shader Resource " + r.Resource.ToString(); string typename = "Unknown"; object tag = null; if (!filledSlot) { name = "Empty"; format = "-"; typename = "-"; w = h = d = a = 0; } // check to see if it's a texture for (int t = 0; t < texs.Length; t++) { if (texs[t].ID == r.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"; tag = texs[t]; } } // if not a texture, it must be a buffer for (int t = 0; t < bufs.Length; t++) { if (bufs[t].ID == r.Resource) { w = bufs[t].length; h = 0; d = 0; a = 0; format = ""; 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) + "]"; // get the buffer type, whether it's just a basic type or a complex struct if (shaderInput != null && !shaderInput.IsTexture) { if (r.Format.compType == FormatComponentType.None) { if (shaderInput.variableType.members.Length > 0) format = "struct " + shaderInput.variableType.Name; else format = shaderInput.variableType.Name; } else { format = r.Format.ToString(); } } tag = bufs[t]; } } var node = resources.Nodes.Add(new object[] { slotname, name, typename, w, h, d, a, format }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = tag; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); } i++; } } resources.EndUpdate(); resources.NodesSelection.Clear(); samplers.BeginUpdate(); samplers.Nodes.Clear(); if (stage.Samplers != null) { int i = 0; foreach (var s in stage.Samplers) { ShaderResource shaderInput = null; if (shaderDetails != null) { foreach (var bind in shaderDetails.Resources) { if (bind.IsSampler && bind.bindPoint == i) shaderInput = bind; } } bool filledSlot = (s.AddressU != ""); bool usedSlot = (shaderInput != null); // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled" (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { string slotname = i.ToString(); if (shaderInput != null && shaderInput.name != "") slotname += ": " + shaderInput.name; 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; var node = samplers.Nodes.Add(new object[] { slotname, 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() }); if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); } i++; } } samplers.EndUpdate(); samplers.NodesSelection.Clear(); cbuffers.BeginUpdate(); cbuffers.Nodes.Clear(); if (stage.ConstantBuffers != null) { UInt32 i = 0; foreach (var b in stage.ConstantBuffers) { ConstantBlock shaderCBuf = null; if (shaderDetails != null && i < shaderDetails.ConstantBlocks.Length && shaderDetails.ConstantBlocks[i].name != "") shaderCBuf = shaderDetails.ConstantBlocks[i]; bool filledSlot = (b.Buffer != ResourceId.Null); bool usedSlot = (shaderCBuf != null); // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not (showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled" (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { string name = "Constant Buffer " + b.Buffer.ToString(); UInt32 length = 1; int numvars = shaderCBuf != null ? shaderCBuf.variables.Length : 0; if (!filledSlot) { name = "Empty"; length = 0; } for (int t = 0; t < bufs.Length; t++) { if (bufs[t].ID == b.Buffer) { name = bufs[t].name; length = bufs[t].length; } } string slotname = i.ToString(); if (shaderCBuf != null && shaderCBuf.name != "") slotname += ": " + shaderCBuf.name; var node = cbuffers.Nodes.Add(new object[] { slotname, name, b.VecOffset, b.VecCount, numvars, length }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; node.Tag = i; if (!filledSlot) EmptyRow(node); if (!usedSlot) InactiveRow(node); } i++; } } cbuffers.EndUpdate(); cbuffers.NodesSelection.Clear(); classes.BeginUpdate(); classes.Nodes.Clear(); { UInt32 i = 0; foreach (var inst in stage.ClassInstances) { string interfaceName = String.Format("Interface {0}", i); if (shaderDetails != null && i < shaderDetails.Interfaces.Length) interfaceName = shaderDetails.Interfaces[i].Name; classes.Nodes.Add(new object[] { i.ToString(), interfaceName, inst }); i++; } } classes.EndUpdate(); classes.NodesSelection.Clear(); }
public ViewBufTag(D3D11PipelineState.ShaderStage.ResourceView v, FetchBuffer b) { view = v; buf = b; }
public void CloseLogfile() { if (!m_LogLoaded) return; m_LogFile = ""; m_Renderer.CloseThreadSync(); m_Renderer = new RenderManager(); m_APIProperties = null; m_FrameInfo = null; m_DrawCalls = null; m_Buffers = null; m_Textures = null; m_D3D11PipelineState = null; m_GLPipelineState = null; m_PipelineState.SetStates(null, null, null); DebugMessages.Clear(); UnreadMessageCount = 0; m_LogLoaded = false; foreach (var logviewer in m_LogViewers) { Control c = (Control)logviewer; if (c.InvokeRequired) c.Invoke(new Action(() => logviewer.OnLogfileClosed())); else logviewer.OnLogfileClosed(); } }
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(); UInt64 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(); UInt64 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; } } } string ifmt = "UNKNOWN"; if (m_Core.CurDrawcall.indexByteWidth == 2) ifmt = "R16_UINT"; if (m_Core.CurDrawcall.indexByteWidth == 4) ifmt = "R32_UINT"; ExportHTMLTable(writer, new string[] { "Buffer", "Format", "Offset", "Byte Length" }, new object[] { name, ifmt, ia.ibuffer.Offset.ToString(), length.ToString() }); } writer.WriteStartElement("p"); writer.WriteEndElement(); ExportHTMLTable(writer, new string[] { "Primitive Topology" }, new object[] { m_Core.CurDrawcall.topology.Str() }); }
// when loading a log while replaying remotely, provide the proxy renderer that will be used // as well as the hostname to replay on. public void LoadLogfile(int proxyRenderer, string replayHost, string logFile, bool temporary) { m_LogFile = logFile; m_LogLoadingInProgress = true; if (File.Exists(Core.ConfigFilename)) m_Config.Serialize(Core.ConfigFilename); float postloadProgress = 0.0f; bool progressThread = true; // start a modal dialog to prevent the user interacting with the form while the log is loading. // We'll close it down when log loading finishes (whether it succeeds or fails) ModalPopup modal = new ModalPopup(LogLoadCallback, true); Thread modalThread = Helpers.NewThread(new ThreadStart(() => { modal.SetModalText(string.Format("Loading Log {0}.", m_LogFile)); AppWindow.BeginInvoke(new Action(() => { modal.ShowDialog(AppWindow); })); })); modalThread.Start(); // this thread continually ticks and notifies any threads of the progress, through a float // that is updated by the main loading code Thread thread = Helpers.NewThread(new ThreadStart(() => { modal.LogfileProgressBegin(); foreach (var p in m_ProgressListeners) p.LogfileProgressBegin(); while (progressThread) { Thread.Sleep(2); float progress = 0.5f * m_Renderer.LoadProgress + 0.49f * postloadProgress + 0.01f; modal.LogfileProgress(progress); foreach (var p in m_ProgressListeners) p.LogfileProgress(progress); } })); thread.Start(); // this function call will block until the log is either loaded, or there's some failure m_Renderer.Init(proxyRenderer, replayHost, logFile); // if the renderer isn't running, we hit a failure case so display an error message if (!m_Renderer.Running) { string errmsg = "Unknown error message"; if (m_Renderer.InitException.Data.Contains("status")) errmsg = ((ReplayCreateStatus)m_Renderer.InitException.Data["status"]).Str(); if(proxyRenderer >= 0) MessageBox.Show(String.Format("{0}\nFailed to transfer and replay on remote host {1}: {2}.\n\n" + "Check diagnostic log in Help menu for more details.", logFile, replayHost, errmsg), "Error opening log", MessageBoxButtons.OK, MessageBoxIcon.Error); else MessageBox.Show(String.Format("{0}\nFailed to open logfile for replay: {1}.\n\n" + "Check diagnostic log in Help menu for more details.", logFile, errmsg), "Error opening log", MessageBoxButtons.OK, MessageBoxIcon.Error); progressThread = false; thread.Join(); m_LogLoadingInProgress = false; modal.LogfileProgress(-1.0f); foreach (var p in m_ProgressListeners) p.LogfileProgress(-1.0f); return; } if (!temporary) { m_Config.AddRecentFile(m_Config.RecentLogFiles, logFile, 10); if (File.Exists(Core.ConfigFilename)) m_Config.Serialize(Core.ConfigFilename); } m_FrameID = 0; m_EventID = 0; m_FrameInfo = null; m_APIProperties = null; // fetch initial data like drawcalls, textures and buffers m_Renderer.Invoke((ReplayRenderer r) => { m_FrameInfo = r.GetFrameInfo(); m_APIProperties = r.GetAPIProperties(); postloadProgress = 0.2f; m_DrawCalls = new FetchDrawcall[m_FrameInfo.Length][]; postloadProgress = 0.4f; for (int i = 0; i < m_FrameInfo.Length; i++) m_DrawCalls[i] = FakeProfileMarkers(i, r.GetDrawcalls((UInt32)i)); postloadProgress = 0.7f; m_Buffers = r.GetBuffers(); postloadProgress = 0.8f; var texs = new List<FetchTexture>(r.GetTextures()); m_Textures = texs.OrderBy(o => o.name).ToArray(); postloadProgress = 0.9f; m_D3D11PipelineState = r.GetD3D11PipelineState(); m_GLPipelineState = r.GetGLPipelineState(); m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_GLPipelineState); UnreadMessageCount = 0; AddMessages(m_FrameInfo[0].debugMessages); postloadProgress = 1.0f; }); Thread.Sleep(20); DateTime today = DateTime.Now; DateTime compare = today.AddDays(-21); if (compare.CompareTo(Config.DegradedLog_LastUpdate) >= 0 && m_APIProperties.degraded) { Config.DegradedLog_LastUpdate = today; MessageBox.Show(String.Format("{0}\nThis log opened with degraded support - " + "this could mean missing hardware support caused a fallback to software rendering.\n\n" + "This warning will not appear every time this happens, " + "check debug errors/warnings window for more details.", logFile), "Degraded support of log", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } m_LogLoaded = true; progressThread = false; List<ILogViewerForm> logviewers = new List<ILogViewerForm>(); logviewers.AddRange(m_LogViewers); // notify all the registers log viewers that a log has been loaded foreach (var logviewer in logviewers) { if (logviewer == null || !(logviewer is Control)) continue; Control c = (Control)logviewer; if (c.InvokeRequired) { if (!c.IsDisposed) { c.Invoke(new Action(() => { try { logviewer.OnLogfileLoaded(); } catch (Exception ex) { throw new AccessViolationException("Rethrown from Invoke:\n" + ex.ToString()); } })); } } else if (!c.IsDisposed) logviewer.OnLogfileLoaded(); } m_LogLoadingInProgress = false; modal.LogfileProgress(1.0f); foreach (var p in m_ProgressListeners) p.LogfileProgress(1.0f); }
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(); UInt64 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()); } }
public void SetEventID(ILogViewerForm exclude, UInt32 frameID, UInt32 eventID) { m_FrameID = frameID; m_EventID = eventID; m_DeferredEvent = 0; m_Renderer.Invoke((ReplayRenderer r) => { r.SetContextFilter(ResourceId.Null, 0, 0); }); m_Renderer.Invoke((ReplayRenderer r) => { r.SetFrameEvent(m_FrameID, m_EventID); m_D3D11PipelineState = r.GetD3D11PipelineState(); m_GLPipelineState = r.GetGLPipelineState(); m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_GLPipelineState); }); foreach (var logviewer in m_LogViewers) { if(logviewer == exclude) continue; Control c = (Control)logviewer; if (c.InvokeRequired) c.BeginInvoke(new Action(() => logviewer.OnEventSelected(frameID, eventID))); else logviewer.OnEventSelected(frameID, eventID); } }
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 & 0x1) == 0 ? "_" : "R") + ((b.WriteMask & 0x2) == 0 ? "_" : "G") + ((b.WriteMask & 0x4) == 0 ? "_" : "B") + ((b.WriteMask & 0x8) == 0 ? "_" : "A") }); 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("Stencil State"); writer.WriteEndElement(); ExportHTMLTable(writer, new string[] { "Stencil Test Enable", "Stencil Read Mask", "Stencil Write Mask" }, new object[] { om.m_State.StencilEnable ? "Yes" : "No", om.m_State.StencilReadMask.ToString("X2"), om.m_State.StencilWriteMask.ToString("X2") }); writer.WriteStartElement("p"); writer.WriteEndElement(); ExportHTMLTable(writer, new string[] { "Face", "Function", "Pass Operation", "Fail Operation", "Depth Fail Operation" }, new object[][] { new object[] { "Front", om.m_State.m_FrontFace.Func, om.m_State.m_FrontFace.PassOp, om.m_State.m_FrontFace.FailOp, om.m_State.m_FrontFace.DepthFailOp }, new object[] { "Back", om.m_State.m_BackFace.Func, om.m_State.m_BackFace.PassOp, om.m_State.m_BackFace.FailOp, om.m_State.m_BackFace.DepthFailOp }, }); } { 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()); } }
// setting a context filter allows replaying of deferred events. You can set the deferred // events to replay in a context, after replaying up to a given event on the main thread public void SetContextFilter(ILogViewerForm exclude, UInt32 eventID, ResourceId ctx, UInt32 firstDeferred, UInt32 lastDeferred) { m_EventID = eventID; m_DeferredEvent = lastDeferred; m_Renderer.Invoke((ReplayRenderer r) => { r.SetContextFilter(ctx, firstDeferred, lastDeferred); }); m_Renderer.Invoke((ReplayRenderer r) => { r.SetFrameEvent(m_EventID, true); m_D3D11PipelineState = r.GetD3D11PipelineState(); m_GLPipelineState = r.GetGLPipelineState(); m_VulkanPipelineState = r.GetVulkanPipelineState(); m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_GLPipelineState, m_VulkanPipelineState); }); foreach (var logviewer in m_LogViewers) { if (logviewer == exclude) continue; Control c = (Control)logviewer; if (c.InvokeRequired) c.BeginInvoke(new Action(() => logviewer.OnEventSelected(eventID))); else logviewer.OnEventSelected(eventID); } }