mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-26 09:21:37 +00:00
Implement VK_KHR_push_descriptor extension. Closes #905
This commit is contained in:
@@ -769,9 +769,11 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
const rdcarray<VKPipe::BindingElement> *slotBinds = NULL;
|
||||
BindType bindType = BindType::Unknown;
|
||||
ShaderStageMask stageBits = ShaderStageMask::Unknown;
|
||||
bool pushDescriptor = false;
|
||||
|
||||
if(bindset < pipe.descriptorSets.count() && bind < pipe.descriptorSets[bindset].bindings.count())
|
||||
{
|
||||
pushDescriptor = pipe.descriptorSets[bindset].pushDescriptor;
|
||||
slotBinds = &pipe.descriptorSets[bindset].bindings[bind].binds;
|
||||
bindType = pipe.descriptorSets[bindset].bindings[bind].type;
|
||||
stageBits = pipe.descriptorSets[bindset].bindings[bind].stageFlags;
|
||||
@@ -817,6 +819,9 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
|
||||
QString setname = QString::number(bindset);
|
||||
|
||||
if(pushDescriptor)
|
||||
setname = tr("Push ") + setname;
|
||||
|
||||
QString slotname = QString::number(bind);
|
||||
if(shaderRes && !shaderRes->name.isEmpty())
|
||||
slotname += lit(": ") + shaderRes->name;
|
||||
@@ -931,7 +936,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
if(!isbuf)
|
||||
{
|
||||
node = new RDTreeWidgetItem({
|
||||
QString(), bindset, slotname, ToQStr(bindType), ResourceId(), lit("-"), QString(),
|
||||
QString(), setname, slotname, ToQStr(bindType), ResourceId(), lit("-"), QString(),
|
||||
QString(),
|
||||
});
|
||||
|
||||
@@ -945,7 +950,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
QFormatStr("Viewing bytes %1 - %2").arg(descriptorBind->byteOffset).arg(descriptorLen);
|
||||
|
||||
node = new RDTreeWidgetItem({
|
||||
QString(), bindset, slotname, ToQStr(bindType),
|
||||
QString(), setname, slotname, ToQStr(bindType),
|
||||
descriptorBind ? descriptorBind->resourceResourceId : ResourceId(),
|
||||
tr("%1 bytes").arg(len), range, QString(),
|
||||
});
|
||||
@@ -966,7 +971,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
range = QFormatStr("bytes %1 - %2").arg(descriptorBind->byteOffset).arg(descriptorLen);
|
||||
|
||||
node = new RDTreeWidgetItem({
|
||||
QString(), bindset, slotname, ToQStr(bindType),
|
||||
QString(), setname, slotname, ToQStr(bindType),
|
||||
descriptorBind ? descriptorBind->resourceResourceId : ResourceId(), format, range,
|
||||
QString(),
|
||||
});
|
||||
@@ -984,7 +989,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
if(descriptorBind == NULL || descriptorBind->samplerResourceId == ResourceId())
|
||||
{
|
||||
node = new RDTreeWidgetItem({
|
||||
QString(), bindset, slotname, ToQStr(bindType), ResourceId(), lit("-"), QString(),
|
||||
QString(), setname, slotname, ToQStr(bindType), ResourceId(), lit("-"), QString(),
|
||||
QString(),
|
||||
});
|
||||
|
||||
@@ -992,8 +997,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
}
|
||||
else
|
||||
{
|
||||
node =
|
||||
new RDTreeWidgetItem(makeSampler(QString::number(bindset), slotname, *descriptorBind));
|
||||
node = new RDTreeWidgetItem(makeSampler(setname, slotname, *descriptorBind));
|
||||
|
||||
if(!filledSlot)
|
||||
setEmptyRow(node);
|
||||
@@ -1014,7 +1018,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
if(descriptorBind == NULL || descriptorBind->resourceResourceId == ResourceId())
|
||||
{
|
||||
node = new RDTreeWidgetItem({
|
||||
QString(), bindset, slotname, ToQStr(bindType), ResourceId(), lit("-"), QString(),
|
||||
QString(), setname, slotname, ToQStr(bindType), ResourceId(), lit("-"), QString(),
|
||||
QString(),
|
||||
});
|
||||
|
||||
@@ -1055,7 +1059,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
dim += QFormatStr(", %1x MSAA").arg(samples);
|
||||
|
||||
node = new RDTreeWidgetItem({
|
||||
QString(), bindset, slotname, typeName, descriptorBind->resourceResourceId, dim,
|
||||
QString(), setname, slotname, typeName, descriptorBind->resourceResourceId, dim,
|
||||
format, QString(),
|
||||
});
|
||||
|
||||
@@ -1073,7 +1077,7 @@ void VulkanPipelineStateViewer::addResourceRow(ShaderReflection *shaderDetails,
|
||||
if(descriptorBind == NULL || descriptorBind->samplerResourceId == ResourceId())
|
||||
{
|
||||
samplerNode = new RDTreeWidgetItem({
|
||||
QString(), bindset, slotname, ToQStr(bindType), ResourceId(), lit("-"), QString(),
|
||||
QString(), setname, slotname, ToQStr(bindType), ResourceId(), lit("-"), QString(),
|
||||
QString(),
|
||||
});
|
||||
|
||||
@@ -1151,8 +1155,11 @@ void VulkanPipelineStateViewer::addConstantBlockRow(ShaderReflection *shaderDeta
|
||||
BindType bindType = BindType::ConstantBuffer;
|
||||
ShaderStageMask stageBits = ShaderStageMask::Unknown;
|
||||
|
||||
bool pushDescriptor = false;
|
||||
|
||||
if(bindset < pipe.descriptorSets.count() && bind < pipe.descriptorSets[bindset].bindings.count())
|
||||
{
|
||||
pushDescriptor = pipe.descriptorSets[bindset].pushDescriptor;
|
||||
slotBinds = &pipe.descriptorSets[bindset].bindings[bind].binds;
|
||||
bindType = pipe.descriptorSets[bindset].bindings[bind].type;
|
||||
stageBits = pipe.descriptorSets[bindset].bindings[bind].stageFlags;
|
||||
@@ -1183,6 +1190,9 @@ void VulkanPipelineStateViewer::addConstantBlockRow(ShaderReflection *shaderDeta
|
||||
|
||||
QString setname = QString::number(bindset);
|
||||
|
||||
if(pushDescriptor)
|
||||
setname = tr("Push ") + setname;
|
||||
|
||||
QString slotname = QString::number(bind);
|
||||
if(cblock != NULL && !cblock->name.isEmpty())
|
||||
slotname += lit(": ") + cblock->name;
|
||||
@@ -2581,6 +2591,9 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe::
|
||||
|
||||
QString setname = QString::number(bindMap.bindset);
|
||||
|
||||
if(set.pushDescriptor)
|
||||
setname = tr("Push ") + setname;
|
||||
|
||||
QString slotname = QFormatStr("%1: %2").arg(bindMap.bind).arg(b.name);
|
||||
|
||||
for(uint32_t a = 0; a < bind.descriptorCount; a++)
|
||||
@@ -2643,6 +2656,9 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe::
|
||||
|
||||
QString setname = QString::number(bindMap.bindset);
|
||||
|
||||
if(set.pushDescriptor)
|
||||
setname = tr("Push ") + setname;
|
||||
|
||||
QString slotname = QFormatStr("%1: %2").arg(bindMap.bind).arg(b.name);
|
||||
|
||||
for(uint32_t a = 0; a < bind.descriptorCount; a++)
|
||||
@@ -2756,6 +2772,9 @@ void VulkanPipelineStateViewer::exportHTML(QXmlStreamWriter &xml, const VKPipe::
|
||||
|
||||
QString setname = QString::number(bindMap.bindset);
|
||||
|
||||
if(set.pushDescriptor)
|
||||
setname = tr("Push ") + setname;
|
||||
|
||||
QString slotname = QFormatStr("%1: %2").arg(bindMap.bind).arg(b.name);
|
||||
|
||||
for(uint32_t a = 0; a < bind.descriptorCount; a++)
|
||||
|
||||
@@ -218,7 +218,8 @@ struct DescriptorSet
|
||||
bool operator==(const DescriptorSet &o) const
|
||||
{
|
||||
return layoutResourceId == o.layoutResourceId &&
|
||||
descriptorSetResourceId == o.descriptorSetResourceId && bindings == o.bindings;
|
||||
descriptorSetResourceId == o.descriptorSetResourceId &&
|
||||
pushDescriptor == o.pushDescriptor && bindings == o.bindings;
|
||||
}
|
||||
bool operator<(const DescriptorSet &o) const
|
||||
{
|
||||
@@ -226,6 +227,8 @@ struct DescriptorSet
|
||||
return layoutResourceId < o.layoutResourceId;
|
||||
if(!(descriptorSetResourceId == o.descriptorSetResourceId))
|
||||
return descriptorSetResourceId < o.descriptorSetResourceId;
|
||||
if(!(pushDescriptor == o.pushDescriptor))
|
||||
return pushDescriptor < o.pushDescriptor;
|
||||
if(!(bindings == o.bindings))
|
||||
return bindings < o.bindings;
|
||||
return false;
|
||||
@@ -234,6 +237,8 @@ struct DescriptorSet
|
||||
ResourceId layoutResourceId;
|
||||
DOCUMENT("The :class:`ResourceId` of the descriptor set object.");
|
||||
ResourceId descriptorSetResourceId;
|
||||
DOCUMENT("Indicates if this is a virtual 'push' descriptor set.");
|
||||
bool pushDescriptor = false;
|
||||
|
||||
DOCUMENT(R"(A list of :class:`VKDescriptorBinding` with the bindings within this set.
|
||||
This list is indexed by the binding, so it may be sparse (some entries do not contain any elements).
|
||||
|
||||
@@ -439,6 +439,7 @@ enum class VulkanChunk : uint32_t
|
||||
vkRegisterDeviceEventEXT,
|
||||
vkRegisterDisplayEventEXT,
|
||||
vkCmdIndirectSubCommand,
|
||||
vkCmdPushDescriptorSetKHR,
|
||||
Max,
|
||||
};
|
||||
|
||||
|
||||
@@ -623,6 +623,9 @@ static const VkExtensionProperties supportedExtensions[] = {
|
||||
{
|
||||
VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_KHR_MAINTENANCE1_SPEC_VERSION,
|
||||
},
|
||||
{
|
||||
VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION,
|
||||
},
|
||||
{
|
||||
VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,
|
||||
VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION,
|
||||
@@ -2226,6 +2229,11 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
|
||||
return true;
|
||||
break;
|
||||
|
||||
case VulkanChunk::vkCmdPushDescriptorSetKHR:
|
||||
return Serialise_vkCmdPushDescriptorSetKHR(
|
||||
ser, VK_NULL_HANDLE, VK_PIPELINE_BIND_POINT_GRAPHICS, VK_NULL_HANDLE, 0, 0, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
SystemChunk system = (SystemChunk)chunk;
|
||||
@@ -2865,7 +2873,6 @@ void WrappedVulkan::AddUsage(VulkanDrawcallTreeNode &drawNode, vector<DebugMessa
|
||||
DescriptorSetInfo &descset = m_DescriptorSetState[descSets[bindset].descSet];
|
||||
DescSetLayout &layout = c.m_DescSetLayout[descset.layout];
|
||||
|
||||
ResourceId origId = GetResourceManager()->GetOriginalID(descSets[bindset].descSet);
|
||||
ResourceId layoutId = GetResourceManager()->GetOriginalID(descset.layout);
|
||||
|
||||
if(layout.bindings.empty())
|
||||
|
||||
@@ -186,6 +186,7 @@ class WrappedVulkan : public IFrameCapturer
|
||||
private:
|
||||
friend class VulkanReplay;
|
||||
friend class VulkanDebugManager;
|
||||
friend struct VulkanRenderState;
|
||||
friend class VulkanShaderCache;
|
||||
|
||||
struct ScopedDebugMessageSink
|
||||
@@ -473,6 +474,8 @@ private:
|
||||
|
||||
std::vector<std::pair<ResourceId, ImageRegionState> > imgbarriers;
|
||||
|
||||
ResourceId pushDescriptorID[64];
|
||||
|
||||
VulkanDrawcallTreeNode *draw; // the root draw to copy from when submitting
|
||||
uint32_t eventCount; // how many events are in this cmd buffer, for quick skipping
|
||||
uint32_t curEventID; // current event ID while reading or executing
|
||||
@@ -586,14 +589,18 @@ private:
|
||||
// need it on replay too
|
||||
struct DescriptorSetInfo
|
||||
{
|
||||
~DescriptorSetInfo()
|
||||
~DescriptorSetInfo() { clear(); }
|
||||
ResourceId layout;
|
||||
vector<DescriptorSetSlot *> currentBindings;
|
||||
|
||||
void clear()
|
||||
{
|
||||
layout = ResourceId();
|
||||
|
||||
for(size_t i = 0; i < currentBindings.size(); i++)
|
||||
delete[] currentBindings[i];
|
||||
currentBindings.clear();
|
||||
}
|
||||
ResourceId layout;
|
||||
vector<DescriptorSetSlot *> currentBindings;
|
||||
};
|
||||
|
||||
// capture-side data
|
||||
@@ -1626,4 +1633,10 @@ public:
|
||||
// VK_AMD_shader_info
|
||||
VkResult vkGetShaderInfoAMD(VkDevice device, VkPipeline pipeline, VkShaderStageFlagBits shaderStage,
|
||||
VkShaderInfoTypeAMD infoType, size_t *pInfoSize, void *pInfo);
|
||||
|
||||
// VK_KHR_push_descriptor
|
||||
IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdPushDescriptorSetKHR, VkCommandBuffer commandBuffer,
|
||||
VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
|
||||
uint32_t set, uint32_t descriptorWriteCount,
|
||||
const VkWriteDescriptorSet *pDescriptorWrites);
|
||||
};
|
||||
|
||||
@@ -300,7 +300,8 @@
|
||||
CheckExt(VK_KHR_external_semaphore_win32); \
|
||||
CheckExt(VK_KHR_external_semaphore_fd); \
|
||||
CheckExt(VK_KHR_get_memory_requirements2); \
|
||||
CheckExt(VK_AMD_shader_info);
|
||||
CheckExt(VK_AMD_shader_info); \
|
||||
CheckExt(VK_KHR_push_descriptor);
|
||||
|
||||
#define HookInitVulkanInstanceExts() \
|
||||
HookInitExtension(VK_KHR_surface, DestroySurfaceKHR); \
|
||||
@@ -363,6 +364,7 @@
|
||||
HookInitExtension(VK_KHR_get_memory_requirements2, GetImageMemoryRequirements2KHR); \
|
||||
HookInitExtension(VK_KHR_get_memory_requirements2, GetImageSparseMemoryRequirements2KHR); \
|
||||
HookInitExtension(VK_AMD_shader_info, GetShaderInfoAMD); \
|
||||
HookInitExtension(VK_KHR_push_descriptor, CmdPushDescriptorSetKHR); \
|
||||
HookInitDevice_PlatformSpecific()
|
||||
|
||||
#define DefineHooks() \
|
||||
@@ -776,6 +778,9 @@
|
||||
HookDefine6(VkResult, vkGetShaderInfoAMD, VkDevice, device, VkPipeline, pipeline, \
|
||||
VkShaderStageFlagBits, shaderStage, VkShaderInfoTypeAMD, infoType, size_t *, \
|
||||
pInfoSize, void *, pInfo); \
|
||||
HookDefine6(void, vkCmdPushDescriptorSetKHR, VkCommandBuffer, commandBuffer, \
|
||||
VkPipelineBindPoint, pipelineBindPoint, VkPipelineLayout, layout, uint32_t, set, \
|
||||
uint32_t, descriptorWriteCount, const VkWriteDescriptorSet *, pDescriptorWrites); \
|
||||
HookDefine_PlatformSpecific()
|
||||
|
||||
struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable
|
||||
|
||||
@@ -30,6 +30,8 @@ void DescSetLayout::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo
|
||||
{
|
||||
dynamicCount = 0;
|
||||
|
||||
flags = pCreateInfo->flags;
|
||||
|
||||
// descriptor set layouts can be sparse, such that only three bindings exist
|
||||
// but they are at 0, 5 and 10.
|
||||
// We assume here that while the layouts may be sparse that's mostly to allow
|
||||
@@ -63,7 +65,7 @@ void DescSetLayout::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo
|
||||
}
|
||||
}
|
||||
|
||||
void DescSetLayout::CreateBindingsArray(vector<DescriptorSetSlot *> &descBindings)
|
||||
void DescSetLayout::CreateBindingsArray(std::vector<DescriptorSetSlot *> &descBindings) const
|
||||
{
|
||||
descBindings.resize(bindings.size());
|
||||
for(size_t i = 0; i < bindings.size(); i++)
|
||||
@@ -73,6 +75,33 @@ void DescSetLayout::CreateBindingsArray(vector<DescriptorSetSlot *> &descBinding
|
||||
}
|
||||
}
|
||||
|
||||
void DescSetLayout::UpdateBindingsArray(const DescSetLayout &prevLayout,
|
||||
std::vector<DescriptorSetSlot *> &descBindings) const
|
||||
{
|
||||
// if we have fewer bindings now, delete the orphaned bindings arrays
|
||||
for(size_t i = bindings.size(); i < prevLayout.bindings.size(); i++)
|
||||
SAFE_DELETE_ARRAY(descBindings[i]);
|
||||
|
||||
// resize to the new number of bindings
|
||||
descBindings.resize(bindings.size());
|
||||
|
||||
// re-allocate slots and move any previous bindings that overlapped over.
|
||||
for(size_t i = 0; i < bindings.size(); i++)
|
||||
{
|
||||
// allocate new slot array
|
||||
DescriptorSetSlot *newSlots = new DescriptorSetSlot[bindings[i].descriptorCount];
|
||||
|
||||
// copy over any previous bindings that overlapped
|
||||
memcpy(newSlots, descBindings[i],
|
||||
sizeof(DescriptorSetSlot) *
|
||||
RDCMIN(prevLayout.bindings[i].descriptorCount, bindings[i].descriptorCount));
|
||||
|
||||
// delete old array, and assign the new one
|
||||
SAFE_DELETE_ARRAY(descBindings[i]);
|
||||
descBindings[i] = newSlots;
|
||||
}
|
||||
}
|
||||
|
||||
bool DescSetLayout::operator==(const DescSetLayout &other) const
|
||||
{
|
||||
// shortcut for equality to ourselves
|
||||
|
||||
@@ -35,7 +35,9 @@ struct DescSetLayout
|
||||
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
|
||||
const VkDescriptorSetLayoutCreateInfo *pCreateInfo);
|
||||
|
||||
void CreateBindingsArray(vector<DescriptorSetSlot *> &descBindings);
|
||||
void CreateBindingsArray(std::vector<DescriptorSetSlot *> &descBindings) const;
|
||||
void UpdateBindingsArray(const DescSetLayout &prevLayout,
|
||||
std::vector<DescriptorSetSlot *> &descBindings) const;
|
||||
|
||||
struct Binding
|
||||
{
|
||||
@@ -71,6 +73,7 @@ struct DescSetLayout
|
||||
vector<Binding> bindings;
|
||||
|
||||
uint32_t dynamicCount;
|
||||
VkDescriptorSetLayoutCreateFlags flags;
|
||||
|
||||
bool operator==(const DescSetLayout &other) const;
|
||||
bool operator!=(const DescSetLayout &other) const { return !(*this == other); }
|
||||
|
||||
@@ -55,21 +55,30 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res)
|
||||
|
||||
VkInitialContents initialContents(type, VkInitialContents::DescriptorSet);
|
||||
|
||||
for(size_t i = 0; i < layout.bindings.size(); i++)
|
||||
initialContents.numDescriptors += layout.bindings[i].descriptorCount;
|
||||
|
||||
initialContents.descriptorSlots = new DescriptorSetSlot[initialContents.numDescriptors];
|
||||
RDCEraseMem(initialContents.descriptorSlots,
|
||||
sizeof(DescriptorSetSlot) * initialContents.numDescriptors);
|
||||
|
||||
uint32_t e = 0;
|
||||
for(size_t i = 0; i < layout.bindings.size(); i++)
|
||||
if((layout.flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR) == 0)
|
||||
{
|
||||
for(uint32_t b = 0; b < layout.bindings[i].descriptorCount; b++)
|
||||
for(size_t i = 0; i < layout.bindings.size(); i++)
|
||||
initialContents.numDescriptors += layout.bindings[i].descriptorCount;
|
||||
|
||||
initialContents.descriptorSlots = new DescriptorSetSlot[initialContents.numDescriptors];
|
||||
RDCEraseMem(initialContents.descriptorSlots,
|
||||
sizeof(DescriptorSetSlot) * initialContents.numDescriptors);
|
||||
|
||||
uint32_t e = 0;
|
||||
for(size_t i = 0; i < layout.bindings.size(); i++)
|
||||
{
|
||||
initialContents.descriptorSlots[e++] = record->descInfo->descBindings[i][b];
|
||||
for(uint32_t b = 0; b < layout.bindings[i].descriptorCount; b++)
|
||||
{
|
||||
initialContents.descriptorSlots[e++] = record->descInfo->descBindings[i][b];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Push descriptor set with initial contents! Should never have been marked dirty");
|
||||
initialContents.numDescriptors = 0;
|
||||
initialContents.descriptorSlots = NULL;
|
||||
}
|
||||
|
||||
GetResourceManager()->SetInitialContents(id, initialContents);
|
||||
return true;
|
||||
@@ -565,6 +574,12 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id, W
|
||||
const DescSetLayout &layout =
|
||||
m_CreationInfo.m_DescSetLayout[m_DescriptorSetState[liveid].layout];
|
||||
|
||||
if(layout.flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)
|
||||
{
|
||||
RDCERR("Push descriptor set with initial contents!");
|
||||
return true;
|
||||
}
|
||||
|
||||
VkInitialContents initialContents(type, VkInitialContents::DescriptorSet);
|
||||
|
||||
initialContents.numDescriptors = (uint32_t)layout.bindings.size();
|
||||
|
||||
@@ -1194,7 +1194,18 @@ void VulkanReplay::SavePipelineState()
|
||||
|
||||
ResourceId layoutId = m_pDriver->m_DescriptorSetState[src].layout;
|
||||
|
||||
dst.descriptorSetResourceId = rm->GetOriginalID(src);
|
||||
// push descriptors don't have a real descriptor set backing them
|
||||
if(c.m_DescSetLayout[layoutId].flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)
|
||||
{
|
||||
dst.descriptorSetResourceId = ResourceId();
|
||||
dst.pushDescriptor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst.descriptorSetResourceId = rm->GetOriginalID(src);
|
||||
dst.pushDescriptor = false;
|
||||
}
|
||||
|
||||
dst.layoutResourceId = rm->GetOriginalID(layoutId);
|
||||
dst.bindings.resize(m_pDriver->m_DescriptorSetState[src].currentBindings.size());
|
||||
for(size_t b = 0; b < m_pDriver->m_DescriptorSetState[src].currentBindings.size(); b++)
|
||||
|
||||
@@ -833,6 +833,9 @@ VkResourceRecord::~VkResourceRecord()
|
||||
|
||||
if(resType == eResDescriptorSetLayout || resType == eResDescriptorSet)
|
||||
SAFE_DELETE(descInfo);
|
||||
|
||||
if(resType == eResPipelineLayout)
|
||||
SAFE_DELETE(pipeLayoutInfo);
|
||||
}
|
||||
|
||||
void SparseMapping::Update(uint32_t numBindings, const VkSparseImageMemoryBind *pBindings)
|
||||
|
||||
@@ -919,6 +919,11 @@ struct DescriptorSetData
|
||||
map<ResourceId, pair<uint32_t, FrameRefType> > bindFrameRefs;
|
||||
};
|
||||
|
||||
struct PipelineLayoutData
|
||||
{
|
||||
std::vector<DescSetLayout> layouts;
|
||||
};
|
||||
|
||||
struct MemMapState
|
||||
{
|
||||
MemMapState()
|
||||
@@ -1062,6 +1067,7 @@ public:
|
||||
MemMapState *memMapState; // only for device memory
|
||||
CmdBufferRecordingInfo *cmdInfo; // only for command buffers
|
||||
AttachmentInfo *imageAttachments; // only for framebuffers and render passes
|
||||
PipelineLayoutData *pipeLayoutInfo; // only for pipeline layouts
|
||||
DescriptorSetData *descInfo; // only for descriptor sets and descriptor set layouts
|
||||
};
|
||||
|
||||
|
||||
@@ -246,11 +246,8 @@ void VulkanRenderState::BindPipeline(VkCommandBuffer cmd, PipelineBinding bindin
|
||||
}
|
||||
}
|
||||
|
||||
ObjDisp(cmd)->CmdBindDescriptorSets(
|
||||
Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(layout), (uint32_t)i, 1,
|
||||
UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkDescriptorSet>(
|
||||
graphics.descSets[i].descSet)),
|
||||
descLayout.dynamicCount, dynamicOffsets);
|
||||
BindDescriptorSet(descLayout, cmd, layout, VK_PIPELINE_BIND_POINT_GRAPHICS, (uint32_t)i,
|
||||
dynamicOffsets);
|
||||
|
||||
if(graphics.descSets[i].offsets.size() < descLayout.dynamicCount)
|
||||
SAFE_DELETE_ARRAY(dynamicOffsets);
|
||||
@@ -315,11 +312,8 @@ void VulkanRenderState::BindPipeline(VkCommandBuffer cmd, PipelineBinding bindin
|
||||
}
|
||||
}
|
||||
|
||||
ObjDisp(cmd)->CmdBindDescriptorSets(
|
||||
Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(layout), (uint32_t)i, 1,
|
||||
UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkDescriptorSet>(
|
||||
compute.descSets[i].descSet)),
|
||||
descLayout.dynamicCount, dynamicOffsets);
|
||||
BindDescriptorSet(descLayout, cmd, layout, VK_PIPELINE_BIND_POINT_COMPUTE, (uint32_t)i,
|
||||
dynamicOffsets);
|
||||
|
||||
if(compute.descSets[i].offsets.size() < descLayout.dynamicCount)
|
||||
SAFE_DELETE_ARRAY(dynamicOffsets);
|
||||
@@ -328,6 +322,102 @@ void VulkanRenderState::BindPipeline(VkCommandBuffer cmd, PipelineBinding bindin
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanRenderState::BindDescriptorSet(const DescSetLayout &descLayout, VkCommandBuffer cmd,
|
||||
VkPipelineLayout layout, VkPipelineBindPoint bindPoint,
|
||||
uint32_t setIndex, uint32_t *dynamicOffsets)
|
||||
{
|
||||
ResourceId descSet = (bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS)
|
||||
? graphics.descSets[setIndex].descSet
|
||||
: compute.descSets[setIndex].descSet;
|
||||
|
||||
if((descLayout.flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR) == 0)
|
||||
{
|
||||
ObjDisp(cmd)->CmdBindDescriptorSets(
|
||||
Unwrap(cmd), bindPoint, Unwrap(layout), (uint32_t)setIndex, 1,
|
||||
UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkDescriptorSet>(descSet)),
|
||||
descLayout.dynamicCount, dynamicOffsets);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this isn't a real descriptor set, it's a push descriptor, so we need to push the
|
||||
// current state.
|
||||
std::vector<VkWriteDescriptorSet> writes;
|
||||
|
||||
WrappedVulkan::DescriptorSetInfo &setInfo = m_pDriver->m_DescriptorSetState[descSet];
|
||||
|
||||
for(size_t b = 0; b < descLayout.bindings.size(); b++)
|
||||
{
|
||||
VkWriteDescriptorSet push = {};
|
||||
|
||||
// skip if this binding isn't used
|
||||
if(descLayout.bindings[b].descriptorCount == 0)
|
||||
continue;
|
||||
|
||||
push.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
// push.dstSet; // unused for push descriptors
|
||||
push.dstBinding = (uint32_t)b;
|
||||
push.dstArrayElement = 0;
|
||||
push.descriptorType = descLayout.bindings[b].descriptorType;
|
||||
push.descriptorCount = descLayout.bindings[b].descriptorCount;
|
||||
|
||||
DescriptorSetSlot *slots = setInfo.currentBindings[b];
|
||||
|
||||
if(push.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
|
||||
push.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
|
||||
{
|
||||
VkBufferView *dst = new VkBufferView[push.descriptorCount];
|
||||
|
||||
for(uint32_t a = 0; a < push.descriptorCount; a++)
|
||||
dst[a] = Unwrap(slots[a].texelBufferView);
|
||||
|
||||
push.pTexelBufferView = dst;
|
||||
}
|
||||
else if(push.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
|
||||
push.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
|
||||
push.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
|
||||
push.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
|
||||
push.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
|
||||
{
|
||||
VkDescriptorImageInfo *dst = new VkDescriptorImageInfo[push.descriptorCount];
|
||||
|
||||
for(uint32_t a = 0; a < push.descriptorCount; a++)
|
||||
{
|
||||
dst[a] = slots[a].imageInfo;
|
||||
dst[a].sampler = Unwrap(dst[a].sampler);
|
||||
dst[a].imageView = Unwrap(dst[a].imageView);
|
||||
}
|
||||
|
||||
push.pImageInfo = dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
VkDescriptorBufferInfo *dst = new VkDescriptorBufferInfo[push.descriptorCount];
|
||||
|
||||
for(uint32_t a = 0; a < push.descriptorCount; a++)
|
||||
{
|
||||
dst[a] = slots[a].bufferInfo;
|
||||
dst[a].buffer = Unwrap(dst[a].buffer);
|
||||
}
|
||||
|
||||
push.pBufferInfo = dst;
|
||||
}
|
||||
|
||||
writes.push_back(push);
|
||||
}
|
||||
|
||||
ObjDisp(cmd)->CmdPushDescriptorSetKHR(Unwrap(cmd), bindPoint, Unwrap(layout), setIndex,
|
||||
(uint32_t)writes.size(), writes.data());
|
||||
|
||||
// delete dynamically allocated arrays
|
||||
for(VkWriteDescriptorSet &push : writes)
|
||||
{
|
||||
SAFE_DELETE_ARRAY(push.pImageInfo);
|
||||
SAFE_DELETE_ARRAY(push.pBufferInfo);
|
||||
SAFE_DELETE_ARRAY(push.pTexelBufferView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanRenderState::EndRenderPass(VkCommandBuffer cmd)
|
||||
{
|
||||
ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd));
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
struct VulkanCreationInfo;
|
||||
class VulkanResourceManager;
|
||||
class WrappedVulkan;
|
||||
struct DescSetLayout;
|
||||
|
||||
struct VulkanRenderState
|
||||
{
|
||||
@@ -46,6 +47,10 @@ struct VulkanRenderState
|
||||
void EndRenderPass(VkCommandBuffer cmd);
|
||||
void BindPipeline(VkCommandBuffer cmd, PipelineBinding binding, bool subpass0);
|
||||
|
||||
void BindDescriptorSet(const DescSetLayout &descLayout, VkCommandBuffer cmd,
|
||||
VkPipelineLayout layout, VkPipelineBindPoint bindPoint, uint32_t setIndex,
|
||||
uint32_t *dynamicOffsets);
|
||||
|
||||
// dynamic state
|
||||
vector<VkViewport> views;
|
||||
vector<VkRect2D> scissors;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
template <>
|
||||
std::string DoStringise(const VulkanChunk &el)
|
||||
{
|
||||
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1098, "Chunks changed without updating names");
|
||||
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1099, "Chunks changed without updating names");
|
||||
|
||||
BEGIN_ENUM_STRINGISE(VulkanChunk)
|
||||
{
|
||||
@@ -130,6 +130,7 @@ std::string DoStringise(const VulkanChunk &el)
|
||||
STRINGISE_ENUM_CLASS(vkRegisterDeviceEventEXT);
|
||||
STRINGISE_ENUM_CLASS(vkRegisterDisplayEventEXT);
|
||||
STRINGISE_ENUM_CLASS_NAMED(vkCmdIndirectSubCommand, "Indirect sub-command");
|
||||
STRINGISE_ENUM_CLASS(vkCmdPushDescriptorSetKHR);
|
||||
STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk");
|
||||
}
|
||||
END_ENUM_STRINGISE()
|
||||
|
||||
@@ -594,6 +594,21 @@ bool WrappedVulkan::Serialise_vkBeginCommandBuffer(SerialiserType &ser, VkComman
|
||||
{
|
||||
m_LastCmdBufferID = CommandBuffer;
|
||||
|
||||
// when loading, allocate a new resource ID for each push descriptor slot in this command buffer
|
||||
if(IsLoading(m_State))
|
||||
{
|
||||
for(size_t i = 0; i < ARRAY_COUNT(BakedCmdBufferInfo::pushDescriptorID); i++)
|
||||
m_BakedCmdBufferInfo[BakedCommandBuffer].pushDescriptorID[i] =
|
||||
ResourceIDGen::GetNewUniqueID();
|
||||
}
|
||||
|
||||
// clear/invalidate descriptor set state for this command buffer.
|
||||
for(size_t i = 0; i < ARRAY_COUNT(BakedCmdBufferInfo::pushDescriptorID); i++)
|
||||
{
|
||||
m_DescriptorSetState[m_BakedCmdBufferInfo[BakedCommandBuffer].pushDescriptorID[i]] =
|
||||
DescriptorSetInfo();
|
||||
}
|
||||
|
||||
m_BakedCmdBufferInfo[m_LastCmdBufferID].level = m_BakedCmdBufferInfo[BakedCommandBuffer].level =
|
||||
AllocateInfo.level;
|
||||
m_BakedCmdBufferInfo[m_LastCmdBufferID].beginFlags =
|
||||
@@ -2924,6 +2939,368 @@ void WrappedVulkan::vkCmdDebugMarkerInsertEXT(VkCommandBuffer commandBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
bool WrappedVulkan::Serialise_vkCmdPushDescriptorSetKHR(SerialiserType &ser,
|
||||
VkCommandBuffer commandBuffer,
|
||||
VkPipelineBindPoint pipelineBindPoint,
|
||||
VkPipelineLayout layout, uint32_t set,
|
||||
uint32_t descriptorWriteCount,
|
||||
const VkWriteDescriptorSet *pDescriptorWrites)
|
||||
{
|
||||
SERIALISE_ELEMENT(commandBuffer);
|
||||
SERIALISE_ELEMENT(pipelineBindPoint);
|
||||
SERIALISE_ELEMENT(layout);
|
||||
SERIALISE_ELEMENT(set);
|
||||
SERIALISE_ELEMENT(descriptorWriteCount);
|
||||
SERIALISE_ELEMENT_ARRAY(pDescriptorWrites, descriptorWriteCount);
|
||||
|
||||
Serialise_DebugMessages(ser);
|
||||
|
||||
SERIALISE_CHECK_READ_ERRORS();
|
||||
|
||||
if(IsReplayingAndReading())
|
||||
{
|
||||
m_LastCmdBufferID = GetResourceManager()->GetOriginalID(GetResID(commandBuffer));
|
||||
|
||||
ResourceId setId = m_BakedCmdBufferInfo[m_LastCmdBufferID].pushDescriptorID[set];
|
||||
|
||||
if(IsActiveReplaying(m_State))
|
||||
{
|
||||
if(InRerecordRange(m_LastCmdBufferID))
|
||||
{
|
||||
commandBuffer = RerecordCmdBuf(m_LastCmdBufferID);
|
||||
|
||||
if(IsPartialCmdBuf(m_LastCmdBufferID))
|
||||
{
|
||||
std::vector<VulkanRenderState::Pipeline::DescriptorAndOffsets> &descsets =
|
||||
(pipelineBindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS)
|
||||
? m_RenderState.graphics.descSets
|
||||
: m_RenderState.compute.descSets;
|
||||
|
||||
// expand as necessary
|
||||
if(descsets.size() < set + 1)
|
||||
descsets.resize(set + 1);
|
||||
|
||||
descsets[set].descSet = setId;
|
||||
}
|
||||
|
||||
// actual replay of the command will happen below
|
||||
}
|
||||
else
|
||||
{
|
||||
commandBuffer = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// track while reading, as we need to track resource usage
|
||||
std::vector<BakedCmdBufferInfo::CmdBufferState::DescriptorAndOffsets> &descsets =
|
||||
(pipelineBindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS)
|
||||
? m_BakedCmdBufferInfo[m_LastCmdBufferID].state.graphicsDescSets
|
||||
: m_BakedCmdBufferInfo[m_LastCmdBufferID].state.computeDescSets;
|
||||
|
||||
// expand as necessary
|
||||
if(descsets.size() < set + 1)
|
||||
descsets.resize(set + 1);
|
||||
|
||||
// we use a 'special' ID for the push descriptor at this index, since there's no actual
|
||||
// allocated object corresponding to it.
|
||||
descsets[set].descSet = setId;
|
||||
}
|
||||
|
||||
if(commandBuffer != VK_NULL_HANDLE)
|
||||
{
|
||||
// since we version push descriptors per-command buffer, we can safely update them always
|
||||
// without worrying about overlap. We just need to check that we're in the record range so
|
||||
// that we don't pull in descriptor updates after the point in the command buffer we're
|
||||
// recording to
|
||||
{
|
||||
const std::vector<ResourceId> &descSetLayouts =
|
||||
m_CreationInfo.m_PipelineLayout[GetResID(layout)].descSetLayouts;
|
||||
|
||||
const DescSetLayout &desclayout = m_CreationInfo.m_DescSetLayout[descSetLayouts[set]];
|
||||
|
||||
for(uint32_t i = 0; i < descriptorWriteCount; i++)
|
||||
{
|
||||
const VkWriteDescriptorSet &writeDesc = pDescriptorWrites[i];
|
||||
|
||||
// update our local tracking
|
||||
std::vector<DescriptorSetSlot *> &bindings = m_DescriptorSetState[setId].currentBindings;
|
||||
ResourceId prevLayout = m_DescriptorSetState[setId].layout;
|
||||
|
||||
if(prevLayout == ResourceId())
|
||||
{
|
||||
desclayout.CreateBindingsArray(bindings);
|
||||
}
|
||||
else if(prevLayout != descSetLayouts[set])
|
||||
{
|
||||
desclayout.UpdateBindingsArray(m_CreationInfo.m_DescSetLayout[prevLayout], bindings);
|
||||
}
|
||||
|
||||
m_DescriptorSetState[setId].layout = descSetLayouts[set];
|
||||
|
||||
RDCASSERT(writeDesc.dstBinding < bindings.size());
|
||||
|
||||
DescriptorSetSlot **bind = &bindings[writeDesc.dstBinding];
|
||||
const DescSetLayout::Binding *layoutBinding = &desclayout.bindings[writeDesc.dstBinding];
|
||||
uint32_t curIdx = writeDesc.dstArrayElement;
|
||||
|
||||
if(writeDesc.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
|
||||
writeDesc.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
|
||||
{
|
||||
for(uint32_t d = 0; d < writeDesc.descriptorCount; d++, curIdx++)
|
||||
{
|
||||
// allow consecutive descriptor bind updates. See vkUpdateDescriptorSets for more
|
||||
// explanation
|
||||
if(curIdx >= layoutBinding->descriptorCount)
|
||||
{
|
||||
layoutBinding++;
|
||||
bind++;
|
||||
curIdx = 0;
|
||||
}
|
||||
|
||||
(*bind)[curIdx].texelBufferView = writeDesc.pTexelBufferView[d];
|
||||
}
|
||||
}
|
||||
else if(writeDesc.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
|
||||
writeDesc.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
|
||||
writeDesc.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
|
||||
writeDesc.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
|
||||
writeDesc.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
|
||||
{
|
||||
for(uint32_t d = 0; d < writeDesc.descriptorCount; d++, curIdx++)
|
||||
{
|
||||
// allow consecutive descriptor bind updates. See vkUpdateDescriptorSets for more
|
||||
// explanation
|
||||
if(curIdx >= layoutBinding->descriptorCount)
|
||||
{
|
||||
layoutBinding++;
|
||||
bind++;
|
||||
curIdx = 0;
|
||||
}
|
||||
|
||||
(*bind)[curIdx].imageInfo = writeDesc.pImageInfo[d];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint32_t d = 0; d < writeDesc.descriptorCount; d++, curIdx++)
|
||||
{
|
||||
// allow consecutive descriptor bind updates. See vkUpdateDescriptorSets for more
|
||||
// explanation
|
||||
if(curIdx >= layoutBinding->descriptorCount)
|
||||
{
|
||||
layoutBinding++;
|
||||
bind++;
|
||||
curIdx = 0;
|
||||
}
|
||||
|
||||
(*bind)[curIdx].bufferInfo = writeDesc.pBufferInfo[d];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now unwrap everything in-place to save on temp allocs.
|
||||
VkWriteDescriptorSet *writes = (VkWriteDescriptorSet *)pDescriptorWrites;
|
||||
|
||||
for(uint32_t i = 0; i < descriptorWriteCount; i++)
|
||||
{
|
||||
for(uint32_t d = 0; d < writes[i].descriptorCount; d++)
|
||||
{
|
||||
VkBufferView *pTexelBufferView = (VkBufferView *)writes[i].pTexelBufferView;
|
||||
VkDescriptorBufferInfo *pBufferInfo = (VkDescriptorBufferInfo *)writes[i].pBufferInfo;
|
||||
VkDescriptorImageInfo *pImageInfo = (VkDescriptorImageInfo *)writes[i].pImageInfo;
|
||||
|
||||
if(pTexelBufferView)
|
||||
pTexelBufferView[d] = Unwrap(pTexelBufferView[d]);
|
||||
|
||||
if(pBufferInfo)
|
||||
pBufferInfo[d].buffer = Unwrap(pBufferInfo[d].buffer);
|
||||
|
||||
if(pImageInfo)
|
||||
{
|
||||
pImageInfo[d].imageView = Unwrap(pImageInfo[d].imageView);
|
||||
pImageInfo[d].sampler = Unwrap(pImageInfo[d].sampler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjDisp(commandBuffer)
|
||||
->CmdPushDescriptorSetKHR(Unwrap(commandBuffer), pipelineBindPoint, Unwrap(layout), set,
|
||||
descriptorWriteCount, pDescriptorWrites);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WrappedVulkan::vkCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,
|
||||
VkPipelineBindPoint pipelineBindPoint,
|
||||
VkPipelineLayout layout, uint32_t set,
|
||||
uint32_t descriptorWriteCount,
|
||||
const VkWriteDescriptorSet *pDescriptorWrites)
|
||||
{
|
||||
SCOPED_DBG_SINK();
|
||||
|
||||
{
|
||||
// need to count up number of descriptor infos, to be able to alloc enough space
|
||||
uint32_t numInfos = 0;
|
||||
for(uint32_t i = 0; i < descriptorWriteCount; i++)
|
||||
numInfos += pDescriptorWrites[i].descriptorCount;
|
||||
|
||||
byte *memory = GetTempMemory(sizeof(VkDescriptorBufferInfo) * numInfos +
|
||||
sizeof(VkWriteDescriptorSet) * descriptorWriteCount);
|
||||
|
||||
RDCCOMPILE_ASSERT(sizeof(VkDescriptorBufferInfo) >= sizeof(VkDescriptorImageInfo),
|
||||
"Descriptor structs sizes are unexpected, ensure largest size is used");
|
||||
|
||||
VkWriteDescriptorSet *unwrappedWrites = (VkWriteDescriptorSet *)memory;
|
||||
VkDescriptorBufferInfo *nextDescriptors =
|
||||
(VkDescriptorBufferInfo *)(unwrappedWrites + descriptorWriteCount);
|
||||
|
||||
for(uint32_t i = 0; i < descriptorWriteCount; i++)
|
||||
{
|
||||
unwrappedWrites[i] = pDescriptorWrites[i];
|
||||
unwrappedWrites[i].dstSet = Unwrap(unwrappedWrites[i].dstSet);
|
||||
|
||||
VkDescriptorBufferInfo *bufInfos = nextDescriptors;
|
||||
VkDescriptorImageInfo *imInfos = (VkDescriptorImageInfo *)bufInfos;
|
||||
VkBufferView *bufViews = (VkBufferView *)bufInfos;
|
||||
nextDescriptors += pDescriptorWrites[i].descriptorCount;
|
||||
|
||||
RDCCOMPILE_ASSERT(sizeof(VkDescriptorBufferInfo) >= sizeof(VkDescriptorImageInfo),
|
||||
"Structure sizes mean not enough space is allocated for write data");
|
||||
RDCCOMPILE_ASSERT(sizeof(VkDescriptorBufferInfo) >= sizeof(VkBufferView),
|
||||
"Structure sizes mean not enough space is allocated for write data");
|
||||
|
||||
// unwrap and assign the appropriate array
|
||||
if(pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
|
||||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
|
||||
{
|
||||
unwrappedWrites[i].pTexelBufferView = (VkBufferView *)bufInfos;
|
||||
for(uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++)
|
||||
bufViews[j] = Unwrap(pDescriptorWrites[i].pTexelBufferView[j]);
|
||||
}
|
||||
else if(pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
|
||||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
|
||||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
|
||||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
|
||||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
|
||||
{
|
||||
bool hasSampler =
|
||||
(pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
|
||||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||
bool hasImage =
|
||||
(pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
|
||||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
|
||||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
|
||||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
|
||||
|
||||
unwrappedWrites[i].pImageInfo = (VkDescriptorImageInfo *)bufInfos;
|
||||
for(uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++)
|
||||
{
|
||||
if(hasImage)
|
||||
imInfos[j].imageView = Unwrap(pDescriptorWrites[i].pImageInfo[j].imageView);
|
||||
if(hasSampler)
|
||||
imInfos[j].sampler = Unwrap(pDescriptorWrites[i].pImageInfo[j].sampler);
|
||||
imInfos[j].imageLayout = pDescriptorWrites[i].pImageInfo[j].imageLayout;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unwrappedWrites[i].pBufferInfo = bufInfos;
|
||||
for(uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++)
|
||||
{
|
||||
bufInfos[j].buffer = Unwrap(pDescriptorWrites[i].pBufferInfo[j].buffer);
|
||||
bufInfos[j].offset = pDescriptorWrites[i].pBufferInfo[j].offset;
|
||||
bufInfos[j].range = pDescriptorWrites[i].pBufferInfo[j].range;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SERIALISE_TIME_CALL(ObjDisp(commandBuffer)
|
||||
->CmdPushDescriptorSetKHR(Unwrap(commandBuffer), pipelineBindPoint,
|
||||
Unwrap(layout), set, descriptorWriteCount,
|
||||
unwrappedWrites));
|
||||
}
|
||||
|
||||
if(IsCaptureMode(m_State))
|
||||
{
|
||||
VkResourceRecord *record = GetRecord(commandBuffer);
|
||||
|
||||
CACHE_THREAD_SERIALISER();
|
||||
|
||||
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdPushDescriptorSetKHR);
|
||||
Serialise_vkCmdPushDescriptorSetKHR(ser, commandBuffer, pipelineBindPoint, layout, set,
|
||||
descriptorWriteCount, pDescriptorWrites);
|
||||
|
||||
record->AddChunk(scope.Get());
|
||||
for(uint32_t i = 0; i < descriptorWriteCount; i++)
|
||||
{
|
||||
const VkWriteDescriptorSet &write = pDescriptorWrites[i];
|
||||
|
||||
FrameRefType ref = eFrameRef_Write;
|
||||
|
||||
switch(write.descriptorType)
|
||||
{
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: ref = eFrameRef_Read; break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: ref = eFrameRef_Write; break;
|
||||
default: RDCERR("Unexpected descriptor type");
|
||||
}
|
||||
|
||||
for(uint32_t d = 0; d < write.descriptorCount; d++)
|
||||
{
|
||||
if(write.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
|
||||
write.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
|
||||
{
|
||||
record->MarkResourceFrameReferenced(GetResID(write.pTexelBufferView[d]), eFrameRef_Read);
|
||||
if(GetRecord(write.pTexelBufferView[d])->baseResource != ResourceId())
|
||||
record->MarkResourceFrameReferenced(GetRecord(write.pTexelBufferView[d])->baseResource,
|
||||
ref);
|
||||
}
|
||||
else if(write.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
|
||||
write.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
|
||||
write.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
|
||||
write.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
|
||||
write.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
|
||||
{
|
||||
// ignore descriptors not part of the write, by NULL'ing out those members
|
||||
// as they might not even point to a valid object
|
||||
if(write.descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER)
|
||||
{
|
||||
record->MarkResourceFrameReferenced(GetResID(write.pImageInfo[d].imageView),
|
||||
eFrameRef_Read);
|
||||
if(GetRecord(write.pImageInfo[d].imageView)->baseResource != ResourceId())
|
||||
record->MarkResourceFrameReferenced(
|
||||
GetRecord(write.pImageInfo[d].imageView)->baseResource, ref);
|
||||
}
|
||||
|
||||
if(write.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
|
||||
write.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
|
||||
record->MarkResourceFrameReferenced(GetResID(write.pImageInfo[d].sampler),
|
||||
eFrameRef_Read);
|
||||
}
|
||||
else
|
||||
{
|
||||
record->MarkResourceFrameReferenced(GetResID(write.pBufferInfo[d].buffer), eFrameRef_Read);
|
||||
if(GetRecord(write.pBufferInfo[d].buffer)->baseResource != ResourceId())
|
||||
record->MarkResourceFrameReferenced(
|
||||
GetRecord(write.pBufferInfo[d].buffer)->baseResource, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateCommandPool, VkDevice device,
|
||||
const VkCommandPoolCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool);
|
||||
@@ -3011,3 +3388,8 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdDebugMarkerEndEXT, VkCommandBuffer co
|
||||
|
||||
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdDebugMarkerInsertEXT, VkCommandBuffer commandBuffer,
|
||||
const VkDebugMarkerMarkerInfoEXT *pMarker);
|
||||
|
||||
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdPushDescriptorSetKHR, VkCommandBuffer commandBuffer,
|
||||
VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
|
||||
uint32_t set, uint32_t descriptorWriteCount,
|
||||
const VkWriteDescriptorSet *pDescriptorWrites);
|
||||
|
||||
@@ -516,10 +516,15 @@ VkResult WrappedVulkan::vkAllocateDescriptorSets(VkDevice device,
|
||||
capframe = IsActiveCapturing(m_State);
|
||||
}
|
||||
|
||||
if(capframe)
|
||||
GetResourceManager()->MarkPendingDirty(id);
|
||||
else
|
||||
GetResourceManager()->MarkDirtyResource(id);
|
||||
// only mark descriptor set as dirty if it's not a push descriptor layout
|
||||
if((layoutRecord->descInfo->layout->flags &
|
||||
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR) == 0)
|
||||
{
|
||||
if(capframe)
|
||||
GetResourceManager()->MarkPendingDirty(id);
|
||||
else
|
||||
GetResourceManager()->MarkDirtyResource(id);
|
||||
}
|
||||
|
||||
record->descInfo = new DescriptorSetData();
|
||||
record->descInfo->layout = layoutRecord->descInfo->layout;
|
||||
|
||||
@@ -1248,6 +1248,10 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
|
||||
ObjDisp(physicalDevice)
|
||||
->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &m_PhysicalDeviceData.features);
|
||||
|
||||
RDCASSERT(m_PhysicalDeviceData.props.limits.maxBoundDescriptorSets <
|
||||
ARRAY_COUNT(BakedCmdBufferInfo::pushDescriptorID),
|
||||
m_PhysicalDeviceData.props.limits.maxBoundDescriptorSets);
|
||||
|
||||
for(int i = VK_FORMAT_BEGIN_RANGE + 1; i < VK_FORMAT_END_RANGE; i++)
|
||||
ObjDisp(physicalDevice)
|
||||
->GetPhysicalDeviceFormatProperties(Unwrap(physicalDevice), VkFormat(i),
|
||||
|
||||
@@ -180,10 +180,14 @@ VkResult WrappedVulkan::vkCreatePipelineLayout(VkDevice device,
|
||||
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pPipelineLayout);
|
||||
record->AddChunk(chunk);
|
||||
|
||||
record->pipeLayoutInfo = new PipelineLayoutData();
|
||||
|
||||
for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
|
||||
{
|
||||
VkResourceRecord *layoutrecord = GetRecord(pCreateInfo->pSetLayouts[i]);
|
||||
record->AddParent(layoutrecord);
|
||||
|
||||
record->pipeLayoutInfo->layouts.push_back(*layoutrecord->descInfo->layout);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1765,10 +1765,11 @@ void DoSerialise(SerialiserType &ser, VKPipe::DescriptorSet &el)
|
||||
{
|
||||
SERIALISE_MEMBER(layoutResourceId);
|
||||
SERIALISE_MEMBER(descriptorSetResourceId);
|
||||
SERIALISE_MEMBER(pushDescriptor);
|
||||
|
||||
SERIALISE_MEMBER(bindings);
|
||||
|
||||
SIZE_CHECK(32);
|
||||
SIZE_CHECK(40);
|
||||
}
|
||||
|
||||
template <typename SerialiserType>
|
||||
|
||||
Reference in New Issue
Block a user