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:
baldurk
2014-08-13 15:56:55 +01:00
parent a56608e0cd
commit 7ab9815aaf
16 changed files with 274 additions and 101 deletions
+1 -2
View File
@@ -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);
}
+1 -2
View File
@@ -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;
+15
View File
@@ -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++)
{
+111 -55
View File
@@ -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)
{
+2
View File
@@ -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
+5 -7
View File
@@ -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);
}
+1
View File
@@ -72,6 +72,7 @@ struct D3D11PipelineState
ShaderStage() : Shader(), ShaderDetails(NULL) {}
ResourceId Shader;
ShaderReflection *ShaderDetails;
ShaderBindpointMapping BindpointMapping;
ShaderStageType stage;
+1
View File
@@ -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;
+13 -2
View File
@@ -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;
};
+49 -13
View File
@@ -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;
+2
View File
@@ -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;
};
+17 -2
View File
@@ -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
+3 -2
View File
@@ -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 + ">";