mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Open shader source from resource inspector
This commit is contained in:
@@ -207,6 +207,7 @@ TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ShaderSourceFile)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ShaderVariable)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, SigParameter)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, TextureDescription)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ShaderEntryPoint)
|
||||
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, Attachment)
|
||||
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, BindingElement)
|
||||
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, Blend)
|
||||
|
||||
@@ -163,6 +163,8 @@ void ResourceInspector::Inspect(ResourceId id)
|
||||
|
||||
ui->viewContents->setVisible(m_Ctx.GetTexture(id) || m_Ctx.GetBuffer(id));
|
||||
|
||||
m_Entries.clear();
|
||||
|
||||
m_ResourceModel->reset();
|
||||
m_FilterModel->sort(0);
|
||||
|
||||
@@ -181,7 +183,16 @@ void ResourceInspector::Inspect(ResourceId id)
|
||||
m_Ctx.Replay().AsyncInvoke([this, id](IReplayController *r) {
|
||||
rdcarray<EventUsage> usage = r->GetUsage(id);
|
||||
|
||||
GUIInvoke::call([this, id, usage] {
|
||||
rdcarray<ShaderEntryPoint> entries = r->GetShaderEntryPoints(id);
|
||||
|
||||
GUIInvoke::call([this, id, entries, usage] {
|
||||
|
||||
if(!entries.isEmpty())
|
||||
{
|
||||
m_Entries = entries;
|
||||
ui->viewContents->setVisible(true);
|
||||
}
|
||||
|
||||
CombineUsageEvents(
|
||||
m_Ctx, usage, [this, id](uint32_t startEID, uint32_t endEID, ResourceUsage use) {
|
||||
QString text;
|
||||
@@ -392,6 +403,30 @@ void ResourceInspector::on_viewContents_clicked()
|
||||
|
||||
m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this);
|
||||
}
|
||||
else if(!m_Entries.isEmpty())
|
||||
{
|
||||
ShaderEntryPoint entry = m_Entries[0];
|
||||
|
||||
if(m_Entries.count() > 1)
|
||||
{
|
||||
// TODO need to let the user choose the entry point
|
||||
}
|
||||
|
||||
ResourceId id = m_Resource;
|
||||
ICaptureContext *ctx = &m_Ctx;
|
||||
m_Ctx.Replay().AsyncInvoke([ctx, id, entry](IReplayController *r) {
|
||||
ShaderReflection *refl = r->GetShader(id, entry);
|
||||
|
||||
if(!refl)
|
||||
return;
|
||||
|
||||
GUIInvoke::call([ctx, refl] {
|
||||
IShaderViewer *viewer = ctx->ViewShader(refl, ResourceId());
|
||||
|
||||
ctx->AddDockWindow(viewer->Widget(), DockReference::MainToolArea, NULL);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceInspector::on_resourceUsage_doubleClicked(const QModelIndex &index)
|
||||
|
||||
@@ -74,6 +74,8 @@ private:
|
||||
Ui::ResourceInspector *ui;
|
||||
ICaptureContext &m_Ctx;
|
||||
|
||||
rdcarray<ShaderEntryPoint> m_Entries;
|
||||
|
||||
ResourceId m_Resource;
|
||||
ResourceListItemModel *m_ResourceModel;
|
||||
QSortFilterProxyModel *m_FilterModel;
|
||||
|
||||
@@ -844,6 +844,27 @@ newly generated messages will be returned after that.
|
||||
)");
|
||||
virtual rdcarray<DebugMessage> GetDebugMessages() = 0;
|
||||
|
||||
DOCUMENT(R"(Retrieve a list of entry points for a shader.
|
||||
|
||||
If the given ID doesn't specify a shader, an empty list will be return. On some APIs, the list will
|
||||
only ever have one result (only one entry point per shader).
|
||||
|
||||
:param ResourceId shader: The shader to look up entry points for.
|
||||
:return: The list of the :class:`ShaderEntryPoint` messages.
|
||||
:rtype: ``list`` of :class:`ShaderEntryPoint`
|
||||
)");
|
||||
virtual rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader) = 0;
|
||||
|
||||
DOCUMENT(R"(Retrieve the information about the frame contained in the capture.
|
||||
|
||||
:param ResourceId shader: The shader to get reflection data for.
|
||||
:param ShaderEntryPoint entry: The entry point within the shader to reflect. May be ignored on some
|
||||
APIs
|
||||
:return: The frame information.
|
||||
:rtype: ShaderReflection
|
||||
)");
|
||||
virtual ShaderReflection *GetShader(ResourceId shader, ShaderEntryPoint entry) = 0;
|
||||
|
||||
DOCUMENT(R"(Retrieve the history of modifications to the selected pixel on the selected texture.
|
||||
|
||||
:param ResourceId texture: The texture to search for modifications.
|
||||
|
||||
@@ -451,6 +451,18 @@ able to be read from and written to arbitrarily.
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(ShaderResource);
|
||||
|
||||
DOCUMENT("Describes an entry point in a shader.");
|
||||
struct ShaderEntryPoint
|
||||
{
|
||||
DOCUMENT("The name of the entry point.");
|
||||
rdcstr name;
|
||||
|
||||
DOCUMENT("The :class:`ShaderStage` for this entry point .");
|
||||
ShaderStage stage;
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(ShaderEntryPoint);
|
||||
|
||||
DOCUMENT("Contains a single flag used at compile-time on a shader.");
|
||||
struct ShaderCompileFlag
|
||||
{
|
||||
|
||||
@@ -202,6 +202,7 @@ public:
|
||||
{
|
||||
return ResourceId();
|
||||
}
|
||||
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader) { return {}; }
|
||||
ShaderReflection *GetShader(ResourceId shader, string entryPoint) { return NULL; }
|
||||
vector<string> GetDisassemblyTargets() { return {"N/A"}; }
|
||||
string DisassembleShader(ResourceId pipeline, const ShaderReflection *refl, const string &target)
|
||||
|
||||
@@ -783,6 +783,38 @@ ResourceId ReplayProxy::RenderOverlay(ResourceId texid, CompType typeHint, Debug
|
||||
PROXY_FUNCTION(RenderOverlay, texid, typeHint, overlay, eventID, passEvents);
|
||||
}
|
||||
|
||||
template <typename ParamSerialiser, typename ReturnSerialiser>
|
||||
rdcarray<ShaderEntryPoint> ReplayProxy::Proxied_GetShaderEntryPoints(ParamSerialiser ¶mser,
|
||||
ReturnSerialiser &retser,
|
||||
ResourceId id)
|
||||
{
|
||||
const ReplayProxyPacket packet = eReplayProxy_GetShaderEntryPoints;
|
||||
rdcarray<ShaderEntryPoint> ret;
|
||||
|
||||
{
|
||||
BEGIN_PARAMS();
|
||||
SERIALISE_ELEMENT(id);
|
||||
END_PARAMS();
|
||||
}
|
||||
|
||||
if(paramser.IsReading() && !paramser.IsErrored() && !m_IsErrored)
|
||||
ret = m_Remote->GetShaderEntryPoints(id);
|
||||
|
||||
{
|
||||
ReturnSerialiser &ser = retser;
|
||||
PACKET_HEADER(packet);
|
||||
SERIALISE_ELEMENT(ret);
|
||||
ser.EndChunk();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
rdcarray<ShaderEntryPoint> ReplayProxy::GetShaderEntryPoints(ResourceId id)
|
||||
{
|
||||
PROXY_FUNCTION(GetShaderEntryPoints, id);
|
||||
}
|
||||
|
||||
template <typename ParamSerialiser, typename ReturnSerialiser>
|
||||
ShaderReflection *ReplayProxy::Proxied_GetShader(ParamSerialiser ¶mser, ReturnSerialiser &retser,
|
||||
ResourceId id, std::string entryPoint)
|
||||
|
||||
@@ -47,6 +47,7 @@ enum ReplayProxyPacket
|
||||
eReplayProxy_GetTexture,
|
||||
eReplayProxy_GetBuffers,
|
||||
eReplayProxy_GetBuffer,
|
||||
eReplayProxy_GetShaderEntryPoints,
|
||||
eReplayProxy_GetShader,
|
||||
eReplayProxy_GetDebugMessages,
|
||||
|
||||
@@ -439,6 +440,7 @@ public:
|
||||
DebugOverlay overlay, uint32_t eventID,
|
||||
const std::vector<uint32_t> &passEvents);
|
||||
|
||||
IMPLEMENT_FUNCTION_PROXIED(rdcarray<ShaderEntryPoint>, GetShaderEntryPoints, ResourceId shader);
|
||||
IMPLEMENT_FUNCTION_PROXIED(ShaderReflection *, GetShader, ResourceId shader,
|
||||
std::string entryPoint);
|
||||
|
||||
|
||||
@@ -228,6 +228,18 @@ TextureDescription D3D11Replay::GetTexture(ResourceId id)
|
||||
return tex;
|
||||
}
|
||||
|
||||
rdcarray<ShaderEntryPoint> D3D11Replay::GetShaderEntryPoints(ResourceId shader)
|
||||
{
|
||||
auto it = WrappedShader::m_ShaderList.find(shader);
|
||||
|
||||
if(it == WrappedShader::m_ShaderList.end())
|
||||
return {};
|
||||
|
||||
ShaderReflection &ret = it->second->GetDetails();
|
||||
|
||||
return {{"main", ret.Stage}};
|
||||
}
|
||||
|
||||
ShaderReflection *D3D11Replay::GetShader(ResourceId shader, string entryPoint)
|
||||
{
|
||||
auto it = WrappedShader::m_ShaderList.find(shader);
|
||||
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
|
||||
vector<DebugMessage> GetDebugMessages();
|
||||
|
||||
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
|
||||
ShaderReflection *GetShader(ResourceId shader, string entryPoint);
|
||||
|
||||
vector<string> GetDisassemblyTargets();
|
||||
|
||||
@@ -234,6 +234,19 @@ TextureDescription D3D12Replay::GetTexture(ResourceId id)
|
||||
return ret;
|
||||
}
|
||||
|
||||
rdcarray<ShaderEntryPoint> D3D12Replay::GetShaderEntryPoints(ResourceId shader)
|
||||
{
|
||||
WrappedID3D12Shader *sh =
|
||||
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12Shader>(shader);
|
||||
|
||||
if(!sh)
|
||||
return {};
|
||||
|
||||
ShaderReflection &ret = sh->GetDetails();
|
||||
|
||||
return {{"main", ret.Stage}};
|
||||
}
|
||||
|
||||
ShaderReflection *D3D12Replay::GetShader(ResourceId shader, string entryPoint)
|
||||
{
|
||||
WrappedID3D12Shader *sh =
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
|
||||
vector<DebugMessage> GetDebugMessages();
|
||||
|
||||
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
|
||||
ShaderReflection *GetShader(ResourceId shader, string entryPoint);
|
||||
|
||||
vector<string> GetDisassemblyTargets();
|
||||
|
||||
@@ -1071,6 +1071,22 @@ TextureFilter MakeFilter(GLenum minf, GLenum magf, bool shadowSampler, float max
|
||||
return ret;
|
||||
}
|
||||
|
||||
ShaderStage MakeShaderStage(GLenum type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case eGL_VERTEX_SHADER: return ShaderStage::Vertex;
|
||||
case eGL_TESS_CONTROL_SHADER: return ShaderStage::Tess_Control;
|
||||
case eGL_TESS_EVALUATION_SHADER: return ShaderStage::Tess_Eval;
|
||||
case eGL_GEOMETRY_SHADER: return ShaderStage::Geometry;
|
||||
case eGL_FRAGMENT_SHADER: return ShaderStage::Fragment;
|
||||
case eGL_COMPUTE_SHADER: return ShaderStage::Compute;
|
||||
default: RDCERR("Unexpected shader stage %s", ToStr(type).c_str());
|
||||
}
|
||||
|
||||
return ShaderStage::Count;
|
||||
}
|
||||
|
||||
CompareFunc MakeCompareFunc(GLenum func)
|
||||
{
|
||||
switch(func)
|
||||
|
||||
@@ -296,6 +296,7 @@ GLenum MakeGLPrimitiveTopology(Topology Topo);
|
||||
BufferCategory MakeBufferCategory(GLenum bufferTarget);
|
||||
AddressMode MakeAddressMode(GLenum addr);
|
||||
TextureFilter MakeFilter(GLenum minf, GLenum magf, bool shadowSampler, float maxAniso);
|
||||
ShaderStage MakeShaderStage(GLenum type);
|
||||
CompareFunc MakeCompareFunc(GLenum func);
|
||||
StencilOp MakeStencilOp(GLenum op);
|
||||
LogicOp MakeLogicOp(GLenum op);
|
||||
|
||||
@@ -759,6 +759,22 @@ vector<DebugMessage> GLReplay::GetDebugMessages()
|
||||
return m_pDriver->GetDebugMessages();
|
||||
}
|
||||
|
||||
rdcarray<ShaderEntryPoint> GLReplay::GetShaderEntryPoints(ResourceId shader)
|
||||
{
|
||||
if(m_pDriver->m_Shaders.find(shader) == m_pDriver->m_Shaders.end())
|
||||
return {};
|
||||
|
||||
WrappedOpenGL::ShaderData &shaderDetails = m_pDriver->m_Shaders[shader];
|
||||
|
||||
if(shaderDetails.prog == 0)
|
||||
{
|
||||
RDCERR("Can't get shader details without separable program");
|
||||
return {};
|
||||
}
|
||||
|
||||
return {{"main", MakeShaderStage(shaderDetails.type)}};
|
||||
}
|
||||
|
||||
ShaderReflection *GLReplay::GetShader(ResourceId shader, string entryPoint)
|
||||
{
|
||||
auto &shaderDetails = m_pDriver->m_Shaders[shader];
|
||||
|
||||
@@ -101,6 +101,8 @@ public:
|
||||
|
||||
std::vector<ResourceId> GetTextures();
|
||||
TextureDescription GetTexture(ResourceId id);
|
||||
|
||||
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
|
||||
ShaderReflection *GetShader(ResourceId shader, string entryPoint);
|
||||
|
||||
vector<string> GetDisassemblyTargets();
|
||||
|
||||
@@ -117,20 +117,7 @@ void WrappedOpenGL::ShaderData::Compile(WrappedOpenGL &gl, ResourceId id, GLuint
|
||||
reflection.ID = id;
|
||||
reflection.EntryPoint = "main";
|
||||
|
||||
switch(settings.stage)
|
||||
{
|
||||
case SPIRVShaderStage::Vertex: reflection.Stage = ShaderStage::Vertex; break;
|
||||
case SPIRVShaderStage::TessControl: reflection.Stage = ShaderStage::Tess_Control; break;
|
||||
case SPIRVShaderStage::TessEvaluation: reflection.Stage = ShaderStage::Tess_Eval; break;
|
||||
case SPIRVShaderStage::Geometry: reflection.Stage = ShaderStage::Geometry; break;
|
||||
case SPIRVShaderStage::Fragment: reflection.Stage = ShaderStage::Fragment; break;
|
||||
case SPIRVShaderStage::Compute: reflection.Stage = ShaderStage::Compute; break;
|
||||
case SPIRVShaderStage::Invalid:
|
||||
default:
|
||||
RDCERR("Unexpected shader stage %u", settings.stage);
|
||||
reflection.Stage = ShaderStage::Vertex;
|
||||
break;
|
||||
}
|
||||
reflection.Stage = MakeShaderStage(type);
|
||||
|
||||
// TODO sort these so that the first file contains the entry point
|
||||
reflection.DebugInfo.files.resize(sources.size());
|
||||
|
||||
@@ -129,6 +129,7 @@ struct SPVModule
|
||||
SPVInstruction *GetByID(uint32_t id);
|
||||
string Disassemble(const string &entryPoint);
|
||||
|
||||
std::vector<std::string> EntryPoints() const;
|
||||
ShaderStage StageForEntry(const string &entryPoint) const;
|
||||
|
||||
void MakeReflection(ShaderStage stage, const string &entryPoint, ShaderReflection &reflection,
|
||||
|
||||
@@ -3877,6 +3877,17 @@ void AddSignatureParameter(bool isInput, ShaderStage stage, uint32_t id,
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> SPVModule::EntryPoints() const
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
|
||||
for(SPVInstruction *inst : entries)
|
||||
if(inst->entry)
|
||||
ret.push_back(inst->entry->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ShaderStage SPVModule::StageForEntry(const string &entryPoint) const
|
||||
{
|
||||
for(SPVInstruction *inst : entries)
|
||||
|
||||
@@ -879,6 +879,23 @@ BufferDescription VulkanReplay::GetBuffer(ResourceId id)
|
||||
return ret;
|
||||
}
|
||||
|
||||
rdcarray<ShaderEntryPoint> VulkanReplay::GetShaderEntryPoints(ResourceId shader)
|
||||
{
|
||||
auto shad = m_pDriver->m_CreationInfo.m_ShaderModule.find(shader);
|
||||
|
||||
if(shad == m_pDriver->m_CreationInfo.m_ShaderModule.end())
|
||||
return {};
|
||||
|
||||
std::vector<std::string> entries = shad->second.spirv.EntryPoints();
|
||||
|
||||
rdcarray<ShaderEntryPoint> ret;
|
||||
|
||||
for(const std::string &e : entries)
|
||||
ret.push_back({e, shad->second.spirv.StageForEntry(e)});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ShaderReflection *VulkanReplay::GetShader(ResourceId shader, string entryPoint)
|
||||
{
|
||||
auto shad = m_pDriver->m_CreationInfo.m_ShaderModule.find(shader);
|
||||
|
||||
@@ -145,6 +145,7 @@ public:
|
||||
std::vector<ResourceId> GetTextures();
|
||||
TextureDescription GetTexture(ResourceId id);
|
||||
|
||||
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
|
||||
ShaderReflection *GetShader(ResourceId shader, string entryPoint);
|
||||
|
||||
vector<string> GetDisassemblyTargets();
|
||||
|
||||
@@ -224,6 +224,15 @@ void DoSerialise(SerialiserType &ser, ShaderResource &el)
|
||||
SIZE_CHECK(80);
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
void DoSerialise(SerialiserType &ser, ShaderEntryPoint &el)
|
||||
{
|
||||
SERIALISE_MEMBER(name);
|
||||
SERIALISE_MEMBER(stage);
|
||||
|
||||
SIZE_CHECK(24);
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
void DoSerialise(SerialiserType &ser, ShaderCompileFlag &el)
|
||||
{
|
||||
@@ -2199,6 +2208,7 @@ INSTANTIATE_SERIALISE_TYPE(ShaderConstant)
|
||||
INSTANTIATE_SERIALISE_TYPE(ConstantBlock)
|
||||
INSTANTIATE_SERIALISE_TYPE(ShaderSampler)
|
||||
INSTANTIATE_SERIALISE_TYPE(ShaderResource)
|
||||
INSTANTIATE_SERIALISE_TYPE(ShaderEntryPoint)
|
||||
INSTANTIATE_SERIALISE_TYPE(ShaderCompileFlags)
|
||||
INSTANTIATE_SERIALISE_TYPE(ShaderDebugChunk)
|
||||
INSTANTIATE_SERIALISE_TYPE(ShaderReflection)
|
||||
|
||||
@@ -318,6 +318,16 @@ rdcarray<DebugMessage> ReplayController::GetDebugMessages()
|
||||
return m_pDevice->GetDebugMessages();
|
||||
}
|
||||
|
||||
rdcarray<ShaderEntryPoint> ReplayController::GetShaderEntryPoints(ResourceId shader)
|
||||
{
|
||||
return m_pDevice->GetShaderEntryPoints(m_pDevice->GetLiveID(shader));
|
||||
}
|
||||
|
||||
ShaderReflection *ReplayController::GetShader(ResourceId shader, ShaderEntryPoint entry)
|
||||
{
|
||||
return m_pDevice->GetShader(m_pDevice->GetLiveID(shader), entry.name);
|
||||
}
|
||||
|
||||
rdcarray<EventUsage> ReplayController::GetUsage(ResourceId id)
|
||||
{
|
||||
id = m_pDevice->GetLiveID(id);
|
||||
|
||||
@@ -167,6 +167,9 @@ public:
|
||||
const rdcarray<ResourceDescription> &GetResources();
|
||||
rdcarray<DebugMessage> GetDebugMessages();
|
||||
|
||||
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
|
||||
ShaderReflection *GetShader(ResourceId shader, ShaderEntryPoint entry);
|
||||
|
||||
rdcarray<PixelModification> PixelHistory(ResourceId target, uint32_t x, uint32_t y, uint32_t slice,
|
||||
uint32_t mip, uint32_t sampleIdx, CompType typeHint);
|
||||
ShaderDebugTrace *DebugVertex(uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset,
|
||||
|
||||
@@ -100,6 +100,7 @@ public:
|
||||
|
||||
virtual vector<DebugMessage> GetDebugMessages() = 0;
|
||||
|
||||
virtual rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader) = 0;
|
||||
virtual ShaderReflection *GetShader(ResourceId shader, string entryPoint) = 0;
|
||||
|
||||
virtual vector<string> GetDisassemblyTargets() = 0;
|
||||
|
||||
Reference in New Issue
Block a user