mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 17:40:39 +00:00
Add externally visible API to query for pixel history
This commit is contained in:
@@ -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<uint32_t>(), 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<PixelModification> ProxySerialiser::PixelHistory(uint32_t frameID, vector<uint32_t> events, ResourceId target, uint32_t x, uint32_t y)
|
||||
{
|
||||
vector<PixelModification> 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;
|
||||
|
||||
@@ -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<PixelModification> PixelHistory(uint32_t frameID, vector<uint32_t> 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]);
|
||||
|
||||
@@ -2705,3 +2705,9 @@ ResourceId D3D11DebugManager::RenderOverlay(ResourceId texid, TextureDisplayOver
|
||||
|
||||
return m_OverlayResourceId;
|
||||
}
|
||||
|
||||
vector<PixelModification> D3D11DebugManager::PixelHistory(uint32_t frameID, vector<uint32_t> events, ResourceId target, uint32_t x, uint32_t y)
|
||||
{
|
||||
RDCUNIMPLEMENTED("D3D11DebugManager::PixelHistory");
|
||||
return vector<PixelModification>();
|
||||
}
|
||||
|
||||
@@ -152,6 +152,7 @@ class D3D11DebugManager
|
||||
|
||||
void RenderHighlightBox(float w, float h, float scale);
|
||||
|
||||
vector<PixelModification> PixelHistory(uint32_t frameID, vector<uint32_t> 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]);
|
||||
|
||||
@@ -1276,6 +1276,11 @@ void D3D11Replay::FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vec
|
||||
return;
|
||||
}
|
||||
|
||||
vector<PixelModification> D3D11Replay::PixelHistory(uint32_t frameID, vector<uint32_t> 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);
|
||||
|
||||
@@ -110,7 +110,8 @@ class D3D11Replay : public IReplayDriver
|
||||
void RenderHighlightBox(float w, float h, float scale);
|
||||
|
||||
void FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector<ShaderVariable> &outvars, const vector<byte> &data);
|
||||
|
||||
|
||||
vector<PixelModification> PixelHistory(uint32_t frameID, vector<uint32_t> 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]);
|
||||
|
||||
@@ -1313,6 +1313,12 @@ void GLReplay::BuildCustomShader(string source, string entry, const uint32_t com
|
||||
RDCUNIMPLEMENTED("BuildCustomShader");
|
||||
}
|
||||
|
||||
vector<PixelModification> GLReplay::PixelHistory(uint32_t frameID, vector<uint32_t> events, ResourceId target, uint32_t x, uint32_t y)
|
||||
{
|
||||
RDCUNIMPLEMENTED("GLReplay::PixelHistory");
|
||||
return vector<PixelModification>();
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
@@ -110,7 +110,8 @@ class GLReplay : public IReplayDriver
|
||||
void RenderHighlightBox(float w, float h, float scale);
|
||||
|
||||
void FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector<ShaderVariable> &outvars, const vector<byte> &data);
|
||||
|
||||
|
||||
vector<PixelModification> PixelHistory(uint32_t frameID, vector<uint32_t> 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]);
|
||||
|
||||
@@ -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<byte> buf;
|
||||
|
||||
@@ -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<rdctype::wstr> *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<PixelModification> *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);
|
||||
|
||||
@@ -93,6 +93,7 @@ class IRemoteDriver
|
||||
|
||||
virtual void FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector<ShaderVariable> &outvars, const vector<byte> &data) = 0;
|
||||
|
||||
virtual vector<PixelModification> PixelHistory(uint32_t frameID, vector<uint32_t> 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;
|
||||
|
||||
@@ -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<PixelModification> *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<uint32_t> 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<PixelModification> *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)
|
||||
|
||||
@@ -158,6 +158,7 @@ struct ReplayRenderer
|
||||
bool GetResolve(uint64_t *callstack, uint32_t callstackLen, rdctype::array<rdctype::wstr> *trace);
|
||||
ShaderReflection *GetShaderDetails(ResourceId shader);
|
||||
|
||||
bool PixelHistory(ResourceId target, uint32_t x, uint32_t y, rdctype::array<PixelModification> *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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user