Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 136 additions & 22 deletions renderdoc/core/replay_proxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ rdcstr DoStringise(const ReplayProxyPacket &el)
STRINGISE_ENUM_NAMED(eReplayProxy_GetBuffer, "GetBuffer");
STRINGISE_ENUM_NAMED(eReplayProxy_GetShaderEntryPoints, "GetShaderEntryPoints");
STRINGISE_ENUM_NAMED(eReplayProxy_GetShader, "GetShader");
STRINGISE_ENUM_NAMED(eReplayProxy_GetShaderReflectionByPointer, "GetShaderReflectionByPointer");
STRINGISE_ENUM_NAMED(eReplayProxy_GetDebugMessages, "GetDebugMessages");

STRINGISE_ENUM_NAMED(eReplayProxy_GetBufferData, "GetBufferData");
Expand Down Expand Up @@ -274,6 +275,9 @@ ReplayProxy::~ReplayProxy()

for(auto it = m_ShaderReflectionCache.begin(); it != m_ShaderReflectionCache.end(); ++it)
delete it->second;

for(auto it = m_PointerReflectionCache.begin(); it != m_PointerReflectionCache.end(); ++it)
delete it->second;
}

#pragma region Proxied Functions
Expand Down Expand Up @@ -1242,6 +1246,64 @@ const ShaderReflection *ReplayProxy::GetShader(ResourceId pipeline, ResourceId s
PROXY_FUNCTION(GetShader, pipeline, shader, entry);
}

const ShaderReflection *ReplayProxy::GetShaderReflectionByPointer(uint64_t reflectionPointer)
{
PROXY_FUNCTION(GetShaderReflectionByPointer, reflectionPointer);
}

template <typename ParamSerialiser, typename ReturnSerialiser>
const ShaderReflection *ReplayProxy::Proxied_GetShaderReflectionByPointer(ParamSerialiser &paramser,
ReturnSerialiser &retser,
uint64_t reflectionPointer)
{
const ReplayProxyPacket expectedPacket = eReplayProxy_GetShaderReflectionByPointer;
ReplayProxyPacket packet = eReplayProxy_GetShaderReflectionByPointer;

const ShaderReflection *reflection = NULL;

// Host-side cache check, before requesting on the remote
if(retser.IsReading())
{
auto it = m_PointerReflectionCache.find(reflectionPointer);

if(it != m_PointerReflectionCache.end())
return it->second;
}

// Serialize the request containing the opaque pointer value.
{
BEGIN_PARAMS();
SERIALISE_ELEMENT(reflectionPointer);
END_PARAMS();
}

// Only the remote can dereference this pointer.
if(paramser.IsReading())
{
reflection = (const ShaderReflection *)(uintptr_t)reflectionPointer;
}

// Allocate a local copy of the ShaderReflection object on the host
// and store it in the cache
{
ReturnSerialiser &ser = retser;
PACKET_HEADER(packet);
SERIALISE_ELEMENT_OPT(reflection);
SERIALISE_ELEMENT(packet);
ser.EndChunk();

if(ser.IsReading())
{
m_PointerReflectionCache[reflectionPointer] = reflection;
reflection = NULL;
}
}

CheckError(packet, expectedPacket);

return m_PointerReflectionCache[reflectionPointer];
}

