Exemple #1
0
        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);
        }
Exemple #11
0
        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);
            }
        }
Exemple #12
0
        // 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;
 }
Exemple #14
0
        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;
 }
Exemple #20
0
        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() });
        }
Exemple #22
0
        // 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());
            }
        }
Exemple #24
0
        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());
            }
        }
Exemple #26
0
        // 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);
            }
        }