From 87adee1bf100878fd92ae3a6529a8c74f62bfd78 Mon Sep 17 00:00:00 2001 From: Steve Legg Date: Thu, 19 Jan 2017 23:42:26 +0000 Subject: [PATCH] Implement multi-instance mesh picking --- qrenderdoc/Windows/BufferViewer.cpp | 5 +-- renderdoc/api/replay/renderdoc_replay.h | 5 +-- renderdoc/replay/replay_output.cpp | 41 ++++++++++++++++++++++--- renderdoc/replay/replay_renderer.h | 2 +- renderdocui/Interop/ReplayRenderer.cs | 13 ++++++-- renderdocui/Windows/BufferViewer.cs | 12 +++++++- 6 files changed, 65 insertions(+), 13 deletions(-) diff --git a/qrenderdoc/Windows/BufferViewer.cpp b/qrenderdoc/Windows/BufferViewer.cpp index e1b93e028..5120cb7a5 100644 --- a/qrenderdoc/Windows/BufferViewer.cpp +++ b/qrenderdoc/Windows/BufferViewer.cpp @@ -739,8 +739,9 @@ void BufferViewer::render_clicked(QMouseEvent *e) if((e->buttons() & Qt::RightButton) && m_Output) { m_Ctx->Renderer()->AsyncInvoke([this, curpos](IReplayRenderer *r) { - uint32_t vertSelected = - m_Output->PickVertex(m_Ctx->CurEvent(), (uint32_t)curpos.x(), (uint32_t)curpos.y()); + uint32_t instanceSelected = 0; + uint32_t vertSelected = m_Output->PickVertex(m_Ctx->CurEvent(), (uint32_t)curpos.x(), + (uint32_t)curpos.y(), &instanceSelected); if(vertSelected != ~0U) { diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index 95db97cb4..fb725ede5 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -170,7 +170,7 @@ struct IReplayOutput virtual ResourceId GetCustomShaderTexID() = 0; virtual bool PickPixel(ResourceId texID, bool customShader, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, PixelValue *val) = 0; - virtual uint32_t PickVertex(uint32_t eventID, uint32_t x, uint32_t y) = 0; + virtual uint32_t PickVertex(uint32_t eventID, uint32_t x, uint32_t y, uint32_t *pickedInstance) = 0; }; #endif @@ -224,7 +224,8 @@ extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayOutput_PickPixel( uint32_t sliceFace, uint32_t mip, uint32_t sample, PixelValue *val); extern "C" RENDERDOC_API uint32_t RENDERDOC_CC ReplayOutput_PickVertex(ReplayOutput *output, uint32_t eventID, uint32_t x, - uint32_t y); + uint32_t y, + uint32_t *pickedInstance); // for C++ expose the interface as a virtual interface #ifdef __cplusplus diff --git a/renderdoc/replay/replay_output.cpp b/renderdoc/replay/replay_output.cpp index 66fc6b07d..ec76475c1 100644 --- a/renderdoc/replay/replay_output.cpp +++ b/renderdoc/replay/replay_output.cpp @@ -421,7 +421,7 @@ bool ReplayOutput::PickPixel(ResourceId tex, bool customShader, uint32_t x, uint return true; } -uint32_t ReplayOutput::PickVertex(uint32_t eventID, uint32_t x, uint32_t y) +uint32_t ReplayOutput::PickVertex(uint32_t eventID, uint32_t x, uint32_t y, uint32_t *pickedInstance) { FetchDrawcall *draw = m_pRenderer->GetDrawcallByEID(eventID); @@ -442,7 +442,39 @@ uint32_t ReplayOutput::PickVertex(uint32_t eventID, uint32_t x, uint32_t y) cfg.second.buf = m_pDevice->GetLiveID(cfg.second.buf); cfg.second.idxbuf = m_pDevice->GetLiveID(cfg.second.idxbuf); - return m_pDevice->PickVertex(m_EventID, cfg, x, y); + *pickedInstance = 0; + + if(draw->flags & eDraw_Instanced) + { + 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); + + cfg.position = fmt; + + uint32_t ret = m_pDevice->PickVertex(m_EventID, cfg, x, y); + if(ret != ~0U) + { + *pickedInstance = inst; + return ret; + } + } + + return ~0U; + } + else + { + return m_pDevice->PickVertex(m_EventID, cfg, x, y); + } } bool ReplayOutput::SetPixelContextLocation(uint32_t x, uint32_t y) @@ -898,7 +930,8 @@ extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayOutput_PickPixel( extern "C" RENDERDOC_API uint32_t RENDERDOC_CC ReplayOutput_PickVertex(ReplayOutput *output, uint32_t eventID, uint32_t x, - uint32_t y) + uint32_t y, + uint32_t *pickedInstance) { - return output->PickVertex(eventID, x, y); + return output->PickVertex(eventID, x, y, pickedInstance); } diff --git a/renderdoc/replay/replay_renderer.h b/renderdoc/replay/replay_renderer.h index 0f683d164..dc97c8c09 100644 --- a/renderdoc/replay/replay_renderer.h +++ b/renderdoc/replay/replay_renderer.h @@ -60,7 +60,7 @@ public: ResourceId GetCustomShaderTexID() { return m_CustomShaderResourceId; } bool PickPixel(ResourceId texID, bool customShader, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, PixelValue *val); - uint32_t PickVertex(uint32_t eventID, uint32_t x, uint32_t y); + uint32_t PickVertex(uint32_t eventID, uint32_t x, uint32_t y, uint32_t *pickedInstance); private: ReplayOutput(ReplayRenderer *parent, WindowingSystem system, void *data, OutputType type); diff --git a/renderdocui/Interop/ReplayRenderer.cs b/renderdocui/Interop/ReplayRenderer.cs index 8a4915e15..611c5fed1 100644 --- a/renderdocui/Interop/ReplayRenderer.cs +++ b/renderdocui/Interop/ReplayRenderer.cs @@ -152,7 +152,7 @@ namespace renderdoc private static extern bool ReplayOutput_PickPixel(IntPtr real, ResourceId texID, bool customShader, UInt32 x, UInt32 y, UInt32 sliceFace, UInt32 mip, UInt32 sample, IntPtr outval); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] - private static extern UInt32 ReplayOutput_PickVertex(IntPtr real, UInt32 eventID, UInt32 x, UInt32 y); + private static extern UInt32 ReplayOutput_PickVertex(IntPtr real, UInt32 eventID, UInt32 x, UInt32 y, IntPtr outPickedInstance); private IntPtr m_Real = IntPtr.Zero; @@ -269,9 +269,16 @@ namespace renderdoc return ret; } - public UInt32 PickVertex(UInt32 eventID, UInt32 x, UInt32 y) + public UInt32 PickVertex(UInt32 eventID, UInt32 x, UInt32 y, out UInt32 pickedInstance) { - return ReplayOutput_PickVertex(m_Real, eventID, x, y); + IntPtr mem = CustomMarshal.Alloc(typeof(UInt32)); + + UInt32 pickedVertex = ReplayOutput_PickVertex(m_Real, eventID, x, y, mem); + pickedInstance = (UInt32)CustomMarshal.PtrToStructure(mem, typeof(UInt32), true); + + CustomMarshal.Free(mem); + + return pickedVertex; } }; diff --git a/renderdocui/Windows/BufferViewer.cs b/renderdocui/Windows/BufferViewer.cs index d6aa591a3..e8bddc589 100644 --- a/renderdocui/Windows/BufferViewer.cs +++ b/renderdocui/Windows/BufferViewer.cs @@ -2379,12 +2379,21 @@ namespace renderdocui.Windows m_Core.Renderer.BeginInvoke((ReplayRenderer r) => { - UInt32 vertSelected = m_Output.PickVertex(m_Core.CurEvent, (UInt32)p.X, (UInt32)p.Y); + UInt32 instanceSelected = 0; + UInt32 vertSelected = m_Output.PickVertex(m_Core.CurEvent, (UInt32)p.X, (UInt32)p.Y, out instanceSelected); if (vertSelected != UInt32.MaxValue) { this.BeginInvoke(new Action(() => { + if (instanceSelected != m_MeshDisplay.curInstance) + { + m_MeshDisplay.curInstance = instanceSelected; + instanceIdx.Text = instanceSelected.ToString(); + instanceIdxToolitem.Text = instanceIdx.Text; + OnEventSelected(m_Core.CurEvent); + } + var ui = GetUIState(m_MeshDisplay.type); int row = (int)vertSelected; @@ -2401,6 +2410,7 @@ namespace renderdocui.Windows SyncViews(ui.m_GridView, true, true); } + })); } });