template <typename ParamSerialiser, typename ReturnSerialiser>
rdcstr ReplayProxy::Proxied_DisassembleShader(ParamSerialiser &paramser, ReturnSerialiser &retser,
ResourceId pipeline, const ShaderReflection *refl,
Expand Down Expand Up @@ -1376,11 +1438,15 @@ void ReplayProxy::Proxied_ReloadShaderDebugInformation(ParamSerialiser &paramser
const ReplayProxyPacket expectedPacket = eReplayProxy_ReloadShaderDebugInformation;
ReplayProxyPacket packet = eReplayProxy_ReloadShaderDebugInformation;

// Clear the shader refleciton cache
// Clear the shader reflection cache
for(auto it = m_ShaderReflectionCache.begin(); it != m_ShaderReflectionCache.end(); ++it)
delete it->second;
m_ShaderReflectionCache.clear();

for(auto it = m_PointerReflectionCache.begin(); it != m_PointerReflectionCache.end(); ++it)
delete it->second;
m_PointerReflectionCache.clear();

{
BEGIN_PARAMS();
END_PARAMS();
Expand Down Expand Up @@ -1793,6 +1859,15 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
{
const ReplayProxyPacket expectedPacket = eReplayProxy_SavePipelineState;
ReplayProxyPacket packet = eReplayProxy_SavePipelineState;
rdcarray<uint64_t> reflectionPointers;

const auto fillReflectionPointers = [&reflectionPointers](const auto &stages,
size_t extraCount = 0) {
reflectionPointers.resize(ARRAY_COUNT(stages) + extraCount);

for(size_t i = 0; i < ARRAY_COUNT(stages); i++)
reflectionPointers[i] = (uint64_t)(uintptr_t)stages[i]->reflection;
};

{
BEGIN_PARAMS();
Expand All @@ -1813,20 +1888,60 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
PACKET_HEADER(packet);
if(m_APIProps.pipelineType == GraphicsAPI::D3D11)
{
D3D11Pipe::Shader *stages[] = {
&m_D3D11PipelineState->vertexShader, &m_D3D11PipelineState->hullShader,
&m_D3D11PipelineState->domainShader, &m_D3D11PipelineState->geometryShader,
&m_D3D11PipelineState->pixelShader, &m_D3D11PipelineState->computeShader};

fillReflectionPointers(stages, 1);

if(m_D3D11PipelineState->inputAssembly.resourceId != ResourceId())
{
reflectionPointers[ARRAY_COUNT(stages)] =
(uint64_t)(uintptr_t)m_D3D11PipelineState->inputAssembly.bytecode;
}

SERIALISE_ELEMENT(*m_D3D11PipelineState);
}
else if(m_APIProps.pipelineType == GraphicsAPI::D3D12)
{
D3D12Pipe::Shader *stages[] = {
&m_D3D12PipelineState->vertexShader, &m_D3D12PipelineState->hullShader,
&m_D3D12PipelineState->domainShader, &m_D3D12PipelineState->geometryShader,
&m_D3D12PipelineState->pixelShader, &m_D3D12PipelineState->computeShader,
&m_D3D12PipelineState->ampShader, &m_D3D12PipelineState->meshShader,
};

fillReflectionPointers(stages);

SERIALISE_ELEMENT(*m_D3D12PipelineState);
}
else if(m_APIProps.pipelineType == GraphicsAPI::OpenGL)
{
GLPipe::Shader *stages[] = {
&m_GLPipelineState->vertexShader, &m_GLPipelineState->tessControlShader,
&m_GLPipelineState->tessEvalShader, &m_GLPipelineState->geometryShader,
&m_GLPipelineState->fragmentShader, &m_GLPipelineState->computeShader,
};

fillReflectionPointers(stages);

SERIALISE_ELEMENT(*m_GLPipelineState);
}
else if(m_APIProps.pipelineType == GraphicsAPI::Vulkan)
{
VKPipe::Shader *stages[] = {
&m_VulkanPipelineState->vertexShader, &m_VulkanPipelineState->tessControlShader,
&m_VulkanPipelineState->tessEvalShader, &m_VulkanPipelineState->geometryShader,
&m_VulkanPipelineState->fragmentShader, &m_VulkanPipelineState->computeShader,
&m_VulkanPipelineState->taskShader, &m_VulkanPipelineState->meshShader,
};

fillReflectionPointers(stages);

SERIALISE_ELEMENT(*m_VulkanPipelineState);
}
SERIALISE_ELEMENT(reflectionPointers);
SERIALISE_ELEMENT(packet);
ser.EndChunk();

Expand All @@ -1841,13 +1956,17 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
};

for(size_t i = 0; i < ARRAY_COUNT(stages); i++)
if(stages[i]->resourceId != ResourceId())
stages[i]->reflection =
GetShader(ResourceId(), stages[i]->resourceId, ShaderEntryPoint());
if(reflectionPointers[i] != 0)
{
stages[i]->reflection = GetShaderReflectionByPointer(reflectionPointers[i]);
}

if(m_D3D11PipelineState->inputAssembly.resourceId != ResourceId())
m_D3D11PipelineState->inputAssembly.bytecode = GetShader(
ResourceId(), m_D3D11PipelineState->inputAssembly.resourceId, ShaderEntryPoint());
{
const size_t inputAssemblyByteCodeIndex = ARRAY_COUNT(stages);
m_D3D11PipelineState->inputAssembly.bytecode =
GetShaderReflectionByPointer(reflectionPointers[inputAssemblyByteCodeIndex]);
}
}
else if(m_APIProps.pipelineType == GraphicsAPI::D3D12 && m_D3D12PipelineState)
{
Expand All @@ -1858,11 +1977,9 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
&m_D3D12PipelineState->ampShader, &m_D3D12PipelineState->meshShader,
};

ResourceId pipe = m_D3D12PipelineState->pipelineResourceId;

for(size_t i = 0; i < ARRAY_COUNT(stages); i++)
if(stages[i]->resourceId != ResourceId())
stages[i]->reflection = GetShader(pipe, stages[i]->resourceId, ShaderEntryPoint());
if(reflectionPointers[i] != 0)
stages[i]->reflection = GetShaderReflectionByPointer(reflectionPointers[i]);
}
else if(m_APIProps.pipelineType == GraphicsAPI::OpenGL && m_GLPipelineState)
{
Expand All @@ -1873,9 +1990,8 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
};

for(size_t i = 0; i < ARRAY_COUNT(stages); i++)
if(stages[i]->shaderResourceId != ResourceId())
stages[i]->reflection =
GetShader(ResourceId(), stages[i]->shaderResourceId, ShaderEntryPoint());
if(reflectionPointers[i] != 0)
stages[i]->reflection = GetShaderReflectionByPointer(reflectionPointers[i]);
}
else if(m_APIProps.pipelineType == GraphicsAPI::Vulkan && m_VulkanPipelineState)
{
Expand All @@ -1886,17 +2002,10 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
&m_VulkanPipelineState->taskShader, &m_VulkanPipelineState->meshShader,
};

ResourceId pipe = m_VulkanPipelineState->graphics.pipelineResourceId;

for(size_t i = 0; i < ARRAY_COUNT(stages); i++)
{
if(i == 5)
pipe = m_VulkanPipelineState->compute.pipelineResourceId;

if(stages[i]->resourceId != ResourceId())
stages[i]->reflection =
GetShader(pipe, stages[i]->resourceId,
ShaderEntryPoint(stages[i]->entryPoint, stages[i]->stage));
if(reflectionPointers[i] != 0)
stages[i]->reflection = GetShaderReflectionByPointer(reflectionPointers[i]);
}
}
}
Expand Down Expand Up @@ -3043,6 +3152,10 @@ IReplayDriver *ReplayProxy::MakeDummyDriver()
shaders.push_back(it->second);
m_ShaderReflectionCache.clear();

