blob: 0706ed592539897cafa24e84cf5e7db65dcc8d53 [file] [log] [blame]
/*
* Copyright (c) 2015-2025 The Khronos Group Inc.
* Copyright (c) 2015-2025 Valve Corporation
* Copyright (c) 2015-2025 LunarG, Inc.
* Copyright (c) 2015-2025 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifdef VK_USE_PLATFORM_METAL_EXT
#include "utils/math_utils.h"
#include "../framework/layer_validation_tests.h"
#include "../framework/external_memory_sync.h"
#include "containers/container_utils.h"
// We need these instead of using FindSupportedExternalMemoryHandleTypes because otherwise we'll get
// VUID-VkPhysicalDeviceExternalImageFormatInfo-handleType-parameter due to sending flags that are not supported due to extensions
// not being present
VkExternalMemoryHandleTypeFlags FindSupportedExternalMemoryHandleTypesMetal(VkPhysicalDevice gpu,
const VkBufferCreateInfo& buffer_create_info,
VkExternalMemoryFeatureFlags requested_features) {
VkPhysicalDeviceExternalBufferInfo external_info = vku::InitStructHelper();
external_info.flags = buffer_create_info.flags;
external_info.usage = buffer_create_info.usage;
const VkExternalMemoryHandleTypeFlags all_metal_buffer_types =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
VkExternalMemoryHandleTypeFlags supported_types = 0;
IterateFlags<VkExternalMemoryHandleTypeFlagBits>(all_metal_buffer_types, [&](VkExternalMemoryHandleTypeFlagBits flag) {
external_info.handleType = flag;
VkExternalBufferProperties external_properties = vku::InitStructHelper();
vk::GetPhysicalDeviceExternalBufferProperties(gpu, &external_info, &external_properties);
const auto external_features = external_properties.externalMemoryProperties.externalMemoryFeatures;
if ((external_features & requested_features) == requested_features) {
supported_types |= flag;
}
});
return supported_types;
}
VkExternalMemoryHandleTypeFlags FindSupportedExternalMemoryHandleTypesMetal(VkPhysicalDevice gpu,
const VkImageCreateInfo& image_create_info,
VkExternalMemoryFeatureFlags requested_features) {
VkPhysicalDeviceExternalImageFormatInfo external_info = vku::InitStructHelper();
VkPhysicalDeviceImageFormatInfo2 image_info = vku::InitStructHelper(&external_info);
image_info.format = image_create_info.format;
image_info.type = image_create_info.imageType;
image_info.tiling = image_create_info.tiling;
image_info.usage = image_create_info.usage;
image_info.flags = image_create_info.flags;
const VkExternalMemoryHandleTypeFlags all_metal_image_types =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
VkExternalMemoryHandleTypeFlags supported_types = 0;
IterateFlags<VkExternalMemoryHandleTypeFlagBits>(all_metal_image_types, [&](VkExternalMemoryHandleTypeFlagBits flag) {
external_info.handleType = flag;
VkExternalImageFormatProperties external_properties = vku::InitStructHelper();
VkImageFormatProperties2 image_properties = vku::InitStructHelper(&external_properties);
VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(gpu, &image_info, &image_properties);
const auto external_features = external_properties.externalMemoryProperties.externalMemoryFeatures;
if (result == VK_SUCCESS && (external_features & requested_features) == requested_features) {
supported_types |= flag;
}
});
return supported_types;
}
class NegativeExternalMemoryMetal : public VkLayerTest {};
TEST_F(NegativeExternalMemoryMetal, AllocateExportableImageWithoutDedicatedAllocationInPNext) {
TEST_DESCRIPTION("Allocate exportable metal texture without dedicated allocation in pNext chain");
AddRequiredExtensions(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
// Create export image
VkExternalMemoryImageCreateInfo external_image_info = vku::InitStructHelper();
VkImageCreateInfo image_info = vku::InitStructHelper(&external_image_info);
image_info.imageType = VK_IMAGE_TYPE_2D;
image_info.arrayLayers = 1;
image_info.extent = {64, 64, 1};
image_info.format = VK_FORMAT_R8G8B8A8_UNORM;
image_info.mipLevels = 1;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
auto exportable_types =
FindSupportedExternalMemoryHandleTypesMetal(Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT);
VkExternalMemoryHandleTypeFlagBits metal_texture_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT;
if ((exportable_types & metal_texture_type) == 0u) {
GTEST_SKIP() << "Unable to find exportable metal texture handle type";
}
external_image_info.handleTypes = metal_texture_type;
vkt::Image image(*m_device, image_info, vkt::no_mem);
VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(nullptr);
export_memory_info.handleTypes = metal_texture_type;
auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, image.MemoryRequirements(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info);
m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-00639");
image.Memory().TryInit(*m_device, alloc_info);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeExternalMemoryMetal, AllocateImportableImageWithoutDedicatedAllocationInPNext) {
TEST_DESCRIPTION("Import metal texture at allocation without dedicated allocation in pNext chain");
AddRequiredExtensions(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
// Create export image
VkExternalMemoryImageCreateInfo external_image_info = vku::InitStructHelper();
VkImageCreateInfo image_info = vku::InitStructHelper(&external_image_info);
image_info.imageType = VK_IMAGE_TYPE_2D;
image_info.arrayLayers = 1;
image_info.extent = {64, 64, 1};
image_info.format = VK_FORMAT_R8G8B8A8_UNORM;
image_info.mipLevels = 1;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
auto exportable_types = FindSupportedExternalMemoryHandleTypesMetal(
Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT);
VkExternalMemoryHandleTypeFlagBits metal_texture_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT;
if ((exportable_types & metal_texture_type) == 0u) {
GTEST_SKIP() << "Unable to find exportable metal texture handle type";
}
external_image_info.handleTypes = metal_texture_type;
vkt::Image image(*m_device, image_info, vkt::no_mem);
VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper();
dedicated_info.image = image;
VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(&dedicated_info);
export_memory_info.handleTypes = metal_texture_type;
image.AllocateAndBindMemory(*m_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info);
VkMemoryGetMetalHandleInfoEXT get_handle_info = vku::InitStructHelper();
get_handle_info.handleType = metal_texture_type;
get_handle_info.memory = image.Memory().handle();
void* import_handle = nullptr;
vk::GetMemoryMetalHandleEXT(*m_device, &get_handle_info, &import_handle);
VkImportMemoryMetalHandleInfoEXT metal_import_info = vku::InitStructHelper();
metal_import_info.handleType = metal_texture_type;
metal_import_info.handle = import_handle;
VkMemoryAllocateInfo import_allocate_info = vku::InitStructHelper(&metal_import_info);
VkDeviceMemory device_memory = VK_NULL_HANDLE;
m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-10395");
vk::AllocateMemory(*m_device, &import_allocate_info, nullptr, &device_memory);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeExternalMemoryMetal, AllocateImportableImageWithoutDedicatedImageAllocation) {
TEST_DESCRIPTION("Import invalid metal texture without dedicated image specified");
AddRequiredExtensions(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
// Create export image
VkExternalMemoryImageCreateInfo external_image_info = vku::InitStructHelper();
VkImageCreateInfo image_info = vku::InitStructHelper(&external_image_info);
image_info.imageType = VK_IMAGE_TYPE_2D;
image_info.arrayLayers = 1;
image_info.extent = {64, 64, 1};
image_info.format = VK_FORMAT_R8G8B8A8_UNORM;
image_info.mipLevels = 1;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
auto exportable_types = FindSupportedExternalMemoryHandleTypesMetal(
Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT);
VkExternalMemoryHandleTypeFlagBits metal_texture_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT;
if ((exportable_types & metal_texture_type) == 0u) {
GTEST_SKIP() << "Unable to find exportable metal texture handle type";
}
external_image_info.handleTypes = metal_texture_type;
vkt::Image image(*m_device, image_info, vkt::no_mem);
VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper();
dedicated_info.image = image;
VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(&dedicated_info);
export_memory_info.handleTypes = metal_texture_type;
image.AllocateAndBindMemory(*m_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info);
VkMemoryGetMetalHandleInfoEXT get_handle_info = vku::InitStructHelper();
get_handle_info.handleType = metal_texture_type;
get_handle_info.memory = image.Memory().handle();
void* import_handle = nullptr;
vk::GetMemoryMetalHandleEXT(*m_device, &get_handle_info, &import_handle);
dedicated_info.image = VK_NULL_HANDLE; // This is what makes it illegal
VkImportMemoryMetalHandleInfoEXT metal_import_info = vku::InitStructHelper(&dedicated_info);
metal_import_info.handleType = metal_texture_type;
metal_import_info.handle = import_handle;
VkMemoryAllocateInfo import_allocate_info = vku::InitStructHelper(&metal_import_info);
VkDeviceMemory device_memory = VK_NULL_HANDLE;
m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-10395");
vk::AllocateMemory(*m_device, &import_allocate_info, nullptr, &device_memory);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeExternalMemoryMetal, AllocateImportableImageWithAllocationSizeNot0) {
TEST_DESCRIPTION("Import invalid metal texture with allocation size being non-0");
AddRequiredExtensions(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
// Create export image
VkExternalMemoryImageCreateInfo external_image_info = vku::InitStructHelper();
VkImageCreateInfo image_info = vku::InitStructHelper(&external_image_info);
image_info.imageType = VK_IMAGE_TYPE_2D;
image_info.arrayLayers = 1;
image_info.extent = {64, 64, 1};
image_info.format = VK_FORMAT_R8G8B8A8_UNORM;
image_info.mipLevels = 1;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
auto exportable_types = FindSupportedExternalMemoryHandleTypesMetal(
Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT);
VkExternalMemoryHandleTypeFlagBits metal_texture_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT;
if ((exportable_types & metal_texture_type) == 0u) {
GTEST_SKIP() << "Unable to find exportable metal texture handle type";
}
external_image_info.handleTypes = metal_texture_type;
vkt::Image image(*m_device, image_info, vkt::no_mem);
VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper();
dedicated_info.image = image;
VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(&dedicated_info);
export_memory_info.handleTypes = metal_texture_type;
image.AllocateAndBindMemory(*m_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info);
VkMemoryGetMetalHandleInfoEXT get_handle_info = vku::InitStructHelper();
get_handle_info.handleType = metal_texture_type;
get_handle_info.memory = image.Memory().handle();
void* import_handle = nullptr;
vk::GetMemoryMetalHandleEXT(*m_device, &get_handle_info, &import_handle);
VkImportMemoryMetalHandleInfoEXT metal_import_info = vku::InitStructHelper(&dedicated_info);
metal_import_info.handleType = metal_texture_type;
metal_import_info.handle = import_handle;
VkMemoryAllocateInfo import_allocate_info = vku::InitStructHelper(&metal_import_info);
import_allocate_info.allocationSize = 100; // This is what makes it illegal
VkDeviceMemory device_memory = VK_NULL_HANDLE;
m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-10397");
vk::AllocateMemory(*m_device, &import_allocate_info, nullptr, &device_memory);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeExternalMemoryMetal, GetResourceHandleWithoutExportStructAtCreation) {
TEST_DESCRIPTION("Get resource handle that was created without the export struct at creation");
AddRequiredExtensions(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkExternalMemoryBufferCreateInfo external_buffer_info = vku::InitStructHelper();
const auto buffer_info = vkt::Buffer::CreateInfo(4096, VK_BUFFER_USAGE_TRANSFER_DST_BIT, {}, &external_buffer_info);
const auto exportable_types =
FindSupportedExternalMemoryHandleTypesMetal(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT);
auto metal_types = static_cast<VkExternalMemoryHandleTypeFlagBits>(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT);
auto valid_types = static_cast<VkExternalMemoryHandleTypeFlagBits>(exportable_types & metal_types);
if (valid_types == 0u) {
GTEST_SKIP() << "Unable to find exportable metal handle type";
}
const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(valid_types);
external_buffer_info.handleTypes = handle_type;
vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem);
// Check if dedicated allocation is required
bool dedicated_allocation = false;
IterateFlags<VkExternalMemoryHandleTypeFlagBits>(exportable_types, [&](VkExternalMemoryHandleTypeFlagBits handle_type) {
if (HandleTypeNeedsDedicatedAllocation(Gpu(), buffer_info, handle_type)) {
dedicated_allocation = true;
}
});
VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper();
dedicated_info.buffer = buffer;
auto alloc_info =
vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
dedicated_allocation ? &dedicated_info : nullptr);
VkResult result = buffer.Memory().TryInit(*m_device, alloc_info);
if (result != VK_SUCCESS) {
GTEST_SKIP() << "vkAllocateMemory failed. Unable to continue test to check for incorrect import handle type.";
}
void* handle = nullptr;
VkMemoryGetMetalHandleInfoEXT get_handle_info = vku::InitStructHelper();
get_handle_info.memory = buffer.Memory().handle();
get_handle_info.handleType = handle_type;
m_errorMonitor->SetDesiredError("VUID-VkMemoryGetMetalHandleInfoEXT-memory-10413");
vk::GetMemoryMetalHandleEXT(*m_device, &get_handle_info, &handle);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeExternalMemoryMetal, GetResourceHandleWithIncorrectHandleType) {
TEST_DESCRIPTION("Get resource handle that was created with a different external handle type");
AddRequiredExtensions(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkExternalMemoryBufferCreateInfo external_buffer_info = vku::InitStructHelper();
const auto buffer_info = vkt::Buffer::CreateInfo(4096, VK_BUFFER_USAGE_TRANSFER_DST_BIT, {}, &external_buffer_info);
const auto exportable_types =
FindSupportedExternalMemoryHandleTypesMetal(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT);
auto metal_types = static_cast<VkExternalMemoryHandleTypeFlagBits>(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT);
auto valid_types = static_cast<VkExternalMemoryHandleTypeFlagBits>(exportable_types & metal_types);
if (valid_types == 0u) {
GTEST_SKIP() << "Unable to find exportable metal handle type";
}
const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(valid_types);
external_buffer_info.handleTypes = handle_type;
vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem);
// Check if dedicated allocation is required
bool dedicated_allocation = false;
IterateFlags<VkExternalMemoryHandleTypeFlagBits>(exportable_types, [&](VkExternalMemoryHandleTypeFlagBits handle_type) {
if (HandleTypeNeedsDedicatedAllocation(Gpu(), buffer_info, handle_type)) {
dedicated_allocation = true;
}
});
VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper();
dedicated_info.buffer = buffer;
VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(dedicated_allocation ? &dedicated_info : nullptr);
export_memory_info.handleTypes = handle_type;
auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info);
VkResult result = buffer.Memory().TryInit(*m_device, alloc_info);
if (result != VK_SUCCESS) {
GTEST_SKIP() << "vkAllocateMemory failed. Unable to continue test to check for incorrect import handle type.";
}
void* handle = nullptr;
VkMemoryGetMetalHandleInfoEXT get_handle_info = vku::InitStructHelper();
get_handle_info.memory = buffer.Memory().handle();
// Get the other handle type that was not used to allocate the memory
get_handle_info.handleType = static_cast<VkExternalMemoryHandleTypeFlagBits>(handle_type ^ metal_types);
m_errorMonitor->SetDesiredError("VUID-VkMemoryGetMetalHandleInfoEXT-handleType-10414");
vk::GetMemoryMetalHandleEXT(*m_device, &get_handle_info, &handle);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeExternalMemoryMetal, GetResourceHandleWithNonMetalHandle) {
TEST_DESCRIPTION("Get resource handle as non metal handle");
AddRequiredExtensions(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkExternalMemoryBufferCreateInfo external_buffer_info = vku::InitStructHelper();
const auto buffer_info = vkt::Buffer::CreateInfo(4096, VK_BUFFER_USAGE_TRANSFER_DST_BIT, {}, &external_buffer_info);
const auto exportable_types =
FindSupportedExternalMemoryHandleTypesMetal(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT);
auto metal_types = static_cast<VkExternalMemoryHandleTypeFlagBits>(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT);
auto valid_types = static_cast<VkExternalMemoryHandleTypeFlagBits>(exportable_types & metal_types);
if (valid_types == 0u) {
GTEST_SKIP() << "Unable to find exportable metal handle type";
}
const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(valid_types);
external_buffer_info.handleTypes = handle_type;
vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem);
// Check if dedicated allocation is required
bool dedicated_allocation = false;
IterateFlags<VkExternalMemoryHandleTypeFlagBits>(exportable_types, [&](VkExternalMemoryHandleTypeFlagBits handle_type) {
if (HandleTypeNeedsDedicatedAllocation(Gpu(), buffer_info, handle_type)) {
dedicated_allocation = true;
}
});
VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper();
dedicated_info.buffer = buffer;
VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(dedicated_allocation ? &dedicated_info : nullptr);
export_memory_info.handleTypes = handle_type;
auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info);
VkResult result = buffer.Memory().TryInit(*m_device, alloc_info);
if (result != VK_SUCCESS) {
GTEST_SKIP() << "vkAllocateMemory failed. Unable to continue test to check for incorrect import handle type.";
}
void* handle = nullptr;
VkMemoryGetMetalHandleInfoEXT get_handle_info = vku::InitStructHelper();
get_handle_info.memory = buffer.Memory().handle();
// Get the other handle type that was not used to allocate the memory
get_handle_info.handleType = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(~metal_types);
m_errorMonitor->SetDesiredError("VUID-VkMemoryGetMetalHandleInfoEXT-handleType-10415");
// We are trying to get the handle using a type that was not specified at creation, so we also get this one
m_errorMonitor->SetAllowedFailureMsg("VUID-VkMemoryGetMetalHandleInfoEXT-handleType-10414");
vk::GetMemoryMetalHandleEXT(*m_device, &get_handle_info, &handle);
m_errorMonitor->VerifyFound();
}
#endif // VK_USE_PLATFORM_METAL_EXT