mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-26 11:50:59 +00:00
Display cbuffer contents within vulkan pipe viewer
* For now, we just assume that cbuffers are tightly packed according to D3D11 rules (matrices, structs, float3/4 are all float4 aligned), and once final SPIR-V is generated everything should have explicit offsets, strides, and sizes
This commit is contained in:
@@ -46,11 +46,11 @@ struct VulkanPipelineState
|
||||
|
||||
struct BindingElement
|
||||
{
|
||||
ResourceId view; // buffer, image, attachment
|
||||
ResourceId view; // bufferview, imageview, attachmentview
|
||||
ResourceId res; // buffer, image, attachment
|
||||
ResourceId sampler;
|
||||
uint32_t offset; // for dynamic offsets
|
||||
|
||||
// VKTODOLOW do we want image layout here?
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
// may only be one element if not an array
|
||||
|
||||
@@ -180,6 +180,18 @@ void VulkanCreationInfo::AttachmentView::Init(const VkAttachmentViewCreateInfo*
|
||||
image = VKMGR()->GetNonDispWrapper(pCreateInfo->image)->id;
|
||||
}
|
||||
|
||||
void VulkanCreationInfo::BufferView::Init(const VkBufferViewCreateInfo* pCreateInfo)
|
||||
{
|
||||
buffer = VKMGR()->GetNonDispWrapper(pCreateInfo->buffer)->id;
|
||||
offset = pCreateInfo->offset;
|
||||
size = pCreateInfo->range;
|
||||
}
|
||||
|
||||
void VulkanCreationInfo::ImageView::Init(const VkImageViewCreateInfo* pCreateInfo)
|
||||
{
|
||||
image = VKMGR()->GetNonDispWrapper(pCreateInfo->image)->id;
|
||||
}
|
||||
|
||||
void VulkanCreationInfo::DescSetLayout::Init(const VkDescriptorSetLayoutCreateInfo* pCreateInfo)
|
||||
{
|
||||
bindings.resize(pCreateInfo->count);
|
||||
|
||||
@@ -175,6 +175,24 @@ struct VulkanCreationInfo
|
||||
uint32_t width, height, layers;
|
||||
};
|
||||
map<ResourceId, Framebuffer> m_Framebuffer;
|
||||
|
||||
struct BufferView
|
||||
{
|
||||
void Init(const VkBufferViewCreateInfo* pCreateInfo);
|
||||
|
||||
ResourceId buffer;
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
};
|
||||
map<ResourceId, BufferView> m_BufferView;
|
||||
|
||||
struct ImageView
|
||||
{
|
||||
void Init(const VkImageViewCreateInfo* pCreateInfo);
|
||||
|
||||
ResourceId image;
|
||||
};
|
||||
map<ResourceId, ImageView> m_ImageView;
|
||||
|
||||
struct AttachmentView
|
||||
{
|
||||
|
||||
@@ -1145,7 +1145,16 @@ vector<byte> VulkanReplay::GetBufferData(ResourceId buff, uint32_t offset, uint3
|
||||
VkQueue q = m_pDriver->GetQ();
|
||||
const VkLayerDispatchTable *vt = ObjDisp(dev);
|
||||
|
||||
ResourceId memid = m_pDriver->m_BufferMemBinds[buff];
|
||||
ResourceId memid;
|
||||
|
||||
{
|
||||
auto it = m_pDriver->m_BufferMemBinds.find(buff);
|
||||
if(it == m_pDriver->m_BufferMemBinds.end())
|
||||
{
|
||||
RDCWARN("Buffer has no memory bound, or no buffer of this ID");
|
||||
return vector<byte>();
|
||||
}
|
||||
}
|
||||
|
||||
VkBuffer srcBuf = m_pDriver->GetResourceManager()->GetCurrentHandle<VkBuffer>(buff);
|
||||
|
||||
@@ -1454,11 +1463,23 @@ void VulkanReplay::SavePipelineState()
|
||||
|
||||
// only one of these is ever set
|
||||
if(info->imageView != VK_NULL_HANDLE)
|
||||
{
|
||||
dst.bindings[b].binds[a].view = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->imageView)->id);
|
||||
dst.bindings[b].binds[a].res = rm->GetOriginalID(c.m_ImageView[dst.bindings[b].binds[a].view].image);
|
||||
}
|
||||
if(info->bufferView != VK_NULL_HANDLE)
|
||||
{
|
||||
dst.bindings[b].binds[a].view = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->bufferView)->id);
|
||||
dst.bindings[b].binds[a].res = rm->GetOriginalID(c.m_BufferView[dst.bindings[b].binds[a].view].buffer);
|
||||
dst.bindings[b].binds[a].offset = *(uint32_t *)&info->imageLayout;
|
||||
dst.bindings[b].binds[a].offset += c.m_BufferView[dst.bindings[b].binds[a].view].offset;
|
||||
dst.bindings[b].binds[a].size = c.m_BufferView[dst.bindings[b].binds[a].view].size;
|
||||
}
|
||||
if(info->attachmentView != VK_NULL_HANDLE)
|
||||
{
|
||||
dst.bindings[b].binds[a].view = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->attachmentView)->id);
|
||||
dst.bindings[b].binds[a].res = rm->GetOriginalID(c.m_AttachmentView[dst.bindings[b].binds[a].view].image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1621,9 +1642,271 @@ void VulkanReplay::SavePipelineState()
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanReplay::FillCBufferVariables(rdctype::array<ShaderConstant> invars, vector<ShaderVariable> &outvars, const vector<byte> &data, size_t &offset)
|
||||
{
|
||||
for(int v=0; v < invars.count; v++)
|
||||
{
|
||||
string basename = invars[v].name.elems;
|
||||
|
||||
uint32_t rows = invars[v].type.descriptor.rows;
|
||||
uint32_t cols = invars[v].type.descriptor.cols;
|
||||
uint32_t elems = RDCMAX(1U,invars[v].type.descriptor.elements);
|
||||
bool rowMajor = invars[v].type.descriptor.rowMajorStorage != 0;
|
||||
bool isArray = elems > 1;
|
||||
|
||||
if(invars[v].type.members.count > 0)
|
||||
{
|
||||
// structs are aligned
|
||||
offset = AlignUp16(offset);
|
||||
|
||||
ShaderVariable var;
|
||||
var.name = basename;
|
||||
var.rows = var.columns = 0;
|
||||
var.type = eVar_Float;
|
||||
|
||||
vector<ShaderVariable> varmembers;
|
||||
|
||||
if(isArray)
|
||||
{
|
||||
for(uint32_t i=0; i < elems; i++)
|
||||
{
|
||||
// each struct in the array is aligned
|
||||
offset = AlignUp16(offset);
|
||||
|
||||
ShaderVariable vr;
|
||||
vr.name = StringFormat::Fmt("%s[%u]", basename.c_str(), i);
|
||||
vr.rows = vr.columns = 0;
|
||||
vr.type = eVar_Float;
|
||||
|
||||
vector<ShaderVariable> mems;
|
||||
|
||||
FillCBufferVariables(invars[v].type.members, mems, data, offset);
|
||||
|
||||
vr.isStruct = true;
|
||||
|
||||
vr.members = mems;
|
||||
|
||||
varmembers.push_back(vr);
|
||||
}
|
||||
|
||||
var.isStruct = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var.isStruct = true;
|
||||
|
||||
FillCBufferVariables(invars[v].type.members, varmembers, data, offset);
|
||||
}
|
||||
|
||||
{
|
||||
var.members = varmembers;
|
||||
outvars.push_back(var);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE this won't work as-is for doubles, the below logic
|
||||
// assumes 32-bit values. This code will all go away anyway
|
||||
// once offsets & strides are correctly listed per-element
|
||||
size_t elemByteSize = sizeof(uint32_t);
|
||||
size_t sz = elemByteSize;
|
||||
|
||||
// vector
|
||||
if(cols == 1)
|
||||
{
|
||||
if(isArray)
|
||||
{
|
||||
// arrays are aligned to float4 boundary
|
||||
offset = AlignUp16(offset);
|
||||
|
||||
// array elements are also aligned - note, last
|
||||
// element only takes up however much space it would
|
||||
// so e.g. a float3 array leaves one float at the end
|
||||
// that could be there
|
||||
sz *= 4*elems;
|
||||
sz -= (4-rows)*elemByteSize;
|
||||
}
|
||||
else if(rows > 2)
|
||||
{
|
||||
// float3s and float4s are aligned
|
||||
offset = AlignUp16(offset);
|
||||
sz *= rows;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// matrices are aligned to float4 boundary
|
||||
offset = AlignUp16(offset);
|
||||
|
||||
// matrices act like an array of vectors, whether they
|
||||
// are an array or not. We just need to determine if
|
||||
// those vectors are the matrix's rows, or its columns,
|
||||
// and adjust number of elements - even a float2x2 is
|
||||
// stored in two float4s.
|
||||
if(rowMajor)
|
||||
{
|
||||
// account for array elems as well as columns.
|
||||
// Note the last array elem can have space after
|
||||
// it which can be filled with another element, so
|
||||
// need to ensure the 'stride' accounts for that.
|
||||
sz *= 4*elems*cols;
|
||||
sz -= (4-rows)*elemByteSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
sz *= 4*elems*rows;
|
||||
sz -= (4-cols)*elemByteSize;
|
||||
}
|
||||
}
|
||||
|
||||
// after alignment, this is where we'll read from
|
||||
size_t dataOffset = offset;
|
||||
|
||||
offset += sz;
|
||||
|
||||
size_t outIdx = outvars.size();
|
||||
outvars.resize(outvars.size()+1);
|
||||
|
||||
{
|
||||
outvars[outIdx].name = basename;
|
||||
outvars[outIdx].rows = 1;
|
||||
outvars[outIdx].type = invars[v].type.descriptor.type;
|
||||
outvars[outIdx].isStruct = false;
|
||||
outvars[outIdx].columns = cols;
|
||||
|
||||
ShaderVariable &var = outvars[outIdx];
|
||||
|
||||
if(!isArray)
|
||||
{
|
||||
outvars[outIdx].rows = rows;
|
||||
|
||||
if(dataOffset < data.size())
|
||||
{
|
||||
const byte *d = &data[dataOffset];
|
||||
|
||||
RDCASSERT(rows <= 4 && rows*cols <= 16);
|
||||
|
||||
if(!rowMajor)
|
||||
{
|
||||
uint32_t tmp[16] = {0};
|
||||
|
||||
for(uint32_t r=0; r < rows; r++)
|
||||
{
|
||||
size_t srcoffs = 4*elemByteSize*r;
|
||||
size_t dstoffs = cols*elemByteSize*r;
|
||||
memcpy((byte *)(tmp) + dstoffs, d + srcoffs,
|
||||
RDCMIN(data.size()-dataOffset + srcoffs, elemByteSize*cols));
|
||||
}
|
||||
|
||||
// transpose
|
||||
for(size_t r=0; r < rows; r++)
|
||||
for(size_t c=0; c < cols; c++)
|
||||
outvars[outIdx].value.uv[r*cols+c] = tmp[c*rows+r];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint32_t r=0; r < rows; r++)
|
||||
{
|
||||
size_t srcoffs = 4*elemByteSize*r;
|
||||
size_t dstoffs = cols*elemByteSize*r;
|
||||
memcpy((byte *)(&outvars[outIdx].value.uv[0]) + dstoffs, d + srcoffs,
|
||||
RDCMIN(data.size()-dataOffset + srcoffs, elemByteSize*cols));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[64] = {0};
|
||||
|
||||
var.name = outvars[outIdx].name;
|
||||
var.rows = 0;
|
||||
var.columns = 0;
|
||||
|
||||
bool isMatrix = rows > 1 && cols > 1;
|
||||
|
||||
vector<ShaderVariable> varmembers;
|
||||
varmembers.resize(elems);
|
||||
|
||||
string base = outvars[outIdx].name.elems;
|
||||
|
||||
uint32_t primaryDim = cols;
|
||||
uint32_t secondaryDim = rows;
|
||||
if(rowMajor)
|
||||
{
|
||||
primaryDim = rows;
|
||||
secondaryDim = cols;
|
||||
}
|
||||
|
||||
for(uint32_t e=0; e < elems; e++)
|
||||
{
|
||||
varmembers[e].name = StringFormat::Fmt("%s[%u]", base.c_str(), e);
|
||||
varmembers[e].rows = rows;
|
||||
varmembers[e].type = invars[v].type.descriptor.type;
|
||||
varmembers[e].isStruct = false;
|
||||
varmembers[e].columns = cols;
|
||||
|
||||
size_t rowDataOffset = dataOffset+e*primaryDim*4*elemByteSize;
|
||||
|
||||
if(rowDataOffset < data.size())
|
||||
{
|
||||
const byte *d = &data[rowDataOffset];
|
||||
|
||||
// each primary element (row or column) is stored in a float4.
|
||||
// we copy some padding here, but that will come out in the wash
|
||||
// when we transpose
|
||||
for(uint32_t p=0; p < primaryDim; p++)
|
||||
{
|
||||
memcpy(&(varmembers[e].value.uv[secondaryDim*p]), d + 4*elemByteSize*p,
|
||||
RDCMIN(data.size()- rowDataOffset, elemByteSize*secondaryDim));
|
||||
}
|
||||
|
||||
if(!rowMajor)
|
||||
{
|
||||
ShaderVariable tmp = varmembers[e];
|
||||
// transpose
|
||||
for(size_t ri=0; ri < rows; ri++)
|
||||
for(size_t ci=0; ci < cols; ci++)
|
||||
varmembers[e].value.uv[ri*cols+ci] = tmp.value.uv[ci*rows+ri];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var.isStruct = false;
|
||||
var.members = varmembers;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanReplay::FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector<ShaderVariable> &outvars, const vector<byte> &data)
|
||||
{
|
||||
RDCUNIMPLEMENTED("FillCBufferVariables");
|
||||
// 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_ShaderInfo.find(shader);
|
||||
|
||||
if(it == m_pDriver->m_ShaderInfo.end())
|
||||
{
|
||||
RDCERR("Can't get shader details");
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderReflection &refl = it->second.refl;
|
||||
|
||||
if(cbufSlot >= (uint32_t)refl.ConstantBlocks.count)
|
||||
{
|
||||
RDCERR("Invalid cbuffer slot");
|
||||
return;
|
||||
}
|
||||
|
||||
ConstantBlock &c = refl.ConstantBlocks[cbufSlot];
|
||||
|
||||
size_t zero = 0;
|
||||
FillCBufferVariables(c.variables, outvars, data, zero);
|
||||
}
|
||||
|
||||
bool VulkanReplay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float *minval, float *maxval)
|
||||
|
||||
@@ -215,5 +215,7 @@ class VulkanReplay : public IReplayDriver
|
||||
|
||||
WrappedVulkan *m_pDriver;
|
||||
|
||||
void FillCBufferVariables(rdctype::array<ShaderConstant>, vector<ShaderVariable> &outvars, const vector<byte> &data, size_t &offset);
|
||||
|
||||
VulkanDebugManager *GetDebugManager();
|
||||
};
|
||||
|
||||
@@ -565,6 +565,9 @@ bool WrappedVulkan::Serialise_vkCreateBufferView(
|
||||
{
|
||||
device = GetResourceManager()->GetLiveHandle<VkDevice>(devId);
|
||||
VkBufferView view = VK_NULL_HANDLE;
|
||||
|
||||
// use original ID
|
||||
m_CreationInfo.m_BufferView[id].Init(&info);
|
||||
|
||||
VkResult ret = ObjDisp(device)->CreateBufferView(Unwrap(device), &info, &view);
|
||||
|
||||
@@ -748,6 +751,9 @@ bool WrappedVulkan::Serialise_vkCreateImageView(
|
||||
{
|
||||
device = GetResourceManager()->GetLiveHandle<VkDevice>(devId);
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
|
||||
// use original ID
|
||||
m_CreationInfo.m_ImageView[id].Init(&info);
|
||||
|
||||
VkResult ret = ObjDisp(device)->CreateImageView(Unwrap(device), &info, &view);
|
||||
|
||||
|
||||
@@ -665,6 +665,39 @@ namespace renderdocui.Code
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (IsLogVK)
|
||||
{
|
||||
VulkanPipelineState.Pipeline pipe = m_Vulkan.graphics;
|
||||
if (stage == ShaderStageType.Compute)
|
||||
pipe = m_Vulkan.compute;
|
||||
|
||||
VulkanPipelineState.ShaderStage s = null;
|
||||
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStageType.Vertex: s = m_Vulkan.VS; break;
|
||||
case ShaderStageType.Tess_Control: s = m_Vulkan.TCS; break;
|
||||
case ShaderStageType.Tess_Eval: s = m_Vulkan.TES; break;
|
||||
case ShaderStageType.Geometry: s = m_Vulkan.GS; break;
|
||||
case ShaderStageType.Fragment: s = m_Vulkan.FS; break;
|
||||
case ShaderStageType.Compute: s = m_Vulkan.CS; break;
|
||||
}
|
||||
|
||||
if (s.ShaderDetails != null && BufIdx < s.ShaderDetails.ConstantBlocks.Length)
|
||||
{
|
||||
var bind = s.BindpointMapping.ConstantBlocks[s.ShaderDetails.ConstantBlocks[BufIdx].bindPoint];
|
||||
|
||||
// TODO do we need to worry about arrays of uniform buffers?
|
||||
var descriptorBind = pipe.DescSets[bind.bindset].bindings[bind.bind].binds[0];
|
||||
|
||||
buf = descriptorBind.res;
|
||||
// VKTODOLOW maybe increase parameter to ulong and upcast others?
|
||||
ByteOffset = (uint)descriptorBind.offset;
|
||||
ByteSize = (uint)descriptorBind.size;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf = ResourceId.Null;
|
||||
|
||||
@@ -53,8 +53,10 @@ namespace renderdoc
|
||||
public class BindingElement
|
||||
{
|
||||
public ResourceId view;
|
||||
public ResourceId res;
|
||||
public ResourceId sampler;
|
||||
public UInt32 offset;
|
||||
public UInt64 offset;
|
||||
public UInt64 size;
|
||||
};
|
||||
[CustomMarshalAs(CustomUnmanagedType.TemplatedArray)]
|
||||
public BindingElement[] binds;
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace renderdocui.Windows.PipelineState
|
||||
|
||||
// Set a shader stage's resources and values
|
||||
private void SetShaderState(FetchTexture[] texs, FetchBuffer[] bufs,
|
||||
VulkanPipelineState.ShaderStage stage,
|
||||
VulkanPipelineState.ShaderStage stage, VulkanPipelineState.Pipeline pipe,
|
||||
Label shader, TreelistView.TreeListView resources, TreelistView.TreeListView samplers,
|
||||
TreelistView.TreeListView cbuffers, TreelistView.TreeListView classes)
|
||||
{
|
||||
@@ -249,7 +249,63 @@ namespace renderdocui.Windows.PipelineState
|
||||
vs = cbuffers.VScrollValue();
|
||||
cbuffers.BeginUpdate();
|
||||
cbuffers.Nodes.Clear();
|
||||
if(stage.ShaderDetails != null)
|
||||
{
|
||||
UInt32 i = 0;
|
||||
foreach (var b in shaderDetails.ConstantBlocks)
|
||||
{
|
||||
BindpointMap bindMap = stage.BindpointMapping.ConstantBlocks[b.bindPoint];
|
||||
|
||||
// TODO do we need to worry about arrays of uniform buffers?
|
||||
var descriptorBind = pipe.DescSets[bindMap.bindset].bindings[bindMap.bind].binds[0];
|
||||
|
||||
bool filledSlot = (descriptorBind.res != ResourceId.Null);
|
||||
bool usedSlot = bindMap.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 = "Constant Buffer " + descriptorBind.res.ToString();
|
||||
UInt64 length = descriptorBind.size;
|
||||
int numvars = b.variables.Length;
|
||||
|
||||
if (!filledSlot)
|
||||
{
|
||||
name = "Empty";
|
||||
length = 0;
|
||||
}
|
||||
|
||||
for (int t = 0; t < bufs.Length; t++)
|
||||
if (bufs[t].ID == descriptorBind.res)
|
||||
name = bufs[t].name;
|
||||
|
||||
if (name == "")
|
||||
name = "Constant Buffer " + descriptorBind.res.ToString();
|
||||
|
||||
string slotname = i.ToString();
|
||||
slotname += ": " + b.name;
|
||||
|
||||
string sizestr = String.Format("{0} Variables, {1} bytes", numvars, length);
|
||||
string vecrange = String.Format("{0} - {1}", descriptorBind.offset, descriptorBind.offset + descriptorBind.size);
|
||||
|
||||
var node = cbuffers.Nodes.Add(new object[] { slotname, name, vecrange, sizestr });
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
cbuffers.EndUpdate();
|
||||
cbuffers.NodesSelection.Clear();
|
||||
cbuffers.SetVScrollValue(vs);
|
||||
@@ -562,12 +618,12 @@ namespace renderdocui.Windows.PipelineState
|
||||
viBuffers.EndUpdate();
|
||||
viBuffers.SetVScrollValue(vs);
|
||||
|
||||
SetShaderState(texs, bufs, state.VS, vsShader, vsResources, vsSamplers, vsCBuffers, vsClasses);
|
||||
SetShaderState(texs, bufs, state.GS, gsShader, gsResources, gsSamplers, gsCBuffers, gsClasses);
|
||||
SetShaderState(texs, bufs, state.TCS, hsShader, hsResources, hsSamplers, hsCBuffers, hsClasses);
|
||||
SetShaderState(texs, bufs, state.TES, dsShader, dsResources, dsSamplers, dsCBuffers, dsClasses);
|
||||
SetShaderState(texs, bufs, state.FS, psShader, psResources, psSamplers, psCBuffers, psClasses);
|
||||
SetShaderState(texs, bufs, state.CS, csShader, csResources, csSamplers, csCBuffers, csClasses);
|
||||
SetShaderState(texs, bufs, state.VS, state.graphics, vsShader, vsResources, vsSamplers, vsCBuffers, vsClasses);
|
||||
SetShaderState(texs, bufs, state.GS, state.graphics, gsShader, gsResources, gsSamplers, gsCBuffers, gsClasses);
|
||||
SetShaderState(texs, bufs, state.TCS, state.graphics, hsShader, hsResources, hsSamplers, hsCBuffers, hsClasses);
|
||||
SetShaderState(texs, bufs, state.TES, state.graphics, dsShader, dsResources, dsSamplers, dsCBuffers, dsClasses);
|
||||
SetShaderState(texs, bufs, state.FS, state.graphics, psShader, psResources, psSamplers, psCBuffers, psClasses);
|
||||
SetShaderState(texs, bufs, state.CS, state.compute, csShader, csResources, csSamplers, csCBuffers, csClasses);
|
||||
|
||||
vs = csUAVs.VScrollValue();
|
||||
csUAVs.Nodes.Clear();
|
||||
@@ -1288,6 +1344,20 @@ namespace renderdocui.Windows.PipelineState
|
||||
|
||||
private void ShowCBuffer(VulkanPipelineState.ShaderStage stage, UInt32 slot)
|
||||
{
|
||||
VulkanPipelineState.Pipeline pipe = m_Core.CurVulkanPipelineState.graphics;
|
||||
if(stage.stage == ShaderStageType.Compute)
|
||||
pipe = m_Core.CurVulkanPipelineState.compute;
|
||||
|
||||
var existing = ConstantBufferPreviewer.Has(stage.stage, slot);
|
||||
if (existing != null)
|
||||
{
|
||||
existing.Show();
|
||||
return;
|
||||
}
|
||||
|
||||
var prev = new ConstantBufferPreviewer(m_Core, stage.stage, slot);
|
||||
|
||||
prev.ShowDock(m_DockContent.Pane, DockAlignment.Right, 0.3);
|
||||
}
|
||||
|
||||
private void cbuffers_NodeDoubleClicked(TreelistView.Node node)
|
||||
|
||||
Reference in New Issue
Block a user