Be more informative with 'capture incompatible' error messages on vulkan

This commit is contained in:
baldurk
2022-06-06 12:51:23 +01:00
parent 958e568c9d
commit c73c54dd6f
7 changed files with 206 additions and 91 deletions
+10 -4
View File
@@ -238,12 +238,18 @@ extern void *LoadVulkanLibrary();
class VkDriverInfo
{
public:
GPUVendor Vendor() { return m_Vendor; }
uint32_t Major() { return m_Major; }
uint32_t Minor() { return m_Minor; }
uint32_t Patch() { return m_Patch; }
GPUVendor Vendor() const { return m_Vendor; }
uint32_t Major() const { return m_Major; }
uint32_t Minor() const { return m_Minor; }
uint32_t Patch() const { return m_Patch; }
VkDriverInfo(const VkPhysicalDeviceProperties &physProps, bool active = false);
bool operator==(const VkDriverInfo &o) const
{
return m_Vendor == o.m_Vendor && m_Major == o.m_Major && m_Minor == o.m_Minor &&
m_Patch == o.m_Patch;
}
// checks for when we're running on metal and some non-queryable things aren't supported
bool RunningOnMetal() const { return metalBackend; }
// A workaround for a couple of bugs, removing texelFetch use from shaders.
+63
View File
@@ -4098,6 +4098,69 @@ void WrappedVulkan::AddDebugMessage(DebugMessage msg)
}
}
rdcstr WrappedVulkan::GetPhysDeviceCompatString(bool externalResource, bool origInvalid)
{
const VkDriverInfo &capture = m_OrigPhysicalDeviceData.driverInfo;
const VkDriverInfo &replay = m_PhysicalDeviceData.driverInfo;
if(origInvalid)
{
return StringFormat::Fmt(
"This was invalid at capture time.\n"
"You must use API validation, as RenderDoc does not handle invalid API use like this.\n\n"
"Captured on device: %s %s, %u.%u.%u",
ToStr(capture.Vendor()).c_str(), m_OrigPhysicalDeviceData.props.deviceName, capture.Major(),
capture.Minor(), capture.Patch());
}
rdcstr ret;
if(externalResource)
{
ret =
"This resource was externally imported, which cannot happen at replay time.\n"
"Some drivers do not allow externally-imported resources to be bound to non-external "
"memory, meaning that captures using resources like this can't be replayed.\n\n";
}
if(capture == replay)
{
ret += StringFormat::Fmt("Captured and replayed on the same device: %s %s, %u.%u.%u",
ToStr(capture.Vendor()).c_str(),
m_OrigPhysicalDeviceData.props.deviceName, capture.Major(),
capture.Minor(), capture.Patch());
}
else
{
ret += StringFormat::Fmt(
"Capture was made on: %s %s, %u.%u.%u\n"
"Replayed on: %s %s, %u.%u.%u\n",
// capture device
ToStr(capture.Vendor()).c_str(), m_OrigPhysicalDeviceData.props.deviceName, capture.Major(),
capture.Minor(), capture.Patch(),
// replay device
ToStr(replay.Vendor()).c_str(), m_PhysicalDeviceData.props.deviceName, replay.Major(),
replay.Minor(), replay.Patch());
if(capture.Vendor() != replay.Vendor())
{
ret += "Captures are not commonly portable between GPUs from different vendors.";
}
else if(strcmp(m_OrigPhysicalDeviceData.props.deviceName, m_PhysicalDeviceData.props.deviceName))
{
ret += "Captures are sometimes not portable between different GPUs from a vendor.";
}
else
{
ret += "Driver changes can sometimes cause captures to no longer work.";
}
}
return ret;
}
void WrappedVulkan::CheckErrorVkResult(VkResult vkr)
{
if(vkr == VK_SUCCESS || HasFatalError() || IsCaptureMode(m_State))
+5 -1
View File
@@ -434,6 +434,8 @@ private:
VkDevice m_Device;
// the data about the physical device used for the above device
PhysicalDeviceData m_PhysicalDeviceData;
// the driver info for the original device
PhysicalDeviceData m_OrigPhysicalDeviceData;
// the family index that we've selected in CreateDevice for our queue. During replay, this is an
// index in the replay-time queues, not the capture-time queues (i.e. after remapping)
uint32_t m_QueueFamilyIdx;
@@ -903,8 +905,10 @@ private:
void FirstFrame();
rdcstr GetPhysDeviceCompatString(bool external, bool origInvalid);
bool CheckMemoryRequirements(const char *resourceName, ResourceId memId,
VkDeviceSize memoryOffset, VkMemoryRequirements mrq, bool external);
VkDeviceSize memoryOffset, const VkMemoryRequirements &mrq,
bool external, const VkMemoryRequirements &origMrq);
void AddImplicitResolveResourceUsage(uint32_t subpass = 0);
rdcarray<VkImageMemoryBarrier> GetImplicitRenderPassBarriers(uint32_t subpass = 0);
+8 -2
View File
@@ -1497,12 +1497,15 @@ void VulkanCreationInfo::Memory::SimplifyBindings()
}
void VulkanCreationInfo::Buffer::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkBufferCreateInfo *pCreateInfo)
const VkBufferCreateInfo *pCreateInfo,
VkMemoryRequirements origMrq)
{
usage = pCreateInfo->usage;
size = pCreateInfo->size;
gpuAddress = 0;
mrq = origMrq;
external = false;
if(FindNextStruct(pCreateInfo, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO))
@@ -1522,7 +1525,8 @@ void VulkanCreationInfo::BufferView::Init(VulkanResourceManager *resourceMan,
}
void VulkanCreationInfo::Image::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkImageCreateInfo *pCreateInfo)
const VkImageCreateInfo *pCreateInfo,
VkMemoryRequirements origMrq)
{
type = pCreateInfo->imageType;
format = pCreateInfo->format;
@@ -1531,6 +1535,8 @@ void VulkanCreationInfo::Image::Init(VulkanResourceManager *resourceMan, VulkanC
mipLevels = pCreateInfo->mipLevels;
samples = RDCMAX(VK_SAMPLE_COUNT_1_BIT, pCreateInfo->samples);
mrq = origMrq;
linear = pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR;
external = false;
+6 -2
View File
@@ -558,12 +558,14 @@ struct VulkanCreationInfo
struct Buffer
{
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkBufferCreateInfo *pCreateInfo);
const VkBufferCreateInfo *pCreateInfo, VkMemoryRequirements origMrq);
VkBufferUsageFlags usage;
uint64_t size;
uint64_t gpuAddress;
bool external;
VkMemoryRequirements mrq;
};
std::unordered_map<ResourceId, Buffer> m_Buffer;
@@ -582,7 +584,7 @@ struct VulkanCreationInfo
struct Image
{
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkImageCreateInfo *pCreateInfo);
const VkImageCreateInfo *pCreateInfo, VkMemoryRequirements origMrq);
VkImageType type;
VkFormat format;
@@ -594,6 +596,8 @@ struct VulkanCreationInfo
bool external;
bool cube;
TextureCategory creationFlags;
VkMemoryRequirements mrq;
};
std::unordered_map<ResourceId, Image> m_Image;
@@ -332,7 +332,7 @@ RDResult WrappedVulkan::Initialise(VkInitParams &params, uint64_t sectionVersion
if(supportedExtensions.find(params.Extensions[i]) == supportedExtensions.end())
{
RETURN_ERROR_RESULT(ResultCode::APIHardwareUnsupported,
"Capture requires extension '%s' which is not supported",
"Capture requires instance extension '%s' which is not supported\n",
params.Extensions[i].c_str());
}
}
@@ -1609,6 +1609,17 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
RDCLOG("Creating replay device from physical device %u", physicalDeviceIndex);
ObjDisp(physicalDevice)
->GetPhysicalDeviceProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.props);
ObjDisp(physicalDevice)
->GetPhysicalDeviceMemoryProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.memProps);
ObjDisp(physicalDevice)
->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &m_PhysicalDeviceData.availFeatures);
m_PhysicalDeviceData.driverInfo = VkDriverInfo(m_PhysicalDeviceData.props, true);
rdcarray<VkDeviceQueueGlobalPriorityCreateInfoKHR *> queuePriorities;
for(uint32_t i = 0; i < CreateInfo.queueCreateInfoCount; i++)
@@ -1622,6 +1633,11 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
queuePriorities.push_back(queuePrio);
}
const PhysicalDeviceData &origData = m_OriginalPhysicalDevices[physicalDeviceIndex];
m_OrigPhysicalDeviceData = origData;
m_OrigPhysicalDeviceData.driverInfo = VkDriverInfo(origData.props, false);
// we must make any modifications locally, so the free of pointers
// in the serialised VkDeviceCreateInfo don't double-free
VkDeviceCreateInfo createInfo = CreateInfo;
@@ -1671,8 +1687,9 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
if(supportedExtensions.find(Extensions[i]) == supportedExtensions.end())
{
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires extension '%s' which is not supported",
Extensions[i].c_str());
"Capture requires extension '%s' which is not supported\n"
"\n%s",
Extensions[i].c_str(), GetPhysDeviceCompatString(false, false).c_str());
return false;
}
}
@@ -1816,10 +1833,8 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
q.queueFlags |= VK_QUEUE_TRANSFER_BIT;
}
PhysicalDeviceData &origData = m_OriginalPhysicalDevices[physicalDeviceIndex];
uint32_t origQCount = origData.queueCount;
VkQueueFamilyProperties *origprops = origData.queueProps;
const VkQueueFamilyProperties *origprops = origData.queueProps;
// create queue remapping
for(uint32_t origQIndex = 0; origQIndex < origQCount; origQIndex++)
@@ -2105,7 +2120,8 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
{ \
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported, \
"Capture requires physical device feature '" #feature \
"' which is not supported"); \
"' which is not supported\n\n%s", \
GetPhysDeviceCompatString(false, false).c_str()); \
return false; \
}
@@ -2176,14 +2192,14 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
#define END_PHYS_EXT_CHECK() }
#define CHECK_PHYS_EXT_FEATURE(feature) \
if(ext->feature && !avail.feature) \
{ \
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported, \
"Capture requires physical device feature '" #feature \
"' in struct '%s' which is not supported", \
structName); \
return false; \
#define CHECK_PHYS_EXT_FEATURE(feature) \
if(ext->feature && !avail.feature) \
{ \
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported, \
"Capture requires physical device feature '" #feature \
"' in struct '%s' which is not supported\n\n%s", \
structName, GetPhysDeviceCompatString(false, false).c_str()); \
return false; \
}
VkPhysicalDeviceDescriptorIndexingFeatures descIndexingFeatures = {};
@@ -2272,7 +2288,9 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires bufferDeviceAddress support, which is available, but "
"bufferDeviceAddressCaptureReplay support is not available which is required to "
"replay");
"replay\n"
"\n%s",
GetPhysDeviceCompatString(false, false).c_str());
return false;
}
}
@@ -2478,7 +2496,9 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires bufferDeviceAddress support, which is available, but "
"bufferDeviceAddressCaptureReplay support is not available which is required to "
"replay");
"replay\n"
"\n%s",
GetPhysDeviceCompatString(false, false).c_str());
return false;
}
}
@@ -2497,7 +2517,9 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Capture requires bufferDeviceAddress support, which is available, but "
"bufferDeviceAddressCaptureReplay support is not available which is required to "
"replay");
"replay\n"
"\n%s",
GetPhysDeviceCompatString(false, false).c_str());
return false;
}
}
@@ -3573,20 +3595,10 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi
}
}
ObjDisp(physicalDevice)
->GetPhysicalDeviceProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.props);
ObjDisp(physicalDevice)
->GetPhysicalDeviceMemoryProperties(Unwrap(physicalDevice), &m_PhysicalDeviceData.memProps);
ObjDisp(physicalDevice)
->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &m_PhysicalDeviceData.availFeatures);
m_PhysicalDeviceData.enabledFeatures = enabledFeatures;
m_PhysicalDeviceData.driverInfo = VkDriverInfo(m_PhysicalDeviceData.props, true);
m_Replay->SetDriverInformation(m_PhysicalDeviceData.props);
m_PhysicalDeviceData.enabledFeatures = enabledFeatures;
// MoltenVK reports 0x3fffffff for this limit so just ignore that value if it comes up
RDCASSERT(m_PhysicalDeviceData.props.limits.maxBoundDescriptorSets <
ARRAY_COUNT(BakedCmdBufferInfo::pushDescriptorID[0]) ||
@@ -191,8 +191,9 @@ VkBindImageMemoryInfo *WrappedVulkan::UnwrapInfos(CaptureState state,
}
bool WrappedVulkan::CheckMemoryRequirements(const char *resourceName, ResourceId memId,
VkDeviceSize memoryOffset, VkMemoryRequirements mrq,
bool external)
VkDeviceSize memoryOffset,
const VkMemoryRequirements &mrq, bool external,
const VkMemoryRequirements &origMrq)
{
// 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
@@ -203,65 +204,80 @@ bool WrappedVulkan::CheckMemoryRequirements(const char *resourceName, ResourceId
VulkanCreationInfo::Memory &memInfo = m_CreationInfo.m_Memory[memId];
uint32_t bit = 1U << memInfo.memoryTypeIndex;
bool origInvalid = false;
// verify type
if((mrq.memoryTypeBits & bit) == 0)
{
rdcstr bitsString;
for(uint32_t i = 0; i < 32; i++)
if((origMrq.memoryTypeBits & bit) == 0)
{
if(mrq.memoryTypeBits & (1U << i))
bitsString += StringFormat::Fmt("%s%u", bitsString.empty() ? "" : ", ", i);
}
for(uint32_t i = 0; i < 32; i++)
{
if(origMrq.memoryTypeBits & (1U << i))
bitsString += StringFormat::Fmt("%s%u", bitsString.empty() ? "" : ", ", i);
}
if(external)
origInvalid = true;
}
else
{
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"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());
return false;
for(uint32_t i = 0; i < 32; i++)
{
if(mrq.memoryTypeBits & (1U << i))
bitsString += StringFormat::Fmt("%s%u", bitsString.empty() ? "" : ", ", i);
}
}
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Trying to bind %s to memory %s which is type %u, "
"but only these types are allowed: %s\n"
"This is most likely caused by incompatible hardware or drivers between capture and "
"replay, causing a change in memory requirements.",
resourceName, ToStr(memOrigId).c_str(), memInfo.memoryTypeIndex, bitsString.c_str());
"Trying to bind %s to %s, but memory type is %u and only types %s are allowed.\n"
"\n%s",
resourceName, GetResourceDesc(memOrigId).name.c_str(), memInfo.memoryTypeIndex,
bitsString.c_str(), GetPhysDeviceCompatString(external, origInvalid).c_str());
return false;
}
// verify offset alignment
if((memoryOffset % mrq.alignment) != 0)
{
VkDeviceSize align = mrq.alignment;
if((memoryOffset % origMrq.alignment) != 0)
{
origInvalid = true;
align = origMrq.alignment;
}
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Trying to bind %s to memory %s which is type %u, "
"but offset 0x%llx doesn't satisfy alignment 0x%llx.\n"
"This is most likely caused by incompatible hardware or drivers between capture and "
"replay, causing a change in memory requirements.",
resourceName, ToStr(memOrigId).c_str(), memInfo.memoryTypeIndex, memoryOffset, mrq.alignment);
"Trying to bind %s to %s, but memory offset 0x%llx doesn't satisfy alignment 0x%llx.\n"
"\n%s",
resourceName, GetResourceDesc(memOrigId).name.c_str(), memoryOffset, mrq.alignment,
GetPhysDeviceCompatString(external, origInvalid).c_str());
return false;
}
// verify size
if(mrq.size > memInfo.allocSize - memoryOffset)
{
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Trying to bind %s to memory %s which is type %u, "
"but at offset 0x%llx the reported size of 0x%llx won't fit the 0x%llx bytes of memory.\n"
"This is most likely caused by incompatible hardware or drivers between capture and "
"replay, causing a change in memory requirements.",
resourceName, ToStr(memOrigId).c_str(), memInfo.memoryTypeIndex, memoryOffset, mrq.size,
memInfo.allocSize);
VkDeviceSize size = mrq.size;
if(origMrq.size > memInfo.allocSize - memoryOffset)
{
origInvalid = true;
size = origMrq.size;
}
SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Trying to bind %s to %s, but at memory offset 0x%llx the reported size of "
"0x%llx won't fit the 0x%llx bytes of memory.\n"
"\n%s",
resourceName, GetResourceDesc(memOrigId).name.c_str(), memoryOffset, size,
memInfo.allocSize, GetPhysDeviceCompatString(external, origInvalid).c_str());
return false;
}
@@ -296,9 +312,11 @@ bool WrappedVulkan::Serialise_vkAllocateMemory(SerialiserType &ser, VkDevice dev
SET_ERROR_RESULT(
m_FailedReplayResult, ResultCode::APIHardwareUnsupported,
"Tried to allocate memory from index %u, but on replay we only have %u memory types.\n"
"This is most likely caused by incompatible hardware or drivers between capture and "
"replay, causing a change in memory requirements.",
patched.memoryTypeIndex, m_PhysicalDeviceData.memProps.memoryTypeCount);
"\n%s",
patched.memoryTypeIndex, m_PhysicalDeviceData.memProps.memoryTypeCount,
GetPhysDeviceCompatString(
false, patched.memoryTypeIndex >= m_OrigPhysicalDeviceData.memProps.memoryTypeCount)
.c_str());
return false;
}
@@ -1338,8 +1356,8 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory(SerialiserType &ser, VkDevice d
VkMemoryRequirements mrq = {};
ObjDisp(device)->GetBufferMemoryRequirements(Unwrap(device), Unwrap(buffer), &mrq);
bool ok = CheckMemoryRequirements(("Buffer " + ToStr(resOrigId)).c_str(), GetResID(memory),
memoryOffset, mrq, bufInfo.external);
bool ok = CheckMemoryRequirements(GetResourceDesc(resOrigId).name.c_str(), GetResID(memory),
memoryOffset, mrq, bufInfo.external, bufInfo.mrq);
if(!ok)
return false;
@@ -1461,8 +1479,8 @@ bool WrappedVulkan::Serialise_vkBindImageMemory(SerialiserType &ser, VkDevice de
VulkanCreationInfo::Image &imgInfo = m_CreationInfo.m_Image[GetResID(image)];
bool ok = CheckMemoryRequirements(("Image " + ToStr(resOrigId)).c_str(), GetResID(memory),
memoryOffset, mrq, imgInfo.external);
bool ok = CheckMemoryRequirements(GetResourceDesc(resOrigId).name.c_str(), GetResID(memory),
memoryOffset, mrq, imgInfo.external, imgInfo.mrq);
if(!ok)
return false;
@@ -1631,7 +1649,8 @@ bool WrappedVulkan::Serialise_vkCreateBuffer(SerialiserType &ser, VkDevice devic
ResourceId live = GetResourceManager()->WrapResource(Unwrap(device), buf);
GetResourceManager()->AddLiveResource(Buffer, buf);
m_CreationInfo.m_Buffer[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo);
m_CreationInfo.m_Buffer[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo,
memoryRequirements);
}
AddResource(Buffer, ResourceType::Buffer, "Buffer");
@@ -1841,7 +1860,7 @@ VkResult WrappedVulkan::vkCreateBuffer(VkDevice device, const VkBufferCreateInfo
{
GetResourceManager()->AddLiveResource(id, *pBuffer);
m_CreationInfo.m_Buffer[id].Init(GetResourceManager(), m_CreationInfo, pCreateInfo);
m_CreationInfo.m_Buffer[id].Init(GetResourceManager(), m_CreationInfo, pCreateInfo, {});
}
}
else
@@ -2132,7 +2151,8 @@ bool WrappedVulkan::Serialise_vkCreateImage(SerialiserType &ser, VkDevice device
NameVulkanObject(img, StringFormat::Fmt("Image %s", ToStr(Image).c_str()));
m_CreationInfo.m_Image[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo);
m_CreationInfo.m_Image[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo,
memoryRequirements);
bool inserted = false;
auto state = InsertImageState(img, live, CreateInfo, eFrameRef_Unknown, &inserted);
@@ -2525,7 +2545,7 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo *
{
GetResourceManager()->AddLiveResource(id, *pImage);
m_CreationInfo.m_Image[id].Init(GetResourceManager(), m_CreationInfo, pCreateInfo);
m_CreationInfo.m_Image[id].Init(GetResourceManager(), m_CreationInfo, pCreateInfo, {});
}
LockedImageStateRef state =
@@ -2732,9 +2752,9 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory2(SerialiserType &ser, VkDevice
ObjDisp(device)->GetBufferMemoryRequirements(Unwrap(device), Unwrap(bindInfo.buffer), &mrqs[i]);
bool ok =
CheckMemoryRequirements(("Buffer " + ToStr(resOrigId)).c_str(), GetResID(bindInfo.memory),
bindInfo.memoryOffset, mrqs[i], bufInfo.external);
bool ok = CheckMemoryRequirements(GetResourceDesc(resOrigId).name.c_str(),
GetResID(bindInfo.memory), bindInfo.memoryOffset, mrqs[i],
bufInfo.external, bufInfo.mrq);
if(!ok)
return false;
@@ -2877,9 +2897,9 @@ bool WrappedVulkan::Serialise_vkBindImageMemory2(SerialiserType &ser, VkDevice d
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, imgInfo.external);
bool ok = CheckMemoryRequirements(GetResourceDesc(resOrigId).name.c_str(),
GetResID(bindInfo.memory), bindInfo.memoryOffset, mrq,
imgInfo.external, imgInfo.mrq);
if(!ok)
return false;