From 947f7decb21b3082cfbc53dcef8d69a40b014d83 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 3 Jun 2016 17:34:26 +0200 Subject: [PATCH] Add 'show all instances' mode, and make colours consistent. Closes #248 --- docs/window/buffer_viewer.rst | 8 +++ renderdoc/api/replay/control_types.h | 9 +-- renderdoc/core/replay_proxy.cpp | 8 ++- renderdoc/driver/d3d11/d3d11_debug.cpp | 14 ++-- renderdoc/driver/gl/gl_debug.cpp | 13 +--- renderdoc/driver/vulkan/vk_debug.cpp | 2 + renderdoc/driver/vulkan/vk_debug.h | 3 + renderdoc/driver/vulkan/vk_replay.cpp | 76 +++++++++++++++----- renderdoc/replay/replay_output.cpp | 41 ++++++++--- renderdocui/Interop/FetchInfo.cs | 9 +-- renderdocui/Windows/BufferViewer.Designer.cs | 4 +- renderdocui/Windows/BufferViewer.cs | 18 +++-- 12 files changed, 144 insertions(+), 61 deletions(-) diff --git a/docs/window/buffer_viewer.rst b/docs/window/buffer_viewer.rst index 1bd3ad3a3..984b82a82 100644 --- a/docs/window/buffer_viewer.rst +++ b/docs/window/buffer_viewer.rst @@ -59,6 +59,14 @@ You can also use this if the position data isn't detected in your inputs and you Preview: Previewing the uv co-ordinates as colour on the mesh. +When displaying the post-projection output - typically the VS output, but possibly tessellation/geometry output - you can select how much data to display. + +The dropdown above the mesh view will let you choose ``Only this draw``, ``Show previous instances``, ``Show all instances``, or ``Show whole pass``. + +These let you narrow or expand the mesh outputs displayed. At minimum you will see the current draw - a specific instance, if the drawcall is an instanced draw. You can also display other instances in the same drawcall (either up to the selected instance, or all instances before or after the selected instance). Finally you can opt to display all other meshes up to the current draw in the same notional render pass. + +The current draw is always dark tinted, instances within the same draw have a lighter red colour, and other drawcalls in the pass will be light grey. + Raw Buffer Viewer ----------------- diff --git a/renderdoc/api/replay/control_types.h b/renderdoc/api/replay/control_types.h index d8e2dc240..f8e83ad1a 100644 --- a/renderdoc/api/replay/control_types.h +++ b/renderdoc/api/replay/control_types.h @@ -50,6 +50,8 @@ struct MeshFormat bool32 bgraOrder; SpecialFormat specialFormat; + FloatVector meshColour; + bool showAlpha; PrimitiveTopology topo; @@ -71,16 +73,15 @@ struct MeshDisplay bool32 ortho; float fov, aspect; - bool32 thisDrawOnly; + bool32 showPrevInstances; + bool32 showAllInstances; + bool32 showWholePass; uint32_t curInstance; uint32_t highlightVert; MeshFormat position; MeshFormat second; - FloatVector prevMeshColour; - FloatVector currentMeshColour; - FloatVector minBounds; FloatVector maxBounds; bool32 showBBox; diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 29755ea8c..f3d4153fa 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -1310,6 +1310,7 @@ void Serialiser::Serialise(const char *name, MeshFormat &el) Serialise("", el.compType); Serialise("", el.bgraOrder); Serialise("", el.specialFormat); + Serialise("", el.meshColour); Serialise("", el.showAlpha); Serialise("", el.topo); Serialise("", el.numVerts); @@ -1317,7 +1318,7 @@ void Serialiser::Serialise(const char *name, MeshFormat &el) Serialise("", el.nearPlane); Serialise("", el.farPlane); - SIZE_CHECK(MeshFormat, 88); + SIZE_CHECK(MeshFormat, 104); } template <> @@ -1609,6 +1610,11 @@ string ToStrHelper::Get(const ReplayLogType &el) { return "<...>"; } +template <> +string ToStrHelper::Get(const FloatVector &el) +{ + return "<...>"; +} #pragma endregion Plain - old data structures diff --git a/renderdoc/driver/d3d11/d3d11_debug.cpp b/renderdoc/driver/d3d11/d3d11_debug.cpp index c21b370f8..1501c0af7 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.cpp +++ b/renderdoc/driver/d3d11/d3d11_debug.cpp @@ -4773,9 +4773,6 @@ void D3D11DebugManager::RenderMesh(uint32_t eventID, const vector &s m_pImmediateContext->IASetInputLayout(m_DebugRender.GenericHomogLayout); pixelData.OutputDisplayFormat = MESHDISPLAY_SOLID; - pixelData.WireframeColour = - Vec3f(cfg.prevMeshColour.x, cfg.prevMeshColour.y, cfg.prevMeshColour.z); - FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData)); for(size_t i = 0; i < secondaryDraws.size(); i++) { @@ -4783,6 +4780,10 @@ void D3D11DebugManager::RenderMesh(uint32_t eventID, const vector &s if(fmt.buf != ResourceId()) { + pixelData.WireframeColour = Vec3f(fmt.meshColour.x, fmt.meshColour.y, fmt.meshColour.z); + FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, + sizeof(DebugPixelCBufferData)); + m_pImmediateContext->IASetPrimitiveTopology(MakeD3D11PrimitiveTopology(fmt.topo)); auto it = WrappedID3D11Buffer::m_BufferList.find(fmt.buf); @@ -4898,11 +4899,8 @@ void D3D11DebugManager::RenderMesh(uint32_t eventID, const vector &s m_pImmediateContext->OMSetDepthStencilState(m_DebugRender.LEqualDepthState, 0); pixelData.OutputDisplayFormat = MESHDISPLAY_SOLID; - if(secondaryDraws.size() > 0 && cfg.solidShadeMode == eShade_None) - pixelData.WireframeColour = - Vec3f(cfg.currentMeshColour.x, cfg.currentMeshColour.y, cfg.currentMeshColour.z); - else - pixelData.WireframeColour = Vec3f(0.0f, 0.0f, 0.0f); + pixelData.WireframeColour = + Vec3f(cfg.position.meshColour.x, cfg.position.meshColour.y, cfg.position.meshColour.z); FillCBuffer(m_DebugRender.GenericPSCBuffer, (float *)&pixelData, sizeof(DebugPixelCBufferData)); m_pImmediateContext->PSSetConstantBuffers(0, 1, &m_DebugRender.GenericPSCBuffer); diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index 65b35b561..16860e5ca 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -3541,8 +3541,6 @@ void GLReplay::RenderMesh(uint32_t eventID, const vector &secondaryD if(!secondaryDraws.empty()) { - gl.glUniform4fv(colLoc, 1, &cfg.prevMeshColour.x); - gl.glUniform1ui(fmtLoc, MESHDISPLAY_SOLID); gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_LINE); @@ -3558,6 +3556,8 @@ void GLReplay::RenderMesh(uint32_t eventID, const vector &secondaryD if(fmt.buf != ResourceId()) { + gl.glUniform4fv(colLoc, 1, &fmt.meshColour.x); + GLuint vb = m_pDriver->GetResourceManager()->GetCurrentResource(fmt.buf).name; gl.glBindVertexBuffer(0, vb, (GLintptr)fmt.offset, fmt.stride); @@ -3761,14 +3761,7 @@ void GLReplay::RenderMesh(uint32_t eventID, const vector &secondaryD // wireframe render if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw || topo == eGL_PATCHES) { - float wireCol[] = {0.0f, 0.0f, 0.0f, 1.0f}; - if(!secondaryDraws.empty()) - { - wireCol[0] = cfg.currentMeshColour.x; - wireCol[1] = cfg.currentMeshColour.y; - wireCol[2] = cfg.currentMeshColour.z; - } - gl.glUniform4fv(colLoc, 1, wireCol); + gl.glUniform4fv(colLoc, 1, &cfg.position.meshColour.x); gl.glUniform1ui(fmtLoc, MESHDISPLAY_SOLID); diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index 7cbe5ab41..7332a717b 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -49,6 +49,8 @@ void VulkanDebugManager::GPUBuffer::Create(WrappedVulkan *driver, VkDevice dev, totalsize = ringSize == 1 ? size : AlignUp(size, align) * ringSize; curoffset = 0; + ringCount = ringSize; + VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, 0, totalsize, 0, }; diff --git a/renderdoc/driver/vulkan/vk_debug.h b/renderdoc/driver/vulkan/vk_debug.h index 284da33a8..a1cae5b49 100644 --- a/renderdoc/driver/vulkan/vk_debug.h +++ b/renderdoc/driver/vulkan/vk_debug.h @@ -144,6 +144,7 @@ public: void FillDescriptor(VkDescriptorBufferInfo &desc); + size_t GetRingCount() { return size_t(ringCount); } void *Map(VkDeviceSize &bindoffset, VkDeviceSize usedsize = 0); void *Map(uint32_t *bindoffset = NULL, VkDeviceSize usedsize = 0); void Unmap(); @@ -159,6 +160,8 @@ public: VkDeviceSize totalsize; VkDeviceSize curoffset; + uint32_t ringCount; + WrappedVulkan *m_pDriver; VkDevice device; }; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 9a15f007a..f7341e32f 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -1719,17 +1719,7 @@ void VulkanReplay::RenderMesh(uint32_t eventID, const vector &second if(!secondaryDraws.empty()) { - uint32_t uboOffs = 0; - MeshUBOData *data = (MeshUBOData *)GetDebugManager()->m_MeshUBO.Map(&uboOffs); - - data->mvp = ModelViewProj; - data->color = Vec4f(cfg.prevMeshColour.x, cfg.prevMeshColour.y, cfg.prevMeshColour.z, - cfg.prevMeshColour.w); - data->homogenousInput = cfg.position.unproject; - data->pointSpriteSize = Vec2f(0.0f, 0.0f); - data->displayFormat = MESHDISPLAY_SOLID; - - GetDebugManager()->m_MeshUBO.Unmap(); + size_t mapsUsed = 0; for(size_t i = 0; i < secondaryDraws.size(); i++) { @@ -1737,6 +1727,42 @@ void VulkanReplay::RenderMesh(uint32_t eventID, const vector &second if(fmt.buf != ResourceId()) { + // TODO should move the color to a push constant so we don't have to map all the time + uint32_t uboOffs = 0; + MeshUBOData *data = (MeshUBOData *)GetDebugManager()->m_MeshUBO.Map(&uboOffs); + + data->mvp = ModelViewProj; + data->color = Vec4f(fmt.meshColour.x, fmt.meshColour.y, fmt.meshColour.z, fmt.meshColour.w); + data->homogenousInput = cfg.position.unproject; + data->pointSpriteSize = Vec2f(0.0f, 0.0f); + data->displayFormat = MESHDISPLAY_SOLID; + + GetDebugManager()->m_MeshUBO.Unmap(); + + mapsUsed++; + + if(mapsUsed + 1 >= GetDebugManager()->m_MeshUBO.GetRingCount()) + { + // flush and sync so we can use more maps + vt->CmdEndRenderPass(Unwrap(cmd)); + + vkr = vt->EndCommandBuffer(Unwrap(cmd)); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + + m_pDriver->SubmitCmds(); + m_pDriver->FlushQ(); + + mapsUsed = 0; + + cmd = m_pDriver->GetNextCmd(); + + vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE); + + vt->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport); + } + MeshDisplayPipelines secondaryCache = GetDebugManager()->CacheMeshDisplayPipelines(secondaryDraws[i], secondaryDraws[i]); @@ -1772,6 +1798,25 @@ void VulkanReplay::RenderMesh(uint32_t eventID, const vector &second } } } + + { + // flush and sync so we can use more maps + vt->CmdEndRenderPass(Unwrap(cmd)); + + vkr = vt->EndCommandBuffer(Unwrap(cmd)); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + + m_pDriver->SubmitCmds(); + m_pDriver->FlushQ(); + + cmd = m_pDriver->GetNextCmd(); + + vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + vt->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE); + + vt->CmdSetViewport(Unwrap(cmd), 0, 1, &viewport); + } } MeshDisplayPipelines cache = GetDebugManager()->CacheMeshDisplayPipelines(cfg.position, cfg.second); @@ -1857,13 +1902,8 @@ void VulkanReplay::RenderMesh(uint32_t eventID, const vector &second if(cfg.solidShadeMode == eShade_None || cfg.wireframeDraw || cfg.position.topo >= eTopology_PatchList) { - Vec4f wireCol = Vec4f(0.0f, 0.0f, 0.0f, 1.0f); - if(!secondaryDraws.empty()) - { - wireCol.x = cfg.currentMeshColour.x; - wireCol.y = cfg.currentMeshColour.y; - wireCol.z = cfg.currentMeshColour.z; - } + Vec4f wireCol = + Vec4f(cfg.position.meshColour.x, cfg.position.meshColour.y, cfg.position.meshColour.z, 1.0f); uint32_t uboOffs = 0; MeshUBOData *data = (MeshUBOData *)GetDebugManager()->m_MeshUBO.Map(&uboOffs); diff --git a/renderdoc/replay/replay_output.cpp b/renderdoc/replay/replay_output.cpp index 60dec0174..1c25f3b4e 100644 --- a/renderdoc/replay/replay_output.cpp +++ b/renderdoc/replay/replay_output.cpp @@ -106,7 +106,7 @@ bool ReplayOutput::SetTextureDisplay(const TextureDisplay &o) bool ReplayOutput::SetMeshDisplay(const MeshDisplay &o) { - if(o.thisDrawOnly != m_RenderData.meshDisplay.thisDrawOnly) + if(o.showWholePass != m_RenderData.meshDisplay.showWholePass) m_OverlayDirty = true; m_RenderData.meshDisplay = o; m_MainOutput.dirty = true; @@ -158,7 +158,7 @@ void ReplayOutput::RefreshOverlay() m_pDevice->InitPostVSBuffers(draw->eventID); - if(!m_RenderData.meshDisplay.thisDrawOnly && !passEvents.empty()) + if(!m_RenderData.meshDisplay.showWholePass && !passEvents.empty()) { m_pDevice->InitPostVSBuffers(passEvents); @@ -583,12 +583,23 @@ void ReplayOutput::DisplayMesh() vector secondaryDraws; - if(m_RenderData.meshDisplay.type != eMeshDataStage_VSIn && !m_RenderData.meshDisplay.thisDrawOnly) - { - mesh.position.unproject = true; - mesh.second.unproject = true; + // we choose a pallette here so that the colours stay consistent (i.e the + // current draw is always the same colour), but also to indicate somewhat + // the relationship - ie. instances are closer in colour than other draws + // in the pass - for(size_t i = 0; i < passEvents.size(); i++) + // very slightly dark red + const FloatVector drawItself(0.06f, 0.0f, 0.0f, 1.0f); + + // more desaturated/lighter, but still reddish + const FloatVector otherInstances(0.18f, 0.1f, 0.1f, 1.0f); + + // lighter grey with blue tinge to contrast from main/instance draws + const FloatVector passDraws(0.2f, 0.2f, 0.25f, 1.0f); + + if(m_RenderData.meshDisplay.type != eMeshDataStage_VSIn) + { + for(size_t i = 0; m_RenderData.meshDisplay.showWholePass && i < passEvents.size(); i++) { FetchDrawcall *d = m_pRenderer->GetDrawcallByEID(passEvents[i], m_LastDeferredEvent); @@ -601,6 +612,8 @@ void ReplayOutput::DisplayMesh() if(fmt.buf == ResourceId()) fmt = m_pDevice->GetPostVSBuffers(passEvents[i], inst, eMeshDataStage_VSOut); + fmt.meshColour = passDraws; + // if unproject is marked, this output had a 'real' system position output if(fmt.unproject) secondaryDraws.push_back(fmt); @@ -611,15 +624,21 @@ void ReplayOutput::DisplayMesh() // draw previous instances in the current drawcall if(draw->flags & eDraw_Instanced) { - for(uint32_t inst = 0; - inst < RDCMAX(1U, draw->numInstances) && inst < m_RenderData.meshDisplay.curInstance; - inst++) + uint32_t maxInst = 0; + if(m_RenderData.meshDisplay.showPrevInstances) + maxInst = RDCMAX(1U, m_RenderData.meshDisplay.curInstance); + if(m_RenderData.meshDisplay.showAllInstances) + maxInst = RDCMAX(1U, draw->numInstances); + + for(uint32_t inst = 0; inst < maxInst; inst++) { // get the 'most final' stage MeshFormat fmt = m_pDevice->GetPostVSBuffers(draw->eventID, inst, eMeshDataStage_GSOut); if(fmt.buf == ResourceId()) fmt = m_pDevice->GetPostVSBuffers(draw->eventID, inst, eMeshDataStage_VSOut); + fmt.meshColour = otherInstances; + // if unproject is marked, this output had a 'real' system position output if(fmt.unproject) secondaryDraws.push_back(fmt); @@ -627,6 +646,8 @@ void ReplayOutput::DisplayMesh() } } + mesh.position.meshColour = drawItself; + m_pDevice->RenderMesh(m_EventID, secondaryDraws, mesh); } diff --git a/renderdocui/Interop/FetchInfo.cs b/renderdocui/Interop/FetchInfo.cs index 4ffe5f238..ebae2f516 100644 --- a/renderdocui/Interop/FetchInfo.cs +++ b/renderdocui/Interop/FetchInfo.cs @@ -601,6 +601,8 @@ namespace renderdoc public bool bgraOrder; public SpecialFormat specialFormat; + public FloatVector meshColour; + public bool showAlpha; public PrimitiveTopology topo; @@ -622,16 +624,15 @@ namespace renderdoc public float fov = 90.0f; public float aspect = 0.0f; - public bool thisDrawOnly = true; + public bool showPrevInstances = false; + public bool showAllInstances = false; + public bool showWholePass = false; public UInt32 curInstance = 0; public UInt32 highlightVert; public MeshFormat position; public MeshFormat secondary; - public FloatVector prevMeshColour = new FloatVector(); - public FloatVector currentMeshColour = new FloatVector(); - public FloatVector minBounds = new FloatVector(); public FloatVector maxBounds = new FloatVector(); public bool showBBox = false; diff --git a/renderdocui/Windows/BufferViewer.Designer.cs b/renderdocui/Windows/BufferViewer.Designer.cs index 2c89e02f5..33c8be1d5 100644 --- a/renderdocui/Windows/BufferViewer.Designer.cs +++ b/renderdocui/Windows/BufferViewer.Designer.cs @@ -463,9 +463,11 @@ this.drawRange.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.drawRange.Items.AddRange(new object[] { "Only this draw", + "Show previous instances", + "Show all instances", "Show whole pass"}); this.drawRange.Name = "drawRange"; - this.drawRange.Size = new System.Drawing.Size(121, 25); + this.drawRange.Size = new System.Drawing.Size(140, 25); this.drawRange.SelectedIndexChanged += new System.EventHandler(this.drawRange_SelectedIndexChanged); // // toolStripSeparator4 diff --git a/renderdocui/Windows/BufferViewer.cs b/renderdocui/Windows/BufferViewer.cs index f4479c0b0..32d81d23a 100644 --- a/renderdocui/Windows/BufferViewer.cs +++ b/renderdocui/Windows/BufferViewer.cs @@ -303,12 +303,11 @@ namespace renderdocui.Windows m_MeshDisplay.solidShadeMode = SolidShadeMode.None; solidShading.SelectedIndex = 0; - m_MeshDisplay.thisDrawOnly = true; + m_MeshDisplay.showPrevInstances = false; + m_MeshDisplay.showAllInstances = false; + m_MeshDisplay.showWholePass = false; drawRange.SelectedIndex = 0; - m_MeshDisplay.currentMeshColour = new FloatVector(1, 0, 0, 1); - m_MeshDisplay.prevMeshColour = new FloatVector(0, 0, 0, 1); - if (m_Arcball != null) m_Arcball.Camera.Shutdown(); if (m_Flycam != null) @@ -2990,7 +2989,16 @@ namespace renderdocui.Windows private void drawRange_SelectedIndexChanged(object sender, EventArgs e) { - m_MeshDisplay.thisDrawOnly = (drawRange.SelectedIndex == 0); + /* + "Only this draw", + "Show previous instances", + "Show all instances", + "Show whole pass" + */ + + m_MeshDisplay.showPrevInstances = (drawRange.SelectedIndex >= 1); + m_MeshDisplay.showAllInstances = (drawRange.SelectedIndex >= 2); + m_MeshDisplay.showWholePass = (drawRange.SelectedIndex >= 3); render.Invalidate(); }