mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-12 21:10:42 +00:00
Introduce a bindpoint mapping as part of the pipeline state
* For APIs where the shader namespace/bindpoint (which may be arbitrary like 'the Nth texture resource' can be mapped, at each event, to the actual API bind point where the object is. * On D3D11 this is pass-through, on GL this returns the value of each uniform. * This also means GL shader reflection structures are properly immutable and the variance in the uniform values is handled elsewhere. * In future this might need to be expanded to support more complex binding methods, where the mapping returns the resource rather than just mapping to an integer bind ponit.
This commit is contained in:
@@ -384,7 +384,7 @@ void Serialiser::Serialise(const char *name, ConstantBlock &el)
|
||||
{
|
||||
Serialise("", el.name);
|
||||
Serialise("", el.variables);
|
||||
Serialise("", el.bufferAddress);
|
||||
Serialise("", el.bufferBacked);
|
||||
Serialise("", el.bindPoint);
|
||||
}
|
||||
|
||||
@@ -397,7 +397,6 @@ void Serialiser::Serialise(const char *name, ShaderResource &el)
|
||||
Serialise("", el.IsUAV);
|
||||
Serialise("", el.name);
|
||||
Serialise("", el.variableType);
|
||||
Serialise("", el.variableAddress);
|
||||
Serialise("", el.bindPoint);
|
||||
}
|
||||
|
||||
|
||||
@@ -772,7 +772,7 @@ ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc)
|
||||
{
|
||||
ConstantBlock &cb = ret->ConstantBlocks[i];
|
||||
cb.name = dxbc->m_CBuffers[i].name;
|
||||
cb.bufferAddress = (int32_t)i;
|
||||
cb.bufferBacked = true;
|
||||
cb.bindPoint = (uint32_t)i;
|
||||
|
||||
create_array_uninit(cb.variables, dxbc->m_CBuffers[i].variables.size());
|
||||
@@ -798,7 +798,6 @@ ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc)
|
||||
continue;
|
||||
|
||||
ShaderResource res;
|
||||
res.variableAddress = r.bindPoint; // N/A for D3D, bindPoint is address
|
||||
res.bindPoint = r.bindPoint;
|
||||
res.name = r.name;
|
||||
|
||||
|
||||
@@ -486,6 +486,21 @@ D3D11PipelineState D3D11Replay::MakePipelineState()
|
||||
dst.Shader = rm->GetOriginalID(id);
|
||||
dst.ShaderDetails = NULL;
|
||||
|
||||
// create identity bindpoint mapping
|
||||
create_array_uninit(dst.BindpointMapping.ConstantBlocks, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
|
||||
for(int s=0; s < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; s++)
|
||||
{
|
||||
dst.BindpointMapping.ConstantBlocks[s].bind = s;
|
||||
dst.BindpointMapping.ConstantBlocks[s].used = true;
|
||||
}
|
||||
|
||||
create_array_uninit(dst.BindpointMapping.Resources, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
|
||||
for(int32_t s=0; s < D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; s++)
|
||||
{
|
||||
dst.BindpointMapping.Resources[s].bind = s;
|
||||
dst.BindpointMapping.Resources[s].used = true;
|
||||
}
|
||||
|
||||
create_array_uninit(dst.ConstantBuffers, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
|
||||
for(size_t s=0; s < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; s++)
|
||||
{
|
||||
|
||||
@@ -581,14 +581,11 @@ ShaderReflection *GLReplay::GetShader(ResourceId id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO shader reflection struct shouldn't be tied to the current program
|
||||
// This is only really needed to fill the latest sampler uniform values,
|
||||
// which should be saved in a mapping structure
|
||||
GLuint curProg = 0;
|
||||
gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg);
|
||||
|
||||
auto &refl = shaderDetails.reflection;
|
||||
return &shaderDetails.reflection;
|
||||
}
|
||||
|
||||
void GLReplay::GetMapping(WrappedOpenGL &gl, GLuint curProg, int shadIdx, ShaderReflection *refl, ShaderBindpointMapping &mapping)
|
||||
{
|
||||
// in case of bugs, we readback into this array instead of
|
||||
GLint dummyReadback[32];
|
||||
|
||||
@@ -597,30 +594,73 @@ ShaderReflection *GLReplay::GetShader(ResourceId id)
|
||||
dummyReadback[i] = 0x6c7b8a9d;
|
||||
#endif
|
||||
|
||||
// update with latest uniform values
|
||||
for(int32_t i=0; i < refl.Resources.count; i++)
|
||||
GLenum refEnum[] = {
|
||||
eGL_REFERENCED_BY_VERTEX_SHADER,
|
||||
eGL_REFERENCED_BY_TESS_CONTROL_SHADER,
|
||||
eGL_REFERENCED_BY_TESS_EVALUATION_SHADER,
|
||||
eGL_REFERENCED_BY_GEOMETRY_SHADER,
|
||||
eGL_REFERENCED_BY_FRAGMENT_SHADER,
|
||||
eGL_REFERENCED_BY_COMPUTE_SHADER,
|
||||
};
|
||||
|
||||
create_array_uninit(mapping.Resources, refl->Resources.count);
|
||||
for(int32_t i=0; i < refl->Resources.count; i++)
|
||||
{
|
||||
if(refl.Resources.elems[i].IsSRV && refl.Resources.elems[i].IsTexture)
|
||||
if(refl->Resources.elems[i].IsSRV && refl->Resources.elems[i].IsTexture)
|
||||
{
|
||||
GLint loc = gl.glGetUniformLocation(curProg, refl.Resources.elems[i].name.elems);
|
||||
GLint loc = gl.glGetUniformLocation(curProg, refl->Resources.elems[i].name.elems);
|
||||
if(loc >= 0)
|
||||
{
|
||||
gl.glGetUniformiv(curProg, loc, dummyReadback);
|
||||
refl.Resources.elems[i].bindPoint = dummyReadback[0];
|
||||
mapping.Resources[i].bind = dummyReadback[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int32_t i=0; i < refl.ConstantBlocks.count; i++)
|
||||
{
|
||||
if(refl.ConstantBlocks.elems[i].bufferAddress >= 0)
|
||||
else
|
||||
{
|
||||
GLint loc = gl.glGetUniformBlockIndex(curProg, refl.ConstantBlocks.elems[i].name.elems);
|
||||
mapping.Resources[i].bind = -1;
|
||||
}
|
||||
|
||||
GLuint idx = gl.glGetProgramResourceIndex(curProg, eGL_UNIFORM, refl->Resources.elems[i].name.elems);
|
||||
if(idx == GL_INVALID_INDEX)
|
||||
{
|
||||
mapping.Resources[i].used = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint used = 0;
|
||||
gl.glGetProgramResourceiv(curProg, eGL_UNIFORM, idx, 1, &refEnum[shadIdx], 1, NULL, &used);
|
||||
mapping.Resources[i].used = (used != 0);
|
||||
}
|
||||
}
|
||||
|
||||
create_array_uninit(mapping.ConstantBlocks, refl->ConstantBlocks.count);
|
||||
for(int32_t i=0; i < refl->ConstantBlocks.count; i++)
|
||||
{
|
||||
if(refl->ConstantBlocks.elems[i].bufferBacked)
|
||||
{
|
||||
GLint loc = gl.glGetUniformBlockIndex(curProg, refl->ConstantBlocks.elems[i].name.elems);
|
||||
if(loc >= 0)
|
||||
{
|
||||
gl.glGetActiveUniformBlockiv(curProg, loc, eGL_UNIFORM_BLOCK_BINDING, dummyReadback);
|
||||
refl.ConstantBlocks.elems[i].bindPoint = dummyReadback[0];
|
||||
mapping.ConstantBlocks[i].bind = dummyReadback[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mapping.ConstantBlocks[i].bind = -1;
|
||||
}
|
||||
|
||||
GLuint idx = gl.glGetProgramResourceIndex(curProg, eGL_UNIFORM_BLOCK, refl->ConstantBlocks.elems[i].name.elems);
|
||||
if(idx == GL_INVALID_INDEX)
|
||||
{
|
||||
mapping.ConstantBlocks[i].used = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
GLint used = 0;
|
||||
gl.glGetProgramResourceiv(curProg, eGL_UNIFORM_BLOCK, idx, 1, &refEnum[shadIdx], 1, NULL, &used);
|
||||
mapping.ConstantBlocks[i].used = (used != 0);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(RELEASE)
|
||||
@@ -628,8 +668,6 @@ ShaderReflection *GLReplay::GetShader(ResourceId id)
|
||||
if(dummyReadback[i] != 0x6c7b8a9d)
|
||||
RDCERR("Invalid uniform readback - data beyond first element modified!");
|
||||
#endif
|
||||
|
||||
return &refl;
|
||||
}
|
||||
|
||||
void GLReplay::SavePipelineState()
|
||||
@@ -853,7 +891,29 @@ void GLReplay::SavePipelineState()
|
||||
GLuint curProg = 0;
|
||||
gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint*)&curProg);
|
||||
|
||||
GLPipelineState::ShaderStage *stages[6] = {
|
||||
&pipe.m_VS,
|
||||
&pipe.m_TCS,
|
||||
&pipe.m_TES,
|
||||
&pipe.m_GS,
|
||||
&pipe.m_FS,
|
||||
&pipe.m_CS,
|
||||
};
|
||||
ShaderReflection *refls[6] = { NULL };
|
||||
ShaderBindpointMapping *mappings[6] = { NULL };
|
||||
|
||||
struct
|
||||
{
|
||||
GLenum bit;
|
||||
GLenum type;
|
||||
} shaders[] = {
|
||||
{ eGL_VERTEX_SHADER_BIT, eGL_VERTEX_SHADER },
|
||||
{ eGL_TESS_CONTROL_SHADER_BIT, eGL_TESS_CONTROL_SHADER },
|
||||
{ eGL_TESS_EVALUATION_SHADER_BIT, eGL_TESS_EVALUATION_SHADER },
|
||||
{ eGL_GEOMETRY_SHADER_BIT, eGL_GEOMETRY_SHADER },
|
||||
{ eGL_FRAGMENT_SHADER_BIT, eGL_FRAGMENT_SHADER },
|
||||
{ eGL_COMPUTE_SHADER_BIT, eGL_COMPUTE_SHADER },
|
||||
};
|
||||
|
||||
if(curProg == 0)
|
||||
{
|
||||
@@ -877,46 +937,36 @@ void GLReplay::SavePipelineState()
|
||||
|
||||
RDCASSERT(pipeDetails.programs.size());
|
||||
|
||||
struct
|
||||
{
|
||||
GLenum bit;
|
||||
GLenum type;
|
||||
} shaders[] = {
|
||||
{ eGL_VERTEX_SHADER_BIT, eGL_VERTEX_SHADER },
|
||||
{ eGL_FRAGMENT_SHADER_BIT, eGL_FRAGMENT_SHADER },
|
||||
{ eGL_COMPUTE_SHADER_BIT, eGL_COMPUTE_SHADER },
|
||||
{ eGL_GEOMETRY_SHADER_BIT, eGL_GEOMETRY_SHADER },
|
||||
{ eGL_TESS_CONTROL_SHADER_BIT, eGL_TESS_CONTROL_SHADER },
|
||||
{ eGL_TESS_EVALUATION_SHADER_BIT, eGL_TESS_EVALUATION_SHADER },
|
||||
};
|
||||
// TODO: we could pre-flatten this (to list all the shaders in the pipeline)
|
||||
|
||||
// look at the programs in the pipeline
|
||||
for(size_t p=0; p < pipeDetails.programs.size(); p++)
|
||||
{
|
||||
auto &progDetails = m_pDriver->m_Programs[pipeDetails.programs[p].id];
|
||||
|
||||
|
||||
RDCASSERT(progDetails.shaders.size());
|
||||
|
||||
for(size_t s=0; s < ARRAY_COUNT(shaders); s++)
|
||||
curProg = rm->GetCurrentResource(pipeDetails.programs[p].id).name;
|
||||
|
||||
// look at the shaders in the program
|
||||
for(int s=0; s < ARRAY_COUNT(shaders); s++)
|
||||
{
|
||||
// if this program is being used for a shader stage
|
||||
if(pipeDetails.programs[p].use & shaders[s].bit)
|
||||
{
|
||||
auto &progDetails = m_pDriver->m_Programs[pipeDetails.programs[p].id];
|
||||
|
||||
// find the shader stage that's being used
|
||||
for(size_t i=0; i < progDetails.shaders.size(); i++)
|
||||
{
|
||||
if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == shaders[s].type)
|
||||
{
|
||||
ResourceId shid = rm->GetOriginalID(progDetails.shaders[i]);
|
||||
switch(shaders[s].type)
|
||||
{
|
||||
case eGL_VERTEX_SHADER: pipe.m_VS.Shader = shid; break;
|
||||
case eGL_FRAGMENT_SHADER: pipe.m_FS.Shader = shid; break;
|
||||
case eGL_COMPUTE_SHADER: pipe.m_CS.Shader = shid; break;
|
||||
case eGL_GEOMETRY_SHADER: pipe.m_GS.Shader = shid; break;
|
||||
case eGL_TESS_CONTROL_SHADER: pipe.m_TCS.Shader = shid; break;
|
||||
case eGL_TESS_EVALUATION_SHADER: pipe.m_TES.Shader = shid; break;
|
||||
}
|
||||
// set Shader ID and bindpoint mapping directly in the pipe state
|
||||
// store reflection and mapping locally too
|
||||
stages[s]->Shader = rm->GetOriginalID(progDetails.shaders[i]);
|
||||
refls[s] = GetShader(progDetails.shaders[i]);
|
||||
GetMapping(gl, curProg, s, refls[s], stages[s]->BindpointMapping);
|
||||
mappings[s] = &stages[s]->BindpointMapping;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -931,17 +981,23 @@ void GLReplay::SavePipelineState()
|
||||
|
||||
RDCASSERT(progDetails.shaders.size());
|
||||
|
||||
// look at the shaders in the program
|
||||
for(size_t i=0; i < progDetails.shaders.size(); i++)
|
||||
{
|
||||
if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_VERTEX_SHADER)
|
||||
pipe.m_VS.Shader = rm->GetOriginalID(progDetails.shaders[i]);
|
||||
else if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == eGL_FRAGMENT_SHADER)
|
||||
pipe.m_FS.Shader = rm->GetOriginalID(progDetails.shaders[i]);
|
||||
// find the matching stage
|
||||
for(int s=0; s < ARRAY_COUNT(shaders); s++)
|
||||
{
|
||||
if(m_pDriver->m_Shaders[ progDetails.shaders[i] ].type == shaders[s].type)
|
||||
{
|
||||
// set Shader ID and bindpoint mapping directly in the pipe state
|
||||
// store reflection and mapping locally too
|
||||
stages[s]->Shader = rm->GetOriginalID(progDetails.shaders[i]);
|
||||
refls[s] = GetShader(progDetails.shaders[i]);
|
||||
GetMapping(gl, curProg, s, refls[s], stages[s]->BindpointMapping);
|
||||
mappings[s] = &stages[s]->BindpointMapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prefetch uniform values in GetShader()
|
||||
for(size_t s=0; s < progDetails.shaders.size(); s++)
|
||||
refls[s] = GetShader(progDetails.shaders[s]);
|
||||
}
|
||||
|
||||
// GL is ass-backwards in its handling of texture units. When a shader is active
|
||||
@@ -971,7 +1027,7 @@ void GLReplay::SavePipelineState()
|
||||
for(int32_t r=0; r < refls[s]->Resources.count; r++)
|
||||
{
|
||||
// bindPoint is the uniform value for this sampler
|
||||
if(refls[s]->Resources[r].bindPoint == unit)
|
||||
if(mappings[s]->Resources[ refls[s]->Resources[r].bindPoint ].bind == unit)
|
||||
{
|
||||
GLenum t = eGL_UNKNOWN_ENUM;
|
||||
|
||||
@@ -1188,8 +1244,8 @@ void GLReplay::FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector
|
||||
|
||||
RDCEraseEl(var.value);
|
||||
|
||||
bool bufferBacked = (cblock.bindPoint >= 0 && cblock.bufferAddress >= 0 && !data.empty());
|
||||
bool hasValue = bufferBacked || (cblock.bindPoint < 0 && cblock.bufferAddress < 0); // buffer backed (with data), or global uniforms
|
||||
bool bufferBacked = (cblock.bufferBacked && !data.empty());
|
||||
bool hasValue = bufferBacked || !cblock.bufferBacked; // buffer backed (with data), or global uniforms
|
||||
|
||||
if(desc.elements == 1)
|
||||
{
|
||||
|
||||
@@ -134,6 +134,8 @@ class GLReplay : public IReplayDriver
|
||||
void FillCBufferValue(WrappedOpenGL &gl, GLuint prog, bool bufferBacked, bool rowMajor, uint32_t locA, uint32_t locB,
|
||||
const vector<byte> &data, ShaderVariable &outVar);
|
||||
|
||||
void GetMapping(WrappedOpenGL &gl, GLuint curProg, int shadIdx, ShaderReflection *refl, ShaderBindpointMapping &mapping);
|
||||
|
||||
struct OutputWindow : public GLWindowingData
|
||||
{
|
||||
struct
|
||||
|
||||
@@ -135,7 +135,7 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg,
|
||||
res.variableType.descriptor.cols = 4;
|
||||
res.variableType.descriptor.elements = 1;
|
||||
res.variableType.descriptor.rowMajorStorage = false;
|
||||
res.bindPoint = 0;
|
||||
res.bindPoint = (int32_t)resources.size();
|
||||
|
||||
// float samplers
|
||||
if(values[0] == GL_SAMPLER_BUFFER)
|
||||
@@ -380,8 +380,6 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg,
|
||||
continue;
|
||||
}
|
||||
|
||||
res.variableAddress = values[2];
|
||||
|
||||
create_array_uninit(res.name, values[1]);
|
||||
gl.glGetProgramResourceName(sepProg, eGL_UNIFORM, u, values[1], NULL, res.name.elems);
|
||||
res.name.count--; // trim off trailing null
|
||||
@@ -549,8 +547,8 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg,
|
||||
|
||||
ConstantBlock cblock;
|
||||
cblock.name = uboNames[i];
|
||||
cblock.bufferAddress = i;
|
||||
cblock.bindPoint = -1;
|
||||
cblock.bufferBacked = true;
|
||||
cblock.bindPoint = (int32_t)cbuffers.size();
|
||||
std::sort(ubos[i].begin(), ubos[i].end(), ubo_offset_sort());
|
||||
|
||||
cblock.variables = ubos[i];
|
||||
@@ -564,8 +562,8 @@ void MakeShaderReflection(const GLHookSet &gl, GLenum shadType, GLuint sepProg,
|
||||
{
|
||||
ConstantBlock globals;
|
||||
globals.name = "$Globals";
|
||||
globals.bufferAddress = -1;
|
||||
globals.bindPoint = -1;
|
||||
globals.bufferBacked = false;
|
||||
globals.bindPoint = (int32_t)cbuffers.size();
|
||||
globals.variables = globalUniforms;
|
||||
|
||||
cbuffers.push_back(globals);
|
||||
|
||||
@@ -321,12 +321,25 @@ bool WrappedOpenGL::Serialise_glCreateShaderProgramv(GLuint program, GLenum type
|
||||
GLResource res = ProgramRes(GetCtx(), real);
|
||||
|
||||
ResourceId liveId = m_ResourceManager->RegisterResource(res);
|
||||
|
||||
m_Programs[liveId].linked = true;
|
||||
m_Programs[liveId].shaders.push_back(liveId);
|
||||
m_Shaders[liveId].type = Type;
|
||||
m_Shaders[liveId].sources.swap(src);
|
||||
m_Shaders[liveId].prog = real;
|
||||
|
||||
auto &progDetails = m_Programs[liveId];
|
||||
|
||||
progDetails.linked = true;
|
||||
progDetails.shaders.push_back(liveId);
|
||||
|
||||
auto &shadDetails = m_Shaders[liveId];
|
||||
|
||||
shadDetails.type = Type;
|
||||
shadDetails.sources.swap(src);
|
||||
shadDetails.prog = real;
|
||||
MakeShaderReflection(m_Real, Type, real, shadDetails.reflection);
|
||||
|
||||
create_array_uninit(shadDetails.reflection.DebugInfo.files, shadDetails.sources.size());
|
||||
for(size_t i=0; i < shadDetails.sources.size(); i++)
|
||||
{
|
||||
shadDetails.reflection.DebugInfo.files[i].first = StringFormat::Fmt("source%u.glsl", (uint32_t)i);
|
||||
shadDetails.reflection.DebugInfo.files[i].second = shadDetails.sources[i];
|
||||
}
|
||||
|
||||
GetResourceManager()->AddLiveResource(id, res);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ struct D3D11PipelineState
|
||||
ShaderStage() : Shader(), ShaderDetails(NULL) {}
|
||||
ResourceId Shader;
|
||||
ShaderReflection *ShaderDetails;
|
||||
ShaderBindpointMapping BindpointMapping;
|
||||
|
||||
ShaderStageType stage;
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ struct GLPipelineState
|
||||
ShaderStage() : Shader(), ShaderDetails(NULL) {}
|
||||
ResourceId Shader;
|
||||
ShaderReflection *ShaderDetails;
|
||||
ShaderBindpointMapping BindpointMapping;
|
||||
|
||||
ShaderStageType stage;
|
||||
} m_VS, m_TCS, m_TES, m_GS, m_FS, m_CS;
|
||||
|
||||
@@ -164,7 +164,7 @@ struct ConstantBlock
|
||||
{
|
||||
rdctype::str name;
|
||||
rdctype::array<ShaderConstant> variables;
|
||||
int32_t bufferAddress;
|
||||
bool32 bufferBacked;
|
||||
int32_t bindPoint;
|
||||
};
|
||||
|
||||
@@ -179,7 +179,6 @@ struct ShaderResource
|
||||
|
||||
rdctype::str name;
|
||||
ShaderVariableType variableType;
|
||||
int32_t variableAddress;
|
||||
int32_t bindPoint;
|
||||
};
|
||||
|
||||
@@ -209,3 +208,15 @@ struct ShaderReflection
|
||||
// TODO expand this to encompass shader subroutines.
|
||||
rdctype::array<rdctype::str> Interfaces;
|
||||
};
|
||||
|
||||
struct BindpointMap
|
||||
{
|
||||
int32_t bind;
|
||||
bool32 used;
|
||||
};
|
||||
|
||||
struct ShaderBindpointMapping
|
||||
{
|
||||
rdctype::array<BindpointMap> ConstantBlocks;
|
||||
rdctype::array<BindpointMap> Resources;
|
||||
};
|
||||
|
||||
@@ -109,6 +109,39 @@ namespace renderdocui.Code
|
||||
|
||||
// there's a lot of redundancy in these functions
|
||||
|
||||
public ShaderBindpointMapping GetBindpointMapping(ShaderStageType stage)
|
||||
{
|
||||
if (LogLoaded)
|
||||
{
|
||||
if (IsLogD3D11)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStageType.Vertex: return m_D3D11.m_VS.BindpointMapping;
|
||||
case ShaderStageType.Domain: return m_D3D11.m_DS.BindpointMapping;
|
||||
case ShaderStageType.Hull: return m_D3D11.m_HS.BindpointMapping;
|
||||
case ShaderStageType.Geometry: return m_D3D11.m_GS.BindpointMapping;
|
||||
case ShaderStageType.Pixel: return m_D3D11.m_PS.BindpointMapping;
|
||||
case ShaderStageType.Compute: return m_D3D11.m_CS.BindpointMapping;
|
||||
}
|
||||
}
|
||||
else if (IsLogGL)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStageType.Vertex: return m_GL.m_VS.BindpointMapping;
|
||||
case ShaderStageType.Tess_Control: return m_GL.m_TCS.BindpointMapping;
|
||||
case ShaderStageType.Tess_Eval: return m_GL.m_TES.BindpointMapping;
|
||||
case ShaderStageType.Geometry: return m_GL.m_GS.BindpointMapping;
|
||||
case ShaderStageType.Fragment: return m_GL.m_FS.BindpointMapping;
|
||||
case ShaderStageType.Compute: return m_GL.m_CS.BindpointMapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ShaderReflection GetShaderReflection(ShaderStageType stage)
|
||||
{
|
||||
if (LogLoaded)
|
||||
@@ -329,7 +362,7 @@ namespace renderdocui.Code
|
||||
return null;
|
||||
}
|
||||
|
||||
public void GetConstantBuffer(ShaderStageType stage, uint BindPoint, out ResourceId buf, out uint ByteOffset, out uint ByteSize)
|
||||
public void GetConstantBuffer(ShaderStageType stage, uint BufIdx, out ResourceId buf, out uint ByteOffset, out uint ByteSize)
|
||||
{
|
||||
if (LogLoaded)
|
||||
{
|
||||
@@ -347,11 +380,11 @@ namespace renderdocui.Code
|
||||
case ShaderStageType.Compute: s = m_D3D11.m_CS; break;
|
||||
}
|
||||
|
||||
if(BindPoint < s.ConstantBuffers.Length)
|
||||
if(BufIdx < s.ConstantBuffers.Length)
|
||||
{
|
||||
buf = s.ConstantBuffers[BindPoint].Buffer;
|
||||
ByteOffset = s.ConstantBuffers[BindPoint].VecOffset * 4 * sizeof(float);
|
||||
ByteSize = s.ConstantBuffers[BindPoint].VecCount * 4 * sizeof(float);
|
||||
buf = s.ConstantBuffers[BufIdx].Buffer;
|
||||
ByteOffset = s.ConstantBuffers[BufIdx].VecOffset * 4 * sizeof(float);
|
||||
ByteSize = s.ConstantBuffers[BufIdx].VecCount * 4 * sizeof(float);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -370,18 +403,21 @@ namespace renderdocui.Code
|
||||
case ShaderStageType.Compute: s = m_GL.m_CS; break;
|
||||
}
|
||||
|
||||
if(s.ShaderDetails != null && BindPoint < s.ShaderDetails.ConstantBlocks.Length)
|
||||
if(s.ShaderDetails != null && BufIdx < s.ShaderDetails.ConstantBlocks.Length)
|
||||
{
|
||||
if(s.ShaderDetails.ConstantBlocks[BindPoint].bindPoint >= 0 &&
|
||||
s.ShaderDetails.ConstantBlocks[BindPoint].bindPoint < m_GL.UniformBuffers.Length)
|
||||
if (s.ShaderDetails.ConstantBlocks[BufIdx].bindPoint >= 0)
|
||||
{
|
||||
var b = m_GL.UniformBuffers[s.ShaderDetails.ConstantBlocks[BindPoint].bindPoint];
|
||||
int uboIdx = s.BindpointMapping.ConstantBlocks[s.ShaderDetails.ConstantBlocks[BufIdx].bindPoint].bind;
|
||||
if (uboIdx >= 0 && uboIdx < m_GL.UniformBuffers.Length)
|
||||
{
|
||||
var b = m_GL.UniformBuffers[uboIdx];
|
||||
|
||||
buf = b.Resource;
|
||||
ByteOffset = (uint)b.Offset;
|
||||
ByteSize = (uint)b.Size;
|
||||
buf = b.Resource;
|
||||
ByteOffset = (uint)b.Offset;
|
||||
ByteSize = (uint)b.Size;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +106,8 @@ namespace renderdoc
|
||||
private IntPtr _ptr_ShaderDetails;
|
||||
[CustomMarshalAs(CustomUnmanagedType.Skip)]
|
||||
public ShaderReflection ShaderDetails;
|
||||
[CustomMarshalAs(CustomUnmanagedType.CustomClass)]
|
||||
public ShaderBindpointMapping BindpointMapping;
|
||||
|
||||
public ShaderStageType stage;
|
||||
|
||||
|
||||
@@ -90,6 +90,8 @@ namespace renderdoc
|
||||
private IntPtr _ptr_ShaderDetails;
|
||||
[CustomMarshalAs(CustomUnmanagedType.Skip)]
|
||||
public ShaderReflection ShaderDetails;
|
||||
[CustomMarshalAs(CustomUnmanagedType.CustomClass)]
|
||||
public ShaderBindpointMapping BindpointMapping;
|
||||
|
||||
public ShaderStageType stage;
|
||||
};
|
||||
|
||||
@@ -342,7 +342,7 @@ namespace renderdoc
|
||||
[CustomMarshalAs(CustomUnmanagedType.TemplatedArray)]
|
||||
public ShaderConstant[] variables;
|
||||
|
||||
public Int32 bufferAddress;
|
||||
public bool bufferBacked;
|
||||
public Int32 bindPoint;
|
||||
};
|
||||
|
||||
@@ -360,7 +360,6 @@ namespace renderdoc
|
||||
public string name;
|
||||
[CustomMarshalAs(CustomUnmanagedType.CustomClass)]
|
||||
public ShaderVariableType variableType;
|
||||
public Int32 variableAddress;
|
||||
public Int32 bindPoint;
|
||||
};
|
||||
|
||||
@@ -414,4 +413,20 @@ namespace renderdoc
|
||||
[CustomMarshalAs(CustomUnmanagedType.TemplatedArray)]
|
||||
public Interface[] Interfaces;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class BindpointMap
|
||||
{
|
||||
public Int32 bind;
|
||||
public bool used;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class ShaderBindpointMapping
|
||||
{
|
||||
[CustomMarshalAs(CustomUnmanagedType.TemplatedArray)]
|
||||
public BindpointMap[] ConstantBlocks;
|
||||
[CustomMarshalAs(CustomUnmanagedType.TemplatedArray)]
|
||||
public BindpointMap[] Resources;
|
||||
};
|
||||
};
|
||||
@@ -174,7 +174,7 @@ namespace renderdocui.Windows.PipelineState
|
||||
|
||||
// Set a shader stage's resources and values
|
||||
private void SetShaderState(FetchTexture[] texs, FetchBuffer[] bufs,
|
||||
GLPipelineState.ShaderStage stage,
|
||||
GLPipelineState state, GLPipelineState.ShaderStage stage,
|
||||
Label shader, TreelistView.TreeListView resources, TreelistView.TreeListView samplers,
|
||||
TreelistView.TreeListView cbuffers, TreelistView.TreeListView classes)
|
||||
{
|
||||
@@ -196,17 +196,34 @@ namespace renderdocui.Windows.PipelineState
|
||||
UInt32 i = 0;
|
||||
foreach (var shaderCBuf in shaderDetails.ConstantBlocks)
|
||||
{
|
||||
int bindPoint = stage.BindpointMapping.ConstantBlocks[i].bind;
|
||||
|
||||
bool filledSlot = !shaderCBuf.bufferBacked ||
|
||||
(bindPoint >= 0 && bindPoint < state.UniformBuffers.Length && state.UniformBuffers[bindPoint].Resource != ResourceId.Null);
|
||||
bool usedSlot = stage.BindpointMapping.ConstantBlocks[i].used;
|
||||
|
||||
// show if
|
||||
if (usedSlot || // it's referenced by the shader - regardless of empty or not
|
||||
(showDisabled.Checked && !usedSlot && filledSlot) || // it's bound, but not referenced, and we have "show disabled"
|
||||
(showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty"
|
||||
)
|
||||
{
|
||||
string name = shaderCBuf.name;
|
||||
int numvars = shaderCBuf.variables.Length;
|
||||
|
||||
string slotname = i.ToString();
|
||||
|
||||
var node = cbuffers.Nodes.Add(new object[] { slotname, name, "", "", numvars, "" });
|
||||
var node = cbuffers.Nodes.Add(new object[] { slotname, name, bindPoint, "", numvars, "" });
|
||||
|
||||
node.Image = global::renderdocui.Properties.Resources.action;
|
||||
node.HoverImage = global::renderdocui.Properties.Resources.action_hover;
|
||||
node.Tag = i;
|
||||
|
||||
if (!filledSlot)
|
||||
EmptyRow(node);
|
||||
|
||||
if (!usedSlot)
|
||||
InactiveRow(node);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -461,35 +478,40 @@ namespace renderdocui.Windows.PipelineState
|
||||
iabuffers.NodesSelection.Clear();
|
||||
iabuffers.EndUpdate();
|
||||
|
||||
SetShaderState(texs, bufs, state.m_VS, vsShader, vsResources, vsSamplers, vsCBuffers, vsClasses);
|
||||
SetShaderState(texs, bufs, state.m_GS, gsShader, gsResources, gsSamplers, gsCBuffers, gsClasses);
|
||||
SetShaderState(texs, bufs, state.m_TES, tesShader, tesResources, tesSamplers, tesCBuffers, tesClasses);
|
||||
SetShaderState(texs, bufs, state.m_TCS, tcsShader, tcsResources, tcsSamplers, tcsCBuffers, tcsClasses);
|
||||
SetShaderState(texs, bufs, state.m_FS, fsShader, fsResources, fsSamplers, fsCBuffers, fsClasses);
|
||||
SetShaderState(texs, bufs, state.m_CS, csShader, csResources, csSamplers, csCBuffers, csClasses);
|
||||
SetShaderState(texs, bufs, state, state.m_VS, vsShader, vsResources, vsSamplers, vsCBuffers, vsClasses);
|
||||
SetShaderState(texs, bufs, state, state.m_GS, gsShader, gsResources, gsSamplers, gsCBuffers, gsClasses);
|
||||
SetShaderState(texs, bufs, state, state.m_TES, tesShader, tesResources, tesSamplers, tesCBuffers, tesClasses);
|
||||
SetShaderState(texs, bufs, state, state.m_TCS, tcsShader, tcsResources, tcsSamplers, tcsCBuffers, tcsClasses);
|
||||
SetShaderState(texs, bufs, state, state.m_FS, fsShader, fsResources, fsSamplers, fsCBuffers, fsClasses);
|
||||
SetShaderState(texs, bufs, state, state.m_CS, csShader, csResources, csSamplers, csCBuffers, csClasses);
|
||||
|
||||
fsResources.BeginUpdate();
|
||||
fsResources.Nodes.Clear();
|
||||
if (state.Textures != null)
|
||||
{
|
||||
var shaderDetails = state.m_FS.ShaderDetails;
|
||||
var mapping = state.m_FS.BindpointMapping;
|
||||
|
||||
int i = 0;
|
||||
foreach (var r in state.Textures)
|
||||
{
|
||||
ShaderResource shaderInput = null;
|
||||
BindpointMap map = null;
|
||||
|
||||
if (shaderDetails != null)
|
||||
{
|
||||
foreach (var bind in shaderDetails.Resources)
|
||||
{
|
||||
if (bind.IsSRV && bind.bindPoint == i)
|
||||
if (bind.IsSRV && mapping.Resources[bind.bindPoint].bind == i)
|
||||
{
|
||||
shaderInput = bind;
|
||||
map = mapping.Resources[bind.bindPoint];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool filledSlot = (r.Resource != ResourceId.Null);
|
||||
bool usedSlot = (shaderInput != null);
|
||||
bool usedSlot = (shaderInput != null && map.used);
|
||||
|
||||
// show if
|
||||
if (usedSlot || // it's referenced by the shader - regardless of empty or not
|
||||
|
||||
@@ -796,6 +796,7 @@ namespace renderdocui.Windows
|
||||
ResourceId[] Texs = m_Core.CurPipelineState.GetResources(ShaderStageType.Pixel);
|
||||
|
||||
ShaderReflection details = m_Core.CurPipelineState.GetShaderReflection(ShaderStageType.Pixel);
|
||||
ShaderBindpointMapping mapping = m_Core.CurPipelineState.GetBindpointMapping(ShaderStageType.Pixel);
|
||||
|
||||
uint firstuav = uint.MaxValue;
|
||||
|
||||
@@ -865,7 +866,7 @@ namespace renderdocui.Windows
|
||||
{
|
||||
foreach (var bind in details.Resources)
|
||||
{
|
||||
if (bind.bindPoint == i && bind.IsUAV)
|
||||
if (mapping.Resources[bind.bindPoint].bind == i && bind.IsUAV)
|
||||
{
|
||||
bindName = "<" + bind.name + ">";
|
||||
}
|
||||
@@ -939,7 +940,7 @@ namespace renderdocui.Windows
|
||||
{
|
||||
foreach (var bind in details.Resources)
|
||||
{
|
||||
if (bind.bindPoint == i && bind.IsSRV)
|
||||
if (mapping.Resources[bind.bindPoint].bind == i && bind.IsSRV)
|
||||
{
|
||||
used = true;
|
||||
bindName = "<" + bind.name + ">";
|
||||
|
||||
Reference in New Issue
Block a user