Account for pipeline specialisation constants when reflecting shaders

This commit is contained in:
baldurk
2019-08-16 17:38:35 +01:00
parent e71f986f84
commit ee43d4377c
34 changed files with 535 additions and 154 deletions
@@ -109,6 +109,8 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
ResourceId prevShader = m_shader;
m_pipe = m_stage == ShaderStage::Compute ? m_Ctx.CurPipelineState().GetComputePipelineObject()
: m_Ctx.CurPipelineState().GetGraphicsPipelineObject();
m_shader = m_Ctx.CurPipelineState().GetShader(m_stage);
QString entryPoint = m_Ctx.CurPipelineState().GetShaderEntryPoint(m_stage);
const ShaderReflection *reflection = m_Ctx.CurPipelineState().GetShaderReflection(m_stage);
@@ -153,7 +155,7 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
{
m_Ctx.Replay().AsyncInvoke([this, prevShader, entryPoint, offs, wasEmpty](IReplayController *r) {
rdcarray<ShaderVariable> vars = r->GetCBufferVariableContents(
m_shader, entryPoint.toUtf8().data(), m_slot, m_cbuffer, offs);
m_pipe, m_shader, entryPoint.toUtf8().data(), m_slot, m_cbuffer, offs);
GUIInvoke::call(this, [this, prevShader, vars, wasEmpty] {
RDTreeViewExpansionState &prevShaderExpansionState =
@@ -72,6 +72,7 @@ private:
ICaptureContext &m_Ctx;
ResourceId m_cbuffer;
ResourceId m_pipe;
ResourceId m_shader;
ShaderStage m_stage = ShaderStage::Vertex;
uint32_t m_slot = 0;
+4 -2
View File
@@ -478,10 +478,12 @@ void ResourceInspector::on_viewContents_clicked()
// TODO need to let the user choose the entry point
}
// TODO allow choosing parent pipeline?
ResourceId pipeid;
ResourceId id = m_Resource;
ICaptureContext *ctx = &m_Ctx;
m_Ctx.Replay().AsyncInvoke([this, ctx, id, entry](IReplayController *r) {
ShaderReflection *refl = r->GetShader(id, entry);
m_Ctx.Replay().AsyncInvoke([this, ctx, pipeid, id, entry](IReplayController *r) {
ShaderReflection *refl = r->GetShader(pipeid, id, entry);
if(!refl)
return;
+5 -2
View File
@@ -1178,13 +1178,15 @@ only ever have one result (only one entry point per shader).
DOCUMENT(R"(Retrieve the information about the frame contained in the capture.
:param ResourceId pipeline: The pipeline state object, if applicable, that this shader is bound to.
: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;
virtual ShaderReflection *GetShader(ResourceId pipeline, ResourceId shader,
ShaderEntryPoint entry) = 0;
DOCUMENT(R"(Retrieve the history of modifications to the selected pixel on the selected texture.
@@ -1270,6 +1272,7 @@ only ever have one result (only one entry point per shader).
DOCUMENT(R"(Retrieve the contents of a constant block by reading from memory or their source
otherwise.
:param ResourceId pipeline: The pipeline state object, if applicable, that this shader is bound to.
:param ResourceId shader: The id of the shader to use for metadata.
:param str entryPoint: The entry point of the shader being used. In some APIs, this is ignored.
:param int cbufslot: The index in the :data:`ShaderReflection.constantBlocks` list to look up.
@@ -1279,7 +1282,7 @@ otherwise.
:return: The shader variables with their contents.
:rtype: ``list`` of :class:`ShaderVariable`
)");
virtual rdcarray<ShaderVariable> GetCBufferVariableContents(ResourceId shader,
virtual rdcarray<ShaderVariable> GetCBufferVariableContents(ResourceId pipeline, ResourceId shader,
const char *entryPoint,
uint32_t cbufslot, ResourceId buffer,
uint64_t offs) = 0;
+6 -3
View File
@@ -215,8 +215,8 @@ public:
{
return std::vector<CounterResult>();
}
void FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data)
void FillCBufferVariables(ResourceId pipeline, ResourceId shader, std::string entryPoint,
uint32_t cbufSlot, rdcarray<ShaderVariable> &outvars, const bytebuf &data)
{
}
void GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, bytebuf &retData) {}
@@ -235,7 +235,10 @@ public:
return ResourceId();
}
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader) { return {}; }
ShaderReflection *GetShader(ResourceId shader, ShaderEntryPoint entry) { return NULL; }
ShaderReflection *GetShader(ResourceId pipeline, ResourceId shader, ShaderEntryPoint entry)
{
return NULL;
}
std::vector<std::string> GetDisassemblyTargets() { return {"N/A"}; }
std::string DisassembleShader(ResourceId pipeline, const ShaderReflection *refl,
const std::string &target)
+39 -22
View File
@@ -734,15 +734,16 @@ CounterDescription ReplayProxy::DescribeCounter(GPUCounter counterID)
template <typename ParamSerialiser, typename ReturnSerialiser>
void ReplayProxy::Proxied_FillCBufferVariables(ParamSerialiser &paramser, ReturnSerialiser &retser,
ResourceId shader, std::string entryPoint,
uint32_t cbufSlot, rdcarray<ShaderVariable> &outvars,
const bytebuf &data)
ResourceId pipeline, ResourceId shader,
std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data)
{
const ReplayProxyPacket expectedPacket = eReplayProxy_FillCBufferVariables;
ReplayProxyPacket packet = eReplayProxy_FillCBufferVariables;
{
BEGIN_PARAMS();
SERIALISE_ELEMENT(pipeline);
SERIALISE_ELEMENT(shader);
SERIALISE_ELEMENT(entryPoint);
SERIALISE_ELEMENT(cbufSlot);
@@ -753,16 +754,17 @@ void ReplayProxy::Proxied_FillCBufferVariables(ParamSerialiser &paramser, Return
{
REMOTE_EXECUTION();
if(paramser.IsReading() && !paramser.IsErrored() && !m_IsErrored)
m_Remote->FillCBufferVariables(shader, entryPoint, cbufSlot, outvars, data);
m_Remote->FillCBufferVariables(pipeline, shader, entryPoint, cbufSlot, outvars, data);
}
SERIALISE_RETURN(outvars);
}
void ReplayProxy::FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
void ReplayProxy::FillCBufferVariables(ResourceId pipeline, ResourceId shader,
std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data)
{
PROXY_FUNCTION(FillCBufferVariables, shader, entryPoint, cbufSlot, outvars, data);
PROXY_FUNCTION(FillCBufferVariables, pipeline, shader, entryPoint, cbufSlot, outvars, data);
}
template <typename ParamSerialiser, typename ReturnSerialiser>
@@ -1084,22 +1086,24 @@ rdcarray<ShaderEntryPoint> ReplayProxy::GetShaderEntryPoints(ResourceId id)
}
template <typename ParamSerialiser, typename ReturnSerialiser>
ShaderReflection *ReplayProxy::Proxied_GetShader(ParamSerialiser &paramser, ReturnSerialiser &retser,
ResourceId id, ShaderEntryPoint entry)
ShaderReflection *ReplayProxy::Proxied_GetShader(ParamSerialiser &paramser,
ReturnSerialiser &retser, ResourceId pipeline,
ResourceId shader, ShaderEntryPoint entry)
{
const ReplayProxyPacket expectedPacket = eReplayProxy_GetShader;
ReplayProxyPacket packet = eReplayProxy_GetShader;
ShaderReflection *ret = NULL;
// only consider eventID part of the key on APIs where shaders are mutable
ShaderReflKey key(m_APIProps.shadersMutable ? m_EventID : 0, id, entry);
ShaderReflKey key(m_APIProps.shadersMutable ? m_EventID : 0, pipeline, shader, entry);
if(retser.IsReading() && m_ShaderReflectionCache.find(key) != m_ShaderReflectionCache.end())
return m_ShaderReflectionCache[key];
{
BEGIN_PARAMS();
SERIALISE_ELEMENT(id);
SERIALISE_ELEMENT(pipeline);
SERIALISE_ELEMENT(shader);
SERIALISE_ELEMENT(entry);
END_PARAMS();
}
@@ -1107,7 +1111,7 @@ ShaderReflection *ReplayProxy::Proxied_GetShader(ParamSerialiser &paramser, Retu
{
REMOTE_EXECUTION();
if(paramser.IsReading() && !paramser.IsErrored() && !m_IsErrored)
ret = m_Remote->GetShader(id, entry);
ret = m_Remote->GetShader(pipeline, shader, entry);
}
{
@@ -1131,9 +1135,10 @@ ShaderReflection *ReplayProxy::Proxied_GetShader(ParamSerialiser &paramser, Retu
return m_ShaderReflectionCache[key];
}
ShaderReflection *ReplayProxy::GetShader(ResourceId id, ShaderEntryPoint entry)
ShaderReflection *ReplayProxy::GetShader(ResourceId pipeline, ResourceId shader,
ShaderEntryPoint entry)
{
PROXY_FUNCTION(GetShader, id, entry);
PROXY_FUNCTION(GetShader, pipeline, shader, entry);
}
template <typename ParamSerialiser, typename ReturnSerialiser>
@@ -1166,7 +1171,7 @@ std::string ReplayProxy::Proxied_DisassembleShader(ParamSerialiser &paramser,
if(paramser.IsReading() && !paramser.IsErrored() && !m_IsErrored)
{
refl = m_Remote->GetShader(m_Remote->GetLiveID(Shader), EntryPoint);
refl = m_Remote->GetShader(pipeline, m_Remote->GetLiveID(Shader), EntryPoint);
ret = m_Remote->DisassembleShader(pipeline, refl, target);
}
@@ -1591,11 +1596,13 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
for(int i = 0; i < 6; i++)
if(stages[i]->resourceId != ResourceId())
stages[i]->reflection = GetShader(GetLiveID(stages[i]->resourceId), ShaderEntryPoint());
stages[i]->reflection =
GetShader(ResourceId(), GetLiveID(stages[i]->resourceId), ShaderEntryPoint());
if(m_D3D11PipelineState.inputAssembly.resourceId != ResourceId())
m_D3D11PipelineState.inputAssembly.bytecode = GetShader(
GetLiveID(m_D3D11PipelineState.inputAssembly.resourceId), ShaderEntryPoint());
m_D3D11PipelineState.inputAssembly.bytecode =
GetShader(ResourceId(), GetLiveID(m_D3D11PipelineState.inputAssembly.resourceId),
ShaderEntryPoint());
}
else if(m_APIProps.pipelineType == GraphicsAPI::D3D12)
{
@@ -1605,9 +1612,12 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
&m_D3D12PipelineState.pixelShader, &m_D3D12PipelineState.computeShader,
};
ResourceId pipe = GetLiveID(m_D3D12PipelineState.pipelineResourceId);
for(int i = 0; i < 6; i++)
if(stages[i]->resourceId != ResourceId())
stages[i]->reflection = GetShader(GetLiveID(stages[i]->resourceId), ShaderEntryPoint());
stages[i]->reflection =
GetShader(pipe, GetLiveID(stages[i]->resourceId), ShaderEntryPoint());
}
else if(m_APIProps.pipelineType == GraphicsAPI::OpenGL)
{
@@ -1620,7 +1630,7 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
for(int i = 0; i < 6; i++)
if(stages[i]->shaderResourceId != ResourceId())
stages[i]->reflection =
GetShader(GetLiveID(stages[i]->shaderResourceId), ShaderEntryPoint());
GetShader(ResourceId(), GetLiveID(stages[i]->shaderResourceId), ShaderEntryPoint());
}
else if(m_APIProps.pipelineType == GraphicsAPI::Vulkan)
{
@@ -1630,11 +1640,18 @@ void ReplayProxy::Proxied_SavePipelineState(ParamSerialiser &paramser, ReturnSer
&m_VulkanPipelineState.fragmentShader, &m_VulkanPipelineState.computeShader,
};
ResourceId pipe = GetLiveID(m_VulkanPipelineState.graphics.pipelineResourceId);
for(int i = 0; i < 6; i++)
{
if(i == 5)
pipe = GetLiveID(m_VulkanPipelineState.compute.pipelineResourceId);
if(stages[i]->resourceId != ResourceId())
stages[i]->reflection =
GetShader(GetLiveID(stages[i]->resourceId),
GetShader(pipe, GetLiveID(stages[i]->resourceId),
ShaderEntryPoint(stages[i]->entryPoint, stages[i]->stage));
}
}
}
}
@@ -2573,7 +2590,7 @@ bool ReplayProxy::Tick(int type)
case eReplayProxy_GetBuffers: GetBuffers(); break;
case eReplayProxy_GetBuffer: GetBuffer(ResourceId()); break;
case eReplayProxy_GetShaderEntryPoints: GetShaderEntryPoints(ResourceId()); break;
case eReplayProxy_GetShader: GetShader(ResourceId(), ShaderEntryPoint()); break;
case eReplayProxy_GetShader: GetShader(ResourceId(), ResourceId(), ShaderEntryPoint()); break;
case eReplayProxy_GetDebugMessages: GetDebugMessages(); break;
case eReplayProxy_GetBufferData:
{
@@ -2606,7 +2623,7 @@ bool ReplayProxy::Tick(int type)
{
rdcarray<ShaderVariable> vars;
bytebuf data;
FillCBufferVariables(ResourceId(), "", 0, vars, data);
FillCBufferVariables(ResourceId(), ResourceId(), "", 0, vars, data);
break;
}
case eReplayProxy_InitPostVS: InitPostVSBuffers(0); break;
+14 -8
View File
@@ -490,9 +490,9 @@ public:
IMPLEMENT_FUNCTION_PROXIED(std::vector<CounterResult>, FetchCounters,
const std::vector<GPUCounter> &counterID);
IMPLEMENT_FUNCTION_PROXIED(void, FillCBufferVariables, ResourceId shader, std::string entryPoint,
uint32_t cbufSlot, rdcarray<ShaderVariable> &outvars,
const bytebuf &data);
IMPLEMENT_FUNCTION_PROXIED(void, FillCBufferVariables, ResourceId pipeline, ResourceId shader,
std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data);
IMPLEMENT_FUNCTION_PROXIED(void, GetBufferData, ResourceId buff, uint64_t offset, uint64_t len,
bytebuf &retData);
@@ -509,7 +509,7 @@ public:
const std::vector<uint32_t> &passEvents);
IMPLEMENT_FUNCTION_PROXIED(rdcarray<ShaderEntryPoint>, GetShaderEntryPoints, ResourceId shader);
IMPLEMENT_FUNCTION_PROXIED(ShaderReflection *, GetShader, ResourceId shader,
IMPLEMENT_FUNCTION_PROXIED(ShaderReflection *, GetShader, ResourceId pipeline, ResourceId,
ShaderEntryPoint entry);
IMPLEMENT_FUNCTION_PROXIED(std::vector<std::string>, GetDisassemblyTargets);
@@ -638,17 +638,23 @@ private:
struct ShaderReflKey
{
ShaderReflKey() {}
ShaderReflKey(uint32_t eid, ResourceId i, ShaderEntryPoint e) : eventId(eid), id(i), entry(e) {}
ShaderReflKey(uint32_t eid, ResourceId p, ResourceId s, ShaderEntryPoint e)
: eventId(eid), pipeline(p), shader(s), entry(e)
{
}
uint32_t eventId;
ResourceId id;
ResourceId pipeline, shader;
ShaderEntryPoint entry;
bool operator<(const ShaderReflKey &o) const
{
if(eventId != o.eventId)
return eventId < o.eventId;
if(id != o.id)
return id < o.id;
if(pipeline != o.pipeline)
return pipeline < o.pipeline;
if(shader != o.shader)
return shader < o.shader;
return entry < o.entry;
}
+5 -3
View File
@@ -438,7 +438,8 @@ rdcarray<ShaderEntryPoint> D3D11Replay::GetShaderEntryPoints(ResourceId shader)
return {{"main", ret.stage}};
}
ShaderReflection *D3D11Replay::GetShader(ResourceId shader, ShaderEntryPoint entry)
ShaderReflection *D3D11Replay::GetShader(ResourceId pipeline, ResourceId shader,
ShaderEntryPoint entry)
{
auto it = WrappedShader::m_ShaderList.find(shader);
@@ -659,7 +660,7 @@ void D3D11Replay::SavePipelineState(uint32_t eventId)
ResourceId layoutId = GetIDForResource(rs->IA.Layout);
ret.inputAssembly.resourceId = rm->GetOriginalID(layoutId);
ret.inputAssembly.bytecode = GetShader(layoutId, ShaderEntryPoint());
ret.inputAssembly.bytecode = GetShader(ResourceId(), layoutId, ShaderEntryPoint());
ret.inputAssembly.layouts.resize(vec.size());
for(size_t i = 0; i < vec.size(); i++)
@@ -2592,7 +2593,8 @@ void D3D11Replay::RenderHighlightBox(float w, float h, float scale)
}
}
void D3D11Replay::FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
void D3D11Replay::FillCBufferVariables(ResourceId pipeline, ResourceId shader,
std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data)
{
auto it = WrappedShader::m_ShaderList.find(shader);
+4 -3
View File
@@ -119,7 +119,7 @@ public:
std::vector<DebugMessage> GetDebugMessages();
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
ShaderReflection *GetShader(ResourceId shader, ShaderEntryPoint entry);
ShaderReflection *GetShader(ResourceId pipeline, ResourceId shader, ShaderEntryPoint entry);
std::vector<std::string> GetDisassemblyTargets();
std::string DisassembleShader(ResourceId pipeline, const ShaderReflection *refl,
@@ -217,8 +217,9 @@ public:
void RenderHighlightBox(float w, float h, float scale);
void FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data);
void FillCBufferVariables(ResourceId pipeline, ResourceId shader, std::string entryPoint,
uint32_t cbufSlot, rdcarray<ShaderVariable> &outvars,
const bytebuf &data);
std::vector<PixelModification> PixelHistory(std::vector<EventUsage> events, ResourceId target,
uint32_t x, uint32_t y, uint32_t slice, uint32_t mip,
+4 -2
View File
@@ -409,7 +409,8 @@ rdcarray<ShaderEntryPoint> D3D12Replay::GetShaderEntryPoints(ResourceId shader)
return {{"main", ret.stage}};
}
ShaderReflection *D3D12Replay::GetShader(ResourceId shader, ShaderEntryPoint entry)
ShaderReflection *D3D12Replay::GetShader(ResourceId pipeline, ResourceId shader,
ShaderEntryPoint entry)
{
WrappedID3D12Shader *sh =
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12Shader>(shader);
@@ -2652,7 +2653,8 @@ void D3D12Replay::GetBufferData(ResourceId buff, uint64_t offset, uint64_t lengt
GetDebugManager()->GetBufferData(buffer, offset, length, retData);
}
void D3D12Replay::FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
void D3D12Replay::FillCBufferVariables(ResourceId pipeline, ResourceId shader,
std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data)
{
if(shader == ResourceId())
+4 -3
View File
@@ -78,7 +78,7 @@ public:
std::vector<DebugMessage> GetDebugMessages();
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
ShaderReflection *GetShader(ResourceId shader, ShaderEntryPoint entry);
ShaderReflection *GetShader(ResourceId pipeline, ResourceId shader, ShaderEntryPoint entry);
std::vector<std::string> GetDisassemblyTargets();
std::string DisassembleShader(ResourceId pipeline, const ShaderReflection *refl,
@@ -178,8 +178,9 @@ public:
void RenderHighlightBox(float w, float h, float scale);
void FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data);
void FillCBufferVariables(ResourceId pipeline, ResourceId shader, std::string entryPoint,
uint32_t cbufSlot, rdcarray<ShaderVariable> &outvars,
const bytebuf &data);
std::vector<PixelModification> PixelHistory(std::vector<EventUsage> events, ResourceId target,
uint32_t x, uint32_t y, uint32_t slice, uint32_t mip,
+2 -2
View File
@@ -123,7 +123,7 @@ bool GLReplay::CreateOverlayProgram(GLuint Program, GLuint Pipeline, GLuint frag
}
if(i == 0)
vsRefl = GetShader(pipeDetails.stageShaders[i], ShaderEntryPoint());
vsRefl = GetShader(ResourceId(), pipeDetails.stageShaders[i], ShaderEntryPoint());
}
}
}
@@ -151,7 +151,7 @@ bool GLReplay::CreateOverlayProgram(GLuint Program, GLuint Pipeline, GLuint frag
HasGLSLShaders = true;
if(i == 0)
vsRefl = GetShader(progDetails.stageShaders[0], ShaderEntryPoint());
vsRefl = GetShader(ResourceId(), progDetails.stageShaders[0], ShaderEntryPoint());
}
}
}
+6 -6
View File
@@ -125,18 +125,18 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId)
{
if(i == 0)
{
vsRefl = GetShader(pipeDetails.stageShaders[i], ShaderEntryPoint());
vsRefl = GetShader(ResourceId(), pipeDetails.stageShaders[i], ShaderEntryPoint());
glslVer = m_pDriver->m_Shaders[pipeDetails.stageShaders[0]].version;
vsPatch = m_pDriver->m_Shaders[pipeDetails.stageShaders[0]].patchData;
}
else if(i == 2)
{
tesRefl = GetShader(pipeDetails.stageShaders[2], ShaderEntryPoint());
tesRefl = GetShader(ResourceId(), pipeDetails.stageShaders[2], ShaderEntryPoint());
tesPatch = m_pDriver->m_Shaders[pipeDetails.stageShaders[2]].patchData;
}
else if(i == 3)
{
gsRefl = GetShader(pipeDetails.stageShaders[3], ShaderEntryPoint());
gsRefl = GetShader(ResourceId(), pipeDetails.stageShaders[3], ShaderEntryPoint());
gsPatch = m_pDriver->m_Shaders[pipeDetails.stageShaders[3]].patchData;
}
@@ -202,18 +202,18 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId)
{
if(i == 0)
{
vsRefl = GetShader(progDetails.stageShaders[0], ShaderEntryPoint());
vsRefl = GetShader(ResourceId(), progDetails.stageShaders[0], ShaderEntryPoint());
glslVer = m_pDriver->m_Shaders[progDetails.stageShaders[0]].version;
vsPatch = m_pDriver->m_Shaders[progDetails.stageShaders[0]].patchData;
}
else if(i == 2 && progDetails.stageShaders[2] != ResourceId())
{
tesRefl = GetShader(progDetails.stageShaders[2], ShaderEntryPoint());
tesRefl = GetShader(ResourceId(), progDetails.stageShaders[2], ShaderEntryPoint());
tesPatch = m_pDriver->m_Shaders[progDetails.stageShaders[2]].patchData;
}
else if(i == 3 && progDetails.stageShaders[3] != ResourceId())
{
gsRefl = GetShader(progDetails.stageShaders[3], ShaderEntryPoint());
gsRefl = GetShader(ResourceId(), progDetails.stageShaders[3], ShaderEntryPoint());
gsPatch = m_pDriver->m_Shaders[progDetails.stageShaders[3]].patchData;
}
+4 -3
View File
@@ -726,7 +726,7 @@ rdcarray<ShaderEntryPoint> GLReplay::GetShaderEntryPoints(ResourceId shader)
return {{shaderDetails.reflection.entryPoint, shaderDetails.reflection.stage}};
}
ShaderReflection *GLReplay::GetShader(ResourceId shader, ShaderEntryPoint entry)
ShaderReflection *GLReplay::GetShader(ResourceId pipeline, ResourceId shader, ShaderEntryPoint entry)
{
auto &shaderDetails = m_pDriver->m_Shaders[shader];
@@ -2150,8 +2150,9 @@ void GLReplay::OpenGLFillCBufferVariables(GLuint prog, bool bufferBacked, std::s
}
}
void GLReplay::FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data)
void GLReplay::FillCBufferVariables(ResourceId pipeline, ResourceId shader, std::string entryPoint,
uint32_t cbufSlot, rdcarray<ShaderVariable> &outvars,
const bytebuf &data)
{
WrappedOpenGL &drv = *m_pDriver;
+4 -3
View File
@@ -103,7 +103,7 @@ public:
TextureDescription GetTexture(ResourceId id);
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
ShaderReflection *GetShader(ResourceId shader, ShaderEntryPoint entry);
ShaderReflection *GetShader(ResourceId pipeline, ResourceId shader, ShaderEntryPoint entry);
std::vector<std::string> GetDisassemblyTargets();
std::string DisassembleShader(ResourceId pipeline, const ShaderReflection *refl,
@@ -194,8 +194,9 @@ public:
void RenderHighlightBox(float w, float h, float scale);
void FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data);
void FillCBufferVariables(ResourceId pipeline, ResourceId shader, std::string entryPoint,
uint32_t cbufSlot, rdcarray<ShaderVariable> &outvars,
const bytebuf &data);
std::vector<PixelModification> PixelHistory(std::vector<EventUsage> events, ResourceId target,
uint32_t x, uint32_t y, uint32_t slice, uint32_t mip,
+1 -1
View File
@@ -3526,7 +3526,7 @@ void MakeOnlineShaderReflection(ShaderStage stage, const std::string &source,
return;
}
refl = *driver->GetShader(id, ShaderEntryPoint("main", ShaderStage::Fragment));
refl = *driver->GetShader(ResourceId(), id, ShaderEntryPoint("main", ShaderStage::Fragment));
// Note that we can't fill out ShaderBindpointMapping easily on the actual driver through the
// replay interface
+30 -20
View File
@@ -204,7 +204,8 @@ bool DescSetLayout::operator==(const DescSetLayout &other) const
return true;
}
void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan,
VulkanCreationInfo &info, ResourceId id,
const VkGraphicsPipelineCreateInfo *pCreateInfo)
{
flags = pCreateInfo->flags;
@@ -223,23 +224,22 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk
// VkPipelineShaderStageCreateInfo
for(uint32_t i = 0; i < pCreateInfo->stageCount; i++)
{
ResourceId id = GetResID(pCreateInfo->pStages[i].module);
ResourceId shadid = GetResID(pCreateInfo->pStages[i].module);
// convert shader bit to shader index
int stageIndex = StageIndex(pCreateInfo->pStages[i].stage);
Shader &shad = shaders[stageIndex];
shad.module = id;
shad.module = shadid;
shad.entryPoint = pCreateInfo->pStages[i].pName;
ShaderModule::Reflection &reflData = info.m_ShaderModule[id].m_Reflections[shad.entryPoint];
reflData.Init(resourceMan, id, info.m_ShaderModule[id].spirv, shad.entryPoint,
pCreateInfo->pStages[i].stage);
ShaderModuleReflectionKey key(shad.entryPoint, ResourceId());
if(pCreateInfo->pStages[i].pSpecializationInfo)
{
key = ShaderModuleReflectionKey(shad.entryPoint, id);
const byte *data = (const byte *)pCreateInfo->pStages[i].pSpecializationInfo->pData;
const VkSpecializationMapEntry *maps = pCreateInfo->pStages[i].pSpecializationInfo->pMapEntries;
@@ -253,6 +253,11 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk
}
}
ShaderModuleReflection &reflData = info.m_ShaderModule[shadid].m_Reflections[key];
reflData.Init(resourceMan, shadid, info.m_ShaderModule[shadid].spirv, shad.entryPoint,
pCreateInfo->pStages[i].stage, shad.specialization);
shad.refl = &reflData.refl;
shad.mapping = &reflData.mapping;
shad.patchData = &reflData.patchData;
@@ -544,7 +549,7 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk
}
void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkComputePipelineCreateInfo *pCreateInfo)
ResourceId id, const VkComputePipelineCreateInfo *pCreateInfo)
{
flags = pCreateInfo->flags;
@@ -554,19 +559,18 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk
// VkPipelineShaderStageCreateInfo
{
ResourceId id = GetResID(pCreateInfo->stage.module);
ResourceId shadid = GetResID(pCreateInfo->stage.module);
Shader &shad = shaders[5]; // 5 is the compute shader's index (VS, TCS, TES, GS, FS, CS)
shad.module = id;
shad.module = shadid;
shad.entryPoint = pCreateInfo->stage.pName;
ShaderModule::Reflection &reflData = info.m_ShaderModule[id].m_Reflections[shad.entryPoint];
reflData.Init(resourceMan, id, info.m_ShaderModule[id].spirv, shad.entryPoint,
pCreateInfo->stage.stage);
ShaderModuleReflectionKey key(shad.entryPoint, ResourceId());
if(pCreateInfo->stage.pSpecializationInfo)
{
key = ShaderModuleReflectionKey(shad.entryPoint, id);
const byte *data = (const byte *)pCreateInfo->stage.pSpecializationInfo->pData;
const VkSpecializationMapEntry *maps = pCreateInfo->stage.pSpecializationInfo->pMapEntries;
@@ -580,6 +584,11 @@ void VulkanCreationInfo::Pipeline::Init(VulkanResourceManager *resourceMan, Vulk
}
}
ShaderModuleReflection &reflData = info.m_ShaderModule[shadid].m_Reflections[key];
reflData.Init(resourceMan, shadid, info.m_ShaderModule[shadid].spirv, shad.entryPoint,
pCreateInfo->stage.stage, shad.specialization);
shad.refl = &reflData.refl;
shad.mapping = &reflData.mapping;
shad.patchData = &reflData.patchData;
@@ -1044,18 +1053,19 @@ void VulkanCreationInfo::ShaderModule::Init(VulkanResourceManager *resourceMan,
}
}
void VulkanCreationInfo::ShaderModule::Reflection::Init(VulkanResourceManager *resourceMan,
ResourceId id, const rdcspv::Reflector &spv,
const std::string &entry,
VkShaderStageFlagBits stage)
void VulkanCreationInfo::ShaderModuleReflection::Init(VulkanResourceManager *resourceMan,
ResourceId id, const rdcspv::Reflector &spv,
const std::string &entry,
VkShaderStageFlagBits stage,
const std::vector<SpecConstant> &specInfo)
{
if(entryPoint.empty())
{
entryPoint = entry;
stageIndex = StageIndex(stage);
spv.MakeReflection(GraphicsAPI::Vulkan, ShaderStage(stageIndex), entryPoint, {}, refl, mapping,
patchData);
spv.MakeReflection(GraphicsAPI::Vulkan, ShaderStage(stageIndex), entryPoint, specInfo, refl,
mapping, patchData);
refl.resourceId = resourceMan->GetOriginalID(id);
}
+45 -15
View File
@@ -135,11 +135,42 @@ struct DescUpdateTemplate
struct VulkanCreationInfo
{
struct ShaderModuleReflectionKey
{
ShaderModuleReflectionKey(const rdcstr &e, ResourceId p) : entryPoint(e), specialisingPipe(p) {}
bool operator<(const ShaderModuleReflectionKey &o) const
{
if(entryPoint != o.entryPoint)
return entryPoint < o.entryPoint;
return specialisingPipe < o.specialisingPipe;
}
// name of the entry point
rdcstr entryPoint;
// ID of the pipeline ONLY if it contains specialisation constant data
ResourceId specialisingPipe;
};
struct ShaderModuleReflection
{
uint32_t stageIndex;
std::string entryPoint;
std::string disassembly;
ShaderReflection refl;
ShaderBindpointMapping mapping;
SPIRVPatchData patchData;
void Init(VulkanResourceManager *resourceMan, ResourceId id, const rdcspv::Reflector &spv,
const std::string &entry, VkShaderStageFlagBits stage,
const std::vector<SpecConstant> &specInfo);
};
struct Pipeline
{
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, ResourceId id,
const VkGraphicsPipelineCreateInfo *pCreateInfo);
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, ResourceId id,
const VkComputePipelineCreateInfo *pCreateInfo);
ResourceId layout;
@@ -469,23 +500,22 @@ struct VulkanCreationInfo
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkShaderModuleCreateInfo *pCreateInfo);
ShaderModuleReflection &GetReflection(const rdcstr &entry, ResourceId pipe)
{
// look for one from this pipeline specifically, if it was specialised
auto it = m_Reflections.find({entry, pipe});
if(it != m_Reflections.end())
return it->second;
// if not, just return the non-specialised version
return m_Reflections[{entry, ResourceId()}];
}
rdcspv::Reflector spirv;
std::string unstrippedPath;
struct Reflection
{
uint32_t stageIndex;
std::string entryPoint;
std::string disassembly;
ShaderReflection refl;
ShaderBindpointMapping mapping;
SPIRVPatchData patchData;
void Init(VulkanResourceManager *resourceMan, ResourceId id, const rdcspv::Reflector &spv,
const std::string &entry, VkShaderStageFlagBits stage);
};
std::map<std::string, Reflection> m_Reflections;
std::map<ShaderModuleReflectionKey, ShaderModuleReflection> m_Reflections;
};
std::map<ResourceId, ShaderModule> m_ShaderModule;
+21 -28
View File
@@ -330,7 +330,8 @@ rdcarray<ShaderEntryPoint> VulkanReplay::GetShaderEntryPoints(ResourceId shader)
return ret;
}
ShaderReflection *VulkanReplay::GetShader(ResourceId shader, ShaderEntryPoint entry)
ShaderReflection *VulkanReplay::GetShader(ResourceId pipeline, ResourceId shader,
ShaderEntryPoint entry)
{
auto shad = m_pDriver->m_CreationInfo.m_ShaderModule.find(shader);
@@ -340,11 +341,13 @@ ShaderReflection *VulkanReplay::GetShader(ResourceId shader, ShaderEntryPoint en
return NULL;
}
shad->second.m_Reflections[entry.name].Init(GetResourceManager(), shader, shad->second.spirv,
entry.name,
VkShaderStageFlagBits(1 << uint32_t(entry.stage)));
// if this shader was never used in a pipeline the reflection won't be prepared. Do that now -
// this will be ignored if it was already prepared.
shad->second.GetReflection(entry.name, pipeline)
.Init(GetResourceManager(), shader, shad->second.spirv, entry.name,
VkShaderStageFlagBits(1 << uint32_t(entry.stage)), {});
return &shad->second.m_Reflections[entry.name].refl;
return &shad->second.GetReflection(entry.name, pipeline).refl;
}
std::vector<std::string> VulkanReplay::GetDisassemblyTargets()
@@ -450,7 +453,7 @@ std::string VulkanReplay::DisassembleShader(ResourceId pipeline, const ShaderRef
if(target == SPIRVDisassemblyTarget || target.empty())
{
std::string &disasm = it->second.m_Reflections[refl->entryPoint.c_str()].disassembly;
std::string &disasm = it->second.GetReflection(refl->entryPoint, pipeline).disassembly;
if(disasm.empty())
disasm = it->second.spirv.Disassemble(refl->entryPoint.c_str());
@@ -472,7 +475,7 @@ std::string VulkanReplay::DisassembleShader(ResourceId pipeline, const ShaderRef
VkPipeline pipe = m_pDriver->GetResourceManager()->GetLiveHandle<VkPipeline>(pipeline);
VkShaderStageFlagBits stageBit =
VkShaderStageFlagBits(1 << it->second.m_Reflections[refl->entryPoint.c_str()].stageIndex);
VkShaderStageFlagBits(1 << it->second.GetReflection(refl->entryPoint, pipeline).stageIndex);
size_t size;
vt->GetShaderInfoAMD(Unwrap(dev), Unwrap(pipe), stageBit, VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD,
@@ -498,7 +501,7 @@ std::string VulkanReplay::DisassembleShader(ResourceId pipeline, const ShaderRef
CachePipelineExecutables(pipeline);
VkShaderStageFlagBits stageBit =
VkShaderStageFlagBits(1 << it->second.m_Reflections[refl->entryPoint.c_str()].stageIndex);
VkShaderStageFlagBits(1 << it->second.GetReflection(refl->entryPoint, pipeline).stageIndex);
const rdcarray<PipelineExecutables> &executables = m_PipelineExecutables[pipeline];
@@ -1956,13 +1959,10 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
}
}
void VulkanReplay::FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
void VulkanReplay::FillCBufferVariables(ResourceId pipeline, ResourceId shader,
std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data)
{
// Correct SPIR-V will ultimately need to set explicit layout information for each type.
// For now, just assume D3D11 packing (float4 alignment on float4s, float3s, matrices, arrays and
// structures)
auto it = m_pDriver->m_CreationInfo.m_ShaderModule.find(shader);
if(it == m_pDriver->m_CreationInfo.m_ShaderModule.end())
@@ -1971,8 +1971,8 @@ void VulkanReplay::FillCBufferVariables(ResourceId shader, std::string entryPoin
return;
}
ShaderReflection &refl = it->second.m_Reflections[entryPoint].refl;
ShaderBindpointMapping &mapping = it->second.m_Reflections[entryPoint].mapping;
ShaderReflection &refl = it->second.GetReflection(entryPoint, pipeline).refl;
ShaderBindpointMapping &mapping = it->second.GetReflection(entryPoint, pipeline).mapping;
if(cbufSlot >= (uint32_t)refl.constantBlocks.count())
{
@@ -1991,21 +1991,14 @@ void VulkanReplay::FillCBufferVariables(ResourceId shader, std::string entryPoin
// specialised path to display specialization constants
if(mapping.constantBlocks[c.bindPoint].bindset == SpecializationConstantBindSet)
{
// TODO we shouldn't be looking up the pipeline here, this query should work regardless.
ResourceId pipeline = refl.stage == ShaderStage::Compute
? m_pDriver->m_RenderState.compute.pipeline
: m_pDriver->m_RenderState.graphics.pipeline;
if(pipeline != ResourceId())
auto pipeIt = m_pDriver->m_CreationInfo.m_Pipeline.find(pipeline);
if(pipeIt != m_pDriver->m_CreationInfo.m_Pipeline.end())
{
auto pipeIt = m_pDriver->m_CreationInfo.m_Pipeline.find(pipeline);
auto specInfo =
pipeIt->second.shaders[it->second.GetReflection(entryPoint, pipeline).stageIndex].specialization;
if(pipeIt != m_pDriver->m_CreationInfo.m_Pipeline.end())
{
auto specInfo =
pipeIt->second.shaders[it->second.m_Reflections[entryPoint].stageIndex].specialization;
FillSpecConstantVariables(c.variables, outvars, specInfo);
}
FillSpecConstantVariables(c.variables, outvars, specInfo);
}
}
else
+4 -3
View File
@@ -243,7 +243,7 @@ public:
TextureDescription GetTexture(ResourceId id);
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
ShaderReflection *GetShader(ResourceId shader, ShaderEntryPoint entry);
ShaderReflection *GetShader(ResourceId pipeline, ResourceId shader, ShaderEntryPoint entry);
std::vector<std::string> GetDisassemblyTargets();
std::string DisassembleShader(ResourceId pipeline, const ShaderReflection *refl,
@@ -334,8 +334,9 @@ public:
void RenderHighlightBox(float w, float h, float scale);
void FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data);
void FillCBufferVariables(ResourceId pipeline, ResourceId shader, std::string entryPoint,
uint32_t cbufSlot, rdcarray<ShaderVariable> &outvars,
const bytebuf &data);
std::vector<PixelModification> PixelHistory(std::vector<EventUsage> events, ResourceId target,
uint32_t x, uint32_t y, uint32_t slice, uint32_t mip,
@@ -459,7 +459,7 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines(
VulkanCreationInfo::Pipeline &pipeInfo = m_CreationInfo.m_Pipeline[live];
pipeInfo.Init(GetResourceManager(), m_CreationInfo, &CreateInfo);
pipeInfo.Init(GetResourceManager(), m_CreationInfo, live, &CreateInfo);
ResourceId renderPassID = GetResID(CreateInfo.renderPass);
@@ -588,7 +588,8 @@ VkResult WrappedVulkan::vkCreateGraphicsPipelines(VkDevice device, VkPipelineCac
{
GetResourceManager()->AddLiveResource(id, pPipelines[i]);
m_CreationInfo.m_Pipeline[id].Init(GetResourceManager(), m_CreationInfo, &pCreateInfos[i]);
m_CreationInfo.m_Pipeline[id].Init(GetResourceManager(), m_CreationInfo, id,
&pCreateInfos[i]);
}
}
}
@@ -657,7 +658,7 @@ bool WrappedVulkan::Serialise_vkCreateComputePipelines(SerialiserType &ser, VkDe
live = GetResourceManager()->WrapResource(Unwrap(device), pipe);
GetResourceManager()->AddLiveResource(Pipeline, pipe);
m_CreationInfo.m_Pipeline[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo);
m_CreationInfo.m_Pipeline[live].Init(GetResourceManager(), m_CreationInfo, live, &CreateInfo);
}
}
@@ -758,7 +759,8 @@ VkResult WrappedVulkan::vkCreateComputePipelines(VkDevice device, VkPipelineCach
{
GetResourceManager()->AddLiveResource(id, pPipelines[i]);
m_CreationInfo.m_Pipeline[id].Init(GetResourceManager(), m_CreationInfo, &pCreateInfos[i]);
m_CreationInfo.m_Pipeline[id].Init(GetResourceManager(), m_CreationInfo, id,
&pCreateInfos[i]);
}
}
}
+7 -4
View File
@@ -593,11 +593,12 @@ rdcarray<ShaderEntryPoint> ReplayController::GetShaderEntryPoints(ResourceId sha
return m_pDevice->GetShaderEntryPoints(m_pDevice->GetLiveID(shader));
}
ShaderReflection *ReplayController::GetShader(ResourceId shader, ShaderEntryPoint entry)
ShaderReflection *ReplayController::GetShader(ResourceId pipeline, ResourceId shader,
ShaderEntryPoint entry)
{
CHECK_REPLAY_THREAD();
return m_pDevice->GetShader(m_pDevice->GetLiveID(shader), entry);
return m_pDevice->GetShader(m_pDevice->GetLiveID(pipeline), m_pDevice->GetLiveID(shader), entry);
}
rdcarray<EventUsage> ReplayController::GetUsage(ResourceId id)
@@ -1704,7 +1705,8 @@ void ReplayController::FreeTrace(ShaderDebugTrace *trace)
}
rdcarray<ShaderVariable> ReplayController::GetCBufferVariableContents(
ResourceId shader, const char *entryPoint, uint32_t cbufslot, ResourceId buffer, uint64_t offs)
ResourceId pipeline, ResourceId shader, const char *entryPoint, uint32_t cbufslot,
ResourceId buffer, uint64_t offs)
{
CHECK_REPLAY_THREAD();
@@ -1718,10 +1720,11 @@ rdcarray<ShaderVariable> ReplayController::GetCBufferVariableContents(
rdcarray<ShaderVariable> v;
pipeline = m_pDevice->GetLiveID(pipeline);
shader = m_pDevice->GetLiveID(shader);
if(shader != ResourceId())
m_pDevice->FillCBufferVariables(shader, entryPoint, cbufslot, v, data);
m_pDevice->FillCBufferVariables(pipeline, shader, entryPoint, cbufslot, v, data);
return v;
}
+4 -4
View File
@@ -182,7 +182,7 @@ public:
rdcarray<DebugMessage> GetDebugMessages();
rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader);
ShaderReflection *GetShader(ResourceId shader, ShaderEntryPoint entry);
ShaderReflection *GetShader(ResourceId pipeline, 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);
@@ -201,9 +201,9 @@ public:
bool SaveTexture(const TextureSave &saveData, const char *path);
rdcarray<ShaderVariable> GetCBufferVariableContents(ResourceId shader, const char *entryPoint,
uint32_t cbufslot, ResourceId buffer,
uint64_t offs);
rdcarray<ShaderVariable> GetCBufferVariableContents(ResourceId pipeline, ResourceId shader,
const char *entryPoint, uint32_t cbufslot,
ResourceId buffer, uint64_t offs);
rdcarray<WindowingSystem> GetSupportedWindowSystems();
+5 -3
View File
@@ -103,7 +103,8 @@ public:
virtual std::vector<DebugMessage> GetDebugMessages() = 0;
virtual rdcarray<ShaderEntryPoint> GetShaderEntryPoints(ResourceId shader) = 0;
virtual ShaderReflection *GetShader(ResourceId shader, ShaderEntryPoint entry) = 0;
virtual ShaderReflection *GetShader(ResourceId pipeline, ResourceId shader,
ShaderEntryPoint entry) = 0;
virtual std::vector<std::string> GetDisassemblyTargets() = 0;
virtual std::string DisassembleShader(ResourceId pipeline, const ShaderReflection *refl,
@@ -149,8 +150,9 @@ public:
virtual CounterDescription DescribeCounter(GPUCounter counterID) = 0;
virtual std::vector<CounterResult> FetchCounters(const std::vector<GPUCounter> &counterID) = 0;
virtual void FillCBufferVariables(ResourceId shader, std::string entryPoint, uint32_t cbufSlot,
rdcarray<ShaderVariable> &outvars, const bytebuf &data) = 0;
virtual void FillCBufferVariables(ResourceId pipeline, ResourceId shader, std::string entryPoint,
uint32_t cbufSlot, rdcarray<ShaderVariable> &outvars,
const bytebuf &data) = 0;
virtual std::vector<PixelModification> PixelHistory(std::vector<EventUsage> events,
ResourceId target, uint32_t x, uint32_t y,
+1
View File
@@ -23,6 +23,7 @@ set(VULKAN_SRC
vk/vk_sample_locations.cpp
vk/vk_secondary_cmdbuf.cpp
vk/vk_simple_triangle.cpp
vk/vk_spec_constants.cpp
vk/vk_structured_buffer_nested.cpp
vk/vk_vertex_attr_zoo.cpp
vk/vk_video_textures.cpp
+1
View File
@@ -213,6 +213,7 @@
<ClCompile Include="vk\vk_int8_ibuffer.cpp" />
<ClCompile Include="vk\vk_line_raster.cpp" />
<ClCompile Include="vk\vk_multi_thread_windows.cpp" />
<ClCompile Include="vk\vk_spec_constants.cpp" />
<ClCompile Include="vk\vk_vertex_attr_zoo.cpp" />
<ClCompile Include="vk\vk_buffer_address.cpp" />
<ClCompile Include="vk\vk_cbuffer_zoo.cpp" />
+3
View File
@@ -318,6 +318,9 @@
<ClCompile Include="vk\vk_line_raster.cpp">
<Filter>Vulkan\demos</Filter>
</ClCompile>
<ClCompile Include="vk\vk_spec_constants.cpp">
<Filter>Vulkan\demos</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="D3D11">
+188
View File
@@ -0,0 +1,188 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2018-2019 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "vk_test.h"
TEST(VK_Spec_Constants, VulkanGraphicsTest)
{
static constexpr const char *Description =
"Tests using the same shader multiple times with specialisation constants";
const std::string vertex = R"EOSHADER(
#version 420 core
layout(location = 0) in vec3 Position;
void main()
{
gl_Position = vec4(Position.xyz*vec3(1,-1,1), 1);
}
)EOSHADER";
const std::string pixel = R"EOSHADER(
#version 420 core
layout(location = 0, index = 0) out vec4 Color;
layout(constant_id = 0) const int numcols = 0;
layout(set = 0, binding = 0, std140) uniform constsbuf
{
vec4 col[numcols+1];
};
void main()
{
Color = vec4(0,0,0,1);
for(int i=0; i < numcols; i++)
Color += col[i];
}
)EOSHADER";
int main()
{
// initialise, create window, create context, etc
if(!Init())
return 3;
VkDescriptorSetLayout setlayout = createDescriptorSetLayout(vkh::DescriptorSetLayoutCreateInfo({
{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
}));
VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo({setlayout}));
vkh::GraphicsPipelineCreateInfo pipeCreateInfo;
pipeCreateInfo.layout = layout;
pipeCreateInfo.renderPass = mainWindow->rp;
pipeCreateInfo.vertexInputState.vertexBindingDescriptions = {vkh::vertexBind(0, DefaultA2V)};
pipeCreateInfo.vertexInputState.vertexAttributeDescriptions = {
vkh::vertexAttr(0, 0, DefaultA2V, pos),
};
pipeCreateInfo.stages = {
CompileShaderModule(vertex, ShaderLang::glsl, ShaderStage::vert, "main"),
CompileShaderModule(pixel, ShaderLang::glsl, ShaderStage::frag, "main"),
};
VkSpecializationMapEntry specmap[1] = {
{0, 0, sizeof(uint32_t)},
};
uint32_t specval = 0;
VkSpecializationInfo spec = {};
spec.mapEntryCount = 1;
spec.pMapEntries = specmap;
spec.dataSize = sizeof(specval);
spec.pData = &specval;
pipeCreateInfo.stages[1].pSpecializationInfo = &spec;
VkPipeline pipe[4] = {};
for(size_t i = 0; i < ARRAY_COUNT(pipe); i++)
{
specval = (uint32_t)i;
pipe[i] = createGraphicsPipeline(pipeCreateInfo);
}
Vec4f cbufferdata[4] = {
Vec4f(1.0f, 0.0f, 0.0f, 0.0f), Vec4f(0.0, 1.0f, 0.0f, 0.0f), Vec4f(0.0, 0.0f, 1.0f, 0.0f),
};
AllocatedBuffer cb(
allocator, vkh::BufferCreateInfo(sizeof(cbufferdata), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
cb.upload(cbufferdata);
VkDescriptorSet descset = allocateDescriptorSet(setlayout);
vkh::updateDescriptorSets(
device, {
vkh::WriteDescriptorSet(descset, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
{vkh::DescriptorBufferInfo(cb.buffer)}),
});
AllocatedBuffer vb(
allocator, vkh::BufferCreateInfo(sizeof(DefaultTri), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT),
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));
vb.upload(DefaultTri);
while(Running())
{
VkCommandBuffer cmd = GetCommandBuffer();
vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());
VkImage swapimg =
StartUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
vkCmdClearColorImage(cmd, swapimg, VK_IMAGE_LAYOUT_GENERAL,
vkh::ClearColorValue(0.4f, 0.5f, 0.6f, 1.0f), 1,
vkh::ImageSubresourceRange());
vkCmdBeginRenderPass(
cmd, vkh::RenderPassBeginInfo(mainWindow->rp, mainWindow->GetFB(), mainWindow->scissor),
VK_SUBPASS_CONTENTS_INLINE);
VkViewport v = mainWindow->viewport;
v.width /= ARRAY_COUNT(pipe);
vkCmdSetScissor(cmd, 0, 1, &mainWindow->scissor);
vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0});
for(size_t i = 0; i < ARRAY_COUNT(pipe); i++)
{
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe[i]);
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 1, &descset, 0,
NULL);
vkCmdSetViewport(cmd, 0, 1, &v);
vkCmdDraw(cmd, 3, 1, 0, 0);
v.x += v.width;
}
vkCmdEndRenderPass(cmd);
FinishUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
vkEndCommandBuffer(cmd);
Submit(0, 1, {cmd});
Present();
}
return 0;
}
};
REGISTER_TEST();
+2 -1
View File
@@ -23,7 +23,8 @@ class D3D11_CBuffer_Zoo(rdtest.TestCase):
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 0, 0)
var_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetShader(stage),
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage),
pipe.GetShaderEntryPoint(stage), 0,
cbuf.resourceId, cbuf.byteOffset))
+4 -2
View File
@@ -23,7 +23,8 @@ class D3D12_CBuffer_Zoo(rdtest.TestCase):
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 0, 0)
var_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetShader(stage),
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage),
pipe.GetShaderEntryPoint(stage), 0,
cbuf.resourceId, cbuf.byteOffset))
@@ -328,7 +329,8 @@ class D3D12_CBuffer_Zoo(rdtest.TestCase):
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 1, 0)
var_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetShader(stage),
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage),
pipe.GetShaderEntryPoint(stage), 1,
cbuf.resourceId, cbuf.byteOffset))
+4 -2
View File
@@ -23,7 +23,8 @@ class GL_CBuffer_Zoo(rdtest.TestCase):
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 0, 0)
var_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetShader(stage),
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage),
pipe.GetShaderEntryPoint(stage), 0,
cbuf.resourceId, cbuf.byteOffset))
@@ -378,7 +379,8 @@ class GL_CBuffer_Zoo(rdtest.TestCase):
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 1, 0)
var_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetShader(stage),
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage),
pipe.GetShaderEntryPoint(stage), 1,
cbuf.resourceId, cbuf.byteOffset))
+2 -1
View File
@@ -24,7 +24,8 @@ class VK_Adv_CBuffer_Zoo(rdtest.TestCase):
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 0, 0)
var_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetShader(stage),
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage),
pipe.GetShaderEntryPoint(stage), 0,
cbuf.resourceId, cbuf.byteOffset))
+6 -3
View File
@@ -30,7 +30,8 @@ class VK_CBuffer_Zoo(rdtest.TestCase):
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 0, 0)
var_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetShader(stage),
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage),
pipe.GetShaderEntryPoint(stage), 0,
cbuf.resourceId, cbuf.byteOffset))
@@ -321,7 +322,8 @@ class VK_CBuffer_Zoo(rdtest.TestCase):
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 1, 0)
var_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetShader(stage),
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage),
pipe.GetShaderEntryPoint(stage), 1,
cbuf.resourceId, cbuf.byteOffset))
@@ -359,7 +361,8 @@ class VK_CBuffer_Zoo(rdtest.TestCase):
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 0, 0)
var_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetShader(stage),
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage),
pipe.GetShaderEntryPoint(stage), 0,
cbuf.resourceId, cbuf.byteOffset))
@@ -0,0 +1,96 @@
import renderdoc as rd
import rdtest
class VK_Spec_Constants(rdtest.TestCase):
demos_test_name = 'VK_Spec_Constants'
def check_capture(self):
# find the first draw
draw = self.find_draw("Draw")
# Make an output so we can pick pixels
out: rd.ReplayOutput = self.controller.CreateOutput(rd.CreateHeadlessWindowingData(100, 100), rd.ReplayOutputType.Texture)
# We should have 4 draws, with spec constant values 0, 1, 2, 3
for num_colors in range(4):
self.check(draw is not None)
self.controller.SetFrameEvent(draw.eventId, False)
pipe: rd.PipeState = self.controller.GetPipelineState()
shader: rd.ShaderReflection = pipe.GetShaderReflection(rd.ShaderStage.Pixel)
# uniform buffer and spec constants
self.check(len(shader.constantBlocks) == 2)
self.check(shader.constantBlocks[0].bufferBacked)
self.check(not shader.constantBlocks[1].bufferBacked)
self.check(len(shader.constantBlocks[1].variables) == 1)
# should be an array of num_colors+1 elements
array_len = shader.constantBlocks[0].variables[0].type.descriptor.elements
if not rdtest.value_compare(array_len, num_colors+1):
raise rdtest.TestFailureException("CBuffer variable is array of {}, not {}".format(array_len, num_colors+1))
if num_colors > 0:
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(rd.ShaderStage.Pixel, 0, 0)
cb_vars = self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(rd.ShaderStage.Pixel),
pipe.GetShaderEntryPoint(rd.ShaderStage.Pixel), 0,
cbuf.resourceId, cbuf.byteOffset)
self.check(len(cb_vars) == 1)
if not rdtest.value_compare(len(cb_vars[0].members), num_colors+1):
raise rdtest.TestFailureException("CBuffer variable is array of {}, not {}".format(len(cb_vars[0].members), num_colors+1))
for col in range(num_colors):
expected = [0.0, 0.0, 0.0, 0.0]
expected[col] = 1.0
val = [i for i in cb_vars[0].members[col].value.fv[0:4]]
if not rdtest.value_compare(val, expected):
raise rdtest.TestFailureException("Cbuffer[{}] value {} doesn't match expectation {}".format(col, val, expected))
rdtest.log.success("Draw with {} colors uniform buffer is as expected".format(num_colors))
cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(rd.ShaderStage.Pixel, 1, 0)
cb_vars = self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(rd.ShaderStage.Pixel),
pipe.GetShaderEntryPoint(rd.ShaderStage.Pixel), 1,
cbuf.resourceId, cbuf.byteOffset)
self.check(len(cb_vars) == 1)
if not rdtest.value_compare(cb_vars[0].value.i.x, num_colors):
raise rdtest.TestFailureException("Spec constant is {}, not {}".format(cb_vars[0].value.i.x, num_colors))
rdtest.log.success("Draw with {} colors specialisation constant is as expected".format(num_colors))
tex = rd.TextureDisplay()
tex.resourceId = pipe.GetOutputTargets()[0].resourceId
out.SetTextureDisplay(tex)
view = pipe.GetViewport(0)
# Sample the centre of the viewport
picked: rd.PixelValue = out.PickPixel(tex.resourceId, False,
int(view.x) + int(view.width / 2), int(view.height / 2), 0, 0, 0)
# the first num_colors components should be 0.6, the rest should be 0.1 (alpha is always 1.0)
expected = [0.0, 0.0, 0.0, 1.0]
for col in range(num_colors):
expected[col] += 1.0
if not rdtest.value_compare(picked.floatValue, expected):
raise rdtest.TestFailureException("Picked value {} doesn't match expectation {}".format(picked.floatValue, expected))
rdtest.log.success("Draw with {} colors picked value is as expected".format(num_colors))
draw = draw.next
out.Shutdown()