Allow cbuffer previewer to apply custom format to non-buffer-backed CBs

* This in particular means push constants and specialization constants on vulkan
  but also applies to root-value cbuffers on D3D12.
* GL bare uniforms are not feasible to expose in this way.
This commit is contained in:
baldurk committed 2021-04-14 18:59:12 +01:00
1 parent 94b0b04483
commit eac94b74f6
14 files changed
+342 -132

No files matched your search

-1
View File
@@ -393,7 +393,6 @@ TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, DescriptorSet)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, ImageData)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, ImageLayout)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, RenderArea)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, SpecializationConstant)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, XFBBuffer)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, VertexBuffer)
TEMPLATE_NAMESPACE_ARRAY_INSTANTIATE(rdcarray, VKPipe, VertexAttribute)
+38 -19
View File
@@ -107,6 +107,7 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
m_cbuffer = cb.resourceId;
uint64_t offset = cb.byteOffset;
uint64_t size = cb.byteSize;
bytebuf inlineData = cb.inlineData;
ResourceId prevShader = m_shader;
@@ -136,26 +137,24 @@ void ConstantBufferPreviewer::OnEventChanged(uint32_t eventId)
if(!m_formatOverride.type.members.empty())
{
m_Ctx.Replay().AsyncInvoke([this, offset, size, wasEmpty](IReplayController *r) {
bytebuf data;
if(size > 0)
data = r->GetBufferData(m_cbuffer, offset, size);
rdcarray<ShaderVariable> vars = applyFormatOverride(data);
GUIInvoke::call(this, [this, vars, wasEmpty] {
RDTreeViewExpansionState state;
ui->variables->saveExpansion(state, 0);
setVariables(vars);
if(wasEmpty)
{
// Expand before resizing so that collapsed data will already be visible when expanded
ui->variables->expandAll();
for(int i = 0; i < 3; i++)
ui->variables->resizeColumnToContents(i);
ui->variables->collapseAll();
}
ui->variables->applyExpansion(state, 0);
if(!inlineData.empty() && m_cbuffer == ResourceId())
{
setVariablesPreserveExpansion(applyFormatOverride(inlineData), wasEmpty);
}
else
{
m_Ctx.Replay().AsyncInvoke([this, offset, size, wasEmpty](IReplayController *r) {
bytebuf data;
if(size > 0 && m_cbuffer != ResourceId())
data = r->GetBufferData(m_cbuffer, offset, size);
rdcarray<ShaderVariable> vars = applyFormatOverride(data);
GUIInvoke::call(this,
[this, vars, wasEmpty] { setVariablesPreserveExpansion(vars, wasEmpty); });
});
});
}
}
else
{
@@ -327,6 +326,26 @@ void ConstantBufferPreviewer::setVariables(const rdcarray<ShaderVariable> &vars)
ui->variables->endUpdate();
}
void ConstantBufferPreviewer::setVariablesPreserveExpansion(const rdcarray<ShaderVariable> &vars,
bool wasEmpty)
{
RDTreeViewExpansionState state;
ui->variables->saveExpansion(state, 0);
setVariables(vars);
if(wasEmpty)
{
// Expand before resizing so that collapsed data will already be visible when expanded
ui->variables->expandAll();
for(int i = 0; i < 3; i++)
ui->variables->resizeColumnToContents(i);
ui->variables->collapseAll();
}
ui->variables->applyExpansion(state, 0);
}
void ConstantBufferPreviewer::updateLabels()
{
QString bufName = m_Ctx.GetResourceName(m_cbuffer);
@@ -84,6 +84,7 @@ private:
void addVariables(RDTreeWidgetItem *root, const rdcarray<ShaderVariable> &vars);
void setVariables(const rdcarray<ShaderVariable> &vars);
void setVariablesPreserveExpansion(const rdcarray<ShaderVariable> &vars, bool wasEmpty);
void updateLabels();
@@ -1626,12 +1626,28 @@ void VulkanPipelineStateViewer::addConstantBlockRow(ShaderReflection *shaderDeta
{
setname = QString();
slotname = cblock->name;
name = tr("Push constants");
if(cblock->compileConstants)
name = tr("Specialization constants");
else if(descriptorBind && descriptorBind->inlineBlock)
name = tr("Inline uniforms");
else
name = tr("Push constants");
vecrange = QString();
sizestr = tr("%1 Variables").arg(numvars);
// could maybe get range from ShaderVariable.reg if it's filled out
// from SPIR-V side.
if(descriptorBind && descriptorBind->inlineBlock)
{
vecrange = QFormatStr("%1 - %2")
.arg(descriptorBind->byteOffset)
.arg(descriptorBind->byteOffset + descriptorBind->byteSize);
}
else if(!cblock->compileConstants)
{
vecrange = QFormatStr("%1 - %2")
.arg(stage.pushConstantRangeByteOffset)
.arg(stage.pushConstantRangeByteOffset + stage.pushConstantRangeByteSize);
}
}
else
{
@@ -1850,16 +1866,9 @@ void VulkanPipelineStateViewer::setShaderState(const VKPipe::Shader &stage,
ConstantBlock &cblock = shaderDetails->constantBlocks[cb];
if(cblock.bufferBacked == false)
{
// could maybe get range from ShaderVariable.reg if it's filled out
// from SPIR-V side.
RDTreeWidgetItem *node =
new RDTreeWidgetItem({QString(), QString(), cblock.name, tr("Push constants"), QString(),
tr("%1 Variables").arg(cblock.variables.count()), QString()});
node->setTag(QVariant::fromValue(VulkanCBufferTag(cb)));
ubos->addTopLevelItem(node);
addConstantBlockRow(
shaderDetails, stage, stage.bindpointMapping.constantBlocks[cblock.bindPoint].bindset,
stage.bindpointMapping.constantBlocks[cblock.bindPoint].bind, pipe, ubos);
}
}
}
@@ -3225,18 +3234,42 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe::
// push constants
if(!b.bufferBacked)
{
const VKPipe::BindingElement *descriptorBind = NULL;
if(bindMap.bindset < pipeline.descriptorSets.count() &&
bindMap.bind < pipeline.descriptorSets[bindMap.bindset].bindings.count())
descriptorBind = &pipeline.descriptorSets[bindMap.bindset].bindings[bindMap.bind].binds[0];
QString name;
if(b.compileConstants)
name = tr("Specialization constants");
else if(descriptorBind->inlineBlock)
name = tr("Inline uniforms");
else
name = tr("Push constants");
qulonglong offset = 0, size = 0;
if(descriptorBind->inlineBlock)
{
offset = descriptorBind->byteOffset;
size = descriptorBind->byteSize;
}
else if(!b.compileConstants)
{
offset = sh.pushConstantRangeByteOffset;
size = sh.pushConstantRangeByteSize;
}
// could maybe get range/size from ShaderVariable.reg if it's filled out
// from SPIR-V side.
rows.push_back({QString(), b.name, tr("Push constants"), (qulonglong)0, (qulonglong)0,
b.variables.count(), b.byteSize});
rows.push_back({QString(), b.name, name, offset, size, b.variables.count(), b.byteSize});
continue;
}
const VKPipe::DescriptorSet &set =
pipeline.descriptorSets[sh.bindpointMapping.constantBlocks[i].bindset];
const VKPipe::DescriptorBinding &bind =
set.bindings[sh.bindpointMapping.constantBlocks[i].bind];
const VKPipe::DescriptorSet &set = pipeline.descriptorSets[bindMap.bindset];
const VKPipe::DescriptorBinding &bind = set.bindings[bindMap.bind];
QString setname = QString::number(bindMap.bindset);
+7
View File
@@ -409,6 +409,13 @@ struct BoundCBuffer
uint64_t byteOffset = 0;
DOCUMENT("The size in bytes for the constant buffer. Access outside this size returns 0.");
uint64_t byteSize = 0;
DOCUMENT(R"(The inline byte data for this constant buffer, if this binding is not backed by a
typical buffer.
:type: bytes
)");
bytebuf inlineData;
};
DECLARE_REFLECTION_STRUCT(BoundCBuffer);
+93 -27
View File
@@ -905,9 +905,7 @@ rdcarray<VertexInputAttribute> PipeState::GetVertexInputs() const
BoundCBuffer PipeState::GetConstantBuffer(ShaderStage stage, uint32_t BufIdx, uint32_t ArrayIdx) const
{
ResourceId buf;
uint64_t ByteOffset = 0;
uint64_t ByteSize = 0;
BoundCBuffer ret;
if(IsCaptureLoaded())
{
@@ -925,9 +923,9 @@ BoundCBuffer PipeState::GetConstantBuffer(ShaderStage stage, uint32_t BufIdx, ui
const D3D11Pipe::ConstantBuffer &descriptor = s.constantBuffers[bind.bind];
buf = descriptor.resourceId;
ByteOffset = descriptor.vecOffset * 4 * sizeof(float);
ByteSize = descriptor.vecCount * 4 * sizeof(float);
ret.resourceId = descriptor.resourceId;
ret.byteOffset = descriptor.vecOffset * 4 * sizeof(float);
ret.byteSize = descriptor.vecCount * 4 * sizeof(float);
}
}
else if(IsCaptureD3D12())
@@ -956,10 +954,16 @@ BoundCBuffer PipeState::GetConstantBuffer(ShaderStage stage, uint32_t BufIdx, ui
const D3D12Pipe::ConstantBuffer &cb = element.constantBuffers[j];
if(cb.bind == (uint32_t)shaderReg)
{
buf = cb.resourceId;
ByteOffset = cb.byteOffset;
ByteSize = cb.byteSize;
found = true;
ret.resourceId = cb.resourceId;
ret.byteOffset = cb.byteOffset;
ret.byteSize = cb.byteSize;
if(element.immediate)
{
ret.inlineData.resize(cb.rootValues.byteSize());
memcpy(ret.inlineData.data(), cb.rootValues.data(), ret.inlineData.size());
}
break;
}
}
@@ -981,12 +985,12 @@ BoundCBuffer PipeState::GetConstantBuffer(ShaderStage stage, uint32_t BufIdx, ui
{
const GLPipe::Buffer &b = m_GL->uniformBuffers[uboIdx];
buf = b.resourceId;
ByteOffset = b.byteOffset;
ByteSize = b.byteSize;
ret.resourceId = b.resourceId;
ret.byteOffset = b.byteOffset;
ret.byteSize = b.byteSize;
if(ByteSize == 0)
ByteSize = ~0ULL;
if(ret.byteSize == 0)
ret.byteSize = ~0ULL;
}
}
}
@@ -1004,33 +1008,95 @@ BoundCBuffer PipeState::GetConstantBuffer(ShaderStage stage, uint32_t BufIdx, ui
if(s.reflection->constantBlocks[BufIdx].bufferBacked == false)
{
BoundCBuffer ret;
// dummy value, it would be nice to fetch this properly
ret.byteSize = 1024;
if(s.reflection->constantBlocks[BufIdx].compileConstants)
{
ret.inlineData = s.specializationData;
ret.byteSize = ret.inlineData.size();
}
else
{
ret.inlineData.resize((size_t)ret.byteSize);
const bytebuf *src = NULL;
// push constants have a magic bindset value higher than any descriptor set
if(bind.bindset < pipe.descriptorSets.count())
{
if(bind.bind >= pipe.descriptorSets[bind.bindset].bindings.count() ||
ArrayIdx >= pipe.descriptorSets[bind.bindset].bindings[bind.bind].binds.size())
return BoundCBuffer();
src = &pipe.descriptorSets[bind.bindset].inlineData;
const VKPipe::BindingElement &descriptorBind =
pipe.descriptorSets[bind.bindset].bindings[bind.bind].binds[ArrayIdx];
ret.byteOffset = descriptorBind.byteOffset;
ret.byteSize = descriptorBind.byteSize;
}
else
{
src = &m_Vulkan->pushconsts;
switch(stage)
{
case ShaderStage::Vertex:
ret.byteOffset = m_Vulkan->vertexShader.pushConstantRangeByteOffset;
ret.byteSize = m_Vulkan->vertexShader.pushConstantRangeByteSize;
break;
case ShaderStage::Tess_Control:
ret.byteOffset = m_Vulkan->tessControlShader.pushConstantRangeByteOffset;
ret.byteSize = m_Vulkan->tessControlShader.pushConstantRangeByteSize;
break;
case ShaderStage::Tess_Eval:
ret.byteOffset = m_Vulkan->tessEvalShader.pushConstantRangeByteOffset;
ret.byteSize = m_Vulkan->tessEvalShader.pushConstantRangeByteSize;
break;
case ShaderStage::Geometry:
ret.byteOffset = m_Vulkan->geometryShader.pushConstantRangeByteOffset;
ret.byteSize = m_Vulkan->geometryShader.pushConstantRangeByteSize;
break;
case ShaderStage::Fragment:
ret.byteOffset = m_Vulkan->fragmentShader.pushConstantRangeByteOffset;
ret.byteSize = m_Vulkan->fragmentShader.pushConstantRangeByteSize;
break;
case ShaderStage::Compute:
ret.byteOffset = m_Vulkan->computeShader.pushConstantRangeByteOffset;
ret.byteSize = m_Vulkan->computeShader.pushConstantRangeByteSize;
break;
default: break;
}
}
if(ret.byteOffset > src->size())
ret.byteSize = 0;
else if(ret.byteOffset + ret.byteSize > src->size())
ret.byteSize = src->size() - (ret.byteOffset + ret.byteSize);
// consume the byteoffset here when copying data from the source data
ret.inlineData.resize((size_t)ret.byteSize);
memcpy(ret.inlineData.data(), src->data() + ret.byteOffset, (size_t)ret.byteSize);
ret.byteOffset = 0;
}
return ret;
}
if(bind.bindset >= pipe.descriptorSets.count() ||
bind.bind >= pipe.descriptorSets[bind.bindset].bindings.count() ||
ArrayIdx > pipe.descriptorSets[bind.bindset].bindings[bind.bind].binds.size())
ArrayIdx >= pipe.descriptorSets[bind.bindset].bindings[bind.bind].binds.size())
return BoundCBuffer();
const VKPipe::BindingElement &descriptorBind =
pipe.descriptorSets[bind.bindset].bindings[bind.bind].binds[ArrayIdx];
buf = descriptorBind.resourceResourceId;
ByteOffset = descriptorBind.byteOffset;
ByteSize = descriptorBind.byteSize;
ret.resourceId = descriptorBind.resourceResourceId;
ret.byteOffset = descriptorBind.byteOffset;
ret.byteSize = descriptorBind.byteSize;
}
}
}
BoundCBuffer ret;
ret.resourceId = buf;
ret.byteOffset = ByteOffset;
ret.byteSize = ByteSize;
return ret;
}
+9 -4
View File
@@ -1025,7 +1025,8 @@ struct ConstantBlock
bool operator==(const ConstantBlock &o) const
{
return name == o.name && variables == o.variables && bindPoint == o.bindPoint &&
byteSize == o.byteSize && bufferBacked == o.bufferBacked;
byteSize == o.byteSize && bufferBacked == o.bufferBacked &&
compileConstants == o.compileConstants;
}
bool operator<(const ConstantBlock &o) const
{
@@ -1039,6 +1040,8 @@ struct ConstantBlock
return byteSize < o.byteSize;
if(!(bufferBacked == o.bufferBacked))
return bufferBacked < o.bufferBacked;
if(!(compileConstants == o.compileConstants))
return compileConstants < o.compileConstants;
return false;
}
DOCUMENT("The name of this constant block, may be empty on some APIs.");
@@ -1051,14 +1054,16 @@ struct ConstantBlock
DOCUMENT(R"(The bindpoint for this block. This is an index in the
:data:`ShaderBindpointMapping.constantBlocks` list.
)");
int32_t bindPoint;
int32_t bindPoint = 0;
DOCUMENT("The total number of bytes consumed by all of the constants contained in this block.");
uint32_t byteSize;
uint32_t byteSize = 0;
DOCUMENT(R"(``True`` if the contents are stored in a buffer of memory. If not then they are set by
some other API-specific method, such as direct function calls or they may be compile-time
specialisation constants.
)");
bool bufferBacked;
bool bufferBacked = true;
DOCUMENT("``True`` if this is a virtual buffer listing compile-time specialisation constants.");
bool compileConstants = false;
};
DECLARE_REFLECTION_STRUCT(ConstantBlock);
+28 -32
View File
@@ -144,7 +144,11 @@ since single descriptors may only be dynamically skipped by control flow.
DOCUMENT("For 3D textures and texture arrays - the number of array slices in the view.");
uint32_t numSlices = 0;
DOCUMENT("For buffers - the byte offset where the buffer view starts in the underlying buffer.");
DOCUMENT(R"(For buffers - the byte offset where the buffer view starts in the underlying buffer.
For inline block uniforms (see :data:`inlineBlock`) this is the byte offset into the descriptor
set's inline block data.
)");
uint64_t byteOffset = 0;
DOCUMENT("For buffers - how many bytes are in this buffer view.");
uint64_t byteSize = 0;
@@ -294,7 +298,8 @@ struct DescriptorSet
{
return layoutResourceId == o.layoutResourceId &&
descriptorSetResourceId == o.descriptorSetResourceId &&
pushDescriptor == o.pushDescriptor && bindings == o.bindings;
pushDescriptor == o.pushDescriptor && bindings == o.bindings &&
inlineData == o.inlineData;
}
bool operator<(const DescriptorSet &o) const
{
@@ -306,6 +311,8 @@ struct DescriptorSet
return pushDescriptor < o.pushDescriptor;
if(!(bindings == o.bindings))
return bindings < o.bindings;
if(!(inlineData == o.inlineData))
return inlineData < o.inlineData;
return false;
}
DOCUMENT("The :class:`ResourceId` of the descriptor set layout that matches this set.");
@@ -321,6 +328,13 @@ This list is indexed by the binding, so it may be sparse (some entries do not co
:type: List[VKDescriptorBinding]
)");
rdcarray<DescriptorBinding> bindings;
DOCUMENT(R"(The inline byte data within this descriptor set. Individual bindings will have an
offset and size into this buffer.
:type: bytes
)");
bytebuf inlineData;
};
DOCUMENT("Describes the object and descriptor set bindings of a Vulkan pipeline object.");
@@ -526,32 +540,6 @@ struct VertexInput
rdcarray<VertexBuffer> vertexBuffers;
};
DOCUMENT("The provided value for a specialization constant.");
struct SpecializationConstant
{
DOCUMENT("");
SpecializationConstant() = default;
SpecializationConstant(const SpecializationConstant &) = default;
SpecializationConstant &operator=(const SpecializationConstant &) = default;
bool operator==(const SpecializationConstant &o) const
{
return specializationId == o.specializationId && data == o.data;
}
bool operator<(const SpecializationConstant &o) const
{
if(!(specializationId == o.specializationId))
return specializationId < o.specializationId;
if(!(data == o.data))
return data < o.data;
return false;
}
DOCUMENT("The specialization ID");
uint32_t specializationId = 0;
DOCUMENT("A ``bytes`` with the contents of the constant.");
bytebuf data;
};
DOCUMENT("Describes a Vulkan shader stage.");
struct Shader
{
@@ -579,11 +567,20 @@ struct Shader
DOCUMENT("A :class:`ShaderStage` identifying which stage this shader is bound to.");
ShaderStage stage = ShaderStage::Vertex;
DOCUMENT(R"(The provided specialization constants.
DOCUMENT("The byte offset into the push constant data that is visible to this shader.");
uint32_t pushConstantRangeByteOffset = 0;
:type: List[VKSpecializationConstant]
DOCUMENT("The number of bytes in the push constant data that is visible to this shader.");
uint32_t pushConstantRangeByteSize = 0;
DOCUMENT(R"(The provided specialization constant data. Shader constants store the byte offset into
this buffer as their byteOffset. This data includes the applied specialization constants over the
top of the default values, so it is safe to read any constant from here and get the correct current
value.
:type: bytes
)");
rdcarray<SpecializationConstant> specialization;
bytebuf specializationData;
};
DOCUMENT("Describes the state of the fixed-function tessellator.");
@@ -1319,7 +1316,6 @@ DECLARE_REFLECTION_STRUCT(VKPipe::VertexAttribute);
DECLARE_REFLECTION_STRUCT(VKPipe::VertexBinding);
DECLARE_REFLECTION_STRUCT(VKPipe::VertexBuffer);
DECLARE_REFLECTION_STRUCT(VKPipe::VertexInput);
DECLARE_REFLECTION_STRUCT(VKPipe::SpecializationConstant);
DECLARE_REFLECTION_STRUCT(VKPipe::Shader);
DECLARE_REFLECTION_STRUCT(VKPipe::Tessellation);
DECLARE_REFLECTION_STRUCT(VKPipe::XFBBuffer);
+2
View File
@@ -954,6 +954,8 @@ void D3D12Replay::FillRootElements(const D3D12RenderState::RootSignature &rootSi
element.constantBuffers.push_back(D3D12Pipe::ConstantBuffer(p.Constants.ShaderRegister));
D3D12Pipe::ConstantBuffer &cb = element.constantBuffers.back();
cb.resourceId = ResourceId();
cb.byteOffset = 0;
cb.byteSize = uint32_t(sizeof(uint32_t) * p.Constants.Num32BitValues);
if(rootEl < rootSig.sigelems.size())
@@ -46,7 +46,7 @@ void FillSpecConstantVariables(ResourceId shader, const rdcarray<ShaderConstant>
{
for(size_t v = 0; v < invars.size() && v < outvars.size(); v++)
{
if(specInfo[i].specID == invars[v].byteOffset)
if(specInfo[i].specID * sizeof(uint64_t) == invars[v].byteOffset)
{
outvars[v].value.u64v[0] = specInfo[i].value;
}
@@ -1115,7 +1115,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st
ShaderConstant spec;
MakeConstantBlockVariable(spec, pointerTypes, dataTypes[c.type], name, decorations[c.id],
specInfo);
spec.byteOffset = decorations[c.id].specID;
spec.byteOffset = decorations[c.id].specID * sizeof(uint64_t);
spec.defaultValue = c.value.value.u64v[0];
specblock.variables.push_back(spec);
}
@@ -1125,6 +1125,7 @@ void Reflector::MakeReflection(const GraphicsAPI sourceAPI, const ShaderStage st
{
specblock.name = "Specialization Constants";
specblock.bufferBacked = false;
specblock.compileConstants = true;
specblock.byteSize = 0;
Bindpoint bindmap;
+19
View File
@@ -521,6 +521,25 @@ int StageIndex(VkShaderStageFlagBits stageFlag)
return 0;
}
VkShaderStageFlags ShaderMaskFromIndex(size_t index)
{
VkShaderStageFlagBits mask[] = {
VK_SHADER_STAGE_VERTEX_BIT,
VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
VK_SHADER_STAGE_GEOMETRY_BIT,
VK_SHADER_STAGE_FRAGMENT_BIT,
VK_SHADER_STAGE_COMPUTE_BIT,
};
if(index < ARRAY_COUNT(mask))
return mask[index];
RDCERR("Unrecognised shader stage index %d", index);
return 0;
}
void DoPipelineBarrier(VkCommandBuffer cmd, size_t count, const VkImageMemoryBarrier *barriers)
{
RDCASSERT(cmd != VK_NULL_HANDLE);
+1
View File
@@ -102,6 +102,7 @@ void DoPipelineBarrier(VkCommandBuffer cmd, size_t count, const VkMemoryBarrier
int SampleCount(VkSampleCountFlagBits countFlag);
int SampleIndex(VkSampleCountFlagBits countFlag);
int StageIndex(VkShaderStageFlagBits stageFlag);
VkShaderStageFlags ShaderMaskFromIndex(size_t index);
struct PackedWindowHandle
{
+80 -14
View File
@@ -1059,6 +1059,8 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
m_VulkanPipelineState.compute.pipelineLayoutResourceId = rm->GetOriginalID(p.layout);
const VulkanCreationInfo::PipelineLayout &pl = c.m_PipelineLayout[p.layout];
m_VulkanPipelineState.compute.flags = p.flags;
VKPipe::Shader &stage = m_VulkanPipelineState.computeShader;
@@ -1074,13 +1076,43 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
if(p.shaders[i].refl)
stage.reflection = p.shaders[i].refl;
stage.specialization.resize(p.shaders[i].specialization.size());
for(size_t s = 0; s < p.shaders[i].specialization.size(); s++)
stage.pushConstantRangeByteOffset = stage.pushConstantRangeByteSize = 0;
for(const VkPushConstantRange &pr : pl.pushRanges)
{
const SpecConstant &spec = p.shaders[i].specialization[s];
stage.specialization[s].specializationId = spec.specID;
stage.specialization[s].data.resize(spec.dataSize);
memcpy(stage.specialization[s].data.data(), &spec.value, spec.dataSize);
if(pr.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT)
{
stage.pushConstantRangeByteOffset = pr.offset;
stage.pushConstantRangeByteSize = pr.size;
break;
}
}
stage.specializationData.clear();
// set up the defaults
if(p.shaders[i].mapping && p.shaders[i].refl)
{
for(size_t cb = 0; cb < p.shaders[i].mapping->constantBlocks.size(); cb++)
{
if(p.shaders[i].mapping->constantBlocks[cb].bindset == SpecializationConstantBindSet)
{
for(const ShaderConstant &sc : p.shaders[i].refl->constantBlocks[cb].variables)
{
stage.specializationData.resize_for_index(sc.byteOffset + sizeof(uint64_t));
memcpy(stage.specializationData.data() + sc.byteOffset, &sc.defaultValue,
sizeof(uint64_t));
}
break;
}
}
}
// apply any specializations
for(const SpecConstant &s : p.shaders[i].specialization)
{
size_t offs = s.specID * sizeof(uint64_t);
stage.specializationData.resize_for_index(offs + sizeof(uint64_t));
memcpy(stage.specializationData.data() + offs, &s.value, s.dataSize);
}
}
}
@@ -1097,6 +1129,8 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
m_VulkanPipelineState.graphics.pipelineLayoutResourceId = rm->GetOriginalID(p.layout);
const VulkanCreationInfo::PipelineLayout &pl = c.m_PipelineLayout[p.layout];
m_VulkanPipelineState.graphics.flags = p.flags;
// Input Assembly
@@ -1157,13 +1191,43 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
if(p.shaders[i].refl)
stages[i]->reflection = p.shaders[i].refl;
stages[i]->specialization.resize(p.shaders[i].specialization.size());
for(size_t s = 0; s < p.shaders[i].specialization.size(); s++)
stages[i]->pushConstantRangeByteOffset = stages[i]->pushConstantRangeByteSize = 0;
for(const VkPushConstantRange &pr : pl.pushRanges)
{
const SpecConstant &spec = p.shaders[i].specialization[s];
stages[i]->specialization[s].specializationId = spec.specID;
stages[i]->specialization[s].data.resize(spec.dataSize);
memcpy(stages[i]->specialization[s].data.data(), &spec.value, spec.dataSize);
if(pr.stageFlags & ShaderMaskFromIndex(i))
{
stages[i]->pushConstantRangeByteOffset = pr.offset;
stages[i]->pushConstantRangeByteSize = pr.size;
break;
}
}
stages[i]->specializationData.clear();
// set up the defaults
if(p.shaders[i].mapping && p.shaders[i].refl)
{
for(size_t cb = 0; cb < p.shaders[i].mapping->constantBlocks.size(); cb++)
{
if(p.shaders[i].mapping->constantBlocks[cb].bindset == SpecializationConstantBindSet)
{
for(const ShaderConstant &sc : p.shaders[i].refl->constantBlocks[cb].variables)
{
stages[i]->specializationData.resize_for_index(sc.byteOffset + sizeof(uint64_t));
memcpy(stages[i]->specializationData.data() + sc.byteOffset, &sc.defaultValue,
sizeof(uint64_t));
}
break;
}
}
}
// apply any specializations
for(const SpecConstant &s : p.shaders[i].specialization)
{
size_t offs = s.specID * sizeof(uint64_t);
stages[i]->specializationData.resize_for_index(offs + sizeof(uint64_t));
memcpy(stages[i]->specializationData.data() + offs, &s.value, s.dataSize);
}
}
@@ -1600,6 +1664,8 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
const uint32_t *srcOffset = (*srcs[p])[i].offsets.begin();
VKPipe::DescriptorSet &dst = (*dsts[p])[i];
dst.inlineData = m_pDriver->m_DescriptorSetState[src].data.inlineBytes;
curBind.bindset = (uint32_t)i;
ResourceId layoutId = m_pDriver->m_DescriptorSetState[src].layout;
@@ -1869,7 +1935,7 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
dst.bindings[b].binds[a].viewResourceId = ResourceId();
dst.bindings[b].binds[a].resourceResourceId = ResourceId();
dst.bindings[b].binds[a].inlineBlock = true;
dst.bindings[b].binds[a].byteOffset = 0;
dst.bindings[b].binds[a].byteOffset = info[a].inlineOffset;
dst.bindings[b].binds[a].byteSize = descriptorCount;
}
else if(layoutBind.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
@@ -2034,7 +2100,7 @@ void VulkanReplay::FillCBufferVariables(ResourceId pipeline, ResourceId shader,
if(pipeIt != m_pDriver->m_CreationInfo.m_Pipeline.end())
{
auto specInfo =
const rdcarray<SpecConstant> &specInfo =
pipeIt->second.shaders[it->second.GetReflection(entryPoint, pipeline).stageIndex].specialization;
FillSpecConstantVariables(refl.resourceId, c.variables, outvars, specInfo);
+9 -14
View File
@@ -215,6 +215,7 @@ void DoSerialise(SerialiserType &ser, ConstantBlock &el)
SERIALISE_MEMBER(bindPoint);
SERIALISE_MEMBER(byteSize);
SERIALISE_MEMBER(bufferBacked);
SERIALISE_MEMBER(compileConstants);
SIZE_CHECK(64);
}
@@ -1920,7 +1921,9 @@ void DoSerialise(SerialiserType &ser, VKPipe::DescriptorSet &el)
SERIALISE_MEMBER(bindings);
SIZE_CHECK(48);
SERIALISE_MEMBER(inlineData);
SIZE_CHECK(72);
}
template <typename SerialiserType>
@@ -1997,15 +2000,6 @@ void DoSerialise(SerialiserType &ser, VKPipe::VertexInput &el)
SIZE_CHECK(72);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VKPipe::SpecializationConstant &el)
{
SERIALISE_MEMBER(specializationId);
SERIALISE_MEMBER(data);
SIZE_CHECK(32);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VKPipe::Shader &el)
{
@@ -2017,9 +2011,11 @@ void DoSerialise(SerialiserType &ser, VKPipe::Shader &el)
SERIALISE_MEMBER(bindpointMapping);
SERIALISE_MEMBER(stage);
SERIALISE_MEMBER(specialization);
SERIALISE_MEMBER(pushConstantRangeByteOffset);
SERIALISE_MEMBER(pushConstantRangeByteSize);
SERIALISE_MEMBER(specializationData);
SIZE_CHECK(192);
SIZE_CHECK(200);
}
template <typename SerialiserType>
@@ -2278,7 +2274,7 @@ void DoSerialise(SerialiserType &ser, VKPipe::State &el)
SERIALISE_MEMBER(conditionalRendering);
SIZE_CHECK(1928);
SIZE_CHECK(1976);
}
#pragma endregion Vulkan pipeline state
@@ -2380,7 +2376,6 @@ INSTANTIATE_SERIALISE_TYPE(VKPipe::DescriptorSet)
INSTANTIATE_SERIALISE_TYPE(VKPipe::Pipeline)
INSTANTIATE_SERIALISE_TYPE(VKPipe::VertexAttribute)
INSTANTIATE_SERIALISE_TYPE(VKPipe::VertexInput)
INSTANTIATE_SERIALISE_TYPE(VKPipe::SpecializationConstant)
INSTANTIATE_SERIALISE_TYPE(VKPipe::Shader)
INSTANTIATE_SERIALISE_TYPE(VKPipe::ViewState)
INSTANTIATE_SERIALISE_TYPE(VKPipe::ColorBlendState)