Provide more specific error on external-imported resources

* When capturing some external memory driver implementations have completely
  disjoint memory type bits allowed for external and non-external resources.
  This means it is impossible to capture it as external and then replay it as
  non-external, leading to a broken capture.
* This is warned about at capture time but easy to miss. Adding this error here
  is more likely to be seen and found.
This commit is contained in:
baldurk
2020-09-14 15:27:46 +01:00
parent 60eb2c5ab7
commit ce1cfe5330
4 changed files with 51 additions and 12 deletions
+1 -1
View File
@@ -861,7 +861,7 @@ private:
void FirstFrame();
bool CheckMemoryRequirements(const char *resourceName, ResourceId memId,
VkDeviceSize memoryOffset, VkMemoryRequirements mrq);
VkDeviceSize memoryOffset, VkMemoryRequirements mrq, bool external);
void AddImplicitResolveResourceUsage(uint32_t subpass = 0);
rdcarray<VkImageMemoryBarrier> GetImplicitRenderPassBarriers(uint32_t subpass = 0);
+16
View File
@@ -1091,6 +1091,13 @@ void VulkanCreationInfo::Buffer::Init(VulkanResourceManager *resourceMan, Vulkan
usage = pCreateInfo->usage;
size = pCreateInfo->size;
gpuAddress = 0;
external = false;
if(FindNextStruct(pCreateInfo, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO))
{
external = true;
}
}
void VulkanCreationInfo::BufferView::Init(VulkanResourceManager *resourceMan,
@@ -1115,6 +1122,15 @@ void VulkanCreationInfo::Image::Init(VulkanResourceManager *resourceMan, VulkanC
linear = pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR;
external = false;
if(FindNextStruct(pCreateInfo, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV) ||
FindNextStruct(pCreateInfo, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO) ||
FindNextStruct(pCreateInfo, VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID))
{
external = true;
}
creationFlags = TextureCategory::NoFlags;
if(pCreateInfo->usage & VK_IMAGE_USAGE_SAMPLED_BIT)
+2
View File
@@ -496,6 +496,7 @@ struct VulkanCreationInfo
VkBufferUsageFlags usage;
uint64_t size;
uint64_t gpuAddress;
bool external;
};
std::unordered_map<ResourceId, Buffer> m_Buffer;
@@ -523,6 +524,7 @@ struct VulkanCreationInfo
VkSampleCountFlagBits samples;
bool linear;
bool external;
bool cube;
TextureCategory creationFlags;
};
@@ -189,7 +189,8 @@ VkBindImageMemoryInfo *WrappedVulkan::UnwrapInfos(const VkBindImageMemoryInfo *i
}
bool WrappedVulkan::CheckMemoryRequirements(const char *resourceName, ResourceId memId,
VkDeviceSize memoryOffset, VkMemoryRequirements mrq)
VkDeviceSize memoryOffset, VkMemoryRequirements mrq,
bool external)
{
// verify that the memory meets basic requirements. If not, something changed and we should
// bail loading this capture. This is a bit of an under-estimate since we just make sure
@@ -211,6 +212,20 @@ bool WrappedVulkan::CheckMemoryRequirements(const char *resourceName, ResourceId
bitsString += StringFormat::Fmt("%s%u", bitsString.empty() ? "" : ", ", i);
}
if(external)
{
RDCERR(
"Trying to bind %s to memory %s which is type %u, "
"but only these types are allowed: %s\n"
"This resource was created with external memory bindings, which is not represented in "
"the capture.\n"
"Some drivers do not allow externally-imported resources to be bound to non-external "
"memory, meaning this cannot be replayed.",
resourceName, ToStr(memOrigId).c_str(), memInfo.memoryTypeIndex, bitsString.c_str());
m_FailedReplayStatus = ReplayStatus::APIHardwareUnsupported;
return false;
}
RDCERR(
"Trying to bind %s to memory %s which is type %u, "
"but only these types are allowed: %s\n"
@@ -1167,11 +1182,13 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory(SerialiserType &ser, VkDevice d
ResourceId resOrigId = GetResourceManager()->GetOriginalID(GetResID(buffer));
ResourceId memOrigId = GetResourceManager()->GetOriginalID(GetResID(memory));
VulkanCreationInfo::Buffer &bufInfo = m_CreationInfo.m_Buffer[GetResID(buffer)];
VkMemoryRequirements mrq = {};
ObjDisp(device)->GetBufferMemoryRequirements(Unwrap(device), Unwrap(buffer), &mrq);
bool ok = CheckMemoryRequirements(("Buffer " + ToStr(resOrigId)).c_str(), GetResID(memory),
memoryOffset, mrq);
memoryOffset, mrq, bufInfo.external);
if(!ok)
return false;
@@ -1186,7 +1203,6 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory(SerialiserType &ser, VkDevice d
// for buffers created with device addresses, fetch it now as that's possible for both EXT and
// KHR variants now.
VulkanCreationInfo::Buffer &bufInfo = m_CreationInfo.m_Buffer[GetResID(buffer)];
if(bufInfo.usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
{
VkBufferDeviceAddressInfo getInfo = {
@@ -1284,8 +1300,10 @@ bool WrappedVulkan::Serialise_vkBindImageMemory(SerialiserType &ser, VkDevice de
VkMemoryRequirements mrq = {};
ObjDisp(device)->GetImageMemoryRequirements(Unwrap(device), Unwrap(image), &mrq);
VulkanCreationInfo::Image &imgInfo = m_CreationInfo.m_Image[GetResID(image)];
bool ok = CheckMemoryRequirements(("Image " + ToStr(resOrigId)).c_str(), GetResID(memory),
memoryOffset, mrq);
memoryOffset, mrq, imgInfo.external);
if(!ok)
return false;
@@ -1313,7 +1331,6 @@ bool WrappedVulkan::Serialise_vkBindImageMemory(SerialiserType &ser, VkDevice de
AddResourceCurChunk(memOrigId);
AddResourceCurChunk(resOrigId);
VulkanCreationInfo::Image &imgInfo = m_CreationInfo.m_Image[GetResID(image)];
m_CreationInfo.m_Memory[GetResID(memory)].BindMemory(
memoryOffset, mrq.size,
imgInfo.linear ? VulkanCreationInfo::Memory::Linear : VulkanCreationInfo::Memory::Tiled);
@@ -2318,11 +2335,14 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory2(SerialiserType &ser, VkDevice
ResourceId resOrigId = GetResourceManager()->GetOriginalID(GetResID(bindInfo.buffer));
ResourceId memOrigId = GetResourceManager()->GetOriginalID(GetResID(bindInfo.memory));
VulkanCreationInfo::Buffer &bufInfo = m_CreationInfo.m_Buffer[GetResID(bindInfo.buffer)];
VkMemoryRequirements mrq = {};
ObjDisp(device)->GetBufferMemoryRequirements(Unwrap(device), Unwrap(bindInfo.buffer), &mrq);
bool ok = CheckMemoryRequirements(("Buffer " + ToStr(resOrigId)).c_str(),
GetResID(bindInfo.memory), bindInfo.memoryOffset, mrq);
bool ok =
CheckMemoryRequirements(("Buffer " + ToStr(resOrigId)).c_str(), GetResID(bindInfo.memory),
bindInfo.memoryOffset, mrq, bufInfo.external);
if(!ok)
return false;
@@ -2335,7 +2355,6 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory2(SerialiserType &ser, VkDevice
// for buffers created with device addresses, fetch it now as that's possible for both EXT and
// KHR variants now.
VulkanCreationInfo::Buffer &bufInfo = m_CreationInfo.m_Buffer[GetResID(bindInfo.buffer)];
if(bufInfo.usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
{
VkBufferDeviceAddressInfo getInfo = {
@@ -2440,11 +2459,14 @@ bool WrappedVulkan::Serialise_vkBindImageMemory2(SerialiserType &ser, VkDevice d
ResourceId resOrigId = GetResourceManager()->GetOriginalID(GetResID(bindInfo.image));
ResourceId memOrigId = GetResourceManager()->GetOriginalID(GetResID(bindInfo.memory));
VulkanCreationInfo::Image &imgInfo = m_CreationInfo.m_Image[GetResID(bindInfo.image)];
VkMemoryRequirements mrq = {};
ObjDisp(device)->GetImageMemoryRequirements(Unwrap(device), Unwrap(bindInfo.image), &mrq);
bool ok = CheckMemoryRequirements(("Image " + ToStr(resOrigId)).c_str(),
GetResID(bindInfo.memory), bindInfo.memoryOffset, mrq);
bool ok =
CheckMemoryRequirements(("Image " + ToStr(resOrigId)).c_str(), GetResID(bindInfo.memory),
bindInfo.memoryOffset, mrq, imgInfo.external);
if(!ok)
return false;
@@ -2471,7 +2493,6 @@ bool WrappedVulkan::Serialise_vkBindImageMemory2(SerialiserType &ser, VkDevice d
AddResourceCurChunk(memOrigId);
AddResourceCurChunk(resOrigId);
VulkanCreationInfo::Image &imgInfo = m_CreationInfo.m_Image[GetResID(bindInfo.image)];
m_CreationInfo.m_Memory[GetResID(bindInfo.memory)].BindMemory(
bindInfo.memoryOffset, mrq.size,
imgInfo.linear ? VulkanCreationInfo::Memory::Linear : VulkanCreationInfo::Memory::Tiled);