mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-20 20:55:42 +00:00
Reflect multiple entry points & ray properties from DXIL shaders
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <map>
|
||||
#include "api/replay/rdcarray.h"
|
||||
#include "api/replay/rdcflatmap.h"
|
||||
#include "api/replay/rdcpair.h"
|
||||
#include "api/replay/rdcstr.h"
|
||||
#include "common/common.h"
|
||||
@@ -184,6 +185,19 @@ public:
|
||||
const Reflection *GetReflection() const { return m_Reflection; }
|
||||
D3D_PRIMITIVE_TOPOLOGY GetOutputTopology();
|
||||
|
||||
CBufferVariableType GetRayPayload(const ShaderEntryPoint &entry)
|
||||
{
|
||||
if(m_RayPayloads.empty())
|
||||
return {};
|
||||
return m_RayPayloads[entry].first;
|
||||
}
|
||||
CBufferVariableType GetRayAttributes(const ShaderEntryPoint &entry)
|
||||
{
|
||||
if(m_RayPayloads.empty())
|
||||
return {};
|
||||
return m_RayPayloads[entry].second;
|
||||
}
|
||||
|
||||
rdcarray<ShaderEntryPoint> GetEntryPoints() const { return m_EntryPoints; }
|
||||
|
||||
const rdcstr &GetDisassembly(bool dxcStyle);
|
||||
@@ -246,6 +260,8 @@ private:
|
||||
size_t m_NonDebugDXILByteCodeOffset = 0;
|
||||
size_t m_NonDebugDXILByteCodeSize = 0;
|
||||
|
||||
rdcflatmap<ShaderEntryPoint, rdcpair<CBufferVariableType, CBufferVariableType>> m_RayPayloads;
|
||||
|
||||
ShaderStatistics m_ShaderStats;
|
||||
DXBCBytecode::Program *m_DXBCByteCode = NULL;
|
||||
DXIL::Program *m_DXILByteCode = NULL;
|
||||
|
||||
@@ -293,7 +293,8 @@ static void MakeResourceList(bool srv, DXBC::DXBCContainer *dxbc,
|
||||
}
|
||||
}
|
||||
|
||||
void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl)
|
||||
void MakeShaderReflection(DXBC::DXBCContainer *dxbc, const ShaderEntryPoint &entry,
|
||||
ShaderReflection *refl)
|
||||
{
|
||||
if(dxbc == NULL || !RenderDoc::Inst().IsReplayApp())
|
||||
return;
|
||||
@@ -308,6 +309,7 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl)
|
||||
case DXBC::ShaderType::Compute: refl->stage = ShaderStage::Compute; break;
|
||||
case DXBC::ShaderType::Amplification: refl->stage = ShaderStage::Amplification; break;
|
||||
case DXBC::ShaderType::Mesh: refl->stage = ShaderStage::Mesh; break;
|
||||
case DXBC::ShaderType::Library: refl->stage = entry.stage; break;
|
||||
default:
|
||||
RDCERR("Unexpected DXBC shader type %u", dxbc->m_Type);
|
||||
refl->stage = ShaderStage::Vertex;
|
||||
@@ -318,8 +320,6 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl)
|
||||
|
||||
if(dxbc->GetDebugInfo())
|
||||
{
|
||||
refl->debugInfo.entrySourceName = refl->entryPoint = dxbc->GetDebugInfo()->GetEntryFunction();
|
||||
|
||||
refl->debugInfo.encoding = ShaderEncoding::HLSL;
|
||||
|
||||
refl->debugInfo.sourceDebugInformation = true;
|
||||
@@ -330,9 +330,22 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl)
|
||||
|
||||
dxbc->GetDebugInfo()->GetLineInfo(~0U, ~0U, refl->debugInfo.entryLocation);
|
||||
|
||||
rdcstr entry = dxbc->GetDebugInfo()->GetEntryFunction();
|
||||
if(entry.empty())
|
||||
entry = "main";
|
||||
rdcstr entryFunc = entry.name;
|
||||
if(entryFunc.empty())
|
||||
entryFunc = dxbc->GetDebugInfo()->GetEntryFunction();
|
||||
if(entryFunc.empty())
|
||||
entryFunc = "main";
|
||||
|
||||
refl->debugInfo.entrySourceName = refl->entryPoint = entryFunc;
|
||||
|
||||
// demangle DXIL source names for display
|
||||
if(refl->debugInfo.entrySourceName.size() > 2 && refl->debugInfo.entrySourceName[0] == '\x1' &&
|
||||
refl->debugInfo.entrySourceName[1] == '?')
|
||||
{
|
||||
int idx = refl->debugInfo.entrySourceName.indexOf('@');
|
||||
if(idx > 2)
|
||||
refl->debugInfo.entrySourceName = refl->debugInfo.entrySourceName.substr(2, idx - 2);
|
||||
}
|
||||
|
||||
// assume the debug info put the file with the entry point at the start. SDBG seems to do this
|
||||
// by default, and SPDB has an extra sorting step that probably maybe possibly does this.
|
||||
@@ -349,6 +362,7 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl)
|
||||
case DXBC::ShaderType::Hull: profile = "hs"; break;
|
||||
case DXBC::ShaderType::Domain: profile = "ds"; break;
|
||||
case DXBC::ShaderType::Compute: profile = "cs"; break;
|
||||
case DXBC::ShaderType::Library: profile = "lib"; break;
|
||||
default: profile = "xx"; break;
|
||||
}
|
||||
profile += StringFormat::Fmt("_%u_%u", dxbc->m_Version.Major, dxbc->m_Version.Minor);
|
||||
@@ -469,4 +483,24 @@ void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl)
|
||||
refl->taskPayload.variables.push_back(
|
||||
MakeConstantBufferVariable(false, dxbcRefl->TaskPayload.members[v]));
|
||||
}
|
||||
|
||||
DXBC::CBufferVariableType RayPayload = dxbc->GetRayPayload(entry);
|
||||
DXBC::CBufferVariableType RayAttributes = dxbc->GetRayAttributes(entry);
|
||||
|
||||
refl->rayPayload.bufferBacked = false;
|
||||
refl->rayPayload.name = RayPayload.name;
|
||||
refl->rayPayload.variables.reserve(RayPayload.members.size());
|
||||
for(size_t v = 0; v < RayPayload.members.size(); v++)
|
||||
{
|
||||
refl->rayPayload.variables.push_back(MakeConstantBufferVariable(false, RayPayload.members[v]));
|
||||
}
|
||||
|
||||
refl->rayAttributes.bufferBacked = false;
|
||||
refl->rayAttributes.name = RayAttributes.name;
|
||||
refl->rayAttributes.variables.reserve(RayAttributes.members.size());
|
||||
for(size_t v = 0; v < RayAttributes.members.size(); v++)
|
||||
{
|
||||
refl->rayAttributes.variables.push_back(
|
||||
MakeConstantBufferVariable(false, RayAttributes.members[v]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,9 @@ class DXBCContainer;
|
||||
}
|
||||
|
||||
struct ShaderReflection;
|
||||
struct ShaderEntryPoint;
|
||||
|
||||
#define D3Dx_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT 32
|
||||
|
||||
void MakeShaderReflection(DXBC::DXBCContainer *dxbc, ShaderReflection *refl);
|
||||
void MakeShaderReflection(DXBC::DXBCContainer *dxbc, const ShaderEntryPoint &entry,
|
||||
ShaderReflection *refl);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "api/replay/apidefs.h"
|
||||
#include "api/replay/rdcflatmap.h"
|
||||
#include "api/replay/rdcstr.h"
|
||||
#include "common/common.h"
|
||||
#include "driver/dx/official/d3dcommon.h"
|
||||
@@ -1230,6 +1231,10 @@ public:
|
||||
void FetchComputeProperties(DXBC::Reflection *reflection);
|
||||
DXBC::Reflection *GetReflection();
|
||||
rdcarray<ShaderEntryPoint> GetEntryPoints();
|
||||
void FillRayPayloads(
|
||||
Program *executable,
|
||||
rdcflatmap<ShaderEntryPoint, rdcpair<DXBC::CBufferVariableType, DXBC::CBufferVariableType>>
|
||||
&rayPayloads);
|
||||
|
||||
DXBC::ShaderType GetShaderType() const { return m_Type; }
|
||||
uint32_t GetMajorVersion() const { return m_Major; }
|
||||
|
||||
@@ -703,6 +703,175 @@ void Program::FetchComputeProperties(DXBC::Reflection *reflection)
|
||||
reflection->DispatchThreadsDimension[2] = 1;
|
||||
}
|
||||
|
||||
void Program::FillRayPayloads(
|
||||
Program *executable,
|
||||
rdcflatmap<ShaderEntryPoint, rdcpair<DXBC::CBufferVariableType, DXBC::CBufferVariableType>> &rayPayloads)
|
||||
{
|
||||
if(m_Type != DXBC::ShaderType::Library)
|
||||
return;
|
||||
|
||||
DXMeta dx(m_NamedMeta);
|
||||
|
||||
TypeInfo typeInfo(dx.typeAnnotations);
|
||||
|
||||
if(dx.entryPoints)
|
||||
{
|
||||
for(Metadata *entry : dx.entryPoints->children)
|
||||
{
|
||||
if(entry->children.size() > 2 && entry->children[0] != NULL)
|
||||
{
|
||||
ShaderEntryPoint entryPoint;
|
||||
entryPoint.name = entry->children[1]->str;
|
||||
|
||||
Metadata *tags = entry->children[4];
|
||||
|
||||
for(size_t i = 0; i < tags->children.size(); i += 2)
|
||||
{
|
||||
// 8 is the type tag
|
||||
if(getival<uint32_t>(tags->children[i]) == 8U)
|
||||
{
|
||||
entryPoint.stage =
|
||||
GetShaderStage((DXBC::ShaderType)getival<uint32_t>(tags->children[i + 1]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Function *ownFunc = cast<Function>(entry->children[0]->value);
|
||||
Function *executableFunc = NULL;
|
||||
|
||||
// locate the function in the executable program so we can iterate instructions.
|
||||
for(Function *f : executable->m_Functions)
|
||||
{
|
||||
// assume names will match
|
||||
if(f->name == ownFunc->name)
|
||||
{
|
||||
executableFunc = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// intersection shaders only report attributes, they do not access the ray payload
|
||||
if(entryPoint.stage == ShaderStage::Intersection)
|
||||
{
|
||||
// find the reportHit and grab the type from that
|
||||
for(const Instruction *in : executableFunc->instructions)
|
||||
{
|
||||
const Instruction &inst = *in;
|
||||
|
||||
if(inst.op == Operation::Call && inst.getFuncCall()->name.beginsWith("dx.op.reportHit"))
|
||||
{
|
||||
if(inst.args.size() != 4)
|
||||
{
|
||||
RDCERR("Unexpected number of arguments to reportHit");
|
||||
continue;
|
||||
}
|
||||
const Type *executableAttrType = inst.args[3]->type;
|
||||
if(!executableAttrType)
|
||||
{
|
||||
RDCERR("Unexpected untyped payload argument to reportHit");
|
||||
continue;
|
||||
}
|
||||
|
||||
RDCASSERT(executableAttrType->type == Type::Pointer);
|
||||
executableAttrType = (Type *)executableAttrType->inner;
|
||||
|
||||
Type *ownAttrType = NULL;
|
||||
|
||||
// we have the executable type but we can't use that to look up our type info. Try to
|
||||
// go back by name
|
||||
for(Type *t : m_Types)
|
||||
{
|
||||
if(t->type == executableAttrType->type && t->name == executableAttrType->name)
|
||||
{
|
||||
ownAttrType = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ownAttrType)
|
||||
rayPayloads[entryPoint].second = MakePayloadType(typeInfo, ownAttrType);
|
||||
else
|
||||
RDCERR("Couldn't find matching attribute type for '%s' by name",
|
||||
executableAttrType->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// raygen shaders only use the ray payload, not attributes
|
||||
else if(entryPoint.stage == ShaderStage::RayGen)
|
||||
{
|
||||
// find the reportHit and grab the type from that
|
||||
for(const Instruction *in : executableFunc->instructions)
|
||||
{
|
||||
const Instruction &inst = *in;
|
||||
|
||||
if(inst.op == Operation::Call && inst.getFuncCall()->name.beginsWith("dx.op.traceRay"))
|
||||
{
|
||||
if(inst.args.size() != 16)
|
||||
{
|
||||
RDCERR("Unexpected number of arguments to traceRay");
|
||||
continue;
|
||||
}
|
||||
const Type *executablePayloadType = inst.args[15]->type;
|
||||
if(!executablePayloadType)
|
||||
{
|
||||
RDCERR("Unexpected untyped payload argument to traceRay");
|
||||
continue;
|
||||
}
|
||||
|
||||
RDCASSERT(executablePayloadType->type == Type::Pointer);
|
||||
executablePayloadType = (Type *)executablePayloadType->inner;
|
||||
|
||||
Type *ownPayloadType = NULL;
|
||||
|
||||
// we have the executable type but we can't use that to look up our type info. Try to
|
||||
// go back by name
|
||||
for(Type *t : m_Types)
|
||||
{
|
||||
if(t->type == executablePayloadType->type && t->name == executablePayloadType->name)
|
||||
{
|
||||
ownPayloadType = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ownPayloadType)
|
||||
rayPayloads[entryPoint].first = MakePayloadType(typeInfo, ownPayloadType);
|
||||
else
|
||||
RDCERR("Couldn't find matching payload type for '%s' by name",
|
||||
executablePayloadType->name);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(entryPoint.stage == ShaderStage::Miss || entryPoint.stage == ShaderStage::AnyHit ||
|
||||
entryPoint.stage == ShaderStage::ClosestHit)
|
||||
{
|
||||
const Type *payloadType = ownFunc->type->members[0];
|
||||
RDCASSERT(payloadType->type == Type::Pointer);
|
||||
payloadType = (Type *)payloadType->inner;
|
||||
|
||||
rdcpair<DXBC::CBufferVariableType, DXBC::CBufferVariableType> &dst =
|
||||
rayPayloads[entryPoint];
|
||||
|
||||
// miss shaders only use the payload, any-hit and closest-hit use both. The first
|
||||
// parameter is the payload, the second is the attributes
|
||||
dst.first = MakePayloadType(typeInfo, payloadType);
|
||||
if(entryPoint.stage != ShaderStage::Miss)
|
||||
{
|
||||
const Type *attrType = ownFunc->type->members[1];
|
||||
RDCASSERT(attrType->type == Type::Pointer);
|
||||
attrType = (Type *)attrType->inner;
|
||||
|
||||
dst.second = MakePayloadType(typeInfo, attrType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3D_PRIMITIVE_TOPOLOGY Program::GetOutputTopology()
|
||||
{
|
||||
if(m_Type != DXBC::ShaderType::Geometry && m_Type != DXBC::ShaderType::Domain &&
|
||||
|
||||
Reference in New Issue
Block a user