Implement VK_KHR_descriptor_update_template. Closes #934

This commit is contained in:
baldurk
2018-04-24 14:42:05 +01:00
parent ad887b1922
commit 0442c46aff
14 changed files with 1113 additions and 272 deletions
+94
View File
@@ -1683,3 +1683,97 @@ VkDriverInfo::VkDriverInfo(const VkPhysicalDeviceProperties &physProps)
// not fixed yet
qualcommLeakingUBOOffsets = m_Vendor == GPUVendor::Qualcomm;
}
FrameRefType GetRefType(VkDescriptorType descType)
{
switch(descType)
{
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: return 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: return eFrameRef_Write; break;
default: RDCERR("Unexpected descriptor type");
}
return eFrameRef_Read;
}
void DescriptorSetSlot::RemoveBindRefs(VkResourceRecord *record)
{
if(texelBufferView != VK_NULL_HANDLE)
{
record->RemoveBindFrameRef(GetResID(texelBufferView));
VkResourceRecord *viewRecord = GetRecord(texelBufferView);
if(viewRecord && viewRecord->baseResource != ResourceId())
record->RemoveBindFrameRef(viewRecord->baseResource);
}
if(imageInfo.imageView != VK_NULL_HANDLE)
{
record->RemoveBindFrameRef(GetResID(imageInfo.imageView));
VkResourceRecord *viewRecord = GetRecord(imageInfo.imageView);
if(viewRecord)
{
record->RemoveBindFrameRef(viewRecord->baseResource);
if(viewRecord->baseResourceMem != ResourceId())
record->RemoveBindFrameRef(viewRecord->baseResourceMem);
}
}
if(imageInfo.sampler != VK_NULL_HANDLE)
{
record->RemoveBindFrameRef(GetResID(imageInfo.sampler));
}
if(bufferInfo.buffer != VK_NULL_HANDLE)
{
record->RemoveBindFrameRef(GetResID(bufferInfo.buffer));
VkResourceRecord *bufRecord = GetRecord(bufferInfo.buffer);
if(bufRecord && bufRecord->baseResource != ResourceId())
record->RemoveBindFrameRef(bufRecord->baseResource);
}
// NULL everything out now so that we don't accidentally reference an object
// that was removed already
texelBufferView = VK_NULL_HANDLE;
bufferInfo.buffer = VK_NULL_HANDLE;
imageInfo.imageView = VK_NULL_HANDLE;
imageInfo.sampler = VK_NULL_HANDLE;
}
void DescriptorSetSlot::AddBindRefs(VkResourceRecord *record, FrameRefType ref)
{
if(texelBufferView != VK_NULL_HANDLE)
{
record->AddBindFrameRef(GetResID(texelBufferView), eFrameRef_Read,
GetRecord(texelBufferView)->sparseInfo != NULL);
if(GetRecord(texelBufferView)->baseResource != ResourceId())
record->AddBindFrameRef(GetRecord(texelBufferView)->baseResource, ref);
}
if(imageInfo.imageView != VK_NULL_HANDLE)
{
record->AddBindFrameRef(GetResID(imageInfo.imageView), eFrameRef_Read,
GetRecord(imageInfo.imageView)->sparseInfo != NULL);
record->AddBindFrameRef(GetRecord(imageInfo.imageView)->baseResource, ref);
if(GetRecord(imageInfo.imageView)->baseResourceMem != ResourceId())
record->AddBindFrameRef(GetRecord(imageInfo.imageView)->baseResourceMem, eFrameRef_Read);
}
if(imageInfo.sampler != VK_NULL_HANDLE)
{
record->AddBindFrameRef(GetResID(imageInfo.sampler), eFrameRef_Read);
}
if(bufferInfo.buffer != VK_NULL_HANDLE)
{
record->AddBindFrameRef(GetResID(bufferInfo.buffer), eFrameRef_Read,
GetRecord(bufferInfo.buffer)->sparseInfo != NULL);
if(GetRecord(bufferInfo.buffer)->baseResource != ResourceId())
record->AddBindFrameRef(GetRecord(bufferInfo.buffer)->baseResource, ref);
}
}
+17 -1
View File
@@ -59,6 +59,7 @@
#include "api/replay/renderdoc_replay.h"
#include "core/core.h"
#include "core/resource_manager.h"
#include "official/vulkan.h"
#include "serialise/serialiser.h"
#include "vk_dispatchtables.h"
@@ -316,6 +317,10 @@ struct MemoryAllocation
// Writing is unambiguously during capture mode, so we don't have to check both in that case.
#define IsReplayingAndReading() (ser.IsReading() && IsReplayMode(m_State))
struct VkResourceRecord;
FrameRefType GetRefType(VkDescriptorType descType);
// the possible contents of a descriptor set slot,
// taken from the VkWriteDescriptorSet
struct DescriptorSetSlot
@@ -323,6 +328,9 @@ struct DescriptorSetSlot
VkDescriptorBufferInfo bufferInfo;
VkDescriptorImageInfo imageInfo;
VkBufferView texelBufferView;
void RemoveBindRefs(VkResourceRecord *record);
void AddBindRefs(VkResourceRecord *record, FrameRefType ref);
};
DECLARE_REFLECTION_STRUCT(DescriptorSetSlot);
@@ -440,6 +448,9 @@ enum class VulkanChunk : uint32_t
vkRegisterDisplayEventEXT,
vkCmdIndirectSubCommand,
vkCmdPushDescriptorSetKHR,
vkCmdPushDescriptorSetWithTemplateKHR,
vkCreateDescriptorUpdateTemplateKHR,
vkUpdateDescriptorSetWithTemplateKHR,
Max,
};
@@ -476,7 +487,8 @@ DECLARE_REFLECTION_ENUM(VulkanChunk);
SERIALISE_HANDLE(VkFramebuffer) \
SERIALISE_HANDLE(VkCommandPool) \
SERIALISE_HANDLE(VkSwapchainKHR) \
SERIALISE_HANDLE(VkSurfaceKHR)
SERIALISE_HANDLE(VkSurfaceKHR) \
SERIALISE_HANDLE(VkDescriptorUpdateTemplateKHR)
#define SERIALISE_HANDLE(type) DECLARE_REFLECTION_STRUCT(type)
@@ -581,6 +593,8 @@ DECLARE_REFLECTION_STRUCT(VkImageBlit);
DECLARE_REFLECTION_STRUCT(VkImageResolve);
DECLARE_REFLECTION_STRUCT(VkSwapchainCreateInfoKHR);
DECLARE_REFLECTION_STRUCT(VkDebugMarkerMarkerInfoEXT);
DECLARE_REFLECTION_STRUCT(VkDescriptorUpdateTemplateEntryKHR);
DECLARE_REFLECTION_STRUCT(VkDescriptorUpdateTemplateCreateInfoKHR);
DECLARE_DESERIALISE_TYPE(VkDeviceCreateInfo);
DECLARE_DESERIALISE_TYPE(VkBufferCreateInfo);
@@ -600,6 +614,7 @@ DECLARE_DESERIALISE_TYPE(VkComputePipelineCreateInfo);
DECLARE_DESERIALISE_TYPE(VkDescriptorPoolCreateInfo);
DECLARE_DESERIALISE_TYPE(VkWriteDescriptorSet);
DECLARE_DESERIALISE_TYPE(VkDescriptorSetLayoutCreateInfo);
DECLARE_DESERIALISE_TYPE(VkDescriptorUpdateTemplateCreateInfoKHR);
DECLARE_REFLECTION_ENUM(VkFlagWithNoBits);
DECLARE_REFLECTION_ENUM(VkQueueFlagBits);
@@ -664,3 +679,4 @@ DECLARE_REFLECTION_ENUM(VkSurfaceTransformFlagBitsKHR);
DECLARE_REFLECTION_ENUM(VkCompositeAlphaFlagBitsKHR);
DECLARE_REFLECTION_ENUM(VkColorSpaceKHR);
DECLARE_REFLECTION_ENUM(VkPresentModeKHR);
DECLARE_REFLECTION_ENUM(VkDescriptorUpdateTemplateType);
+17
View File
@@ -573,6 +573,10 @@ static const VkExtensionProperties supportedExtensions[] = {
{
VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION,
},
{
VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME,
VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION,
},
#ifdef VK_KHR_display
{
VK_KHR_DISPLAY_EXTENSION_NAME, VK_KHR_DISPLAY_SPEC_VERSION,
@@ -2234,6 +2238,19 @@ bool WrappedVulkan::ProcessChunk(ReadSerialiser &ser, VulkanChunk chunk)
ser, VK_NULL_HANDLE, VK_PIPELINE_BIND_POINT_GRAPHICS, VK_NULL_HANDLE, 0, 0, NULL);
break;
case VulkanChunk::vkCmdPushDescriptorSetWithTemplateKHR:
return Serialise_vkCmdPushDescriptorSetWithTemplateKHR(ser, VK_NULL_HANDLE, VK_NULL_HANDLE,
VK_NULL_HANDLE, 0, NULL);
break;
case VulkanChunk::vkCreateDescriptorUpdateTemplateKHR:
return Serialise_vkCreateDescriptorUpdateTemplateKHR(ser, VK_NULL_HANDLE, NULL, NULL, NULL);
break;
case VulkanChunk::vkUpdateDescriptorSetWithTemplateKHR:
return Serialise_vkUpdateDescriptorSetWithTemplateKHR(ser, VK_NULL_HANDLE, VK_NULL_HANDLE,
VK_NULL_HANDLE, NULL);
break;
default:
{
SystemChunk system = (SystemChunk)chunk;
+23
View File
@@ -1635,8 +1635,31 @@ public:
VkShaderInfoTypeAMD infoType, size_t *pInfoSize, void *pInfo);
// VK_KHR_push_descriptor
void ApplyPushDescriptorWrites(VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount,
const VkWriteDescriptorSet *pDescriptorWrites);
IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdPushDescriptorSetKHR, VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
uint32_t set, uint32_t descriptorWriteCount,
const VkWriteDescriptorSet *pDescriptorWrites);
IMPLEMENT_FUNCTION_SERIALISED(void, vkCmdPushDescriptorSetWithTemplateKHR,
VkCommandBuffer commandBuffer,
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
VkPipelineLayout layout, uint32_t set, const void *pData);
// VK_KHR_descriptor_update_template
IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkCreateDescriptorUpdateTemplateKHR, VkDevice device,
const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate);
IMPLEMENT_FUNCTION_SERIALISED(void, vkDestroyDescriptorUpdateTemplateKHR, VkDevice device,
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
const VkAllocationCallbacks *pAllocator);
IMPLEMENT_FUNCTION_SERIALISED(void, vkUpdateDescriptorSetWithTemplateKHR, VkDevice device,
VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
const void *pData);
};
+20 -1
View File
@@ -307,7 +307,8 @@
CheckExt(KHR_external_semaphore_fd, VKXX); \
CheckExt(KHR_get_memory_requirements2, VK11); \
CheckExt(AMD_shader_info, VKXX); \
CheckExt(KHR_push_descriptor, VKXX);
CheckExt(KHR_push_descriptor, VKXX); \
CheckExt(KHR_descriptor_update_template, VK11);
#define HookInitVulkanInstanceExts() \
HookInitExtension(KHR_surface, DestroySurfaceKHR); \
@@ -370,6 +371,11 @@
HookInitExtension(KHR_get_memory_requirements2, GetImageSparseMemoryRequirements2KHR); \
HookInitExtension(AMD_shader_info, GetShaderInfoAMD); \
HookInitExtension(KHR_push_descriptor, CmdPushDescriptorSetKHR); \
HookInitExtension(KHR_descriptor_update_template, CreateDescriptorUpdateTemplateKHR); \
HookInitExtension(KHR_descriptor_update_template, DestroyDescriptorUpdateTemplateKHR); \
HookInitExtension(KHR_descriptor_update_template, UpdateDescriptorSetWithTemplateKHR); \
HookInitExtension(KHR_push_descriptor &&KHR_descriptor_update_template, \
CmdPushDescriptorSetWithTemplateKHR); \
HookInitDevice_PlatformSpecific()
#define DefineHooks() \
@@ -786,6 +792,19 @@
HookDefine6(void, vkCmdPushDescriptorSetKHR, VkCommandBuffer, commandBuffer, \
VkPipelineBindPoint, pipelineBindPoint, VkPipelineLayout, layout, uint32_t, set, \
uint32_t, descriptorWriteCount, const VkWriteDescriptorSet *, pDescriptorWrites); \
HookDefine4(VkResult, vkCreateDescriptorUpdateTemplateKHR, VkDevice, device, \
const VkDescriptorUpdateTemplateCreateInfoKHR *, pCreateInfo, \
const VkAllocationCallbacks *, pAllocator, VkDescriptorUpdateTemplateKHR *, \
pDescriptorUpdateTemplate); \
HookDefine3(void, vkDestroyDescriptorUpdateTemplateKHR, VkDevice, device, \
VkDescriptorUpdateTemplateKHR, descriptorUpdateTemplate, \
const VkAllocationCallbacks *, pAllocator); \
HookDefine4(void, vkUpdateDescriptorSetWithTemplateKHR, VkDevice, device, VkDescriptorSet, \
descriptorSet, VkDescriptorUpdateTemplateKHR, descriptorUpdateTemplate, \
const void *, pData); \
HookDefine5(void, vkCmdPushDescriptorSetWithTemplateKHR, VkCommandBuffer, commandBuffer, \
VkDescriptorUpdateTemplateKHR, descriptorUpdateTemplate, VkPipelineLayout, layout, \
uint32_t, set, const void *, pData); \
HookDefine_PlatformSpecific()
struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable
+142
View File
@@ -695,3 +695,145 @@ void VulkanCreationInfo::DescSetPool::CreateOverflow(VkDevice device,
overflow.push_back(pool);
}
void DescUpdateTemplate::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo)
{
updates.insert(updates.begin(), pCreateInfo->pDescriptorUpdateEntries,
pCreateInfo->pDescriptorUpdateEntries + pCreateInfo->descriptorUpdateEntryCount);
dataByteSize = 0;
texelBufferViewCount = 0;
bufferInfoCount = 0;
imageInfoCount = 0;
for(const VkDescriptorUpdateTemplateEntryKHR &entry : updates)
{
uint32_t entrySize = 4;
if(entry.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
{
entrySize = sizeof(VkBufferView);
texelBufferViewCount += entry.descriptorCount;
}
else if(entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
{
entrySize = sizeof(VkDescriptorImageInfo);
imageInfoCount += entry.descriptorCount;
}
else
{
entrySize = sizeof(VkDescriptorBufferInfo);
bufferInfoCount += entry.descriptorCount;
}
dataByteSize =
RDCMAX(dataByteSize, entry.offset + entry.stride * entry.descriptorCount + entrySize);
}
if(pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET)
{
if(IsCaptureMode(resourceMan->GetState()))
{
layout = *GetRecord(pCreateInfo->descriptorSetLayout)->descInfo->layout;
}
else
{
layout = info.m_DescSetLayout[GetResID(pCreateInfo->descriptorSetLayout)];
}
}
else
{
if(IsCaptureMode(resourceMan->GetState()))
{
layout = GetRecord(pCreateInfo->pipelineLayout)->pipeLayoutInfo->layouts[pCreateInfo->set];
}
else
{
const std::vector<ResourceId> &descSetLayouts =
info.m_PipelineLayout[GetResID(pCreateInfo->pipelineLayout)].descSetLayouts;
layout = info.m_DescSetLayout[descSetLayouts[pCreateInfo->set]];
}
}
}
void DescUpdateTemplate::Apply(const void *pData, DescUpdateTemplateApplication &application)
{
application.bufView.reserve(texelBufferViewCount);
application.bufInfo.reserve(bufferInfoCount);
application.imgInfo.reserve(imageInfoCount);
for(const VkDescriptorUpdateTemplateEntryKHR &entry : updates)
{
VkWriteDescriptorSet write = {};
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write.dstSet = VK_NULL_HANDLE; // set externally for non-push descriptor template updates.
write.dstBinding = entry.dstBinding;
write.dstArrayElement = entry.dstArrayElement;
write.descriptorType = entry.descriptorType;
write.descriptorCount = entry.descriptorCount;
const byte *src = (const byte *)pData + entry.offset;
if(entry.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
{
size_t idx = application.bufView.size();
application.bufView.resize(idx + entry.descriptorCount);
for(uint32_t d = 0; d < entry.descriptorCount; d++)
{
memcpy(&application.bufView[idx + d], src, sizeof(VkBufferView));
src += entry.stride;
}
write.pTexelBufferView = &application.bufView[idx];
}
else if(entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
{
size_t idx = application.imgInfo.size();
application.imgInfo.resize(idx + entry.descriptorCount);
for(uint32_t d = 0; d < entry.descriptorCount; d++)
{
memcpy(&application.imgInfo[idx + d], src, sizeof(VkDescriptorImageInfo));
src += entry.stride;
}
write.pImageInfo = &application.imgInfo[idx];
}
else
{
size_t idx = application.bufInfo.size();
application.bufInfo.resize(idx + entry.descriptorCount);
for(uint32_t d = 0; d < entry.descriptorCount; d++)
{
memcpy(&application.bufInfo[idx + d], src, sizeof(VkDescriptorBufferInfo));
src += entry.stride;
}
write.pBufferInfo = &application.bufInfo[idx];
}
application.writes.push_back(write);
}
}
+30
View File
@@ -79,6 +79,35 @@ struct DescSetLayout
bool operator!=(const DescSetLayout &other) const { return !(*this == other); }
};
struct DescUpdateTemplateApplication
{
std::vector<VkDescriptorBufferInfo> bufInfo;
std::vector<VkDescriptorImageInfo> imgInfo;
std::vector<VkBufferView> bufView;
std::vector<VkWriteDescriptorSet> writes;
};
struct DescUpdateTemplate
{
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo);
void Apply(const void *pData, DescUpdateTemplateApplication &application);
DescSetLayout layout;
VkPipelineBindPoint bindPoint;
size_t dataByteSize;
uint32_t texelBufferViewCount;
uint32_t bufferInfoCount;
uint32_t imageInfoCount;
std::vector<VkDescriptorUpdateTemplateEntryKHR> updates;
};
struct VulkanCreationInfo
{
struct Pipeline
@@ -390,4 +419,5 @@ struct VulkanCreationInfo
map<ResourceId, string> m_Names;
map<ResourceId, SwapchainInfo> m_SwapChain;
map<ResourceId, DescSetLayout> m_DescSetLayout;
map<ResourceId, DescUpdateTemplate> m_DescUpdateTemplate;
};
+6 -1
View File
@@ -50,9 +50,9 @@ WRAPPED_POOL_INST(WrappedVkDescriptorPool)
WRAPPED_POOL_INST(WrappedVkDescriptorSet)
WRAPPED_POOL_INST(WrappedVkFramebuffer)
WRAPPED_POOL_INST(WrappedVkCommandPool)
WRAPPED_POOL_INST(WrappedVkSwapchainKHR)
WRAPPED_POOL_INST(WrappedVkSurfaceKHR)
WRAPPED_POOL_INST(WrappedVkDescriptorUpdateTemplateKHR)
byte VkResourceRecord::markerValue[32] = {
0xaa, 0xbb, 0xcc, 0xdd, 0x88, 0x77, 0x66, 0x55, 0x01, 0x23, 0x45, 0x67, 0x98, 0x76, 0x54, 0x32,
@@ -121,6 +121,8 @@ VkResourceType IdentifyTypeByPtr(WrappedVkRes *ptr)
return eResSwapchain;
if(WrappedVkSurfaceKHR::IsAlloc(ptr))
return eResSurface;
if(WrappedVkDescriptorUpdateTemplateKHR::IsAlloc(ptr))
return eResDescUpdateTemplate;
RDCERR("Unknown type for ptr 0x%p", ptr);
@@ -836,6 +838,9 @@ VkResourceRecord::~VkResourceRecord()
if(resType == eResPipelineLayout)
SAFE_DELETE(pipeLayoutInfo);
if(resType == eResDescUpdateTemplate)
SAFE_DELETE(descTemplateInfo);
}
void SparseMapping::Update(uint32_t numBindings, const VkSparseImageMemoryBind *pBindings)
+20 -3
View File
@@ -67,9 +67,9 @@ enum VkResourceType
eResEvent,
eResQueryPool,
eResSemaphore,
eResSwapchain,
eResSurface
eResSurface,
eResDescUpdateTemplate,
};
DECLARE_REFLECTION_ENUM(VkResourceType);
@@ -548,6 +548,19 @@ struct WrappedVkSurfaceKHR : WrappedVkNonDispRes
TypeEnum = eResSurface,
};
};
struct WrappedVkDescriptorUpdateTemplateKHR : WrappedVkNonDispRes
{
WrappedVkDescriptorUpdateTemplateKHR(VkDescriptorUpdateTemplateKHR obj, ResourceId objId)
: WrappedVkNonDispRes(obj, objId)
{
}
typedef VkDescriptorUpdateTemplateKHR InnerType;
ALLOCATE_WITH_WRAPPED_POOL(WrappedVkDescriptorUpdateTemplateKHR);
enum
{
TypeEnum = eResDescUpdateTemplate,
};
};
// VkDisplayKHR and VkDisplayModeKHR are both UNWRAPPED because there's no need to wrap them.
// The only thing we need to wrap VkSurfaceKHR for is to get back the window from it later.
@@ -645,6 +658,7 @@ UNWRAP_NONDISP_HELPER(VkFramebuffer)
UNWRAP_NONDISP_HELPER(VkCommandPool)
UNWRAP_NONDISP_HELPER(VkSwapchainKHR)
UNWRAP_NONDISP_HELPER(VkSurfaceKHR)
UNWRAP_NONDISP_HELPER(VkDescriptorUpdateTemplateKHR)
// VkDisplayKHR and VkDisplayModeKHR are both UNWRAPPED because there's no need to wrap them.
// The only thing we need to wrap VkSurfaceKHR for is to get back the window from it later.
@@ -955,6 +969,8 @@ struct AttachmentInfo
VkImageMemoryBarrier barrier;
};
struct DescUpdateTemplate;
struct VkResourceRecord : public ResourceRecord
{
public:
@@ -1068,7 +1084,8 @@ public:
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
DescriptorSetData *descInfo; // only for descriptor sets and descriptor set layouts
DescUpdateTemplate *descTemplateInfo; // only for descriptor update templates
};
VkResourceRecord *bakedCommands;
+61
View File
@@ -196,6 +196,14 @@ static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, const voi
}
}
template <typename SerialiserType>
static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, void *&pNext)
{
const void *tmpNext = pNext;
SerialiseNext(ser, sType, tmpNext);
pNext = (void *)tmpNext;
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkAllocationCallbacks &el)
{
@@ -1877,6 +1885,58 @@ void DoSerialise(SerialiserType &ser, ImageLayouts &el)
SERIALISE_MEMBER(format);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkDescriptorUpdateTemplateEntryKHR &el)
{
SERIALISE_MEMBER(dstBinding);
SERIALISE_MEMBER(dstArrayElement);
SERIALISE_MEMBER(descriptorCount);
SERIALISE_MEMBER(descriptorType);
SERIALISE_MEMBER(offset);
SERIALISE_MEMBER(stride);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, VkDescriptorUpdateTemplateCreateInfoKHR &el)
{
RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO);
SerialiseNext(ser, el.sType, el.pNext);
SERIALISE_MEMBER_TYPED(VkFlagWithNoBits, flags);
SERIALISE_MEMBER(descriptorUpdateEntryCount);
SERIALISE_MEMBER_ARRAY(pDescriptorUpdateEntries, descriptorUpdateEntryCount);
SERIALISE_MEMBER(templateType);
if(el.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET)
{
SERIALISE_MEMBER(descriptorSetLayout);
}
else
{
SERIALISE_MEMBER_EMPTY(descriptorSetLayout);
}
if(el.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR)
{
SERIALISE_MEMBER(pipelineBindPoint);
SERIALISE_MEMBER(pipelineLayout);
SERIALISE_MEMBER(set);
}
else
{
SERIALISE_MEMBER_EMPTY(pipelineBindPoint);
SERIALISE_MEMBER_EMPTY(pipelineLayout);
SERIALISE_MEMBER_EMPTY(set);
}
}
template <>
void Deserialise(const VkDescriptorUpdateTemplateCreateInfoKHR &el)
{
RDCASSERT(el.pNext == NULL); // otherwise delete
delete[] el.pDescriptorUpdateEntries;
}
INSTANTIATE_SERIALISE_TYPE(VkOffset2D);
INSTANTIATE_SERIALISE_TYPE(VkExtent2D);
INSTANTIATE_SERIALISE_TYPE(VkMemoryType);
@@ -1974,6 +2034,7 @@ INSTANTIATE_SERIALISE_TYPE(VkImageBlit);
INSTANTIATE_SERIALISE_TYPE(VkImageResolve);
INSTANTIATE_SERIALISE_TYPE(VkSwapchainCreateInfoKHR);
INSTANTIATE_SERIALISE_TYPE(VkDebugMarkerMarkerInfoEXT);
INSTANTIATE_SERIALISE_TYPE(VkDescriptorUpdateTemplateCreateInfoKHR);
INSTANTIATE_SERIALISE_TYPE(DescriptorSetSlot);
INSTANTIATE_SERIALISE_TYPE(ImageRegionState);
+15 -1
View File
@@ -28,7 +28,7 @@
template <>
std::string DoStringise(const VulkanChunk &el)
{
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1099, "Chunks changed without updating names");
RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1102, "Chunks changed without updating names");
BEGIN_ENUM_STRINGISE(VulkanChunk)
{
@@ -131,6 +131,9 @@ std::string DoStringise(const VulkanChunk &el)
STRINGISE_ENUM_CLASS(vkRegisterDisplayEventEXT);
STRINGISE_ENUM_CLASS_NAMED(vkCmdIndirectSubCommand, "Indirect sub-command");
STRINGISE_ENUM_CLASS(vkCmdPushDescriptorSetKHR);
STRINGISE_ENUM_CLASS(vkCmdPushDescriptorSetWithTemplateKHR);
STRINGISE_ENUM_CLASS(vkCreateDescriptorUpdateTemplateKHR);
STRINGISE_ENUM_CLASS(vkUpdateDescriptorSetWithTemplateKHR);
STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk");
}
END_ENUM_STRINGISE()
@@ -1672,6 +1675,17 @@ std::string DoStringise(const VkPresentModeKHR &el)
END_ENUM_STRINGISE();
}
template <>
std::string DoStringise(const VkDescriptorUpdateTemplateType &el)
{
BEGIN_ENUM_STRINGISE(VkDescriptorUpdateTemplateType);
{
STRINGISE_ENUM(VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET)
STRINGISE_ENUM(VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR)
}
END_ENUM_STRINGISE();
}
template <>
std::string DoStringise(const VkExtent3D &el)
{
+311 -103
View File
@@ -2939,6 +2939,98 @@ void WrappedVulkan::vkCmdDebugMarkerInsertEXT(VkCommandBuffer commandBuffer,
}
}
void WrappedVulkan::ApplyPushDescriptorWrites(VkPipelineLayout layout, uint32_t set,
uint32_t descriptorWriteCount,
const VkWriteDescriptorSet *pDescriptorWrites)
{
ResourceId setId = m_BakedCmdBufferInfo[m_LastCmdBufferID].pushDescriptorID[set];
const std::vector<ResourceId> &descSetLayouts =
m_CreationInfo.m_PipelineLayout[GetResID(layout)].descSetLayouts;
const DescSetLayout &desclayout = m_CreationInfo.m_DescSetLayout[descSetLayouts[set]];
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];
// update our local tracking
for(uint32_t i = 0; i < descriptorWriteCount; i++)
{
const VkWriteDescriptorSet &writeDesc = pDescriptorWrites[i];
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];
}
}
}
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCmdPushDescriptorSetKHR(SerialiserType &ser,
VkCommandBuffer commandBuffer,
@@ -3014,92 +3106,7 @@ bool WrappedVulkan::Serialise_vkCmdPushDescriptorSetKHR(SerialiserType &ser,
// 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];
}
}
}
}
ApplyPushDescriptorWrites(layout, set, descriptorWriteCount, pDescriptorWrites);
// now unwrap everything in-place to save on temp allocs.
VkWriteDescriptorSet *writes = (VkWriteDescriptorSet *)pDescriptorWrites;
@@ -3240,23 +3247,7 @@ void WrappedVulkan::vkCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,
{
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");
}
FrameRefType ref = GetRefType(write.descriptorType);
for(uint32_t d = 0; d < write.descriptorCount; d++)
{
@@ -3301,6 +3292,218 @@ void WrappedVulkan::vkCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer,
}
}
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCmdPushDescriptorSetWithTemplateKHR(
SerialiserType &ser, VkCommandBuffer commandBuffer,
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set,
const void *pData)
{
SERIALISE_ELEMENT(commandBuffer);
SERIALISE_ELEMENT(descriptorUpdateTemplate);
SERIALISE_ELEMENT(layout);
SERIALISE_ELEMENT(set);
// we can't serialise pData as-is, since we need to decode to ResourceId for references, etc. The
// sensible way to do this is to decode the data into a series of writes and serialise that.
DescUpdateTemplateApplication apply;
if(IsCaptureMode(m_State))
{
// decode while capturing.
GetRecord(descriptorUpdateTemplate)->descTemplateInfo->Apply(pData, apply);
}
SERIALISE_ELEMENT(apply.writes).Named("Decoded Writes");
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 =
(m_CreationInfo.m_DescUpdateTemplate[GetResID(descriptorUpdateTemplate)].bindPoint ==
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 =
(m_CreationInfo.m_DescUpdateTemplate[GetResID(descriptorUpdateTemplate)].bindPoint ==
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)
{
VkPipelineBindPoint bindPoint =
m_CreationInfo.m_DescUpdateTemplate[GetResID(descriptorUpdateTemplate)].bindPoint;
// 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
ApplyPushDescriptorWrites(layout, set, (uint32_t)apply.writes.size(), apply.writes.data());
ObjDisp(commandBuffer)
->CmdPushDescriptorSetKHR(Unwrap(commandBuffer), bindPoint, Unwrap(layout), set,
(uint32_t)apply.writes.size(), apply.writes.data());
}
}
return true;
}
void WrappedVulkan::vkCmdPushDescriptorSetWithTemplateKHR(
VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
VkPipelineLayout layout, uint32_t set, const void *pData)
{
SCOPED_DBG_SINK();
// since it's relatively expensive to walk the memory, we gather frame references at the same time
// as unwrapping
std::vector<std::pair<ResourceId, FrameRefType> > frameRefs;
{
DescUpdateTemplate *tempInfo = GetRecord(descriptorUpdateTemplate)->descTemplateInfo;
// allocate the whole blob of memory
byte *memory = GetTempMemory(tempInfo->dataByteSize);
// iterate the entries, copy the descriptor data and unwrap
for(const VkDescriptorUpdateTemplateEntryKHR &entry : tempInfo->updates)
{
byte *dst = memory + entry.offset;
const byte *src = (const byte *)pData + entry.offset;
FrameRefType ref = GetRefType(entry.descriptorType);
if(entry.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
{
for(uint32_t d = 0; d < entry.descriptorCount; d++)
{
memcpy(dst, src, sizeof(VkBufferView));
VkBufferView *bufView = (VkBufferView *)dst;
frameRefs.push_back(std::make_pair(GetResID(*bufView), eFrameRef_Read));
if(GetRecord(*bufView)->baseResource != ResourceId())
frameRefs.push_back(std::make_pair(GetRecord(*bufView)->baseResource, ref));
*bufView = Unwrap(*bufView);
}
}
else if(entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
{
bool hasSampler = (entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
bool hasImage = (entry.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
for(uint32_t d = 0; d < entry.descriptorCount; d++)
{
memcpy(dst, src, sizeof(VkDescriptorImageInfo));
VkDescriptorImageInfo *info = (VkDescriptorImageInfo *)dst;
if(hasSampler)
{
frameRefs.push_back(std::make_pair(GetResID(info->sampler), eFrameRef_Read));
info->sampler = Unwrap(info->sampler);
}
if(hasImage)
{
frameRefs.push_back(std::make_pair(GetResID(info->imageView), eFrameRef_Read));
if(GetRecord(info->imageView)->baseResource != ResourceId())
frameRefs.push_back(std::make_pair(GetRecord(info->imageView)->baseResource, ref));
info->imageView = Unwrap(info->imageView);
}
}
}
else
{
for(uint32_t d = 0; d < entry.descriptorCount; d++)
{
memcpy(dst, src, sizeof(VkDescriptorBufferInfo));
VkDescriptorBufferInfo *info = (VkDescriptorBufferInfo *)dst;
frameRefs.push_back(std::make_pair(GetResID(info->buffer), eFrameRef_Read));
if(GetRecord(info->buffer)->baseResource != ResourceId())
frameRefs.push_back(std::make_pair(GetRecord(info->buffer)->baseResource, ref));
info->buffer = Unwrap(info->buffer);
}
}
}
SERIALISE_TIME_CALL(ObjDisp(commandBuffer)
->CmdPushDescriptorSetWithTemplateKHR(Unwrap(commandBuffer),
Unwrap(descriptorUpdateTemplate),
Unwrap(layout), set, memory));
}
if(IsCaptureMode(m_State))
{
VkResourceRecord *record = GetRecord(commandBuffer);
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdPushDescriptorSetWithTemplateKHR);
Serialise_vkCmdPushDescriptorSetWithTemplateKHR(ser, commandBuffer, descriptorUpdateTemplate,
layout, set, pData);
record->AddChunk(scope.Get());
for(size_t i = 0; i < frameRefs.size(); i++)
record->MarkResourceFrameReferenced(frameRefs[i].first, frameRefs[i].second);
}
}
INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateCommandPool, VkDevice device,
const VkCommandPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool);
@@ -3393,3 +3596,8 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdPushDescriptorSetKHR, VkCommandBuffer
VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
uint32_t set, uint32_t descriptorWriteCount,
const VkWriteDescriptorSet *pDescriptorWrites);
INSTANTIATE_FUNCTION_SERIALISED(void, vkCmdPushDescriptorSetWithTemplateKHR,
VkCommandBuffer commandBuffer,
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
VkPipelineLayout layout, uint32_t set, const void *pData);
@@ -75,6 +75,18 @@ VkDescriptorSetAllocateInfo WrappedVulkan::UnwrapInfo(const VkDescriptorSetAlloc
return ret;
}
template <>
VkDescriptorUpdateTemplateCreateInfoKHR WrappedVulkan::UnwrapInfo(
const VkDescriptorUpdateTemplateCreateInfoKHR *info)
{
VkDescriptorUpdateTemplateCreateInfoKHR ret = *info;
ret.pipelineLayout = Unwrap(ret.pipelineLayout);
ret.descriptorSetLayout = Unwrap(ret.descriptorSetLayout);
return ret;
}
template <>
VkWriteDescriptorSet WrappedVulkan::UnwrapInfo(const VkWriteDescriptorSet *writeDesc)
{
@@ -977,33 +989,19 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
{
for(uint32_t i = 0; i < writeCount; i++)
{
VkResourceRecord *record = GetRecord(pDescriptorWrites[i].dstSet);
const VkWriteDescriptorSet &descWrite = pDescriptorWrites[i];
VkResourceRecord *record = GetRecord(descWrite.dstSet);
RDCASSERT(record->descInfo && record->descInfo->layout);
const DescSetLayout &layout = *record->descInfo->layout;
RDCASSERT(pDescriptorWrites[i].dstBinding < record->descInfo->descBindings.size());
RDCASSERT(descWrite.dstBinding < record->descInfo->descBindings.size());
DescriptorSetSlot **binding = &record->descInfo->descBindings[pDescriptorWrites[i].dstBinding];
DescriptorSetSlot **binding = &record->descInfo->descBindings[descWrite.dstBinding];
const DescSetLayout::Binding *layoutBinding = &layout.bindings[pDescriptorWrites[i].dstBinding];
const DescSetLayout::Binding *layoutBinding = &layout.bindings[descWrite.dstBinding];
FrameRefType ref = eFrameRef_Write;
switch(layoutBinding->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");
}
FrameRefType ref = GetRefType(layoutBinding->descriptorType);
// We need to handle the cases where these bindings are stale:
// ie. image handle 0xf00baa is allocated
@@ -1021,9 +1019,9 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
// This is handled by RemoveBindFrameRef silently dropping id == ResourceId()
// start at the dstArrayElement
uint32_t curIdx = pDescriptorWrites[i].dstArrayElement;
uint32_t curIdx = descWrite.dstArrayElement;
for(uint32_t d = 0; d < pDescriptorWrites[i].descriptorCount; d++, curIdx++)
for(uint32_t d = 0; d < descWrite.descriptorCount; d++, curIdx++)
{
// roll over onto the next binding, on the assumption that it is the same
// type and there is indeed a next binding at all. See spec language:
@@ -1045,98 +1043,34 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
DescriptorSetSlot &bind = (*binding)[curIdx];
if(bind.texelBufferView != VK_NULL_HANDLE)
{
record->RemoveBindFrameRef(GetResID(bind.texelBufferView));
bind.RemoveBindRefs(record);
VkResourceRecord *viewRecord = GetRecord(bind.texelBufferView);
if(viewRecord && viewRecord->baseResource != ResourceId())
record->RemoveBindFrameRef(viewRecord->baseResource);
}
if(bind.imageInfo.imageView != VK_NULL_HANDLE)
if(descWrite.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
descWrite.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
{
record->RemoveBindFrameRef(GetResID(bind.imageInfo.imageView));
VkResourceRecord *viewRecord = GetRecord(bind.imageInfo.imageView);
if(viewRecord)
{
record->RemoveBindFrameRef(viewRecord->baseResource);
if(viewRecord->baseResourceMem != ResourceId())
record->RemoveBindFrameRef(viewRecord->baseResourceMem);
}
bind.texelBufferView = descWrite.pTexelBufferView[d];
}
if(bind.imageInfo.sampler != VK_NULL_HANDLE)
else if(descWrite.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
descWrite.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
descWrite.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
descWrite.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
descWrite.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
{
record->RemoveBindFrameRef(GetResID(bind.imageInfo.sampler));
}
if(bind.bufferInfo.buffer != VK_NULL_HANDLE)
{
record->RemoveBindFrameRef(GetResID(bind.bufferInfo.buffer));
VkResourceRecord *bufRecord = GetRecord(bind.bufferInfo.buffer);
if(bufRecord && bufRecord->baseResource != ResourceId())
record->RemoveBindFrameRef(bufRecord->baseResource);
}
// NULL everything out now so that we don't accidentally reference an object
// that was removed already
bind.texelBufferView = VK_NULL_HANDLE;
bind.bufferInfo.buffer = VK_NULL_HANDLE;
bind.imageInfo.imageView = VK_NULL_HANDLE;
bind.imageInfo.sampler = VK_NULL_HANDLE;
if(pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
{
bind.texelBufferView = pDescriptorWrites[i].pTexelBufferView[d];
}
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)
{
bind.imageInfo = pDescriptorWrites[i].pImageInfo[d];
bind.imageInfo = descWrite.pImageInfo[d];
// ignore descriptors not part of the write, by NULL'ing out those members
// as they might not even point to a valid object
if(pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
if(descWrite.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
bind.imageInfo.imageView = VK_NULL_HANDLE;
else if(pDescriptorWrites[i].descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
else if(descWrite.descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
bind.imageInfo.sampler = VK_NULL_HANDLE;
}
else
{
bind.bufferInfo = pDescriptorWrites[i].pBufferInfo[d];
bind.bufferInfo = descWrite.pBufferInfo[d];
}
if(bind.texelBufferView != VK_NULL_HANDLE)
{
record->AddBindFrameRef(GetResID(bind.texelBufferView), eFrameRef_Read,
GetRecord(bind.texelBufferView)->sparseInfo != NULL);
if(GetRecord(bind.texelBufferView)->baseResource != ResourceId())
record->AddBindFrameRef(GetRecord(bind.texelBufferView)->baseResource, ref);
}
if(bind.imageInfo.imageView != VK_NULL_HANDLE)
{
record->AddBindFrameRef(GetResID(bind.imageInfo.imageView), eFrameRef_Read,
GetRecord(bind.imageInfo.imageView)->sparseInfo != NULL);
record->AddBindFrameRef(GetRecord(bind.imageInfo.imageView)->baseResource, ref);
if(GetRecord(bind.imageInfo.imageView)->baseResourceMem != ResourceId())
record->AddBindFrameRef(GetRecord(bind.imageInfo.imageView)->baseResourceMem,
eFrameRef_Read);
}
if(bind.imageInfo.sampler != VK_NULL_HANDLE)
{
record->AddBindFrameRef(GetResID(bind.imageInfo.sampler), eFrameRef_Read);
}
if(bind.bufferInfo.buffer != VK_NULL_HANDLE)
{
record->AddBindFrameRef(GetResID(bind.bufferInfo.buffer), eFrameRef_Read,
GetRecord(bind.bufferInfo.buffer)->sparseInfo != NULL);
if(GetRecord(bind.bufferInfo.buffer)->baseResource != ResourceId())
record->AddBindFrameRef(GetRecord(bind.bufferInfo.buffer)->baseResource, ref);
}
bind.AddBindRefs(record, ref);
}
}
@@ -1167,23 +1101,7 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
const DescSetLayout::Binding *srclayoutBinding =
&srclayout.bindings[pDescriptorCopies[i].srcBinding];
FrameRefType ref = eFrameRef_Write;
switch(dstlayoutBinding->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");
}
FrameRefType ref = GetRefType(dstlayoutBinding->descriptorType);
// allow roll-over between consecutive bindings. See above in the plain write case for more
// explanation
@@ -1209,59 +1127,317 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
DescriptorSetSlot &bind = (*dstbinding)[curDstIdx];
if(bind.texelBufferView != VK_NULL_HANDLE)
{
dstrecord->RemoveBindFrameRef(GetResID(bind.texelBufferView));
if(GetRecord(bind.texelBufferView)->baseResource != ResourceId())
dstrecord->RemoveBindFrameRef(GetRecord(bind.texelBufferView)->baseResource);
}
if(bind.imageInfo.imageView != VK_NULL_HANDLE)
{
dstrecord->RemoveBindFrameRef(GetResID(bind.imageInfo.imageView));
dstrecord->RemoveBindFrameRef(GetRecord(bind.imageInfo.imageView)->baseResource);
if(GetRecord(bind.imageInfo.imageView)->baseResourceMem != ResourceId())
dstrecord->RemoveBindFrameRef(GetRecord(bind.imageInfo.imageView)->baseResourceMem);
}
if(bind.imageInfo.sampler != VK_NULL_HANDLE)
{
dstrecord->RemoveBindFrameRef(GetResID(bind.imageInfo.sampler));
}
if(bind.bufferInfo.buffer != VK_NULL_HANDLE)
{
dstrecord->RemoveBindFrameRef(GetResID(bind.bufferInfo.buffer));
if(GetRecord(bind.bufferInfo.buffer)->baseResource != ResourceId())
dstrecord->RemoveBindFrameRef(GetRecord(bind.bufferInfo.buffer)->baseResource);
}
bind.RemoveBindRefs(dstrecord);
bind = (*srcbinding)[curSrcIdx];
bind.AddBindRefs(dstrecord, ref);
}
}
}
}
if(bind.texelBufferView != VK_NULL_HANDLE)
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkCreateDescriptorUpdateTemplateKHR(
SerialiserType &ser, VkDevice device, const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate)
{
SERIALISE_ELEMENT(device);
SERIALISE_ELEMENT_LOCAL(CreateInfo, *pCreateInfo);
SERIALISE_ELEMENT_OPT(pAllocator);
SERIALISE_ELEMENT_LOCAL(DescriptorUpdateTemplate, GetResID(*pDescriptorUpdateTemplate))
.TypedAs("VkDescriptorUpdateTemplateKHR");
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
VkDescriptorUpdateTemplateKHR templ = VK_NULL_HANDLE;
VkResult ret = ObjDisp(device)->CreateDescriptorUpdateTemplateKHR(Unwrap(device), &CreateInfo,
NULL, &templ);
if(ret != VK_SUCCESS)
{
RDCERR("Failed on resource serialise-creation, VkResult: %s", ToStr(ret).c_str());
return false;
}
else
{
ResourceId live = GetResourceManager()->WrapResource(Unwrap(device), templ);
GetResourceManager()->AddLiveResource(DescriptorUpdateTemplate, templ);
m_CreationInfo.m_DescUpdateTemplate[live].Init(GetResourceManager(), m_CreationInfo,
&CreateInfo);
}
AddResource(DescriptorUpdateTemplate, ResourceType::StateObject, "Descriptor Update Template");
DerivedResource(device, DescriptorUpdateTemplate);
if(CreateInfo.pipelineLayout != VK_NULL_HANDLE)
DerivedResource(CreateInfo.pipelineLayout, DescriptorUpdateTemplate);
if(CreateInfo.descriptorSetLayout != VK_NULL_HANDLE)
DerivedResource(CreateInfo.descriptorSetLayout, DescriptorUpdateTemplate);
}
return true;
}
VkResult WrappedVulkan::vkCreateDescriptorUpdateTemplateKHR(
VkDevice device, const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate)
{
VkDescriptorUpdateTemplateCreateInfoKHR unwrapped = UnwrapInfo(pCreateInfo);
VkResult ret;
SERIALISE_TIME_CALL(ret = ObjDisp(device)->CreateDescriptorUpdateTemplateKHR(
Unwrap(device), &unwrapped, pAllocator, pDescriptorUpdateTemplate));
if(ret == VK_SUCCESS)
{
ResourceId id = GetResourceManager()->WrapResource(Unwrap(device), *pDescriptorUpdateTemplate);
if(IsCaptureMode(m_State))
{
Chunk *chunk = NULL;
{
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCreateDescriptorUpdateTemplateKHR);
Serialise_vkCreateDescriptorUpdateTemplateKHR(ser, device, pCreateInfo, NULL,
pDescriptorUpdateTemplate);
chunk = scope.Get();
}
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pDescriptorUpdateTemplate);
record->AddChunk(chunk);
record->descTemplateInfo = new DescUpdateTemplate();
record->descTemplateInfo->Init(GetResourceManager(), m_CreationInfo, pCreateInfo);
}
else
{
GetResourceManager()->AddLiveResource(id, *pDescriptorUpdateTemplate);
m_CreationInfo.m_DescUpdateTemplate[id].Init(GetResourceManager(), m_CreationInfo, pCreateInfo);
}
}
return ret;
}
template <typename SerialiserType>
bool WrappedVulkan::Serialise_vkUpdateDescriptorSetWithTemplateKHR(
SerialiserType &ser, VkDevice device, VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const void *pData)
{
SERIALISE_ELEMENT(device);
SERIALISE_ELEMENT(descriptorSet);
SERIALISE_ELEMENT(descriptorUpdateTemplate);
// we can't serialise pData as-is, since we need to decode to ResourceId for references, etc. The
// sensible way to do this is to decode the data into a series of writes and serialise that.
DescUpdateTemplateApplication apply;
if(IsCaptureMode(m_State))
{
// decode while capturing.
GetRecord(descriptorUpdateTemplate)->descTemplateInfo->Apply(pData, apply);
}
SERIALISE_ELEMENT(apply.writes).Named("Decoded Writes");
Serialise_DebugMessages(ser);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
for(VkWriteDescriptorSet &writeDesc : apply.writes)
{
writeDesc.dstSet = descriptorSet;
ReplayDescriptorSetWrite(device, writeDesc);
}
}
return true;
}
// see vkUpdateDescriptorSets for more verbose comments, the concepts are the same here except we
// apply from a template & user memory instead of arrays of VkWriteDescriptorSet/VkCopyDescriptorSet
void WrappedVulkan::vkUpdateDescriptorSetWithTemplateKHR(
VkDevice device, VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, const void *pData)
{
SCOPED_DBG_SINK();
DescUpdateTemplate *tempInfo = GetRecord(descriptorUpdateTemplate)->descTemplateInfo;
{
// allocate the whole blob of memory
byte *memory = GetTempMemory(tempInfo->dataByteSize);
// iterate the entries, copy the descriptor data and unwrap
for(const VkDescriptorUpdateTemplateEntryKHR &entry : tempInfo->updates)
{
byte *dst = memory + entry.offset;
const byte *src = (const byte *)pData + entry.offset;
if(entry.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
{
for(uint32_t d = 0; d < entry.descriptorCount; d++)
{
dstrecord->AddBindFrameRef(GetResID(bind.texelBufferView), eFrameRef_Read,
GetRecord(bind.texelBufferView)->sparseInfo != NULL);
if(GetRecord(bind.texelBufferView)->baseResource != ResourceId())
dstrecord->AddBindFrameRef(GetRecord(bind.texelBufferView)->baseResource, ref);
memcpy(dst, src, sizeof(VkBufferView));
VkBufferView *bufView = (VkBufferView *)dst;
*bufView = Unwrap(*bufView);
dst += entry.stride;
src += entry.stride;
}
if(bind.imageInfo.imageView != VK_NULL_HANDLE)
}
else if(entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
{
bool hasSampler = (entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
bool hasImage = (entry.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
for(uint32_t d = 0; d < entry.descriptorCount; d++)
{
dstrecord->AddBindFrameRef(GetResID(bind.imageInfo.imageView), eFrameRef_Read,
GetRecord(bind.imageInfo.imageView)->sparseInfo != NULL);
dstrecord->AddBindFrameRef(GetRecord(bind.imageInfo.imageView)->baseResource, ref);
if(GetRecord(bind.imageInfo.imageView)->baseResourceMem != ResourceId())
dstrecord->AddBindFrameRef(GetRecord(bind.imageInfo.imageView)->baseResourceMem,
eFrameRef_Read);
memcpy(dst, src, sizeof(VkDescriptorImageInfo));
VkDescriptorImageInfo *info = (VkDescriptorImageInfo *)dst;
if(hasSampler)
info->sampler = Unwrap(info->sampler);
if(hasImage)
info->imageView = Unwrap(info->imageView);
dst += entry.stride;
src += entry.stride;
}
if(bind.imageInfo.sampler != VK_NULL_HANDLE)
}
else
{
for(uint32_t d = 0; d < entry.descriptorCount; d++)
{
dstrecord->AddBindFrameRef(GetResID(bind.imageInfo.sampler), ref);
memcpy(dst, src, sizeof(VkDescriptorBufferInfo));
VkDescriptorBufferInfo *info = (VkDescriptorBufferInfo *)dst;
info->buffer = Unwrap(info->buffer);
dst += entry.stride;
src += entry.stride;
}
if(bind.bufferInfo.buffer != VK_NULL_HANDLE)
}
}
SERIALISE_TIME_CALL(ObjDisp(device)->UpdateDescriptorSetWithTemplateKHR(
Unwrap(device), Unwrap(descriptorSet), Unwrap(descriptorUpdateTemplate), memory));
}
bool capframe = false;
{
SCOPED_LOCK(m_CapTransitionLock);
capframe = IsActiveCapturing(m_State);
}
if(capframe)
{
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(VulkanChunk::vkUpdateDescriptorSetWithTemplateKHR);
Serialise_vkUpdateDescriptorSetWithTemplateKHR(ser, device, descriptorSet,
descriptorUpdateTemplate, pData);
m_FrameCaptureRecord->AddChunk(scope.Get());
// mark the destination set and template as referenced
GetResourceManager()->MarkResourceFrameReferenced(GetResID(descriptorSet), eFrameRef_Write);
GetResourceManager()->MarkResourceFrameReferenced(GetResID(descriptorUpdateTemplate),
eFrameRef_Read);
}
// need to track descriptor set contents whether capframing or idle
if(IsCaptureMode(m_State))
{
for(const VkDescriptorUpdateTemplateEntryKHR &entry : tempInfo->updates)
{
VkResourceRecord *record = GetRecord(descriptorSet);
RDCASSERT(record->descInfo && record->descInfo->layout);
const DescSetLayout &layout = *record->descInfo->layout;
RDCASSERT(entry.dstBinding < record->descInfo->descBindings.size());
DescriptorSetSlot **binding = &record->descInfo->descBindings[entry.dstBinding];
const DescSetLayout::Binding *layoutBinding = &layout.bindings[entry.dstBinding];
FrameRefType ref = GetRefType(layoutBinding->descriptorType);
// start at the dstArrayElement
uint32_t curIdx = entry.dstArrayElement;
for(uint32_t d = 0; d < entry.descriptorCount; d++, curIdx++)
{
// roll over onto the next binding, on the assumption that it is the same
// type and there is indeed a next binding at all. See spec language:
//
// If the dstBinding has fewer than descriptorCount array elements remaining starting from
// dstArrayElement, then the remainder will be used to update the subsequent binding -
// dstBinding+1 starting at array element zero. This behavior applies recursively, with the
// update affecting consecutive bindings as needed to update all descriptorCount
// descriptors. All consecutive bindings updated via a single VkWriteDescriptorSet structure
// must have identical descriptorType and stageFlags, and must all either use immutable
// samplers or must all not use immutable samplers.
if(curIdx >= layoutBinding->descriptorCount)
{
dstrecord->AddBindFrameRef(GetResID(bind.bufferInfo.buffer), eFrameRef_Read,
GetRecord(bind.bufferInfo.buffer)->sparseInfo != NULL);
if(GetRecord(bind.bufferInfo.buffer)->baseResource != ResourceId())
dstrecord->AddBindFrameRef(GetRecord(bind.bufferInfo.buffer)->baseResource, ref);
layoutBinding++;
binding++;
curIdx = 0;
}
const byte *src = (const byte *)pData + entry.offset + entry.stride * d;
DescriptorSetSlot &bind = (*binding)[curIdx];
bind.RemoveBindRefs(record);
if(entry.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
{
bind.texelBufferView = *(VkBufferView *)src;
}
else if(entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
entry.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
{
bind.imageInfo = *(VkDescriptorImageInfo *)src;
// ignore descriptors not part of the write, by NULL'ing out those members
// as they might not even point to a valid object
if(entry.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER)
bind.imageInfo.imageView = VK_NULL_HANDLE;
else if(entry.descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
bind.imageInfo.sampler = VK_NULL_HANDLE;
}
else
{
bind.bufferInfo = *(VkDescriptorBufferInfo *)src;
}
bind.AddBindRefs(record, ref);
}
}
}
@@ -1286,3 +1462,13 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkUpdateDescriptorSets, VkDevice device,
const VkWriteDescriptorSet *pDescriptorWrites,
uint32_t descriptorCopyCount,
const VkCopyDescriptorSet *pDescriptorCopies);
INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateDescriptorUpdateTemplateKHR, VkDevice device,
const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate);
INSTANTIATE_FUNCTION_SERIALISED(void, vkUpdateDescriptorSetWithTemplateKHR, VkDevice device,
VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
const void *pData);
@@ -110,6 +110,7 @@ DESTROY_IMPL(VkCommandPool, DestroyCommandPool)
DESTROY_IMPL(VkQueryPool, DestroyQueryPool)
DESTROY_IMPL(VkFramebuffer, DestroyFramebuffer)
DESTROY_IMPL(VkRenderPass, DestroyRenderPass)
DESTROY_IMPL(VkDescriptorUpdateTemplateKHR, DestroyDescriptorUpdateTemplateKHR)
#undef DESTROY_IMPL
@@ -381,6 +382,13 @@ bool WrappedVulkan::ReleaseResource(WrappedVkRes *res)
vt->DestroySemaphore(Unwrap(dev), real, NULL);
break;
}
case eResDescUpdateTemplate:
{
VkDescriptorUpdateTemplateKHR real = nondisp->real.As<VkDescriptorUpdateTemplateKHR>();
GetResourceManager()->ReleaseWrappedResource(VkDescriptorUpdateTemplateKHR(handle));
vt->DestroyDescriptorUpdateTemplateKHR(Unwrap(dev), real, NULL);
break;
}
}
return true;
@@ -1141,6 +1149,8 @@ static VkResourceRecord *GetObjRecord(VkDebugReportObjectTypeEXT objType, uint64
case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT: return GetRecord((VkSurfaceKHR)object);
case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: return GetRecord((VkSwapchainKHR)object);
case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: return GetRecord((VkCommandPool)object);
case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT:
return GetRecord((VkDescriptorUpdateTemplateKHR)object);
case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT:
case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT:
case VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT:
@@ -1149,7 +1159,6 @@ static VkResourceRecord *GetObjRecord(VkDebugReportObjectTypeEXT objType, uint64
case VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT:
case VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT:
case VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT:
case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT:
case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT:
case VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT: break;
}