public Dictionary <BindpointMap, BoundResource[]> GetReadOnlyResources(ShaderStageType stage) { var ret = new Dictionary <BindpointMap, BoundResource[]>(); if (LogLoaded) { if (IsLogD3D11) { D3D11PipelineState.ShaderStage s = null; switch (stage) { case ShaderStageType.Vertex: s = m_D3D11.m_VS; break; case ShaderStageType.Domain: s = m_D3D11.m_DS; break; case ShaderStageType.Hull: s = m_D3D11.m_HS; break; case ShaderStageType.Geometry: s = m_D3D11.m_GS; break; case ShaderStageType.Pixel: s = m_D3D11.m_PS; break; case ShaderStageType.Compute: s = m_D3D11.m_CS; break; } for (int i = 0; i < s.SRVs.Length; i++) { var key = new BindpointMap(0, i); var val = new BoundResource(); val.Id = s.SRVs[i].Resource; val.HighestMip = (int)s.SRVs[i].HighestMip; val.FirstSlice = (int)s.SRVs[i].FirstArraySlice; ret.Add(key, new BoundResource[] { val }); } return(ret); } else if (IsLogGL) { for (int i = 0; i < m_GL.Textures.Length; i++) { var key = new BindpointMap(0, i); var val = new BoundResource(); val.Id = m_GL.Textures[i].Resource; val.HighestMip = (int)m_GL.Textures[i].HighestMip; val.FirstSlice = (int)m_GL.Textures[i].FirstSlice; ret.Add(key, new BoundResource[] { val }); } return(ret); } else if (IsLogVK) { VulkanPipelineState.Pipeline.DescriptorSet[] descsets = m_Vulkan.graphics.DescSets; if (stage == ShaderStageType.Compute) { descsets = m_Vulkan.compute.DescSets; } ShaderStageBits mask = (ShaderStageBits)(1 << (int)stage); for (int set = 0; set < m_Vulkan.graphics.DescSets.Length; set++) { var descset = m_Vulkan.graphics.DescSets[set]; for (int slot = 0; slot < descset.bindings.Length; slot++) { var bind = descset.bindings[slot]; if ((bind.type == ShaderBindType.ImageSampler || bind.type == ShaderBindType.InputAttachment || bind.type == ShaderBindType.ReadOnlyImage || bind.type == ShaderBindType.ReadOnlyTBuffer ) && (bind.stageFlags & mask) == mask) { var key = new BindpointMap(set, slot); var val = new BoundResource[bind.descriptorCount]; for (UInt32 i = 0; i < bind.descriptorCount; i++) { val[i] = new BoundResource(); val[i].Id = bind.binds[i].res; val[i].HighestMip = (int)bind.binds[i].baseMip; val[i].FirstSlice = (int)bind.binds[i].baseLayer; } ret.Add(key, val); } } } return(ret); } } return(ret); }
public Dictionary <BindpointMap, BoundResource[]> GetReadWriteResources(ShaderStageType stage) { var ret = new Dictionary <BindpointMap, BoundResource[]>(); if (LogLoaded) { if (IsLogD3D11) { if (stage == ShaderStageType.Compute) { for (int i = 0; i < m_D3D11.m_CS.UAVs.Length; i++) { var key = new BindpointMap(0, i); var val = new BoundResource(); val.Id = m_D3D11.m_CS.UAVs[i].Resource; val.HighestMip = (int)m_D3D11.m_CS.UAVs[i].HighestMip; val.FirstSlice = (int)m_D3D11.m_CS.UAVs[i].FirstArraySlice; ret.Add(key, new BoundResource[] { val }); } } else { for (int i = 0; i < m_D3D11.m_OM.UAVs.Length; i++) { var key = new BindpointMap(0, i); var val = new BoundResource(); val.Id = m_D3D11.m_OM.UAVs[i].Resource; val.HighestMip = (int)m_D3D11.m_OM.UAVs[i].HighestMip; val.FirstSlice = (int)m_D3D11.m_OM.UAVs[i].FirstArraySlice; ret.Add(key, new BoundResource[] { val }); } } return(ret); } else if (IsLogGL) { for (int i = 0; i < m_GL.Images.Length; i++) { var key = new BindpointMap(0, i); var val = new BoundResource(); val.Id = m_GL.Images[i].Resource; val.HighestMip = (int)m_GL.Images[i].Level; val.FirstSlice = (int)m_GL.Images[i].Layer; ret.Add(key, new BoundResource[] { val }); } return(ret); } else if (IsLogVK) { VulkanPipelineState.Pipeline.DescriptorSet[] descsets = m_Vulkan.graphics.DescSets; if (stage == ShaderStageType.Compute) { descsets = m_Vulkan.compute.DescSets; } ShaderStageBits mask = (ShaderStageBits)(1 << (int)stage); for (int set = 0; set < descsets.Length; set++) { var descset = descsets[set]; for (int slot = 0; slot < descset.bindings.Length; slot++) { var bind = descset.bindings[slot]; if ((bind.type == ShaderBindType.ReadWriteBuffer || bind.type == ShaderBindType.ReadWriteImage || bind.type == ShaderBindType.ReadWriteTBuffer ) && (bind.stageFlags & mask) == mask) { var key = new BindpointMap(set, slot); var val = new BoundResource[bind.descriptorCount]; for (UInt32 i = 0; i < bind.descriptorCount; i++) { val[i] = new BoundResource(); val[i].Id = bind.binds[i].res; val[i].HighestMip = (int)bind.binds[i].baseMip; val[i].FirstSlice = (int)bind.binds[i].baseLayer; } ret.Add(key, val); } } } return(ret); } } return(ret); }
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; //} } }