From 4e51aab9e593110d64d15edc957377d43b0d88a3 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 8 Jul 2014 09:19:40 +0100 Subject: [PATCH] Add externally visible API to query for pixel history --- renderdoc/core/replay_proxy.cpp | 46 ++++++++++++++ renderdoc/core/replay_proxy.h | 3 + renderdoc/driver/d3d11/d3d11_analyse.cpp | 6 ++ renderdoc/driver/d3d11/d3d11_debug.h | 1 + renderdoc/driver/d3d11/d3d11_replay.cpp | 5 ++ renderdoc/driver/d3d11/d3d11_replay.h | 3 +- renderdoc/driver/gl/gl_replay.cpp | 6 ++ renderdoc/driver/gl/gl_replay.h | 3 +- renderdoc/replay/data_types.h | 17 ++++++ renderdoc/replay/renderdoc.h | 1 + renderdoc/replay/replay_driver.h | 1 + renderdoc/replay/replay_renderer.cpp | 78 ++++++++++++++++++++++++ renderdoc/replay/replay_renderer.h | 1 + renderdocui/Interop/FetchInfo.cs | 21 +++++++ renderdocui/Interop/ReplayRenderer.cs | 20 +++++- 15 files changed, 209 insertions(+), 3 deletions(-) diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index fdfa583c0..1b53a7fa0 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -524,6 +524,24 @@ void Serialiser::Serialise(const char *name, PostVSMeshData &el) Serialise("", el.buf); } +template<> +void Serialiser::Serialise(const char *name, PixelModification &el) +{ + Serialise("", el.eventID); + + Serialise<4>("", el.preMod.value_u); + Serialise<4>("", el.shaderOut.value_u); + Serialise<4>("", el.postMod.value_u); + + Serialise("", el.backfaceCulled); + Serialise("", el.depthClipped); + Serialise("", el.viewClipped); + Serialise("", el.scissorClipped); + Serialise("", el.shaderDiscared); + Serialise("", el.depthTestFailed); + Serialise("", el.stencilTestFailed); +} + template<> void Serialiser::Serialise(const char *name, ShaderDebugState &el) { @@ -751,6 +769,9 @@ bool ProxySerialiser::Tick() case eCommand_RenderOverlay: RenderOverlay(ResourceId(), eTexOverlay_None, 0, 0); break; + case eCommand_PixelHistory: + PixelHistory(0, vector(), ResourceId(), 0, 0); + break; case eCommand_DebugVertex: DebugVertex(0, 0, 0, 0, 0, 0, 0); break; @@ -1439,6 +1460,31 @@ void ProxySerialiser::RemoveReplacement(ResourceId id) } } +vector ProxySerialiser::PixelHistory(uint32_t frameID, vector events, ResourceId target, uint32_t x, uint32_t y) +{ + vector ret; + + m_ToReplaySerialiser->Serialise("", frameID); + m_ToReplaySerialiser->Serialise("", events); + m_ToReplaySerialiser->Serialise("", target); + m_ToReplaySerialiser->Serialise("", x); + m_ToReplaySerialiser->Serialise("", y); + + if(m_ReplayHost) + { + ret = m_Remote->PixelHistory(frameID, events, target, x, y); + } + else + { + if(!SendReplayCommand(eCommand_PixelHistory)) + return ret; + } + + m_FromReplaySerialiser->Serialise("", ret); + + return ret; +} + ShaderDebugTrace ProxySerialiser::DebugVertex(uint32_t frameID, uint32_t eventID, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset) { ShaderDebugTrace ret; diff --git a/renderdoc/core/replay_proxy.h b/renderdoc/core/replay_proxy.h index fcbdb0d27..884a43140 100644 --- a/renderdoc/core/replay_proxy.h +++ b/renderdoc/core/replay_proxy.h @@ -73,6 +73,8 @@ enum CommandPacketType eCommand_RenderOverlay, eCommand_GetAPIProperties, + + eCommand_PixelHistory, }; // This class implements IReplayDriver and StackResolver. On the local machine where the UI @@ -308,6 +310,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver void FreeTargetResource(ResourceId id); + vector PixelHistory(uint32_t frameID, vector events, ResourceId target, uint32_t x, uint32_t y); ShaderDebugTrace DebugVertex(uint32_t frameID, uint32_t eventID, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset); ShaderDebugTrace DebugPixel(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y); ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]); diff --git a/renderdoc/driver/d3d11/d3d11_analyse.cpp b/renderdoc/driver/d3d11/d3d11_analyse.cpp index a2ca538c0..c8a5779ca 100644 --- a/renderdoc/driver/d3d11/d3d11_analyse.cpp +++ b/renderdoc/driver/d3d11/d3d11_analyse.cpp @@ -2705,3 +2705,9 @@ ResourceId D3D11DebugManager::RenderOverlay(ResourceId texid, TextureDisplayOver return m_OverlayResourceId; } + +vector D3D11DebugManager::PixelHistory(uint32_t frameID, vector events, ResourceId target, uint32_t x, uint32_t y) +{ + RDCUNIMPLEMENTED("D3D11DebugManager::PixelHistory"); + return vector(); +} diff --git a/renderdoc/driver/d3d11/d3d11_debug.h b/renderdoc/driver/d3d11/d3d11_debug.h index f4be7980f..9d03e296e 100644 --- a/renderdoc/driver/d3d11/d3d11_debug.h +++ b/renderdoc/driver/d3d11/d3d11_debug.h @@ -152,6 +152,7 @@ class D3D11DebugManager void RenderHighlightBox(float w, float h, float scale); + vector PixelHistory(uint32_t frameID, vector events, ResourceId target, uint32_t x, uint32_t y); ShaderDebugTrace DebugVertex(uint32_t frameID, uint32_t eventID, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset); ShaderDebugTrace DebugPixel(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y); ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]); diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 94be79cfc..c81389343 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -1276,6 +1276,11 @@ void D3D11Replay::FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vec return; } +vector D3D11Replay::PixelHistory(uint32_t frameID, vector events, ResourceId target, uint32_t x, uint32_t y) +{ + return m_pDevice->GetDebugManager()->PixelHistory(frameID, events, target, x, y); +} + ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t frameID, uint32_t eventID, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset) { return m_pDevice->GetDebugManager()->DebugVertex(frameID, eventID, vertid, instid, idx, instOffset, vertOffset); diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index cb03e22e9..93904e029 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.h +++ b/renderdoc/driver/d3d11/d3d11_replay.h @@ -110,7 +110,8 @@ class D3D11Replay : public IReplayDriver void RenderHighlightBox(float w, float h, float scale); void FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector &outvars, const vector &data); - + + vector PixelHistory(uint32_t frameID, vector events, ResourceId target, uint32_t x, uint32_t y); ShaderDebugTrace DebugVertex(uint32_t frameID, uint32_t eventID, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset); ShaderDebugTrace DebugPixel(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y); ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]); diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 8bc0338df..97fc3d971 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -1313,6 +1313,12 @@ void GLReplay::BuildCustomShader(string source, string entry, const uint32_t com RDCUNIMPLEMENTED("BuildCustomShader"); } +vector GLReplay::PixelHistory(uint32_t frameID, vector events, ResourceId target, uint32_t x, uint32_t y) +{ + RDCUNIMPLEMENTED("GLReplay::PixelHistory"); + return vector(); +} + ShaderDebugTrace GLReplay::DebugVertex(uint32_t frameID, uint32_t eventID, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset) { RDCUNIMPLEMENTED("DebugVertex"); diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 2aa2f717f..af4945ba3 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -110,7 +110,8 @@ class GLReplay : public IReplayDriver void RenderHighlightBox(float w, float h, float scale); void FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector &outvars, const vector &data); - + + vector PixelHistory(uint32_t frameID, vector events, ResourceId target, uint32_t x, uint32_t y); ShaderDebugTrace DebugVertex(uint32_t frameID, uint32_t eventID, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset); ShaderDebugTrace DebugPixel(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y); ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]); diff --git a/renderdoc/replay/data_types.h b/renderdoc/replay/data_types.h index cbab17c1e..4284d78c4 100644 --- a/renderdoc/replay/data_types.h +++ b/renderdoc/replay/data_types.h @@ -202,6 +202,23 @@ struct PixelValue }; }; +struct PixelModification +{ + uint32_t eventID; + + PixelValue preMod; + PixelValue shaderOut; + PixelValue postMod; + + bool32 backfaceCulled; + bool32 depthClipped; + bool32 viewClipped; + bool32 scissorClipped; + bool32 shaderDiscarded; + bool32 depthTestFailed; + bool32 stencilTestFailed; +}; + struct PostVSMeshData { rdctype::array buf; diff --git a/renderdoc/replay/renderdoc.h b/renderdoc/replay/renderdoc.h index e5cec3e7a..7f9054f0c 100644 --- a/renderdoc/replay/renderdoc.h +++ b/renderdoc/replay/renderdoc.h @@ -123,6 +123,7 @@ extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_GetBuffers(ReplayRende extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_GetResolve(ReplayRenderer *rend, uint64_t *callstack, uint32_t callstackLen, rdctype::array *trace); extern "C" RENDERDOC_API ShaderReflection* RENDERDOC_CC ReplayRenderer_GetShaderDetails(ReplayRenderer *rend, ResourceId shader); +extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_PixelHistory(ReplayRenderer *rend, ResourceId target, uint32_t x, uint32_t y, rdctype::array *history); extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_VSGetDebugStates(ReplayRenderer *rend, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset, ShaderDebugTrace *trace); extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_PSGetDebugStates(ReplayRenderer *rend, uint32_t x, uint32_t y, ShaderDebugTrace *trace); extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_CSGetDebugStates(ReplayRenderer *rend, uint32_t groupid[3], uint32_t threadid[3], ShaderDebugTrace *trace); diff --git a/renderdoc/replay/replay_driver.h b/renderdoc/replay/replay_driver.h index 53c811409..7b06de05c 100644 --- a/renderdoc/replay/replay_driver.h +++ b/renderdoc/replay/replay_driver.h @@ -93,6 +93,7 @@ class IRemoteDriver virtual void FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector &outvars, const vector &data) = 0; + virtual vector PixelHistory(uint32_t frameID, vector events, ResourceId target, uint32_t x, uint32_t y) = 0; virtual ShaderDebugTrace DebugVertex(uint32_t frameID, uint32_t eventID, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset) = 0; virtual ShaderDebugTrace DebugPixel(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y) = 0; virtual ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]) = 0; diff --git a/renderdoc/replay/replay_renderer.cpp b/renderdoc/replay/replay_renderer.cpp index 4615036a4..86ceced16 100644 --- a/renderdoc/replay/replay_renderer.cpp +++ b/renderdoc/replay/replay_renderer.cpp @@ -326,6 +326,82 @@ bool ReplayRenderer::SaveTexture(ResourceId tex, uint32_t saveMip, const wchar_t return m_pDevice->SaveTexture(m_pDevice->GetLiveID(tex), saveMip, path); } +bool ReplayRenderer::PixelHistory(ResourceId target, uint32_t x, uint32_t y, rdctype::array *history) +{ + bool outofbounds = false; + + for(size_t t=0; t < m_Textures.size(); t++) + { + if(m_Textures[t].ID == target) + { + if(x >= m_Textures[t].width || y >= m_Textures[t].height) + { + RDCDEBUG("PixelHistory out of bounds on %llx (%u,%u) vs (%u,%u)", target, x, y, m_Textures[t].width, m_Textures[t].height); + history->count = 0; + history->elems = NULL; + return false; + } + + break; + } + } + + auto usage = m_pDevice->GetUsage(m_pDevice->GetLiveID(target)); + + vector events; + + for(size_t i=0; i < usage.size(); i++) + { + if(usage[i].eventID > m_EventID) + continue; + + switch(usage[i].usage) + { + case eUsage_IA_VB: + case eUsage_IA_IB: + case eUsage_VS_CB: + case eUsage_HS_CB: + case eUsage_DS_CB: + case eUsage_GS_CB: + case eUsage_PS_CB: + case eUsage_CS_CB: + case eUsage_VS_SRV: + case eUsage_HS_SRV: + case eUsage_DS_SRV: + case eUsage_GS_SRV: + case eUsage_PS_SRV: + case eUsage_CS_SRV: + // read-only, not a valid pixel history event + continue; + + case eUsage_SO: + case eUsage_CS_UAV: + case eUsage_PS_UAV: + case eUsage_OM_RTV: + case eUsage_OM_DSV: + case eUsage_Clear: + // writing - include in pixel history events + break; + } + + events.push_back(usage[i].eventID); + } + + if(events.empty()) + { + RDCDEBUG("Target %llx not written to before %u", target, m_EventID); + history->count = 0; + history->elems = NULL; + return false; + } + + *history = m_pDevice->PixelHistory(m_FrameID, events, m_pDevice->GetLiveID(target), x, y); + + SetFrameEvent(m_FrameID, m_EventID, true); + + return true; +} + bool ReplayRenderer::VSGetDebugStates(uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset, ShaderDebugTrace *trace) { if(trace == NULL) return false; @@ -694,6 +770,8 @@ extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_GetResolve(ReplayRende extern "C" RENDERDOC_API ShaderReflection* RENDERDOC_CC ReplayRenderer_GetShaderDetails(ReplayRenderer *rend, ResourceId shader) { return rend->GetShaderDetails(shader); } +extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_PixelHistory(ReplayRenderer *rend, ResourceId target, uint32_t x, uint32_t y, rdctype::array *history) +{ return rend->PixelHistory(target, x, y, history); } extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_VSGetDebugStates(ReplayRenderer *rend, uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset, ShaderDebugTrace *trace) { return rend->VSGetDebugStates(vertid, instid, idx, instOffset, vertOffset, trace); } extern "C" RENDERDOC_API bool RENDERDOC_CC ReplayRenderer_PSGetDebugStates(ReplayRenderer *rend, uint32_t x, uint32_t y, ShaderDebugTrace *trace) diff --git a/renderdoc/replay/replay_renderer.h b/renderdoc/replay/replay_renderer.h index c9c20ca9a..da518e5df 100644 --- a/renderdoc/replay/replay_renderer.h +++ b/renderdoc/replay/replay_renderer.h @@ -158,6 +158,7 @@ struct ReplayRenderer bool GetResolve(uint64_t *callstack, uint32_t callstackLen, rdctype::array *trace); ShaderReflection *GetShaderDetails(ResourceId shader); + bool PixelHistory(ResourceId target, uint32_t x, uint32_t y, rdctype::array *history); bool VSGetDebugStates(uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset, uint32_t vertOffset, ShaderDebugTrace *trace); bool PSGetDebugStates(uint32_t x, uint32_t y, ShaderDebugTrace *trace); bool CSGetDebugStates(uint32_t groupid[3], uint32_t threadid[3], ShaderDebugTrace *trace); diff --git a/renderdocui/Interop/FetchInfo.cs b/renderdocui/Interop/FetchInfo.cs index cd80059fd..7d3478ae0 100644 --- a/renderdocui/Interop/FetchInfo.cs +++ b/renderdocui/Interop/FetchInfo.cs @@ -457,6 +457,27 @@ namespace renderdoc public ValueUnion value; }; + [StructLayout(LayoutKind.Sequential)] + public class PixelModification + { + public UInt32 eventID; + + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public PixelValue preMod; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public PixelValue shaderOut; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public PixelValue postMod; + + public bool backfaceCulled; + public bool depthClipped; + public bool viewClipped; + public bool scissorClipped; + public bool shaderDiscarded; + public bool depthTestFailed; + public bool stencilTestFailed; + }; + [StructLayout(LayoutKind.Sequential)] public class PostVSMeshData { diff --git a/renderdocui/Interop/ReplayRenderer.cs b/renderdocui/Interop/ReplayRenderer.cs index ce3df5dc8..dd97fe7eb 100644 --- a/renderdocui/Interop/ReplayRenderer.cs +++ b/renderdocui/Interop/ReplayRenderer.cs @@ -209,7 +209,9 @@ namespace renderdoc private static extern bool ReplayRenderer_GetResolve(IntPtr real, UInt64[] callstack, UInt32 callstackLen, IntPtr outtrace); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ReplayRenderer_GetShaderDetails(IntPtr real, ResourceId shader); - + + [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] + private static extern bool ReplayRenderer_PixelHistory(IntPtr real, ResourceId target, UInt32 x, UInt32 y, IntPtr history); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern bool ReplayRenderer_VSGetDebugStates(IntPtr real, UInt32 vertid, UInt32 instid, UInt32 idx, UInt32 instOffset, UInt32 vertOffset, IntPtr outtrace); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] @@ -488,6 +490,22 @@ namespace renderdoc return ret; } + public PixelModification[] PixelHistory(ResourceId target, UInt32 x, UInt32 y) + { + IntPtr mem = CustomMarshal.Alloc(typeof(templated_array)); + + bool success = ReplayRenderer_PixelHistory(m_Real, target, x, y, mem); + + PixelModification[] ret = null; + + if (success) + ret = (PixelModification[])CustomMarshal.GetTemplatedArray(mem, typeof(PixelModification), true); + + CustomMarshal.Free(mem); + + return ret; + } + public ShaderDebugTrace VSGetDebugStates(UInt32 vertid, UInt32 instid, UInt32 idx, UInt32 instOffset, UInt32 vertOffset) { IntPtr mem = CustomMarshal.Alloc(typeof(ShaderDebugTrace));