for(auto it : m_PointerReflectionCache)
shaders.push_back(it.second);
m_PointerReflectionCache.clear();

IReplayDriver *dummy = new DummyDriver(this, shaders, m_StructuredFile);

// the dummy driver now owns the file, remove our reference
Expand Down Expand Up @@ -3107,6 +3220,7 @@ bool ReplayProxy::Tick(int type)
case eReplayProxy_GetBuffer: GetBuffer(ResourceId()); break;
case eReplayProxy_GetShaderEntryPoints: GetShaderEntryPoints(ResourceId()); break;
case eReplayProxy_GetShader: GetShader(ResourceId(), ResourceId(), ShaderEntryPoint()); break;
case eReplayProxy_GetShaderReflectionByPointer: GetShaderReflectionByPointer(0); break;
case eReplayProxy_GetDebugMessages: GetDebugMessages(); break;
case eReplayProxy_GetBufferData:
{
Expand Down
5 changes: 5 additions & 0 deletions renderdoc/core/replay_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ enum ReplayProxyPacket
eReplayProxy_GetBuffer,
eReplayProxy_GetShaderEntryPoints,
eReplayProxy_GetShader,
eReplayProxy_GetShaderReflectionByPointer,
eReplayProxy_GetDebugMessages,

eReplayProxy_GetBufferData,
Expand Down Expand Up @@ -531,6 +532,8 @@ class ReplayProxy : public IReplayDriver
IMPLEMENT_FUNCTION_PROXIED(rdcarray<ShaderEntryPoint>, GetShaderEntryPoints, ResourceId shader);
IMPLEMENT_FUNCTION_PROXIED(const ShaderReflection *, GetShader, ResourceId pipeline, ResourceId,
ShaderEntryPoint entry);
IMPLEMENT_FUNCTION_PROXIED(const ShaderReflection *, GetShaderReflectionByPointer,
uint64_t reflectionPointer);

IMPLEMENT_FUNCTION_PROXIED(rdcarray<rdcstr>, GetDisassemblyTargets, bool withPipeline);
IMPLEMENT_FUNCTION_PROXIED(rdcstr, DisassembleShader, ResourceId pipeline,
Expand Down Expand Up @@ -678,6 +681,8 @@ class ReplayProxy : public IReplayDriver

std::map<ShaderReflKey, const ShaderReflection *> m_ShaderReflectionCache;

std::map<uint64_t, const ShaderReflection *> m_PointerReflectionCache;

// reader from the other side of the host <-> remote connection
ReadSerialiser &m_Reader;
// writer to the other side of the host <-> remote connection
Expand Down