From 3f4ec852ba17bc748f04efe7d1c7345f880a4b6d Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 24 Jun 2016 17:54:41 +0200 Subject: [PATCH] Pass through image layouts for vulkan and display in tooltips. Refs #199 * Semi experimental for now - I'm not convinced that having a tooltip for every image element is the best UI. It will need some iteration. --- renderdoc/api/replay/vk_pipestate.h | 16 +++++++ renderdoc/core/replay_proxy.cpp | 25 ++++++++++- renderdoc/driver/vulkan/vk_common.cpp | 21 ++++----- renderdoc/driver/vulkan/vk_replay.cpp | 24 +++++++++++ renderdocui/Code/CommonPipelineState.cs | 11 +++++ renderdocui/Interop/CustomMarshaling.cs | 9 ++-- renderdocui/Interop/VulkanPipelineState.cs | 37 ++++++++++++++++ .../VulkanPipelineStateViewer.Designer.cs | 2 + .../VulkanPipelineStateViewer.cs | 14 +++--- renderdocui/Windows/TextureViewer.Designer.cs | 43 +++++++++++++------ renderdocui/Windows/TextureViewer.cs | 10 +++++ 11 files changed, 179 insertions(+), 33 deletions(-) diff --git a/renderdoc/api/replay/vk_pipestate.h b/renderdoc/api/replay/vk_pipestate.h index 2612d5916..1e75e7c74 100644 --- a/renderdoc/api/replay/vk_pipestate.h +++ b/renderdoc/api/replay/vk_pipestate.h @@ -348,4 +348,20 @@ struct VulkanPipelineState int32_t x, y, width, height; } renderArea; } Pass; + + struct ImageData + { + ResourceId image; + + struct ImageLayout + { + uint32_t baseMip; + uint32_t baseLayer; + uint32_t numMip; + uint32_t numLayer; + rdctype::str name; + }; + rdctype::array layouts; + }; + rdctype::array images; }; diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index e04bf5b79..71684f9c7 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -962,6 +962,27 @@ void Serialiser::Serialise(const char *name, VulkanPipelineState::CurrentPass &e SIZE_CHECK(VulkanPipelineState::CurrentPass, 104); } +template <> +void Serialiser::Serialise(const char *name, VulkanPipelineState::ImageData::ImageLayout &el) +{ + Serialise("", el.baseMip); + Serialise("", el.baseLayer); + Serialise("", el.numMip); + Serialise("", el.numLayer); + Serialise("", el.name); + + SIZE_CHECK(VulkanPipelineState::ImageData::ImageLayout, 32); +} + +template <> +void Serialiser::Serialise(const char *name, VulkanPipelineState::ImageData &el) +{ + Serialise("", el.image); + Serialise("", el.layouts); + + SIZE_CHECK(VulkanPipelineState::ImageData, 24); +} + template <> void Serialiser::Serialise(const char *name, VulkanPipelineState &el) { @@ -987,7 +1008,9 @@ void Serialiser::Serialise(const char *name, VulkanPipelineState &el) Serialise("", el.DS); Serialise("", el.Pass); - SIZE_CHECK(VulkanPipelineState, 1456); + Serialise("", el.images); + + SIZE_CHECK(VulkanPipelineState, 1472); } #pragma endregion Vulkan pipeline state diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index 982bf67e5..66594754b 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -2225,16 +2225,17 @@ string ToStrHelper::Get(const VkImageLayout &el) { switch(el) { - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_UNDEFINED) - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_GENERAL) - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_PREINITIALIZED) - TOSTR_CASE_STRINGIZE(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) + case VK_IMAGE_LAYOUT_UNDEFINED: return "UNDEFINED"; + case VK_IMAGE_LAYOUT_GENERAL: return "GENERAL"; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: return "COLOR_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return "DEPTH_STENCIL_ATTACHMENT_OPTIMAL"; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return "DEPTH_STENCIL_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: return "SHADER_READ_ONLY_OPTIMAL"; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: return "TRANSFER_SRC_OPTIMAL"; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: return "TRANSFER_DST_OPTIMAL"; + case VK_IMAGE_LAYOUT_PREINITIALIZED: return "PREINITIALIZED"; + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: return "PRESENT_SRC_KHR"; default: break; } diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index eba4a5a6a..76261316a 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -3666,6 +3666,30 @@ void VulkanReplay::SavePipelineState() } } } + + // image layouts + { + create_array_uninit(m_VulkanPipelineState.images, m_pDriver->m_ImageLayouts.size()); + size_t i = 0; + for(auto it = m_pDriver->m_ImageLayouts.begin(); it != m_pDriver->m_ImageLayouts.end(); ++it) + { + VulkanPipelineState::ImageData &img = m_VulkanPipelineState.images[i]; + + img.image = rm->GetOriginalID(it->first); + + create_array_uninit(img.layouts, it->second.subresourceStates.size()); + for(size_t l = 0; l < it->second.subresourceStates.size(); l++) + { + img.layouts[l].name = ToStr::Get(it->second.subresourceStates[l].newLayout); + img.layouts[l].baseMip = it->second.subresourceStates[l].subresourceRange.baseMipLevel; + img.layouts[l].baseLayer = it->second.subresourceStates[l].subresourceRange.baseArrayLayer; + img.layouts[l].numLayer = it->second.subresourceStates[l].subresourceRange.layerCount; + img.layouts[l].numMip = it->second.subresourceStates[l].subresourceRange.levelCount; + } + + i++; + } + } } } diff --git a/renderdocui/Code/CommonPipelineState.cs b/renderdocui/Code/CommonPipelineState.cs index c0ebdb83f..f12db28d6 100644 --- a/renderdocui/Code/CommonPipelineState.cs +++ b/renderdocui/Code/CommonPipelineState.cs @@ -176,6 +176,17 @@ namespace renderdocui.Code } } + public string GetImageLayout(ResourceId id) + { + if (LogLoaded) + { + if (IsLogVK && m_Vulkan.Images.ContainsKey(id)) + return m_Vulkan.Images[id].layouts[0].name; + } + + return "Unknown"; + } + public string Abbrev(ShaderStageType stage) { if (IsLogD3D11 || (!LogLoaded && DefaultType == APIPipelineStateType.D3D11)) diff --git a/renderdocui/Interop/CustomMarshaling.cs b/renderdocui/Interop/CustomMarshaling.cs index a442bcb27..365151210 100644 --- a/renderdocui/Interop/CustomMarshaling.cs +++ b/renderdocui/Interop/CustomMarshaling.cs @@ -473,9 +473,6 @@ namespace renderdoc IntPtr fieldPtr = isUnion ? sourcePtr : OffsetPtr(structureType, fields, fieldIdx, sourcePtr); - var arrayType = NonArrayType(field.FieldType); - int sizeInBytes = SizeOf(arrayType); - // no custom attribute, so just use the regular Marshal code var cma = GetCustomAttr(structureType, fields, fieldIdx); if (cma == null) @@ -544,6 +541,9 @@ namespace renderdoc } else { + var arrayType = NonArrayType(field.FieldType); + int sizeInBytes = SizeOf(arrayType); + Array val = Array.CreateInstance(arrayType, cma.FixedLength); for (int i = 0; i < val.Length; i++) @@ -577,6 +577,9 @@ namespace renderdoc } else { + var arrayType = NonArrayType(field.FieldType); + int sizeInBytes = SizeOf(arrayType); + if (field.FieldType.IsArray && arrayType == typeof(byte)) { byte[] val = new byte[arr.count]; diff --git a/renderdocui/Interop/VulkanPipelineState.cs b/renderdocui/Interop/VulkanPipelineState.cs index c44953643..ac03df271 100644 --- a/renderdocui/Interop/VulkanPipelineState.cs +++ b/renderdocui/Interop/VulkanPipelineState.cs @@ -24,6 +24,7 @@ using System; using System.Runtime.InteropServices; +using System.Collections.Generic; namespace renderdoc { @@ -408,5 +409,41 @@ namespace renderdoc }; [CustomMarshalAs(CustomUnmanagedType.CustomClass)] public CurrentPass Pass; + + [StructLayout(LayoutKind.Sequential)] + public class ImageData + { + public ResourceId image; + + [StructLayout(LayoutKind.Sequential)] + public class ImageLayout + { + public UInt32 baseMip; + public UInt32 baseLayer; + public UInt32 numMip; + public UInt32 numLayer; + + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string name; + }; + + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public ImageLayout[] layouts; + }; + + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + private ImageData[] images_; + + // add to dictionary for convenience + private void PostMarshal() + { + Images = new Dictionary(); + + foreach (ImageData i in images_) + Images.Add(i.image, i); + } + + [CustomMarshalAs(CustomUnmanagedType.Skip)] + public Dictionary Images; }; } diff --git a/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.Designer.cs b/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.Designer.cs index 036a01419..8e7ae33a8 100644 --- a/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.Designer.cs +++ b/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.Designer.cs @@ -2607,6 +2607,8 @@ this.targetOutputs.KeyDown += new System.Windows.Forms.KeyEventHandler(this.defaultCopyPaste_KeyDown); this.targetOutputs.Leave += new System.EventHandler(this.disableSelection_Leave); this.targetOutputs.MouseClick += new System.Windows.Forms.MouseEventHandler(this.hideDisabledEmpty_MouseClick); + this.targetOutputs.MouseLeave += new System.EventHandler(this.resource_MouseLeave); + this.targetOutputs.MouseMove += new System.Windows.Forms.MouseEventHandler(this.resource_MouseMove); // // groupBox37 // diff --git a/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs b/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs index 6d0565548..5b5b8e581 100644 --- a/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/VulkanPipelineStateViewer.cs @@ -253,9 +253,10 @@ namespace renderdocui.Windows.PipelineState node.Italic = true; } - private void ViewDetailsRow(TreelistView.Node node) + private void ViewDetailsRow(TreelistView.Node node, bool highlight) { - node.BackColor = Color.Aquamarine; + if(highlight) + node.BackColor = Color.Aquamarine; m_ViewDetailNodes.Add(node); } @@ -726,8 +727,7 @@ namespace renderdocui.Windows.PipelineState if (!usedSlot) InactiveRow(node); - if (viewDetails) - ViewDetailsRow(node); + ViewDetailsRow(node, viewDetails); } if (bindType == ShaderBindType.ImageSampler) @@ -1620,8 +1620,7 @@ namespace renderdocui.Windows.PipelineState { targets[i] = true; - if (viewDetails) - ViewDetailsRow(node); + ViewDetailsRow(node, viewDetails); } } @@ -1849,6 +1848,9 @@ namespace renderdocui.Windows.PipelineState if (tex != null) { + if(m_Core.CurVulkanPipelineState.Images.ContainsKey(tex.tex.ID)) + text += String.Format("Texture is in the '{0}' layout\n\n", m_Core.CurVulkanPipelineState.Images[tex.tex.ID].layouts[0].name); + if (tex.tex.format != tex.fmt) text += String.Format("The texture is format {0}, the view treats it as {1}.\n", tex.tex.format, tex.fmt); diff --git a/renderdocui/Windows/TextureViewer.Designer.cs b/renderdocui/Windows/TextureViewer.Designer.cs index 95efcc584..a4419d903 100644 --- a/renderdocui/Windows/TextureViewer.Designer.cs +++ b/renderdocui/Windows/TextureViewer.Designer.cs @@ -76,6 +76,7 @@ this.stencilDisplay = new System.Windows.Forms.RadioButton(); this.zoomStrip = new System.Windows.Forms.ToolStrip(); this.toolStripLabel4 = new System.Windows.Forms.ToolStripLabel(); + this.zoomExactSize = new System.Windows.Forms.ToolStripButton(); this.fitToWindow = new System.Windows.Forms.ToolStripButton(); this.zoomOption = new System.Windows.Forms.ToolStripComboBox(); this.flip_y = new System.Windows.Forms.ToolStripButton(); @@ -148,7 +149,8 @@ this.pixelContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components); this.highlightedPixelHistoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.highlightedPixelDebugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.zoomExactSize = new System.Windows.Forms.ToolStripButton(); + this.imageInLayoutMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); subSep = new System.Windows.Forms.ToolStripSeparator(); toolStripLabel2 = new System.Windows.Forms.ToolStripLabel(); toolStripLabel3 = new System.Windows.Forms.ToolStripLabel(); @@ -213,10 +215,12 @@ this.showEmpty, this.usedSep, this.openNewTab, + this.toolStripSeparator1, + this.imageInLayoutMenuItem, this.usedStartLabel}); this.rightclickMenu.MaximumSize = new System.Drawing.Size(0, 480); this.rightclickMenu.Name = "rightclickMenu"; - this.rightclickMenu.Size = new System.Drawing.Size(181, 98); + this.rightclickMenu.Size = new System.Drawing.Size(181, 148); // // showDisabled // @@ -481,7 +485,7 @@ this.zoomStrip.Location = new System.Drawing.Point(0, 50); this.zoomStrip.Margin = new System.Windows.Forms.Padding(0, 0, 12, 0); this.zoomStrip.Name = "zoomStrip"; - this.zoomStrip.Size = new System.Drawing.Size(285, 25); + this.zoomStrip.Size = new System.Drawing.Size(254, 25); this.zoomStrip.TabIndex = 2; // // toolStripLabel4 @@ -490,6 +494,16 @@ this.toolStripLabel4.Size = new System.Drawing.Size(33, 22); this.toolStripLabel4.Text = "Zoom"; // + // zoomExactSize + // + this.zoomExactSize.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.zoomExactSize.Image = ((System.Drawing.Image)(resources.GetObject("zoomExactSize.Image"))); + this.zoomExactSize.ImageTransparentColor = System.Drawing.Color.Magenta; + this.zoomExactSize.Name = "zoomExactSize"; + this.zoomExactSize.Size = new System.Drawing.Size(27, 22); + this.zoomExactSize.Text = "1:1"; + this.zoomExactSize.Click += new System.EventHandler(this.zoomExactSize_Click); + // // fitToWindow // this.fitToWindow.Checked = true; @@ -538,7 +552,7 @@ this.overlayStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripLabel5, this.overlay}); - this.overlayStrip.Location = new System.Drawing.Point(297, 50); + this.overlayStrip.Location = new System.Drawing.Point(266, 50); this.overlayStrip.Margin = new System.Windows.Forms.Padding(0, 0, 12, 0); this.overlayStrip.Name = "overlayStrip"; this.overlayStrip.Size = new System.Drawing.Size(171, 25); @@ -633,7 +647,7 @@ this.autoFit, this.reset01, this.visualiseRange}); - this.rangeStrip.Location = new System.Drawing.Point(480, 50); + this.rangeStrip.Location = new System.Drawing.Point(449, 50); this.rangeStrip.Margin = new System.Windows.Forms.Padding(0, 0, 12, 0); this.rangeStrip.Name = "rangeStrip"; this.rangeStrip.Size = new System.Drawing.Size(337, 25); @@ -1318,15 +1332,16 @@ this.highlightedPixelDebugToolStripMenuItem.Text = "Highlighted Pixel &Debug"; this.highlightedPixelDebugToolStripMenuItem.Click += new System.EventHandler(this.debugPixel_Click); // - // zoomExactSize + // imageInLayoutMenuItem // - this.zoomExactSize.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.zoomExactSize.Image = ((System.Drawing.Image)(resources.GetObject("zoomExactSize.Image"))); - this.zoomExactSize.ImageTransparentColor = System.Drawing.Color.Magenta; - this.zoomExactSize.Name = "zoomExactSize"; - this.zoomExactSize.Size = new System.Drawing.Size(27, 22); - this.zoomExactSize.Text = "1:1"; - this.zoomExactSize.Click += new System.EventHandler(this.zoomExactSize_Click); + this.imageInLayoutMenuItem.Name = "imageInLayoutMenuItem"; + this.imageInLayoutMenuItem.Size = new System.Drawing.Size(180, 22); + this.imageInLayoutMenuItem.Text = "Image in layout "; + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(177, 6); // // TextureViewer // @@ -1490,6 +1505,8 @@ private System.Windows.Forms.ToolStripMenuItem highlightedPixelDebugToolStripMenuItem; private System.Windows.Forms.ToolStripButton viewTexBuffer; private System.Windows.Forms.ToolStripButton zoomExactSize; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem imageInLayoutMenuItem; } } \ No newline at end of file diff --git a/renderdocui/Windows/TextureViewer.cs b/renderdocui/Windows/TextureViewer.cs index 7e4eb426f..7d0556e30 100644 --- a/renderdocui/Windows/TextureViewer.cs +++ b/renderdocui/Windows/TextureViewer.cs @@ -3546,6 +3546,16 @@ namespace renderdocui.Windows menuItems[i].Visible = thumbStripMenu; } + if (m_Core.CurPipelineState.SupportsBarriers) + { + imageInLayoutMenuItem.Visible = true; + imageInLayoutMenuItem.Text = "Image is in layout " + m_Core.CurPipelineState.GetImageLayout(id); + } + else + { + imageInLayoutMenuItem.Visible = false; + } + if (id != ResourceId.Null) { usedSep.Visible = true;