Example #1
0
 public void SetStates(APIProperties props, D3D11PipelineState d3d11, GLPipelineState gl, VulkanPipelineState vk)
 {
     m_APIProps = props;
     m_D3D11    = d3d11;
     m_GL       = gl;
     m_Vulkan   = vk;
 }
Example #2
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);
                }
            }
        }
Example #3
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 (exclude.Contains(logviewer))
                {
                    continue;
                }

                Control c = (Control)logviewer;
                if (c.InvokeRequired)
                {
                    c.Invoke(new Action(() => logviewer.OnEventSelected(eventID)));
                }
                else
                {
                    logviewer.OnEventSelected(eventID);
                }
            }
        }
Example #4
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);
                }
            }
        }
Example #5
0
        public void CloseLogfile()
        {
            if (!m_LogLoaded)
            {
                return;
            }

            m_LogFile = "";

            m_Renderer.CloseThreadSync();

            m_APIProperties = null;
            m_FrameInfo     = null;
            m_DrawCalls     = null;
            m_Buffers       = null;
            m_Textures      = null;

            m_D3D11PipelineState  = null;
            m_D3D12PipelineState  = null;
            m_GLPipelineState     = null;
            m_VulkanPipelineState = null;
            m_PipelineState.SetStates(null, null, null, null, null);

            DebugMessages.Clear();
            UnreadMessageCount = 0;

            m_LogLoaded = false;

            if (m_LogWatcher != null)
            {
                m_LogWatcher.EnableRaisingEvents = false;
            }
            m_LogWatcher = null;

            foreach (var logviewer in m_LogViewers)
            {
                Control c = (Control)logviewer;
                if (c.InvokeRequired)
                {
                    c.Invoke(new Action(() => logviewer.OnLogfileClosed()));
                }
                else
                {
                    logviewer.OnLogfileClosed();
                }
            }
        }
Example #6
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);

            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();
                }
            }
        }
Example #7
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 (!temporary)
            {
                m_Config.AddRecentFile(m_Config.RecentLogFiles, logFile, 10);
            }

            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 = new Thread(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 = new Thread(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;
            }

            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, false));
                }

                m_TimedDrawcalls = false;

                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);

                postloadProgress = 1.0f;
            });

            Thread.Sleep(20);

            m_LogLoaded    = true;
            progressThread = false;

            // notify all the registers log viewers that a log has been loaded
            foreach (var logviewer in m_LogViewers)
            {
                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);
            }
        }
Example #8
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)
            {
                try
                {
                    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
                }
                catch (ArgumentException)
                {
                    // likely an "invalid" directory name - FileSystemWatcher doesn't support UNC paths properly
                }
            }

            List <ILogViewerForm> logviewers = new List <ILogViewerForm>();

            logviewers.AddRange(m_LogViewers);

            // make sure we're on a consistent event before invoking log viewer forms
            FetchDrawcall draw = m_DrawCalls.Last();

            while (draw.children != null && draw.children.Length > 0)
            {
                draw = draw.children.Last();
            }

            SetEventID(logviewers.ToArray(), draw.eventID, true);

            // 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;
 }
