mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-20 14:31:42 +00:00
Implement VK_KHR_descriptor_update_template. Closes #934
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user