Example #10
0
        private void UpdateState()
        {
            if (!m_Core.LogLoaded)
            {
                return;
            }

            FetchTexture[]  texs  = m_Core.CurTextures;
            FetchBuffer[]   bufs  = m_Core.CurBuffers;
            GLPipelineState state = m_Core.CurGLPipelineState;
            FetchDrawcall   draw  = m_Core.CurDrawcall;

            var tick  = global::renderdocui.Properties.Resources.tick;
            var cross = global::renderdocui.Properties.Resources.cross;

            bool[] usedVBuffers = new bool[128];

            for (int i = 0; i < 128; i++)
            {
                usedVBuffers[i] = false;
            }

            ////////////////////////////////////////////////
            // Input Assembler

            inputLayouts.Nodes.Clear();
            inputLayouts.BeginUpdate();
            if (state.m_VtxIn.attributes != null)
            {
                int i = 0;
                foreach (var l in state.m_VtxIn.attributes)
                {
                    if (l.Enabled || showDisabled.Checked)
                    {
                        string byteOffs = l.RelativeOffset.ToString();

                        var node = inputLayouts.Nodes.Add(new object[] {
                            i, l.Enabled ? "Enabled" : "Disabled", "", l.Format, l.BufferSlot.ToString(), byteOffs,
                            "", ""
                        });

                        usedVBuffers[l.BufferSlot] = true;

                        node.Image      = global::renderdocui.Properties.Resources.action;
                        node.HoverImage = global::renderdocui.Properties.Resources.action_hover;

                        if (!l.Enabled)
                        {
                            InactiveRow(node);
                        }
                    }

                    i++;
                }
            }
            inputLayouts.NodesSelection.Clear();
            inputLayouts.EndUpdate();

            topology.Text = state.m_VtxIn.Topology.ToString();
            if (state.m_VtxIn.Topology > PrimitiveTopology.PatchList)
            {
                int numCPs = (int)state.m_VtxIn.Topology - (int)PrimitiveTopology.PatchList + 1;

                topology.Text = string.Format("PatchList ({0} Control Points)", numCPs);
            }

            switch (state.m_VtxIn.Topology)
            {
            case PrimitiveTopology.PointList:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_pointlist;
                break;

            case PrimitiveTopology.LineList:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_linelist;
                break;

            case PrimitiveTopology.LineStrip:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_linestrip;
                break;

            case PrimitiveTopology.TriangleList:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_trilist;
                break;

            case PrimitiveTopology.TriangleStrip:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_tristrip;
                break;

            case PrimitiveTopology.LineList_Adj:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_linelist_adj;
                break;

            case PrimitiveTopology.LineStrip_Adj:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_linestrip_adj;
                break;

            case PrimitiveTopology.TriangleList_Adj:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_trilist_adj;
                break;

            case PrimitiveTopology.TriangleStrip_Adj:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_tristrip_adj;
                break;

            default:
                topologyDiagram.Image = global::renderdocui.Properties.Resources.topo_patch;
                break;
            }

            iabuffers.Nodes.Clear();
            iabuffers.BeginUpdate();

            bool ibufferUsed = draw != null && (draw.flags & DrawcallFlags.UseIBuffer) != 0;

            if (state.m_VtxIn.ibuffer != null)
            {
                if (ibufferUsed || showDisabled.Checked)
                {
                    string ptr    = "Buffer " + state.m_VtxIn.ibuffer.Buffer.ToString();
                    string name   = ptr;
                    UInt32 length = 1;

                    if (!ibufferUsed)
                    {
                        length = 0;
                    }

                    for (int t = 0; t < bufs.Length; t++)
                    {
                        if (bufs[t].ID == state.m_VtxIn.ibuffer.Buffer)
                        {
                            name   = bufs[t].name;
                            length = bufs[t].length;
                        }
                    }

                    var node = iabuffers.Nodes.Add(new object[] { "Index", name, state.m_VtxIn.ibuffer.Format.compByteWidth, state.m_VtxIn.ibuffer.Offset, length });

                    node.Image      = global::renderdocui.Properties.Resources.action;
                    node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
                    node.Tag        = state.m_VtxIn.ibuffer.Buffer;

                    if (!ibufferUsed)
                    {
                        InactiveRow(node);
                    }

                    if (state.m_VtxIn.ibuffer.Buffer == ResourceId.Null)
                    {
                        EmptyRow(node);
                    }
                }
            }
            else
            {
                if (showEmpty.Checked &&
                    (ibufferUsed || showDisabled.Checked))
                {
                    var node = iabuffers.Nodes.Add(new object[] { "Index", "-", "-", "-", "-" });

                    node.Image      = global::renderdocui.Properties.Resources.action;
                    node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
                    node.Tag        = state.m_VtxIn.ibuffer.Buffer;

                    EmptyRow(node);

                    if (!ibufferUsed)
                    {
                        InactiveRow(node);
                    }
                }
            }

            m_VBNodes.Clear();

            if (state.m_VtxIn.vbuffers != null)
            {
                int i = 0;
                foreach (var v in state.m_VtxIn.vbuffers)
                {
                    bool filledSlot = (v.Buffer != ResourceId.Null);
                    bool usedSlot   = (usedVBuffers[i]);

                    // 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   = "Buffer " + v.Buffer.ToString();
                        UInt32 length = 1;

                        if (!filledSlot)
                        {
                            name   = "Empty";
                            length = 0;
                        }

                        for (int t = 0; t < bufs.Length; t++)
                        {
                            if (bufs[t].ID == v.Buffer)
                            {
                                name   = bufs[t].name;
                                length = bufs[t].length;
                            }
                        }

                        var node = iabuffers.Nodes.Add(new object[] { i, name, v.Stride, v.Offset, length });

                        node.Image      = global::renderdocui.Properties.Resources.action;
                        node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
                        node.Tag        = v.Buffer;

                        if (!filledSlot)
                        {
                            EmptyRow(node);
                        }

                        if (!usedSlot)
                        {
                            InactiveRow(node);
                        }

                        m_VBNodes.Add(node);
                    }

                    i++;
                }
            }
            iabuffers.NodesSelection.Clear();
            iabuffers.EndUpdate();

            SetShaderState(texs, bufs, state, state.m_VS, vsShader, vsResources, vsSamplers, vsCBuffers, vsClasses);
            SetShaderState(texs, bufs, state, state.m_GS, gsShader, gsResources, gsSamplers, gsCBuffers, gsClasses);
            SetShaderState(texs, bufs, state, state.m_TES, tesShader, tesResources, tesSamplers, tesCBuffers, tesClasses);
            SetShaderState(texs, bufs, state, state.m_TCS, tcsShader, tcsResources, tcsSamplers, tcsCBuffers, tcsClasses);
            SetShaderState(texs, bufs, state, state.m_FS, fsShader, fsResources, fsSamplers, fsCBuffers, fsClasses);
            SetShaderState(texs, bufs, state, state.m_CS, csShader, csResources, csSamplers, csCBuffers, csClasses);

            fsResources.BeginUpdate();
            fsResources.Nodes.Clear();
            if (state.Textures != null)
            {
                var shaderDetails = state.m_FS.ShaderDetails;
                var mapping       = state.m_FS.BindpointMapping;

                int i = 0;
                foreach (var r in state.Textures)
                {
                    ShaderResource shaderInput = null;
                    BindpointMap   map         = null;

                    if (shaderDetails != null)
                    {
                        foreach (var bind in shaderDetails.Resources)
                        {
                            if (bind.IsSRV && mapping.Resources[bind.bindPoint].bind == i)
                            {
                                shaderInput = bind;
                                map         = mapping.Resources[bind.bindPoint];
                            }
                        }
                    }

                    bool filledSlot = (r.Resource != ResourceId.Null);
                    bool usedSlot   = (shaderInput != null && map.used);

                    // 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) + "]";
                                }

                                tag = bufs[t];
                            }
                        }

                        var node = fsResources.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++;
                }
            }
            fsResources.EndUpdate();
            fsResources.NodesSelection.Clear();

            csUAVs.Nodes.Clear();
            csUAVs.BeginUpdate();

            csUAVs.NodesSelection.Clear();
            csUAVs.EndUpdate();

            gsStreams.BeginUpdate();
            gsStreams.Nodes.Clear();
            gsStreams.EndUpdate();
            gsStreams.NodesSelection.Clear();

            ////////////////////////////////////////////////
            // Rasterizer

            viewports.BeginUpdate();
            viewports.Nodes.Clear();
            viewports.NodesSelection.Clear();
            viewports.EndUpdate();

            scissors.BeginUpdate();
            scissors.Nodes.Clear();
            scissors.NodesSelection.Clear();
            scissors.EndUpdate();

            ////////////////////////////////////////////////
            // Output Merger

            bool[] targets = new bool[8];

            for (int i = 0; i < 8; i++)
            {
                targets[i] = false;
            }

            targetOutputs.BeginUpdate();
            targetOutputs.Nodes.Clear();
            {
                int i = 0;
                foreach (var p in state.m_FB.Color)
                {
                    if (p != ResourceId.Null || showEmpty.Checked)
                    {
                        UInt32 w = 1, h = 1, d = 1;
                        UInt32 a        = 1;
                        string format   = "Unknown";
                        string name     = "Texture " + p.ToString();
                        string typename = "Unknown";
                        object tag      = null;

                        if (p == ResourceId.Null)
                        {
                            name     = "Empty";
                            format   = "-";
                            typename = "-";
                            w        = h = d = a = 0;
                        }

                        for (int t = 0; t < texs.Length; t++)
                        {
                            if (texs[t].ID == p)
                            {
                                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];
                            }
                        }

                        var node = targetOutputs.Nodes.Add(new object[] { i, 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 (p == ResourceId.Null)
                        {
                            EmptyRow(node);
                        }
                        else
                        {
                            targets[i] = true;
                        }
                    }

                    i++;
                }
            }

            {
                int i = 0;
                foreach (ResourceId depthstencil in new ResourceId[] { state.m_FB.Depth, state.m_FB.Stencil })
                {
                    if (depthstencil != ResourceId.Null || showEmpty.Checked)
                    {
                        UInt32 w = 1, h = 1, d = 1;
                        UInt32 a        = 1;
                        string format   = "Unknown";
                        string name     = "Depth Target " + depthstencil.ToString();
                        string typename = "Unknown";
                        object tag      = null;

                        if (depthstencil == ResourceId.Null)
                        {
                            name     = "Empty";
                            format   = "-";
                            typename = "-";
                            w        = h = d = a = 0;
                        }

                        for (int t = 0; t < texs.Length; t++)
                        {
                            if (texs[t].ID == depthstencil)
                            {
                                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];
                            }
                        }

                        string slot = "Depth";
                        if (i == 1)
                        {
                            slot = "Stencil";
                        }

                        var node = targetOutputs.Nodes.Add(new object[] { slot, 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 (depthstencil == ResourceId.Null)
                        {
                            EmptyRow(node);
                        }
                    }

                    i++;
                }
            }
            targetOutputs.EndUpdate();
            targetOutputs.NodesSelection.Clear();

            blendOperations.BeginUpdate();
            blendOperations.Nodes.Clear();
            blendOperations.NodesSelection.Clear();
            blendOperations.EndUpdate();

            stencilFuncs.BeginUpdate();
            stencilFuncs.Nodes.Clear();
            stencilFuncs.Nodes.Add(new object[] { "Front", "", "",
                                                  "", "" });
            stencilFuncs.Nodes.Add(new object[] { "Back", "", "",
                                                  "", "" });
            stencilFuncs.EndUpdate();
            stencilFuncs.NodesSelection.Clear();

            // highlight the appropriate stages in the flowchart
            if (draw == null)
            {
                pipeFlow.SetStagesEnabled(new bool[] { true, true, true, true, true, true, true, true, true });
            }
            else if ((draw.flags & DrawcallFlags.Dispatch) != 0)
            {
                pipeFlow.SetStagesEnabled(new bool[] { false, false, false, false, false, false, false, false, true });
            }
            else
            {
                pipeFlow.SetStagesEnabled(new bool[] {
                    true,
                    true,
                    state.m_TES.Shader != ResourceId.Null,
                    state.m_TCS.Shader != ResourceId.Null,
                    state.m_GS.Shader != ResourceId.Null,
                    true,
                    state.m_FS.Shader != ResourceId.Null,
                    true,
                    false
                });

                // if(streamout only)
                //{
                //    pipeFlow.Rasterizer = false;
                //    pipeFlow.OutputMerger = false;
                //}
            }
        }
Example #11
0
        // Set a shader stage's resources and values
        private void SetShaderState(FetchTexture[] texs, FetchBuffer[] bufs,
                                    GLPipelineState state, GLPipelineState.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 = "Shader " + stage.Shader.ToString();
            }

            if (shaderDetails != null && shaderDetails.DebugInfo.entryFunc != "" && shaderDetails.DebugInfo.files.Length > 0)
            {
                shader.Text = shaderDetails.DebugInfo.entryFunc + "()" + " - " +
                              Path.GetFileName(shaderDetails.DebugInfo.files[0].filename);
            }

            cbuffers.BeginUpdate();
            cbuffers.Nodes.Clear();
            if (shaderDetails != null)
            {
                UInt32 i = 0;
                foreach (var shaderCBuf in shaderDetails.ConstantBlocks)
                {
                    int bindPoint = stage.BindpointMapping.ConstantBlocks[i].bind;

                    bool filledSlot = !shaderCBuf.bufferBacked ||
                                      (bindPoint >= 0 && bindPoint < state.UniformBuffers.Length && state.UniformBuffers[bindPoint].Resource != ResourceId.Null);
                    bool usedSlot = stage.BindpointMapping.ConstantBlocks[i].used;

                    // 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    = shaderCBuf.name;
                        int    numvars = shaderCBuf.variables.Length;

                        string slotname = i.ToString();

                        var node = cbuffers.Nodes.Add(new object[] { slotname, name, bindPoint, "", numvars, "" });

                        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();
        }