| /* |
| * Copyright (c) 2015-2025 The Khronos Group Inc. |
| * Copyright (c) 2015-2025 Valve Corporation |
| * Copyright (c) 2015-2025 LunarG, Inc. |
| * Copyright (c) 2015-2024 Google, Inc. |
| * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. |
| * |
| * 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 |
| */ |
| |
| #include "generated/enum_flag_bits.h" |
| #include "../framework/layer_validation_tests.h" |
| #include "../framework/external_memory_sync.h" |
| #include "utils/math_utils.h" |
| #include "containers/container_utils.h" |
| |
| class NegativeExternalMemorySync : public ExternalMemorySyncTest {}; |
| |
| TEST_F(NegativeExternalMemorySync, CreateBufferIncompatibleHandleTypes) { |
| TEST_DESCRIPTION("Creating buffer with incompatible external memory handle types"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| // Try all flags first. It's unlikely all of them are compatible. |
| VkExternalMemoryBufferCreateInfo external_memory_info = vku::InitStructHelper(); |
| external_memory_info.handleTypes = AllVkExternalMemoryHandleTypeFlagBits; |
| VkBufferCreateInfo buffer_create_info = vku::InitStructHelper(&external_memory_info); |
| buffer_create_info.size = 1024; |
| buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; |
| CreateBufferTest(buffer_create_info, "VUID-VkBufferCreateInfo-pNext-00920"); |
| |
| IgnoreHandleTypeError(m_errorMonitor); |
| // Get all exportable handle types supported by the platform. |
| VkExternalMemoryHandleTypeFlags supported_handle_types = 0; |
| VkExternalMemoryHandleTypeFlags any_compatible_group = 0; |
| IterateFlags<VkExternalMemoryHandleTypeFlagBits>( |
| AllVkExternalMemoryHandleTypeFlagBits, [&](VkExternalMemoryHandleTypeFlagBits flag) { |
| VkPhysicalDeviceExternalBufferInfo external_buffer_info = vku::InitStructHelper(); |
| external_buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; |
| external_buffer_info.handleType = flag; |
| VkExternalBufferProperties external_buffer_properties = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalBufferProperties(Gpu(), &external_buffer_info, &external_buffer_properties); |
| const auto external_features = external_buffer_properties.externalMemoryProperties.externalMemoryFeatures; |
| if (external_features & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) { |
| supported_handle_types |= external_buffer_info.handleType; |
| any_compatible_group = external_buffer_properties.externalMemoryProperties.compatibleHandleTypes; |
| } |
| }); |
| |
| // Main test case. Handle types are supported but not compatible with each other |
| if ((supported_handle_types & any_compatible_group) != supported_handle_types) { |
| external_memory_info.handleTypes = supported_handle_types; |
| CreateBufferTest(buffer_create_info, "VUID-VkBufferCreateInfo-pNext-00920"); |
| } |
| } |
| |
| TEST_F(NegativeExternalMemorySync, CreateImageIncompatibleHandleTypes) { |
| TEST_DESCRIPTION("Creating image with incompatible external memory handle types"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| // Try all flags first. It's unlikely all of them are compatible. |
| VkExternalMemoryImageCreateInfo external_memory_info = vku::InitStructHelper(); |
| external_memory_info.handleTypes = AllVkExternalMemoryHandleTypeFlagBits; |
| VkImageCreateInfo image_create_info = vku::InitStructHelper(&external_memory_info); |
| image_create_info.imageType = VK_IMAGE_TYPE_2D; |
| image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; |
| image_create_info.extent = {32, 32, 1}; |
| image_create_info.mipLevels = 1; |
| image_create_info.arrayLayers = 1; |
| image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; |
| image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| CreateImageTest(image_create_info, "VUID-VkImageCreateInfo-pNext-00990"); |
| |
| // Get all exportable handle types supported by the platform. |
| VkExternalMemoryHandleTypeFlags supported_handle_types = 0; |
| VkExternalMemoryHandleTypeFlags any_compatible_group = 0; |
| |
| VkPhysicalDeviceExternalImageFormatInfo external_image_info = vku::InitStructHelper(); |
| VkPhysicalDeviceImageFormatInfo2 image_info = vku::InitStructHelper(&external_image_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; |
| |
| IgnoreHandleTypeError(m_errorMonitor); |
| IterateFlags<VkExternalMemoryHandleTypeFlagBits>( |
| AllVkExternalMemoryHandleTypeFlagBits, [&](VkExternalMemoryHandleTypeFlagBits flag) { |
| external_image_info.handleType = flag; |
| VkExternalImageFormatProperties external_image_properties = vku::InitStructHelper(); |
| VkImageFormatProperties2 image_properties = vku::InitStructHelper(&external_image_properties); |
| VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(Gpu(), &image_info, &image_properties); |
| const auto external_features = external_image_properties.externalMemoryProperties.externalMemoryFeatures; |
| if (result == VK_SUCCESS && (external_features & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT)) { |
| supported_handle_types |= external_image_info.handleType; |
| any_compatible_group = external_image_properties.externalMemoryProperties.compatibleHandleTypes; |
| } |
| }); |
| |
| // Main test case. Handle types are supported but not compatible with each other |
| if ((supported_handle_types & any_compatible_group) != supported_handle_types) { |
| external_memory_info.handleTypes = supported_handle_types; |
| CreateImageTest(image_create_info, "VUID-VkImageCreateInfo-pNext-00990"); |
| } |
| } |
| |
| TEST_F(NegativeExternalMemorySync, CreateImageIncompatibleHandleTypesNV) { |
| TEST_DESCRIPTION("Creating image with incompatible external memory handle types from NVIDIA extension"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME); |
| AddRequiredExtensions(VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| VkExternalMemoryImageCreateInfoNV external_memory_info = vku::InitStructHelper(); |
| VkImageCreateInfo image_create_info = vku::InitStructHelper(&external_memory_info); |
| image_create_info.imageType = VK_IMAGE_TYPE_2D; |
| image_create_info.format = VK_FORMAT_R8G8B8A8_UNORM; |
| image_create_info.extent = {32, 32, 1}; |
| image_create_info.mipLevels = 1; |
| image_create_info.arrayLayers = 1; |
| image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; |
| image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| |
| // Get all exportable handle types supported by the platform. |
| VkExternalMemoryHandleTypeFlagsNV supported_handle_types = 0; |
| VkExternalMemoryHandleTypeFlagsNV any_compatible_group = 0; |
| |
| IterateFlags<VkExternalMemoryHandleTypeFlagBitsNV>( |
| AllVkExternalMemoryHandleTypeFlagBitsNV, [&](VkExternalMemoryHandleTypeFlagBitsNV flag) { |
| VkExternalImageFormatPropertiesNV external_image_properties = {}; |
| VkResult result = vk::GetPhysicalDeviceExternalImageFormatPropertiesNV( |
| Gpu(), image_create_info.format, image_create_info.imageType, image_create_info.tiling, image_create_info.usage, |
| image_create_info.flags, flag, &external_image_properties); |
| if (result == VK_SUCCESS && |
| (external_image_properties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV)) { |
| supported_handle_types |= flag; |
| any_compatible_group = external_image_properties.compatibleHandleTypes; |
| } |
| }); |
| |
| // Main test case. Handle types are supported but not compatible with each other |
| if ((supported_handle_types & any_compatible_group) != supported_handle_types) { |
| external_memory_info.handleTypes = supported_handle_types; |
| CreateImageTest(image_create_info, "VUID-VkImageCreateInfo-pNext-00991"); |
| } |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ExportImageHandleType) { |
| TEST_DESCRIPTION("Test exporting memory with mismatching handleTypes."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| // 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 = FindSupportedExternalMemoryHandleTypes(Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT); |
| if (GetBitSetCount(exportable_types) < 2) { |
| GTEST_SKIP() << "Cannot find two distinct exportable handle types, skipping test"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_types); |
| exportable_types &= ~handle_type; |
| const auto handle_type2 = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_types); |
| assert(handle_type != handle_type2); |
| |
| // Create an image with one of the handle types |
| external_image_info.handleTypes = handle_type; |
| vkt::Image image(*m_device, image_info, vkt::no_mem); |
| |
| // Create export memory with a different handle type |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.image = image; |
| const bool dedicated_allocation = HandleTypeNeedsDedicatedAllocation(Gpu(), image_info, handle_type2); |
| auto export_memory_info = vku::InitStruct<VkExportMemoryAllocateInfo>(dedicated_allocation ? &dedicated_info : nullptr); |
| export_memory_info.handleTypes = handle_type2; |
| |
| // vkBindImageMemory |
| m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-02728"); |
| image.AllocateAndBindMemory(*m_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info); |
| m_errorMonitor->VerifyFound(); |
| |
| // vkBindImageMemory2 |
| VkBindImageMemoryInfo bind_image_info = vku::InitStructHelper(); |
| bind_image_info.image = image; |
| bind_image_info.memory = image.Memory(); // re-use memory object from the previous check |
| m_errorMonitor->SetDesiredError("VUID-VkBindImageMemoryInfo-memory-02728"); |
| vk::BindImageMemory2(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, BufferMemoryWithUnsupportedHandleType) { |
| TEST_DESCRIPTION("Bind buffer memory with unsupported external memory handle type."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| 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 = |
| FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT); |
| if (!exportable_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| if (exportable_types == AllVkExternalMemoryHandleTypeFlagBits) { |
| GTEST_SKIP() << "This test requires at least one unsupported handle type, but all handle types are supported"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_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; |
| |
| // Create memory object with unsupported handle type |
| const auto not_supported_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(~exportable_types); |
| auto export_memory_info = vku::InitStruct<VkExportMemoryAllocateInfo>(dedicated_allocation ? &dedicated_info : nullptr); |
| export_memory_info.handleTypes = handle_type | not_supported_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 (probably due to unsupported handle type). Unable to reach vkBindBufferMemory to " |
| "run validation"; |
| } |
| |
| m_errorMonitor->SetDesiredError("VUID-VkExportMemoryAllocateInfo-handleTypes-09860"); |
| buffer.BindMemory(buffer.Memory(), 0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, BufferMemoryWithIncompatibleHandleTypes) { |
| TEST_DESCRIPTION("Bind buffer memory with incompatible external memory handle types."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| 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 = |
| FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT); |
| if (!exportable_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_types); |
| const auto compatible_types = GetCompatibleHandleTypes(Gpu(), buffer_info, handle_type); |
| if ((exportable_types & compatible_types) == exportable_types) { |
| GTEST_SKIP() << "Cannot find handle types that are supported but not compatible with each other"; |
| } |
| 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; |
| |
| // Create memory object with incompatible handle types |
| auto export_memory_info = vku::InitStruct<VkExportMemoryAllocateInfo>(dedicated_allocation ? &dedicated_info : nullptr); |
| export_memory_info.handleTypes = exportable_types; |
| m_errorMonitor->SetDesiredError("VUID-VkExportMemoryAllocateInfo-handleTypes-09860"); |
| buffer.AllocateAndBindMemory(*m_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImageMemoryWithUnsupportedHandleType) { |
| TEST_DESCRIPTION("Bind image memory with unsupported external memory handle type."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| 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 = FindSupportedExternalMemoryHandleTypes(Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT); |
| // This test does not support the AHB handle type, which does not |
| // allow to query memory requirements before memory is bound |
| exportable_types &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; |
| if (!exportable_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| if (exportable_types == AllVkExternalMemoryHandleTypeFlagBits) { |
| GTEST_SKIP() << "This test requires at least one unsupported handle type, but all handle types are supported"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_types); |
| |
| // Create an image with supported handle type |
| external_image_info.handleTypes = handle_type; |
| vkt::Image image(*m_device, image_info, vkt::no_mem); |
| |
| // Create memory object which additionally includes unsupported handle type |
| const auto not_supported_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(~exportable_types); |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.image = image; |
| const bool dedicated_allocation = HandleTypeNeedsDedicatedAllocation(Gpu(), image_info, handle_type); |
| auto export_memory_info = vku::InitStruct<VkExportMemoryAllocateInfo>(dedicated_allocation ? &dedicated_info : nullptr); |
| export_memory_info.handleTypes = handle_type | not_supported_type; |
| |
| VkImageMemoryRequirementsInfo2 memory_requirements_info = vku::InitStructHelper(); |
| memory_requirements_info.image = image; |
| |
| VkMemoryDedicatedRequirements memory_dedicated_requirements = vku::InitStructHelper(); |
| VkMemoryRequirements2 memory_requirements = vku::InitStructHelper(&memory_dedicated_requirements); |
| vk::GetImageMemoryRequirements2(*m_device, &memory_requirements_info, &memory_requirements); |
| |
| VkMemoryDedicatedAllocateInfo dedicated_allocate_info = vku::InitStructHelper(); |
| dedicated_allocate_info.image = image; |
| |
| if (memory_dedicated_requirements.requiresDedicatedAllocation) { |
| export_memory_info.pNext = &dedicated_allocate_info; |
| } |
| |
| m_errorMonitor->SetDesiredError("VUID-VkExportMemoryAllocateInfo-handleTypes-09860"); |
| image.AllocateAndBindMemory(*m_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImageMemoryWithIncompatibleHandleTypes) { |
| TEST_DESCRIPTION("Bind image memory with incompatible external memory handle types."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| // 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 = FindSupportedExternalMemoryHandleTypes(Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT); |
| // This test does not support the AHB handle type, which does not |
| // allow to query memory requirements before memory is bound |
| exportable_types &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; |
| if (!exportable_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_types); |
| const auto compatible_types = GetCompatibleHandleTypes(Gpu(), image_info, handle_type); |
| if ((exportable_types & compatible_types) == exportable_types) { |
| GTEST_SKIP() << "Cannot find handle types that are supported but not compatible with each other"; |
| } |
| |
| external_image_info.handleTypes = handle_type; |
| vkt::Image image(*m_device, image_info, vkt::no_mem); |
| |
| bool dedicated_allocation = false; |
| IterateFlags<VkExternalMemoryHandleTypeFlagBits>(exportable_types, [&](VkExternalMemoryHandleTypeFlagBits handle_type) { |
| if (HandleTypeNeedsDedicatedAllocation(Gpu(), image_info, handle_type)) { |
| dedicated_allocation = true; |
| } |
| }); |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.image = image; |
| |
| // Create memory object with incompatible handle types |
| auto export_memory_info = vku::InitStruct<VkExportMemoryAllocateInfo>(dedicated_allocation ? &dedicated_info : nullptr); |
| export_memory_info.handleTypes = exportable_types; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkExportMemoryAllocateInfo-handleTypes-09860"); |
| image.AllocateAndBindMemory(*m_device, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &export_memory_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ExportBufferHandleType) { |
| TEST_DESCRIPTION("Test exporting memory with mismatching handleTypes."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| // Create export buffer |
| VkExternalMemoryBufferCreateInfo external_info = vku::InitStructHelper(); |
| VkBufferCreateInfo buffer_info = vku::InitStructHelper(&external_info); |
| buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; |
| buffer_info.size = 4096; |
| |
| auto exportable_types = FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT); |
| if (GetBitSetCount(exportable_types) < 2) { |
| GTEST_SKIP() << "Cannot find two distinct exportable handle types, skipping test"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_types); |
| exportable_types &= ~handle_type; |
| const auto handle_type2 = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_types); |
| assert(handle_type != handle_type2); |
| |
| // Create a buffer with one of the handle types |
| external_info.handleTypes = handle_type; |
| vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem); |
| |
| // Check if dedicated allocation is required |
| const bool dedicated_allocation = HandleTypeNeedsDedicatedAllocation(Gpu(), buffer_info, handle_type2); |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.buffer = buffer; |
| |
| // Create export memory with a different handle type |
| auto export_memory_info = vku::InitStruct<VkExportMemoryAllocateInfo>(dedicated_allocation ? &dedicated_info : nullptr); |
| export_memory_info.handleTypes = handle_type2; |
| VkBufferMemoryRequirementsInfo2 buffer_memory_requirements_info = vku::InitStructHelper(); |
| buffer_memory_requirements_info.buffer = buffer; |
| VkMemoryDedicatedRequirements memory_dedicated_requirements = vku::InitStructHelper(); |
| VkMemoryRequirements2 mem_reqs2 = vku::InitStructHelper(&memory_dedicated_requirements); |
| vk::GetBufferMemoryRequirements2(device(), &buffer_memory_requirements_info, &mem_reqs2); |
| VkMemoryRequirements buffer_mem_reqs = mem_reqs2.memoryRequirements; |
| const auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer_mem_reqs, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, |
| &export_memory_info); |
| vkt::DeviceMemory memory(*m_device, alloc_info); |
| |
| m_errorMonitor->SetAllowedFailureMsg("VUID-vkBindBufferMemory-buffer-01444"); // required dedicated |
| m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-02726"); |
| if (memory_dedicated_requirements.requiresDedicatedAllocation) { |
| m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-buffer-01444"); |
| } |
| vk::BindBufferMemory(device(), buffer, memory, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| VkBindBufferMemoryInfo bind_buffer_info = vku::InitStructHelper(); |
| bind_buffer_info.buffer = buffer; |
| bind_buffer_info.memory = memory; |
| |
| m_errorMonitor->SetAllowedFailureMsg("VUID-vkBindBufferMemory-buffer-01444"); // required dedicated |
| m_errorMonitor->SetDesiredError("VUID-VkBindBufferMemoryInfo-memory-02726"); |
| if (memory_dedicated_requirements.requiresDedicatedAllocation) { |
| m_errorMonitor->SetDesiredError("VUID-VkBindBufferMemoryInfo-buffer-01444"); |
| } |
| vk::BindBufferMemory2(device(), 1, &bind_buffer_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, TimelineSemaphore) { |
| #ifdef VK_USE_PLATFORM_WIN32_KHR |
| const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; |
| const char *no_tempory_tl_vuid = "VUID-VkImportSemaphoreWin32HandleInfoKHR-flags-03322"; |
| #else |
| const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| const char *no_tempory_tl_vuid = "VUID-VkImportSemaphoreFdInfoKHR-flags-03323"; |
| #endif |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(extension_name); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::timelineSemaphore); |
| RETURN_IF_SKIP(Init()); |
| |
| // Check for external semaphore import and export capability |
| { |
| VkSemaphoreTypeCreateInfo sti = vku::InitStructHelper(); |
| sti.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; |
| VkPhysicalDeviceExternalSemaphoreInfo esi = vku::InitStructHelper(&sti); |
| esi.handleType = handle_type; |
| |
| VkExternalSemaphorePropertiesKHR esp = vku::InitStructHelper(); |
| |
| vk::GetPhysicalDeviceExternalSemaphorePropertiesKHR(Gpu(), &esi, &esp); |
| |
| if (!(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) || |
| !(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External semaphore does not support importing and exporting, skipping test"; |
| } |
| } |
| |
| VkResult err; |
| |
| // Create a semaphore to export payload from |
| VkExportSemaphoreCreateInfo esci = vku::InitStructHelper(); |
| esci.handleTypes = handle_type; |
| VkSemaphoreTypeCreateInfo stci = vku::InitStructHelper(&esci); |
| stci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; |
| VkSemaphoreCreateInfo sci = vku::InitStructHelper(&stci); |
| |
| vkt::Semaphore export_semaphore(*m_device, sci); |
| |
| // Create a semaphore to import payload into |
| stci.pNext = nullptr; |
| vkt::Semaphore import_semaphore(*m_device, sci); |
| |
| ExternalHandle ext_handle{}; |
| err = export_semaphore.ExportHandle(ext_handle, handle_type); |
| ASSERT_EQ(VK_SUCCESS, err); |
| |
| m_errorMonitor->SetDesiredError(no_tempory_tl_vuid); |
| err = import_semaphore.ImportHandle(ext_handle, handle_type, VK_SEMAPHORE_IMPORT_TEMPORARY_BIT); |
| m_errorMonitor->VerifyFound(); |
| |
| err = import_semaphore.ImportHandle(ext_handle, handle_type); |
| ASSERT_EQ(VK_SUCCESS, err); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, SyncFdSemaphore) { |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; |
| |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::timelineSemaphore); |
| RETURN_IF_SKIP(Init()); |
| |
| // Check for external semaphore import and export capability |
| VkPhysicalDeviceExternalSemaphoreInfo esi = vku::InitStructHelper(); |
| esi.handleType = handle_type; |
| |
| VkExternalSemaphorePropertiesKHR esp = vku::InitStructHelper(); |
| |
| vk::GetPhysicalDeviceExternalSemaphorePropertiesKHR(Gpu(), &esi, &esp); |
| |
| if (!(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) || |
| !(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External semaphore does not support importing and exporting"; |
| } |
| |
| if (!(esp.compatibleHandleTypes & handle_type)) { |
| GTEST_SKIP() << "External semaphore does not support VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT"; |
| } |
| |
| // create a timeline semaphore. |
| // Note that adding a sync fd VkExportSemaphoreCreateInfo will cause creation to fail. |
| VkSemaphoreTypeCreateInfo stci = vku::InitStructHelper(); |
| stci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; |
| VkSemaphoreCreateInfo sci = vku::InitStructHelper(&stci); |
| |
| vkt::Semaphore timeline_sem(*m_device, sci); |
| |
| // binary semaphore works fine. |
| VkExportSemaphoreCreateInfo esci = vku::InitStructHelper(); |
| esci.handleTypes = handle_type; |
| stci.pNext = &esci; |
| |
| stci.semaphoreType = VK_SEMAPHORE_TYPE_BINARY; |
| vkt::Semaphore binary_sem(*m_device, sci); |
| |
| // Create a semaphore to import payload into |
| vkt::Semaphore import_semaphore(*m_device); |
| |
| int fd_handle = -1; |
| |
| // timeline not allowed |
| m_errorMonitor->SetDesiredError("VUID-VkSemaphoreGetFdInfoKHR-handleType-01132"); |
| m_errorMonitor->SetDesiredError("VUID-VkSemaphoreGetFdInfoKHR-handleType-03253"); |
| timeline_sem.ExportHandle(fd_handle, handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| // must have pending signal |
| m_errorMonitor->SetDesiredError("VUID-VkSemaphoreGetFdInfoKHR-handleType-03254"); |
| binary_sem.ExportHandle(fd_handle, handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| VkSubmitInfo si = vku::InitStructHelper(); |
| si.signalSemaphoreCount = 1; |
| si.pSignalSemaphores = &binary_sem.handle(); |
| |
| vk::QueueSubmit(m_default_queue->handle(), 1, &si, VK_NULL_HANDLE); |
| |
| binary_sem.ExportHandle(fd_handle, handle_type); |
| |
| // must be temporary |
| m_errorMonitor->SetDesiredError("VUID-VkImportSemaphoreFdInfoKHR-handleType-07307"); |
| import_semaphore.ImportHandle(fd_handle, handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| import_semaphore.ImportHandle(fd_handle, handle_type, VK_SEMAPHORE_IMPORT_TEMPORARY_BIT); |
| |
| m_default_queue->Wait(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, SyncFdSemaphoreTimelineDependency) { |
| TEST_DESCRIPTION("Export using handle with copy transference when semaphore signal depends on unresolved timeline wait"); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::timelineSemaphore); |
| AddRequiredFeature(vkt::Feature::synchronization2); |
| RETURN_IF_SKIP(Init()); |
| |
| if (!m_second_queue) { |
| GTEST_SKIP() << "Two queues are needed to run this test"; |
| } |
| |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; |
| VkPhysicalDeviceExternalSemaphoreInfo external_semahpore_info = vku::InitStructHelper(); |
| external_semahpore_info.handleType = handle_type; |
| VkExternalSemaphoreProperties external_semahpore_props = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalSemaphoreProperties(Gpu(), &external_semahpore_info, &external_semahpore_props); |
| if (!(external_semahpore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) || |
| !(external_semahpore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External semaphore does not support importing and exporting"; |
| } |
| if (!(external_semahpore_props.compatibleHandleTypes & handle_type)) { |
| GTEST_SKIP() << "External semaphore does not support VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT"; |
| } |
| |
| VkExportSemaphoreCreateInfo export_ci = vku::InitStructHelper(); |
| export_ci.handleTypes = handle_type; |
| VkSemaphoreTypeCreateInfo semaphore_type_ci = vku::InitStructHelper(&export_ci); |
| semaphore_type_ci.semaphoreType = VK_SEMAPHORE_TYPE_BINARY; |
| VkSemaphoreCreateInfo semaphore_ci = vku::InitStructHelper(&semaphore_type_ci); |
| vkt::Semaphore binary_semaphore(*m_device, semaphore_ci); |
| |
| vkt::Semaphore timeline_semaphore(*m_device, VK_SEMAPHORE_TYPE_TIMELINE); |
| |
| m_default_queue->Submit2(vkt::no_cmd, vkt::TimelineWait(timeline_semaphore, 1), vkt::Signal(binary_semaphore)); |
| |
| int fd_handle = -1; |
| m_errorMonitor->SetDesiredError("VUID-VkSemaphoreGetFdInfoKHR-handleType-03254"); |
| binary_semaphore.ExportHandle(fd_handle, handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| m_second_queue->Submit2(vkt::no_cmd, vkt::TimelineSignal(timeline_semaphore, 1)); |
| m_default_queue->Wait(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, SyncFdExportFromImportedSemaphore) { |
| TEST_DESCRIPTION("Export from semaphore with imported payload that does not support export"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; |
| { |
| const auto handle_types = FindSupportedExternalSemaphoreHandleTypes( |
| Gpu(), VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT); |
| if ((handle_types & handle_type) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT is not both exportable and importable"; |
| } |
| } |
| const auto export_from_import_handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| { |
| const auto handle_types = FindSupportedExternalSemaphoreHandleTypes(Gpu(), VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT); |
| if ((handle_types & export_from_import_handle_type) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT is not exportable"; |
| } |
| } |
| VkPhysicalDeviceExternalSemaphoreInfo semaphore_info = vku::InitStructHelper(); |
| semaphore_info.handleType = export_from_import_handle_type; |
| VkExternalSemaphoreProperties semaphore_properties = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalSemaphoreProperties(Gpu(), &semaphore_info, &semaphore_properties); |
| if ((handle_type & semaphore_properties.exportFromImportedHandleTypes) != 0) { |
| GTEST_SKIP() << "cannot find handle type that does not support export from imported semaphore"; |
| } |
| |
| // create semaphore and export payload |
| VkExportSemaphoreCreateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = handle_type; |
| const VkSemaphoreCreateInfo create_info = vku::InitStructHelper(&export_info); |
| vkt::Semaphore semaphore(*m_device, create_info); |
| |
| VkSubmitInfo si = vku::InitStructHelper(); |
| si.signalSemaphoreCount = 1; |
| si.pSignalSemaphores = &semaphore.handle(); |
| vk::QueueSubmit(m_default_queue->handle(), 1, &si, VK_NULL_HANDLE); |
| |
| int handle = 0; |
| semaphore.ExportHandle(handle, handle_type); |
| |
| // create semaphore and import payload |
| VkExportSemaphoreCreateInfo export_info2 = vku::InitStructHelper(); // prepare to export from imported semaphore |
| export_info2.handleTypes = export_from_import_handle_type; |
| const VkSemaphoreCreateInfo create_info2 = vku::InitStructHelper(&export_info2); |
| vkt::Semaphore import_semaphore(*m_device, create_info2); |
| import_semaphore.ImportHandle(handle, handle_type, VK_SEMAPHORE_IMPORT_TEMPORARY_BIT); |
| |
| // export from imported semaphore |
| int handle2 = 0; |
| m_errorMonitor->SetDesiredError("VUID-VkSemaphoreGetFdInfoKHR-semaphore-01133"); |
| import_semaphore.ExportHandle(handle2, export_from_import_handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| m_default_queue->Wait(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, SyncFdExportFromImportedFence) { |
| TEST_DESCRIPTION("Export from fence with imported payload that does not support export"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; |
| { |
| const auto handle_types = FindSupportedExternalFenceHandleTypes( |
| Gpu(), VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT); |
| if ((handle_types & handle_type) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT is not both exportable and importable"; |
| } |
| } |
| const auto export_from_import_handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| { |
| const auto handle_types = FindSupportedExternalFenceHandleTypes(Gpu(), VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT); |
| if ((handle_types & export_from_import_handle_type) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT is not exportable"; |
| } |
| } |
| VkPhysicalDeviceExternalFenceInfo fence_info = vku::InitStructHelper(); |
| fence_info.handleType = export_from_import_handle_type; |
| VkExternalFenceProperties fence_properties = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalFenceProperties(Gpu(), &fence_info, &fence_properties); |
| if ((handle_type & fence_properties.exportFromImportedHandleTypes) != 0) { |
| GTEST_SKIP() << "cannot find handle type that does not support export from imported fence"; |
| } |
| |
| // create fence and export payload |
| VkExportFenceCreateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = handle_type; // at first export handle type, then import it |
| const VkFenceCreateInfo create_info = vku::InitStructHelper(&export_info); |
| vkt::Fence fence(*m_device, create_info); |
| |
| VkSubmitInfo si = vku::InitStructHelper(); |
| vk::QueueSubmit(m_default_queue->handle(), 1, &si, fence); |
| |
| int handle = 0; |
| fence.ExportHandle(handle, handle_type); |
| |
| // create fence and import payload |
| VkExportFenceCreateInfo export_info2 = vku::InitStructHelper(); // prepare to export from imported fence |
| export_info2.handleTypes = export_from_import_handle_type; |
| const VkFenceCreateInfo create_info2 = vku::InitStructHelper(&export_info2); |
| vkt::Fence import_fence(*m_device, create_info2); |
| import_fence.ImportHandle(handle, handle_type, VK_FENCE_IMPORT_TEMPORARY_BIT); |
| |
| // export from imported fence |
| int handle2 = 0; |
| m_errorMonitor->SetDesiredError("VUID-VkFenceGetFdInfoKHR-fence-01455"); |
| import_fence.ExportHandle(handle2, export_from_import_handle_type); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, SyncFdSemaphoreType) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::timelineSemaphore); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| VkPhysicalDeviceExternalSemaphoreInfo external_semahpore_info = vku::InitStructHelper(); |
| external_semahpore_info.handleType = handle_type; |
| |
| VkExternalSemaphoreProperties external_semahpore_props = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalSemaphoreProperties(Gpu(), &external_semahpore_info, &external_semahpore_props); |
| if (!(external_semahpore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) || |
| !(external_semahpore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External semaphore does not support importing and exporting"; |
| } |
| if (!(external_semahpore_props.compatibleHandleTypes & handle_type)) { |
| GTEST_SKIP() << "External semaphore does not support VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT"; |
| } |
| |
| VkExportSemaphoreCreateInfo esci = vku::InitStructHelper(); |
| esci.handleTypes = handle_type; |
| VkSemaphoreTypeCreateInfo stci = vku::InitStructHelper(&esci); |
| stci.semaphoreType = VK_SEMAPHORE_TYPE_BINARY; |
| VkSemaphoreCreateInfo sci = vku::InitStructHelper(&stci); |
| vkt::Semaphore binary_sem(*m_device, sci); |
| |
| VkSubmitInfo si = vku::InitStructHelper(); |
| si.signalSemaphoreCount = 1; |
| si.pSignalSemaphores = &binary_sem.handle(); |
| |
| vk::QueueSubmit(m_default_queue->handle(), 1, &si, VK_NULL_HANDLE); |
| |
| int fd_handle = -1; |
| binary_sem.ExportHandle(fd_handle, handle_type); |
| |
| stci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE; |
| vkt::Semaphore import_semaphore(*m_device, sci); |
| m_errorMonitor->SetDesiredError("VUID-VkImportSemaphoreFdInfoKHR-handleType-03264"); |
| import_semaphore.ImportHandle(fd_handle, handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| m_default_queue->Wait(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, TemporaryFence) { |
| #ifdef VK_USE_PLATFORM_WIN32_KHR |
| const auto extension_name = VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| #else |
| const auto extension_name = VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| #endif |
| AddRequiredExtensions(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME); |
| AddRequiredExtensions(extension_name); |
| RETURN_IF_SKIP(Init()); |
| |
| // Check for external fence import and export capability |
| VkPhysicalDeviceExternalFenceInfo efi = vku::InitStructHelper(); |
| efi.handleType = handle_type; |
| VkExternalFencePropertiesKHR efp = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalFencePropertiesKHR(Gpu(), &efi, &efp); |
| |
| if (!(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) || |
| !(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External fence does not support importing and exporting, skipping test."; |
| } |
| |
| // Create a fence to export payload from |
| VkExportFenceCreateInfo efci = vku::InitStructHelper(); |
| efci.handleTypes = handle_type; |
| VkFenceCreateInfo fci = vku::InitStructHelper(&efci); |
| vkt::Fence export_fence(*m_device, fci); |
| |
| // Create a fence to import payload into |
| fci.pNext = nullptr; |
| vkt::Fence import_fence(*m_device, fci); |
| |
| // Export fence payload to an opaque handle |
| ExternalHandle ext_fence{}; |
| export_fence.ExportHandle(ext_fence, handle_type); |
| import_fence.ImportHandle(ext_fence, handle_type, VK_FENCE_IMPORT_TEMPORARY_BIT); |
| |
| // Undo the temporary import |
| vk::ResetFences(device(), 1, &import_fence.handle()); |
| |
| // Signal the previously imported fence twice, the second signal should produce a validation error |
| vk::QueueSubmit(m_default_queue->handle(), 0, nullptr, import_fence); |
| m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-fence-00064"); |
| vk::QueueSubmit(m_default_queue->handle(), 0, nullptr, import_fence); |
| m_errorMonitor->VerifyFound(); |
| |
| m_default_queue->Wait(); |
| |
| // Signal without reseting |
| m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-fence-00063"); |
| vk::QueueSubmit(m_default_queue->handle(), 0, nullptr, import_fence); |
| m_errorMonitor->VerifyFound(); |
| m_default_queue->Wait(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, Fence) { |
| #ifdef VK_USE_PLATFORM_WIN32_KHR |
| const auto extension_name = VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| const auto other_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; |
| const auto bad_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| const char *bad_export_type_vuid = "VUID-VkFenceGetWin32HandleInfoKHR-handleType-01452"; |
| const char *other_export_type_vuid = "VUID-VkFenceGetWin32HandleInfoKHR-handleType-01448"; |
| const char *bad_import_type_vuid = "VUID-VkImportFenceWin32HandleInfoKHR-handleType-01457"; |
| #else |
| const auto extension_name = VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| const auto other_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; |
| const auto bad_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; |
| const char *bad_export_type_vuid = "VUID-VkFenceGetFdInfoKHR-handleType-01456"; |
| const char *other_export_type_vuid = "VUID-VkFenceGetFdInfoKHR-handleType-01453"; |
| const char *bad_import_type_vuid = "VUID-VkImportFenceFdInfoKHR-handleType-01464"; |
| #endif |
| AddRequiredExtensions(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME); |
| AddRequiredExtensions(extension_name); |
| RETURN_IF_SKIP(Init()); |
| |
| // Check for external fence import and export capability |
| VkPhysicalDeviceExternalFenceInfo efi = vku::InitStructHelper(); |
| efi.handleType = handle_type; |
| VkExternalFencePropertiesKHR efp = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalFencePropertiesKHR(Gpu(), &efi, &efp); |
| |
| if (!(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) || |
| !(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External fence does not support importing and exporting, skipping test."; |
| } |
| |
| // Create a fence to export payload from |
| VkExportFenceCreateInfo efci = vku::InitStructHelper(); |
| efci.handleTypes = handle_type; |
| VkFenceCreateInfo fci = vku::InitStructHelper(&efci); |
| vkt::Fence export_fence(*m_device, fci); |
| |
| // Create a fence to import payload into |
| fci.pNext = nullptr; |
| vkt::Fence import_fence(*m_device, fci); |
| |
| ExternalHandle ext_handle{}; |
| |
| // windows vs unix mismatch |
| m_errorMonitor->SetDesiredError(bad_export_type_vuid); |
| export_fence.ExportHandle(ext_handle, bad_type); |
| m_errorMonitor->VerifyFound(); |
| |
| // a valid type for the platform which we didn't ask for during create |
| m_errorMonitor->SetDesiredError(other_export_type_vuid); |
| if constexpr (other_type == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT) { |
| // SYNC_FD is a special snowflake |
| m_errorMonitor->SetAllowedFailureMsg("VUID-VkFenceGetFdInfoKHR-handleType-01454"); |
| } |
| export_fence.ExportHandle(ext_handle, other_type); |
| m_errorMonitor->VerifyFound(); |
| |
| export_fence.ExportHandle(ext_handle, handle_type); |
| |
| m_errorMonitor->SetDesiredError(bad_import_type_vuid); |
| import_fence.ImportHandle(ext_handle, bad_type); |
| m_errorMonitor->VerifyFound(); |
| #ifdef VK_USE_PLATFORM_WIN32_KHR |
| VkImportFenceWin32HandleInfoKHR ifi = vku::InitStructHelper(); |
| ifi.fence = import_fence; |
| ifi.handleType = handle_type; |
| ifi.handle = ext_handle; |
| ifi.flags = 0; |
| ifi.name = L"something"; |
| |
| // If handleType is not VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT, name must be NULL |
| // However, it looks like at least some windows drivers don't support exporting KMT handles for fences |
| if constexpr (handle_type != VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT) { |
| m_errorMonitor->SetDesiredError("VUID-VkImportFenceWin32HandleInfoKHR-handleType-01459"); |
| } |
| // If handle is not NULL, name must be NULL |
| m_errorMonitor->SetDesiredError("VUID-VkImportFenceWin32HandleInfoKHR-handle-01462"); |
| vk::ImportFenceWin32HandleKHR(device(), &ifi); |
| m_errorMonitor->VerifyFound(); |
| #endif |
| auto err = import_fence.ImportHandle(ext_handle, handle_type); |
| ASSERT_EQ(VK_SUCCESS, err); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, SyncFdFence) { |
| const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; |
| |
| AddRequiredExtensions(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| // Check for external fence import and export capability |
| VkPhysicalDeviceExternalFenceInfo efi = vku::InitStructHelper(); |
| efi.handleType = handle_type; |
| VkExternalFencePropertiesKHR efp = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalFencePropertiesKHR(Gpu(), &efi, &efp); |
| |
| if (!(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) || |
| !(efp.externalFenceFeatures & VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External fence does not support importing and exporting, skipping test."; |
| } |
| |
| // Create a fence to export payload from |
| VkExportFenceCreateInfo efci = vku::InitStructHelper(); |
| efci.handleTypes = handle_type; |
| VkFenceCreateInfo fci = vku::InitStructHelper(&efci); |
| vkt::Fence export_fence(*m_device, fci); |
| |
| // Create a fence to import payload into |
| fci.pNext = nullptr; |
| vkt::Fence import_fence(*m_device, fci); |
| |
| int fd_handle = -1; |
| |
| // SYNC_FD must have a pending signal for export |
| m_errorMonitor->SetDesiredError("VUID-VkFenceGetFdInfoKHR-handleType-01454"); |
| export_fence.ExportHandle(fd_handle, handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::QueueSubmit(m_default_queue->handle(), 0, nullptr, export_fence); |
| |
| export_fence.ExportHandle(fd_handle, handle_type); |
| |
| // must be temporary |
| m_errorMonitor->SetDesiredError("VUID-VkImportFenceFdInfoKHR-handleType-07306"); |
| import_fence.ImportHandle(fd_handle, handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| import_fence.ImportHandle(fd_handle, handle_type, VK_FENCE_IMPORT_TEMPORARY_BIT); |
| |
| import_fence.Wait(1000000000); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, TemporarySemaphore) { |
| #ifdef VK_USE_PLATFORM_WIN32_KHR |
| const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; |
| #else |
| const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| #endif |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(extension_name); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| // Check for external semaphore import and export capability |
| VkPhysicalDeviceExternalSemaphoreInfo esi = vku::InitStructHelper(); |
| esi.handleType = handle_type; |
| |
| VkExternalSemaphorePropertiesKHR esp = vku::InitStructHelper(); |
| |
| vk::GetPhysicalDeviceExternalSemaphorePropertiesKHR(Gpu(), &esi, &esp); |
| |
| if (!(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) || |
| !(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External semaphore does not support importing and exporting, skipping test"; |
| } |
| |
| // Create a semaphore to export payload from |
| VkExportSemaphoreCreateInfo esci = vku::InitStructHelper(); |
| esci.handleTypes = handle_type; |
| VkSemaphoreCreateInfo sci = vku::InitStructHelper(&esci); |
| |
| vkt::Semaphore export_semaphore(*m_device, sci); |
| |
| // Create a semaphore to import payload into |
| sci.pNext = nullptr; |
| vkt::Semaphore import_semaphore(*m_device, sci); |
| |
| ExternalHandle ext_handle{}; |
| export_semaphore.ExportHandle(ext_handle, handle_type); |
| import_semaphore.ImportHandle(ext_handle, handle_type, VK_SEMAPHORE_IMPORT_TEMPORARY_BIT); |
| |
| // Wait on the imported semaphore twice in vk::QueueSubmit, the second wait should be an error |
| VkPipelineStageFlags flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; |
| std::vector<VkSubmitInfo> si(4, vku::InitStruct<VkSubmitInfo>()); |
| si[0].signalSemaphoreCount = 1; |
| si[0].pSignalSemaphores = &export_semaphore.handle(); |
| |
| si[1].waitSemaphoreCount = 1; |
| si[1].pWaitSemaphores = &import_semaphore.handle(); |
| si[1].pWaitDstStageMask = &flags; |
| |
| si[2] = si[0]; |
| si[3] = si[1]; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-pWaitSemaphores-03238"); |
| vk::QueueSubmit(m_default_queue->handle(), si.size(), si.data(), VK_NULL_HANDLE); |
| m_errorMonitor->VerifyFound(); |
| |
| auto index = m_device->graphics_queue_node_index_; |
| if (m_device->Physical().queue_properties_[index].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) { |
| // Wait on the imported semaphore twice in vk::QueueBindSparse, the second wait should be an error |
| std::vector<VkBindSparseInfo> bi(4, vku::InitStruct<VkBindSparseInfo>()); |
| bi[0].signalSemaphoreCount = 1; |
| bi[0].pSignalSemaphores = &export_semaphore.handle(); |
| |
| bi[1].waitSemaphoreCount = 1; |
| bi[1].pWaitSemaphores = &import_semaphore.handle(); |
| |
| bi[2] = bi[0]; |
| bi[3] = bi[1]; |
| m_errorMonitor->SetDesiredError("VUID-vkQueueBindSparse-pWaitSemaphores-03245"); |
| vk::QueueBindSparse(m_default_queue->handle(), bi.size(), bi.data(), VK_NULL_HANDLE); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Cleanup |
| m_default_queue->Wait(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, Semaphore) { |
| TEST_DESCRIPTION("Import and export invalid external semaphores, no queue sumbits involved."); |
| #ifdef VK_USE_PLATFORM_WIN32_KHR |
| const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; |
| const auto bad_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| const auto other_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| const char *bad_export_type_vuid = "VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01131"; |
| const char *other_export_type_vuid = "VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01126"; |
| const char *bad_import_type_vuid = "VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-01140"; |
| #else |
| const auto extension_name = VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; |
| const auto bad_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; |
| const auto other_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; |
| const char *bad_export_type_vuid = "VUID-VkSemaphoreGetFdInfoKHR-handleType-01136"; |
| const char *other_export_type_vuid = "VUID-VkSemaphoreGetFdInfoKHR-handleType-01132"; |
| const char *bad_import_type_vuid = "VUID-VkImportSemaphoreFdInfoKHR-handleType-01143"; |
| #endif |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(extension_name); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| // Check for external semaphore import and export capability |
| VkPhysicalDeviceExternalSemaphoreInfo esi = vku::InitStructHelper(); |
| esi.handleType = handle_type; |
| |
| VkExternalSemaphorePropertiesKHR esp = vku::InitStructHelper(); |
| |
| vk::GetPhysicalDeviceExternalSemaphorePropertiesKHR(Gpu(), &esi, &esp); |
| |
| if (!(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) || |
| !(esp.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External semaphore does not support importing and exporting, skipping test"; |
| } |
| // Create a semaphore to export payload from |
| VkExportSemaphoreCreateInfo esci = vku::InitStructHelper(); |
| esci.handleTypes = handle_type; |
| VkSemaphoreCreateInfo sci = vku::InitStructHelper(&esci); |
| |
| vkt::Semaphore export_semaphore(*m_device, sci); |
| |
| // Create a semaphore for importing |
| vkt::Semaphore import_semaphore(*m_device); |
| |
| ExternalHandle ext_handle{}; |
| |
| // windows vs unix mismatch |
| m_errorMonitor->SetDesiredError(bad_export_type_vuid); |
| export_semaphore.ExportHandle(ext_handle, bad_type); |
| m_errorMonitor->VerifyFound(); |
| |
| // not specified during create |
| if constexpr (other_type == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) { |
| // SYNC_FD must have pending signal |
| m_errorMonitor->SetDesiredError("VUID-VkSemaphoreGetFdInfoKHR-handleType-03254"); |
| } |
| m_errorMonitor->SetDesiredError(other_export_type_vuid); |
| export_semaphore.ExportHandle(ext_handle, other_type); |
| m_errorMonitor->VerifyFound(); |
| |
| export_semaphore.ExportHandle(ext_handle, handle_type); |
| |
| m_errorMonitor->SetDesiredError(bad_import_type_vuid); |
| export_semaphore.ImportHandle(ext_handle, bad_type); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryHandleType) { |
| TEST_DESCRIPTION("Validate import memory handleType for buffers and images"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| #ifdef _WIN32 |
| const auto ext_mem_extension_name = VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| #else |
| const auto ext_mem_extension_name = VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME; |
| const auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| #endif |
| AddRequiredExtensions(ext_mem_extension_name); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "External tests are not supported by MockICD, skipping tests"; |
| } |
| |
| // Check for import/export capability |
| // export used to feed memory to test import |
| VkPhysicalDeviceExternalBufferInfo ebi = vku::InitStructHelper(); |
| ebi.handleType = handle_type; |
| ebi.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; |
| |
| VkExternalBufferPropertiesKHR ebp = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalBufferProperties(Gpu(), &ebi, &ebp); |
| if (!(ebp.externalMemoryProperties.compatibleHandleTypes & handle_type) || |
| !(ebp.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) || |
| !(ebp.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "External buffer does not support importing and exporting, skipping test"; |
| } |
| |
| // Check if dedicated allocation is required |
| const bool buffer_dedicated_allocation = |
| ebp.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT; |
| |
| constexpr VkMemoryPropertyFlags mem_flags = 0; |
| constexpr VkDeviceSize buffer_size = 1024; |
| |
| // Create export and import buffers |
| VkExternalMemoryBufferCreateInfo external_buffer_info = vku::InitStructHelper(); |
| external_buffer_info.handleTypes = handle_type; |
| |
| auto buffer_info = vkt::Buffer::CreateInfo(buffer_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| buffer_info.pNext = &external_buffer_info; |
| vkt::Buffer buffer_export(*m_device, buffer_info, vkt::no_mem); |
| const VkMemoryRequirements buffer_export_reqs = buffer_export.MemoryRequirements(); |
| |
| auto importable_buffer_types = |
| FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT); |
| importable_buffer_types &= ~handle_type; // we need to find a flag that is different from handle_type |
| if (importable_buffer_types == 0) GTEST_SKIP() << "Cannot find two different buffer handle types, skipping test"; |
| auto wrong_buffer_handle_type = |
| static_cast<VkExternalMemoryHandleTypeFlagBits>(1 << MostSignificantBit(importable_buffer_types)); |
| external_buffer_info.handleTypes = wrong_buffer_handle_type; |
| |
| vkt::Buffer buffer_import(*m_device, buffer_info, vkt::no_mem); |
| const VkMemoryRequirements buffer_import_reqs = buffer_import.MemoryRequirements(); |
| assert(buffer_import_reqs.memoryTypeBits != 0); // according to spec at least one bit is set |
| if ((buffer_import_reqs.memoryTypeBits & buffer_export_reqs.memoryTypeBits) == 0) { |
| // required by VU 01743 |
| GTEST_SKIP() << "Cannot find memory type that supports both export and import"; |
| } |
| |
| // Allocation info |
| auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer_export_reqs, mem_flags); |
| |
| // Add export allocation info to pNext chain |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = handle_type; |
| |
| alloc_info.pNext = &export_info; |
| |
| // Add dedicated allocation info to pNext chain if required |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.buffer = buffer_export; |
| |
| if (buffer_dedicated_allocation) { |
| export_info.pNext = &dedicated_info; |
| } |
| |
| // Allocate memory to be exported |
| vkt::DeviceMemory memory_buffer_export(*m_device, alloc_info); |
| |
| // Bind exported memory |
| buffer_export.BindMemory(memory_buffer_export, 0); |
| |
| VkExternalMemoryImageCreateInfo external_image_info = vku::InitStructHelper(); |
| external_image_info.handleTypes = handle_type; |
| |
| VkImageCreateInfo image_info = vku::InitStructHelper(&external_image_info); |
| image_info.extent = {64, 64, 1}; |
| image_info.format = VK_FORMAT_R8G8B8A8_UNORM; |
| image_info.imageType = VK_IMAGE_TYPE_2D; |
| image_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| image_info.samples = VK_SAMPLE_COUNT_1_BIT; |
| image_info.arrayLayers = 1; |
| image_info.mipLevels = 1; |
| |
| vkt::Image image_export(*m_device, image_info, vkt::no_mem); |
| |
| const bool image_dedicated_allocation = HandleTypeNeedsDedicatedAllocation(Gpu(), image_info, handle_type); |
| VkMemoryDedicatedAllocateInfo image_dedicated_info = vku::InitStructHelper(); |
| image_dedicated_info.image = image_export; |
| |
| auto export_memory_info = |
| vku::InitStruct<VkExportMemoryAllocateInfo>(image_dedicated_allocation ? &image_dedicated_info : nullptr); |
| export_memory_info.handleTypes = handle_type; |
| image_export.AllocateAndBindMemory(*m_device, mem_flags, &export_memory_info); |
| |
| auto importable_image_types = |
| FindSupportedExternalMemoryHandleTypes(Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT); |
| importable_image_types &= ~handle_type; // we need to find a flag that is different from handle_type |
| if (importable_image_types == 0) { |
| GTEST_SKIP() << "Cannot find two different image handle types"; |
| } |
| auto wrong_image_handle_type = static_cast<VkExternalMemoryHandleTypeFlagBits>(1 << MostSignificantBit(importable_image_types)); |
| if (wrong_image_handle_type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) { |
| GTEST_SKIP() << "Don't want to use AHB as it has extra restrictions"; |
| } |
| external_image_info.handleTypes = wrong_image_handle_type; |
| |
| vkt::Image image_import(*m_device, image_info, vkt::no_mem); |
| |
| #ifdef _WIN32 |
| // Export memory to handle |
| VkMemoryGetWin32HandleInfoKHR mghi_buffer = {VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR, nullptr, |
| memory_buffer_export.handle(), handle_type}; |
| VkMemoryGetWin32HandleInfoKHR mghi_image = {VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR, nullptr, |
| image_export.Memory().handle(), handle_type}; |
| HANDLE handle_buffer; |
| HANDLE handle_image; |
| ASSERT_EQ(VK_SUCCESS, vk::GetMemoryWin32HandleKHR(device(), &mghi_buffer, &handle_buffer)); |
| ASSERT_EQ(VK_SUCCESS, vk::GetMemoryWin32HandleKHR(device(), &mghi_image, &handle_image)); |
| |
| VkImportMemoryWin32HandleInfoKHR import_info_buffer = {VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, nullptr, |
| handle_type, handle_buffer}; |
| VkImportMemoryWin32HandleInfoKHR import_info_image = {VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, nullptr, |
| handle_type, handle_image}; |
| #else |
| // Export memory to fd |
| VkMemoryGetFdInfoKHR mgfi_buffer = vku::InitStructHelper(); |
| mgfi_buffer.handleType = handle_type; |
| mgfi_buffer.memory = memory_buffer_export; |
| |
| VkMemoryGetFdInfoKHR mgfi_image = vku::InitStructHelper(); |
| mgfi_image.handleType = handle_type; |
| mgfi_image.memory = image_export.Memory(); |
| |
| int fd_buffer; |
| int fd_image; |
| ASSERT_EQ(VK_SUCCESS, vk::GetMemoryFdKHR(device(), &mgfi_buffer, &fd_buffer)); |
| ASSERT_EQ(VK_SUCCESS, vk::GetMemoryFdKHR(device(), &mgfi_image, &fd_image)); |
| |
| VkImportMemoryFdInfoKHR import_info_buffer = vku::InitStructHelper(); |
| import_info_buffer.handleType = handle_type; |
| import_info_buffer.fd = fd_buffer; |
| |
| VkImportMemoryFdInfoKHR import_info_image = vku::InitStructHelper(); |
| import_info_image.handleType = handle_type; |
| import_info_image.fd = fd_image; |
| #endif |
| |
| // Import memory |
| alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer_import_reqs, mem_flags); |
| alloc_info.pNext = &import_info_buffer; |
| if constexpr (handle_type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) { |
| alloc_info.allocationSize = buffer_export_reqs.size; |
| } |
| vkt::DeviceMemory memory_buffer_import(*m_device, alloc_info); |
| ASSERT_TRUE(memory_buffer_import.initialized()); |
| |
| VkMemoryRequirements image_import_reqs = image_import.MemoryRequirements(); |
| if (image_import_reqs.memoryTypeBits == 0) { |
| GTEST_SKIP() << "no suitable memory found, skipping test"; |
| } |
| alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, image_import_reqs, mem_flags); |
| alloc_info.pNext = &import_info_image; |
| if constexpr (handle_type == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) { |
| alloc_info.allocationSize = image_export.MemoryRequirements().size; |
| } |
| vkt::DeviceMemory memory_image_import(*m_device, alloc_info); |
| |
| // Bind imported memory with different handleType |
| m_errorMonitor->SetDesiredError("VUID-vkBindBufferMemory-memory-02985"); |
| vk::BindBufferMemory(device(), buffer_import, memory_buffer_import, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| VkBindBufferMemoryInfo bind_buffer_info = vku::InitStructHelper(); |
| bind_buffer_info.buffer = buffer_import; |
| bind_buffer_info.memory = memory_buffer_import; |
| bind_buffer_info.memoryOffset = 0; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkBindBufferMemoryInfo-memory-02985"); |
| vk::BindBufferMemory2(device(), 1, &bind_buffer_info); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-memory-02989"); |
| m_errorMonitor->SetUnexpectedError("VUID-VkBindImageMemoryInfo-pNext-01617"); |
| m_errorMonitor->SetUnexpectedError("VUID-VkBindImageMemoryInfo-pNext-01615"); |
| if (image_dedicated_allocation) { |
| m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-image-01445"); |
| } |
| vk::BindImageMemory(device(), image_import, memory_image_import, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| VkBindImageMemoryInfo bind_image_info = vku::InitStructHelper(); |
| bind_image_info.image = image_import; |
| bind_image_info.memory = memory_image_import; |
| bind_image_info.memoryOffset = 0; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkBindImageMemoryInfo-memory-02989"); |
| m_errorMonitor->SetUnexpectedError("VUID-VkBindImageMemoryInfo-pNext-01617"); |
| m_errorMonitor->SetUnexpectedError("VUID-VkBindImageMemoryInfo-pNext-01615"); |
| if (image_dedicated_allocation) { |
| m_errorMonitor->SetDesiredError("VUID-VkBindImageMemoryInfo-image-01445"); |
| } |
| vk::BindImageMemory2(device(), 1, &bind_image_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, FenceExportWithUnsupportedHandleType) { |
| TEST_DESCRIPTION("Create fence with unsupported external handle type in VkExportFenceCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| const auto exportable_types = FindSupportedExternalFenceHandleTypes(Gpu(), VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT); |
| if (!exportable_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| if (exportable_types == AllVkExternalFenceHandleTypeFlagBits) { |
| GTEST_SKIP() << "This test requires at least one unsupported handle type, but all handle types are supported"; |
| } |
| // Fence export with unsupported handle type |
| const auto unsupported_type = LeastSignificantFlag<VkExternalFenceHandleTypeFlagBits>(~exportable_types); |
| VkExportFenceCreateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = unsupported_type; |
| |
| const VkFenceCreateInfo create_info = vku::InitStructHelper(&export_info); |
| VkFence fence = VK_NULL_HANDLE; |
| m_errorMonitor->SetDesiredError("VUID-VkExportFenceCreateInfo-handleTypes-01446"); |
| vk::CreateFence(device(), &create_info, nullptr, &fence); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, FenceExportWithIncompatibleHandleType) { |
| TEST_DESCRIPTION("Create fence with incompatible external handle types in VkExportFenceCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| const auto exportable_types = FindSupportedExternalFenceHandleTypes(Gpu(), VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT); |
| if (!exportable_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalFenceHandleTypeFlagBits>(exportable_types); |
| const auto compatible_types = GetCompatibleHandleTypes(Gpu(), handle_type); |
| if ((exportable_types & compatible_types) == exportable_types) { |
| GTEST_SKIP() << "Cannot find handle types that are supported but not compatible with each other"; |
| } |
| |
| // Fence export with incompatible handle types |
| VkExportFenceCreateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = exportable_types; |
| |
| const VkFenceCreateInfo create_info = vku::InitStructHelper(&export_info); |
| VkFence fence = VK_NULL_HANDLE; |
| m_errorMonitor->SetDesiredError("VUID-VkExportFenceCreateInfo-handleTypes-01446"); |
| vk::CreateFence(device(), &create_info, nullptr, &fence); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, SemaphoreExportWithUnsupportedHandleType) { |
| TEST_DESCRIPTION("Create semaphore with unsupported external handle type in VkExportSemaphoreCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| const auto exportable_types = FindSupportedExternalSemaphoreHandleTypes(Gpu(), VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT); |
| if (!exportable_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| if (exportable_types == AllVkExternalSemaphoreHandleTypeFlagBits) { |
| GTEST_SKIP() << "This test requires at least one unsupported handle type, but all handle types are supported"; |
| } |
| // Semaphore export with unsupported handle type |
| const auto unsupported_type = LeastSignificantFlag<VkExternalSemaphoreHandleTypeFlagBits>(~exportable_types); |
| VkExportSemaphoreCreateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = unsupported_type; |
| |
| const VkSemaphoreCreateInfo create_info = vku::InitStructHelper(&export_info); |
| VkSemaphore semaphore = VK_NULL_HANDLE; |
| m_errorMonitor->SetDesiredError("VUID-VkExportSemaphoreCreateInfo-handleTypes-01124"); |
| vk::CreateSemaphore(device(), &create_info, nullptr, &semaphore); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, SemaphoreExportWithIncompatibleHandleType) { |
| TEST_DESCRIPTION("Create semaphore with incompatible external handle types in VkExportSemaphoreCreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| const auto exportable_types = FindSupportedExternalSemaphoreHandleTypes(Gpu(), VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT); |
| if (!exportable_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalSemaphoreHandleTypeFlagBits>(exportable_types); |
| const auto compatible_types = GetCompatibleHandleTypes(Gpu(), handle_type); |
| if ((exportable_types & compatible_types) == exportable_types) { |
| GTEST_SKIP() << "Cannot find handle types that are supported but not compatible with each other"; |
| } |
| |
| // Semaphore export with incompatible handle types |
| VkExportSemaphoreCreateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = exportable_types; |
| |
| const VkSemaphoreCreateInfo create_info = vku::InitStructHelper(&export_info); |
| VkSemaphore semaphore = VK_NULL_HANDLE; |
| m_errorMonitor->SetDesiredError("VUID-VkExportSemaphoreCreateInfo-handleTypes-01124"); |
| vk::CreateSemaphore(device(), &create_info, nullptr, &semaphore); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, MemoryAndMemoryNV) { |
| TEST_DESCRIPTION("Test for both external memory and external memory NV in image create pNext chain."); |
| |
| AddRequiredExtensions(VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| VkExternalMemoryImageCreateInfoNV external_mem_nv = vku::InitStructHelper(); |
| VkExternalMemoryImageCreateInfo external_mem = vku::InitStructHelper(&external_mem_nv); |
| VkImageCreateInfo ici = vku::InitStructHelper(&external_mem); |
| ici.imageType = VK_IMAGE_TYPE_2D; |
| ici.arrayLayers = 1; |
| ici.extent = {64, 64, 1}; |
| ici.format = VK_FORMAT_R8G8B8A8_UNORM; |
| ici.mipLevels = 1; |
| ici.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| ici.samples = VK_SAMPLE_COUNT_1_BIT; |
| ici.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| |
| const auto supported_types_nv = |
| FindSupportedExternalMemoryHandleTypesNV(Gpu(), ici, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV); |
| const auto supported_types = FindSupportedExternalMemoryHandleTypes(Gpu(), ici, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT); |
| if (!supported_types_nv || !supported_types) { |
| GTEST_SKIP() << "Cannot find one regular handle type and one nvidia extension's handle type"; |
| } |
| external_mem_nv.handleTypes = LeastSignificantFlag<VkExternalMemoryFeatureFlagBitsNV>(supported_types_nv); |
| external_mem.handleTypes = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(supported_types); |
| CreateImageTest(ici, "VUID-VkImageCreateInfo-pNext-00988"); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, MemoryImageLayout) { |
| TEST_DESCRIPTION("Validate layout of image with external memory"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddOptionalExtensions(VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| VkExternalMemoryImageCreateInfo external_mem = vku::InitStructHelper(); |
| VkImageCreateInfo ici = vku::InitStructHelper(&external_mem); |
| ici.imageType = VK_IMAGE_TYPE_2D; |
| ici.arrayLayers = 1; |
| ici.extent = {32, 32, 1}; |
| ici.format = VK_FORMAT_R8G8B8A8_UNORM; |
| ici.mipLevels = 1; |
| ici.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; |
| ici.samples = VK_SAMPLE_COUNT_1_BIT; |
| ici.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| |
| const auto supported_types = FindSupportedExternalMemoryHandleTypes(Gpu(), ici, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT); |
| if (supported_types) { |
| external_mem.handleTypes = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(supported_types); |
| CreateImageTest(ici, "VUID-VkImageCreateInfo-pNext-01443"); |
| } |
| if (IsExtensionsEnabled(VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME)) { |
| VkExternalMemoryImageCreateInfoNV external_mem_nv = vku::InitStructHelper(); |
| const auto supported_types_nv = |
| FindSupportedExternalMemoryHandleTypesNV(Gpu(), ici, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV); |
| if (supported_types_nv) { |
| external_mem_nv.handleTypes = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBitsNV>(supported_types_nv); |
| ici.pNext = &external_mem_nv; |
| CreateImageTest(ici, "VUID-VkImageCreateInfo-pNext-01443"); |
| } |
| } |
| } |
| |
| #ifdef VK_USE_PLATFORM_WIN32_KHR |
| TEST_F(NegativeExternalMemorySync, D3D12FenceSubmitInfo) { |
| TEST_DESCRIPTION("Test invalid D3D12FenceSubmitInfo"); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| vkt::Semaphore semaphore(*m_device); |
| |
| // VkD3D12FenceSubmitInfoKHR::waitSemaphoreValuesCount == 1 is different from VkSubmitInfo::waitSemaphoreCount == 0 |
| { |
| const uint64_t waitSemaphoreValues = 0; |
| VkD3D12FenceSubmitInfoKHR d3d12_fence_submit_info = vku::InitStructHelper(); |
| d3d12_fence_submit_info.waitSemaphoreValuesCount = 1; |
| d3d12_fence_submit_info.pWaitSemaphoreValues = &waitSemaphoreValues; |
| const VkSubmitInfo submit_info = vku::InitStructHelper(&d3d12_fence_submit_info); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkD3D12FenceSubmitInfoKHR-waitSemaphoreValuesCount-00079"); |
| vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE); |
| m_errorMonitor->VerifyFound(); |
| } |
| // VkD3D12FenceSubmitInfoKHR::signalSemaphoreCount == 0 is different from VkSubmitInfo::signalSemaphoreCount == 1 |
| { |
| VkD3D12FenceSubmitInfoKHR d3d12_fence_submit_info = vku::InitStructHelper(); |
| VkSubmitInfo submit_info = vku::InitStructHelper(&d3d12_fence_submit_info); |
| submit_info.signalSemaphoreCount = 1; |
| submit_info.pSignalSemaphores = &semaphore.handle(); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkD3D12FenceSubmitInfoKHR-signalSemaphoreValuesCount-00080"); |
| vk::QueueSubmit(m_default_queue->handle(), 1, &submit_info, VK_NULL_HANDLE); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| #endif // VK_USE_PLATFORM_WIN32_KHR |
| |
| TEST_F(NegativeExternalMemorySync, GetMemoryFdHandle) { |
| TEST_DESCRIPTION("Validate VkMemoryGetFdInfoKHR passed to vkGetMemoryFdKHR"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| int fd = -1; |
| |
| // Allocate memory without VkExportMemoryAllocateInfo in the pNext chain |
| { |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(); |
| alloc_info.allocationSize = 32; |
| alloc_info.memoryTypeIndex = 0; |
| vkt::DeviceMemory memory(*m_device, alloc_info); |
| |
| VkMemoryGetFdInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory; |
| get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryGetFdInfoKHR-handleType-00671"); |
| vk::GetMemoryFdKHR(*m_device, &get_handle_info, &fd); |
| m_errorMonitor->VerifyFound(); |
| } |
| // VkExportMemoryAllocateInfo::handleTypes does not include requested handle type |
| { |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = 0; |
| |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&export_info); |
| alloc_info.allocationSize = 1024; |
| alloc_info.memoryTypeIndex = 0; |
| vkt::DeviceMemory memory(*m_device, alloc_info); |
| |
| VkMemoryGetFdInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory; |
| get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryGetFdInfoKHR-handleType-00671"); |
| vk::GetMemoryFdKHR(*m_device, &get_handle_info, &fd); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Request handle of the wrong type |
| { |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; |
| |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&export_info); |
| alloc_info.allocationSize = 1024; |
| alloc_info.memoryTypeIndex = 0; |
| |
| vkt::DeviceMemory memory(*m_device, alloc_info); |
| VkMemoryGetFdInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory; |
| get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryGetFdInfoKHR-handleType-00672"); |
| vk::GetMemoryFdKHR(*m_device, &get_handle_info, &fd); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryFromFdHandle) { |
| TEST_DESCRIPTION("POSIX fd handle memory import. Import parameters do not match payload's parameters"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "External tests are not supported by MockICD, skipping tests"; |
| } |
| constexpr auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| VkExternalMemoryFeatureFlags external_features = 0; |
| { |
| constexpr auto required_features = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; |
| VkPhysicalDeviceExternalBufferInfo external_info = vku::InitStructHelper(); |
| external_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; |
| external_info.handleType = handle_type; |
| VkExternalBufferProperties external_properties = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalBufferProperties(Gpu(), &external_info, &external_properties); |
| external_features = external_properties.externalMemoryProperties.externalMemoryFeatures; |
| if ((external_features & required_features) != required_features) { |
| GTEST_SKIP() << "External buffer does not support both export and import, skipping test"; |
| } |
| } |
| |
| vkt::Buffer buffer; |
| { |
| VkExternalMemoryBufferCreateInfo external_info = vku::InitStructHelper(); |
| external_info.handleTypes = handle_type; |
| auto create_info = vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| create_info.pNext = &external_info; |
| buffer.InitNoMemory(*m_device, create_info); |
| } |
| |
| vkt::DeviceMemory memory; |
| VkDeviceSize payload_size = 0; |
| uint32_t payload_memory_type = 0; |
| { |
| const bool dedicated_allocation = (external_features & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0; |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.buffer = buffer; |
| auto export_info = vku::InitStruct<VkExportMemoryAllocateInfo>(dedicated_allocation ? &dedicated_info : nullptr); |
| export_info.handleTypes = handle_type; |
| auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &export_info); |
| memory.Init(*m_device, alloc_info); |
| buffer.BindMemory(memory, 0); |
| payload_size = alloc_info.allocationSize; |
| payload_memory_type = alloc_info.memoryTypeIndex; |
| } |
| |
| int fd = -1; |
| { |
| VkMemoryGetFdInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory; |
| get_handle_info.handleType = handle_type; |
| ASSERT_EQ(VK_SUCCESS, vk::GetMemoryFdKHR(*m_device, &get_handle_info, &fd)); |
| } |
| VkImportMemoryFdInfoKHR import_info = vku::InitStructHelper(); |
| import_info.handleType = handle_type; |
| import_info.fd = fd; |
| VkMemoryAllocateInfo alloc_info_with_import = vku::InitStructHelper(&import_info); |
| VkDeviceMemory imported_memory = VK_NULL_HANDLE; |
| |
| // allocationSize != payload's allocationSize |
| { |
| alloc_info_with_import.allocationSize = payload_size * 2; |
| alloc_info_with_import.memoryTypeIndex = payload_memory_type; |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-allocationSize-01742"); |
| vk::AllocateMemory(*m_device, &alloc_info_with_import, nullptr, &imported_memory); |
| m_errorMonitor->VerifyFound(); |
| } |
| // memoryTypeIndex != payload's memoryTypeIndex |
| { |
| alloc_info_with_import.allocationSize = payload_size; |
| alloc_info_with_import.memoryTypeIndex = payload_memory_type + 1; |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-allocationSize-01742"); |
| // If device only has 1 memory type |
| m_errorMonitor->SetUnexpectedError("VUID-vkAllocateMemory-pAllocateInfo-01714"); |
| vk::AllocateMemory(*m_device, &alloc_info_with_import, nullptr, &imported_memory); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Finish this test with a successful import operation in order to release the ownership of the file descriptor. |
| // The alternative is to use 'close' system call. |
| { |
| alloc_info_with_import.allocationSize = payload_size; |
| alloc_info_with_import.memoryTypeIndex = payload_memory_type; |
| vkt::DeviceMemory successfully_imported_memory(*m_device, alloc_info_with_import); |
| } |
| } |
| |
| #ifdef VK_USE_PLATFORM_WIN32_KHR |
| TEST_F(NegativeExternalMemorySync, GetMemoryWin32Handle) { |
| TEST_DESCRIPTION("Validate VkMemoryGetWin32HandleInfoKHR passed to vkGetMemoryWin32HandleKHR"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| HANDLE handle = NULL; |
| |
| // Allocate memory without VkExportMemoryAllocateInfo in the pNext chain |
| { |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(); |
| alloc_info.allocationSize = 32; |
| alloc_info.memoryTypeIndex = 0; |
| vkt::DeviceMemory memory(*m_device, alloc_info); |
| |
| VkMemoryGetWin32HandleInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory; |
| get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00662"); |
| vk::GetMemoryWin32HandleKHR(*m_device, &get_handle_info, &handle); |
| m_errorMonitor->VerifyFound(); |
| } |
| // VkExportMemoryAllocateInfo::handleTypes does not include requested handle type |
| { |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = 0; |
| |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&export_info); |
| alloc_info.allocationSize = 1024; |
| alloc_info.memoryTypeIndex = 0; |
| vkt::DeviceMemory memory(*m_device, alloc_info); |
| |
| VkMemoryGetWin32HandleInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory; |
| get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00662"); |
| vk::GetMemoryWin32HandleKHR(*m_device, &get_handle_info, &handle); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Request handle of the wrong type |
| { |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&export_info); |
| alloc_info.allocationSize = 1024; |
| alloc_info.memoryTypeIndex = 0; |
| |
| vkt::DeviceMemory memory(*m_device, alloc_info); |
| VkMemoryGetWin32HandleInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory; |
| get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00664"); |
| vk::GetMemoryWin32HandleKHR(*m_device, &get_handle_info, &handle); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryFromWin32Handle) { |
| TEST_DESCRIPTION("Win32 handle memory import. Import parameters do not match payload's parameters"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| constexpr auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| |
| VkExternalMemoryFeatureFlags external_features = 0; |
| { |
| constexpr auto required_features = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; |
| VkPhysicalDeviceExternalImageFormatInfo external_info = vku::InitStructHelper(); |
| external_info.handleType = handle_type; |
| VkPhysicalDeviceImageFormatInfo2 image_info = vku::InitStructHelper(&external_info); |
| image_info.format = VK_FORMAT_R8G8B8A8_UNORM; |
| image_info.type = VK_IMAGE_TYPE_2D; |
| image_info.tiling = VK_IMAGE_TILING_OPTIMAL; |
| image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| VkExternalImageFormatProperties external_properties = vku::InitStructHelper(); |
| VkImageFormatProperties2 image_properties = vku::InitStructHelper(&external_properties); |
| const VkResult result = vk::GetPhysicalDeviceImageFormatProperties2(Gpu(), &image_info, &image_properties); |
| external_features = external_properties.externalMemoryProperties.externalMemoryFeatures; |
| if (result != VK_SUCCESS || (external_features & required_features) != required_features) { |
| GTEST_SKIP() << "External image does not support both export and import, skipping test"; |
| } |
| } |
| |
| vkt::Image image; |
| { |
| VkExternalMemoryImageCreateInfo external_info = vku::InitStructHelper(); |
| external_info.handleTypes = handle_type; |
| auto create_info = vkt::Image::ImageCreateInfo2D(1, 1, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); |
| create_info.pNext = &external_info; |
| image.InitNoMemory(*m_device, create_info); |
| } |
| |
| vkt::DeviceMemory memory; |
| VkDeviceSize payload_size = 0; |
| uint32_t payload_memory_type = 0; |
| { |
| const bool dedicated_allocation = (external_features & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0; |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.image = image; |
| auto export_info = vku::InitStruct<VkExportMemoryAllocateInfo>(dedicated_allocation ? &dedicated_info : nullptr); |
| export_info.handleTypes = handle_type; |
| auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, image.MemoryRequirements(), 0, &export_info); |
| memory.Init(*m_device, alloc_info); |
| image.BindMemory(memory, 0); |
| payload_size = alloc_info.allocationSize; |
| payload_memory_type = alloc_info.memoryTypeIndex; |
| } |
| |
| HANDLE handle = NULL; |
| { |
| VkMemoryGetWin32HandleInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory; |
| get_handle_info.handleType = handle_type; |
| ASSERT_EQ(VK_SUCCESS, vk::GetMemoryWin32HandleKHR(*m_device, &get_handle_info, &handle)); |
| } |
| VkImportMemoryWin32HandleInfoKHR import_info = vku::InitStructHelper(); |
| import_info.handleType = handle_type; |
| import_info.handle = handle; |
| VkMemoryAllocateInfo alloc_info_with_import = vku::InitStructHelper(&import_info); |
| VkDeviceMemory imported_memory = VK_NULL_HANDLE; |
| |
| // allocationSize != payload's allocationSize |
| { |
| alloc_info_with_import.allocationSize = payload_size * 2; |
| alloc_info_with_import.memoryTypeIndex = payload_memory_type; |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-allocationSize-01743"); |
| vk::AllocateMemory(*m_device, &alloc_info_with_import, nullptr, &imported_memory); |
| m_errorMonitor->VerifyFound(); |
| } |
| // memoryTypeIndex != payload's memoryTypeIndex |
| { |
| alloc_info_with_import.allocationSize = payload_size; |
| alloc_info_with_import.memoryTypeIndex = payload_memory_type + 1; |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-allocationSize-01743"); |
| vk::AllocateMemory(*m_device, &alloc_info_with_import, nullptr, &imported_memory); |
| m_errorMonitor->VerifyFound(); |
| } |
| // Importing memory object payloads from Windows handles does not transfer ownership of the handle to the driver. |
| // For NT handle types, the application must release handle ownership using the CloseHandle system call. |
| // That's in contrast with the POSIX file descriptor handles, where memory import operation transfers the ownership, |
| // so the application does not need to call 'close' system call. |
| ::CloseHandle(handle); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, Win32ExportFromImportedSemaphore) { |
| TEST_DESCRIPTION("Export from semaphore with imported payload that does not support export"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| const auto handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| { |
| const auto handle_types = FindSupportedExternalSemaphoreHandleTypes( |
| Gpu(), VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT); |
| if ((handle_types & handle_type) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT is not both exportable and importable"; |
| } |
| } |
| const auto export_from_import_handle_type = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; |
| { |
| const auto handle_types = FindSupportedExternalSemaphoreHandleTypes(Gpu(), VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT); |
| if ((handle_types & export_from_import_handle_type) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT is not exportable"; |
| } |
| } |
| VkPhysicalDeviceExternalSemaphoreInfo semaphore_info = vku::InitStructHelper(); |
| semaphore_info.handleType = export_from_import_handle_type; |
| VkExternalSemaphoreProperties semaphore_properties = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalSemaphoreProperties(Gpu(), &semaphore_info, &semaphore_properties); |
| if ((handle_type & semaphore_properties.exportFromImportedHandleTypes) != 0) { |
| GTEST_SKIP() << "cannot find handle type that does not support export from imported semaphore"; |
| } |
| |
| // create semaphore and export payload |
| VkExportSemaphoreCreateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = handle_type; |
| const VkSemaphoreCreateInfo create_info = vku::InitStructHelper(&export_info); |
| vkt::Semaphore semaphore(*m_device, create_info); |
| HANDLE handle = NULL; |
| semaphore.ExportHandle(handle, handle_type); |
| |
| // create semaphore and import payload |
| VkExportSemaphoreCreateInfo export_info2 = vku::InitStructHelper(); // prepare to export from imported semaphore |
| export_info2.handleTypes = export_from_import_handle_type; |
| const VkSemaphoreCreateInfo create_info2 = vku::InitStructHelper(&export_info2); |
| vkt::Semaphore import_semaphore(*m_device, create_info2); |
| import_semaphore.ImportHandle(handle, handle_type); |
| |
| // export from imported semaphore |
| HANDLE handle2 = NULL; |
| m_errorMonitor->SetDesiredError("VUID-VkSemaphoreGetWin32HandleInfoKHR-semaphore-01128"); |
| import_semaphore.ExportHandle(handle2, export_from_import_handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| ::CloseHandle(handle); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, Win32ExportFromImportedFence) { |
| TEST_DESCRIPTION("Export from fence with imported payload that does not support export"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| const auto handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| { |
| const auto handle_types = FindSupportedExternalFenceHandleTypes( |
| Gpu(), VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT); |
| if ((handle_types & VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT is not both exportable and importable"; |
| } |
| } |
| const auto export_from_import_handle_type = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; |
| { |
| const auto handle_types = FindSupportedExternalFenceHandleTypes(Gpu(), VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT); |
| if ((handle_types & export_from_import_handle_type) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT is not exportable"; |
| } |
| } |
| VkPhysicalDeviceExternalFenceInfo fence_info = vku::InitStructHelper(); |
| fence_info.handleType = export_from_import_handle_type; |
| VkExternalFenceProperties fence_properties = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalFenceProperties(Gpu(), &fence_info, &fence_properties); |
| if ((handle_type & fence_properties.exportFromImportedHandleTypes) != 0) { |
| GTEST_SKIP() << "cannot find handle type that does not support export from imported fence"; |
| } |
| |
| // create fence and export payload |
| VkExportFenceCreateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = handle_type; // at first export handle type, then import it |
| const VkFenceCreateInfo create_info = vku::InitStructHelper(&export_info); |
| vkt::Fence fence(*m_device, create_info); |
| HANDLE handle = NULL; |
| fence.ExportHandle(handle, handle_type); |
| |
| // create fence and import payload |
| VkExportFenceCreateInfo export_info2 = vku::InitStructHelper(); // prepare to export from imported fence |
| export_info2.handleTypes = export_from_import_handle_type; |
| const VkFenceCreateInfo create_info2 = vku::InitStructHelper(&export_info2); |
| vkt::Fence import_fence(*m_device, create_info2); |
| import_fence.ImportHandle(handle, handle_type); |
| |
| // export from imported fence |
| HANDLE handle2 = NULL; |
| m_errorMonitor->SetDesiredError("VUID-VkFenceGetWin32HandleInfoKHR-fence-01450"); |
| import_fence.ExportHandle(handle2, export_from_import_handle_type); |
| m_errorMonitor->VerifyFound(); |
| |
| ::CloseHandle(handle); |
| } |
| #endif |
| |
| TEST_F(NegativeExternalMemorySync, BufferDedicatedAllocation) { |
| TEST_DESCRIPTION("Bind external buffer that requires dedicated allocation to non-dedicated memory."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| 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_dedicated_types = FindSupportedExternalMemoryHandleTypes( |
| Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT); |
| if (!exportable_dedicated_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type that requires dedicated allocation"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_dedicated_types); |
| |
| VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(); |
| export_memory_info.handleTypes = handle_type; |
| external_buffer_info.handleTypes = handle_type; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-00639"); |
| // pNext chain contains VkExportMemoryAllocateInfo but not VkMemoryDedicatedAllocateInfo |
| vkt::Buffer buffer(*m_device, buffer_info, 0, &export_memory_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImageDedicatedAllocation) { |
| TEST_DESCRIPTION("Bind external image that requires dedicated allocation to non-dedicated memory."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| 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_dedicated_types = FindSupportedExternalMemoryHandleTypes( |
| Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT); |
| // This test does not support the AHB handle type, which does not |
| // allow to query memory requirements before memory is bound |
| exportable_dedicated_types &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; |
| if (!exportable_dedicated_types) { |
| GTEST_SKIP() << "Unable to find exportable handle type that requires dedicated allocation"; |
| } |
| const auto handle_type = LeastSignificantFlag<VkExternalMemoryHandleTypeFlagBits>(exportable_dedicated_types); |
| |
| VkExportMemoryAllocateInfo export_memory_info = vku::InitStructHelper(); |
| export_memory_info.handleTypes = handle_type; |
| external_image_info.handleTypes = handle_type; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-00639"); |
| // pNext chain contains VkExportMemoryAllocateInfo but not VkMemoryDedicatedAllocateInfo |
| vkt::Image image; |
| image.InitNoMemory(*m_device, image_info); |
| { |
| VkImageMemoryRequirementsInfo2 image_memory_requirements_info = vku::InitStructHelper(); |
| image_memory_requirements_info.image = image; |
| VkMemoryDedicatedRequirements memory_dedicated_requirements = vku::InitStructHelper(); |
| |
| VkMemoryRequirements2 memory_requirements = vku::InitStructHelper(&memory_dedicated_requirements); |
| vk::GetImageMemoryRequirements2(device(), &image_memory_requirements_info, &memory_requirements); |
| |
| if (memory_dedicated_requirements.requiresDedicatedAllocation) { |
| m_errorMonitor->SetDesiredError("VUID-vkBindImageMemory-image-01445"); |
| } |
| } |
| image.AllocateAndBindMemory(*m_device, 0, &export_memory_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| #ifdef VK_USE_PLATFORM_WIN32_KHR |
| TEST_F(NegativeExternalMemorySync, Win32MemoryHandleProperties) { |
| TEST_DESCRIPTION("Call vkGetMemoryWin32HandlePropertiesKHR with invalid Win32 handle or with opaque handle type"); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| constexpr auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; |
| constexpr auto opaque_handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| |
| // Generally, which value is considered invalid depends on the specific Win32 function. |
| // VVL assumes that both these values do not represent a valid handle. |
| constexpr HANDLE invalid_win32_handle = NULL; |
| const HANDLE less_common_invalid_win32_handle = INVALID_HANDLE_VALUE; |
| |
| const HANDLE handle_that_passes_validation = (HANDLE)0x12345678; |
| |
| VkMemoryWin32HandlePropertiesKHR properties = vku::InitStructHelper(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkGetMemoryWin32HandlePropertiesKHR-handle-00665"); |
| vk::GetMemoryWin32HandlePropertiesKHR(*m_device, handle_type, invalid_win32_handle, &properties); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkGetMemoryWin32HandlePropertiesKHR-handle-00665"); |
| vk::GetMemoryWin32HandlePropertiesKHR(*m_device, handle_type, less_common_invalid_win32_handle, &properties); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkGetMemoryWin32HandlePropertiesKHR-handleType-00666"); |
| vk::GetMemoryWin32HandlePropertiesKHR(*m_device, opaque_handle_type, handle_that_passes_validation, &properties); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryWin32ImageNoDedicated) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| auto image_info = vkt::Image::ImageCreateInfo2D(64, 64, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); |
| |
| const auto handle_types = FindSupportedExternalMemoryHandleTypes( |
| Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT); |
| if ((handle_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT is not both exportable and importable"; |
| } |
| |
| VkExternalMemoryImageCreateInfo external_image_info = vku::InitStructHelper(); |
| external_image_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| image_info.pNext = &external_image_info; |
| |
| vkt::Image image(*m_device, image_info, vkt::no_mem); |
| |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, image.MemoryRequirements(), 0, &export_info); |
| |
| vkt::DeviceMemory memory_export(*m_device, alloc_info); |
| |
| VkMemoryGetWin32HandleInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory_export; |
| get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| |
| HANDLE handle = NULL; |
| vk::GetMemoryWin32HandleKHR(device(), &get_handle_info, &handle); |
| |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.image = image; |
| |
| VkImportMemoryWin32HandleInfoKHR import_info = vku::InitStructHelper(&dedicated_info); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| import_info.handle = handle; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-image-01876"); |
| alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, image.MemoryRequirements(), 0, &import_info); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| |
| // "For handle types defined as NT handles, the handles returned by vkGetFenceWin32HandleKHR are owned by the application. To |
| // avoid leaking resources, the application must release ownership of them using the CloseHandle system call when they are no |
| // longer needed." |
| ::CloseHandle(handle); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryWin32BufferDifferentDedicated) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| auto buffer_info = vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| const auto handle_types = FindSupportedExternalMemoryHandleTypes( |
| Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT); |
| if ((handle_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT) == 0) { |
| GTEST_SKIP() << "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT is not both exportable and importable"; |
| } |
| |
| VkExternalMemoryBufferCreateInfo external_buffer_info = vku::InitStructHelper(); |
| external_buffer_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| buffer_info.pNext = &external_buffer_info; |
| |
| vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem); |
| |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.buffer = buffer; |
| |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(&dedicated_info); |
| export_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &export_info); |
| |
| vkt::DeviceMemory memory_export(*m_device, alloc_info); |
| |
| VkMemoryGetWin32HandleInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory_export; |
| get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| |
| HANDLE handle = NULL; |
| vk::GetMemoryWin32HandleKHR(device(), &get_handle_info, &handle); |
| |
| buffer_info.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; |
| vkt::Buffer buffer2(*m_device, buffer_info, vkt::no_mem); |
| dedicated_info.buffer = buffer2; |
| |
| VkImportMemoryWin32HandleInfoKHR import_info = vku::InitStructHelper(&dedicated_info); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| import_info.handle = handle; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-buffer-01877"); |
| alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer2.MemoryRequirements(), 0, &import_info); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| |
| // "For handle types defined as NT handles, the handles returned by vkGetFenceWin32HandleKHR are owned by the application. To |
| // avoid leaking resources, the application must release ownership of them using the CloseHandle system call when they are no |
| // longer needed." |
| ::CloseHandle(handle); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryWin32BufferSupport) { |
| TEST_DESCRIPTION("Memory imported from handle type that is not reported as importable by VkExternalBufferProperties."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| constexpr auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; |
| auto buffer_ci = vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| |
| VkPhysicalDeviceExternalBufferInfo external_info = vku::InitStructHelper(); |
| external_info.flags = buffer_ci.flags; |
| external_info.usage = buffer_ci.usage; |
| external_info.handleType = handle_type; |
| VkExternalBufferProperties external_properties = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceExternalBufferProperties(Gpu(), &external_info, &external_properties); |
| |
| if ((external_properties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0) { |
| GTEST_SKIP() << "Need buffer with no import support"; |
| } |
| |
| // allocate memory and export payload as win32 handle |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = handle_type; |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&export_info); |
| alloc_info.allocationSize = 4096; |
| alloc_info.memoryTypeIndex = 0; |
| vkt::DeviceMemory memory(*m_device, alloc_info); |
| |
| HANDLE handle = NULL; |
| VkMemoryGetWin32HandleInfoKHR get_handle_info = vku::InitStructHelper(); |
| get_handle_info.memory = memory; |
| get_handle_info.handleType = handle_type; |
| vk::GetMemoryWin32HandleKHR(*m_device, &get_handle_info, &handle); |
| |
| // create memory object by importing payload through win32 handle |
| VkImportMemoryWin32HandleInfoKHR import_info = vku::InitStructHelper(); |
| import_info.handleType = handle_type; |
| import_info.handle = handle; |
| VkMemoryAllocateInfo alloc_info_with_import = vku::InitStructHelper(&import_info); |
| alloc_info_with_import.allocationSize = 4096; |
| alloc_info_with_import.memoryTypeIndex = 0; |
| vkt::DeviceMemory imported_memory(*m_device, alloc_info_with_import); |
| |
| VkExternalMemoryBufferCreateInfo external_buffer_info = vku::InitStructHelper(); |
| external_buffer_info.handleTypes = handle_type; |
| buffer_ci.pNext = &external_buffer_info; |
| |
| // It's hard to get configuration with current Windows drivers for this test. |
| // Protected memory feature is not supported that is used on Linux to get non-importable memory. |
| // D3D11_TEXTURE handle type does job that is does not report import capability but |
| // also it's not supported for this usage, so disable that error message and sacrifice some |
| // correctness with a purpose to reach code path we need to test. |
| // NOTE: the approach with D3D11_TEXTURE does not work for images, that's why no similar test for images |
| m_errorMonitor->SetUnexpectedError("VUID-VkBufferCreateInfo-pNext-00920"); |
| vkt::Buffer buffer(*m_device, buffer_ci, vkt::no_mem); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkImportMemoryWin32HandleInfoKHR-handleType-09861"); |
| buffer.BindMemory(imported_memory, 0); |
| m_errorMonitor->VerifyFound(); |
| ::CloseHandle(handle); |
| } |
| #endif |
| |
| TEST_F(NegativeExternalMemorySync, FdMemoryHandleProperties) { |
| TEST_DESCRIPTION("Call vkGetMemoryFdPropertiesKHR with invalid fd handle or with opaque handle type"); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| constexpr auto handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; |
| constexpr auto opaque_handle_type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| constexpr int invalid_fd_handle = -1; |
| constexpr int valid_fd_handle = 0; |
| |
| VkMemoryFdPropertiesKHR properties = vku::InitStructHelper(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkGetMemoryFdPropertiesKHR-fd-00673"); |
| vk::GetMemoryFdPropertiesKHR(*m_device, handle_type, invalid_fd_handle, &properties); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkGetMemoryFdPropertiesKHR-handleType-00674"); |
| vk::GetMemoryFdPropertiesKHR(*m_device, opaque_handle_type, valid_fd_handle, &properties); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryFdBufferNoDedicated) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| VkExternalMemoryBufferCreateInfo external_buffer_info = vku::InitStructHelper(); |
| external_buffer_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| auto buffer_info = vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT, {}, &external_buffer_info); |
| if (!FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT)) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| if (!FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "Unable to find importable handle type"; |
| } |
| const auto compatible_types = GetCompatibleHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); |
| if ((VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT & compatible_types) == 0) { |
| GTEST_SKIP() << "Cannot find handle types that are supported but not compatible with each other"; |
| } |
| |
| vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem); |
| |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(); |
| export_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &export_info); |
| |
| vkt::DeviceMemory memory_export(*m_device, alloc_info); |
| |
| VkMemoryGetFdInfoKHR mgfi = vku::InitStructHelper(); |
| mgfi.memory = memory_export; |
| mgfi.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| int fd; |
| vk::GetMemoryFdKHR(device(), &mgfi, &fd); |
| if (fd < 0) { |
| GTEST_SKIP() << "Cannot export FD memory"; |
| } |
| |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.image = VK_NULL_HANDLE; |
| dedicated_info.buffer = buffer; |
| |
| VkImportMemoryFdInfoKHR import_info = vku::InitStructHelper(&dedicated_info); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| import_info.fd = fd; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-buffer-01879"); |
| alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &import_info); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryFdBufferDifferentDedicated) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| VkExternalMemoryBufferCreateInfo external_buffer_info = vku::InitStructHelper(); |
| external_buffer_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| auto buffer_info = vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT, {}, &external_buffer_info); |
| if (!FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT)) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| if (!FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "Unable to find importable handle type"; |
| } |
| const auto compatible_types = GetCompatibleHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); |
| if ((VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT & compatible_types) == 0) { |
| GTEST_SKIP() << "Cannot find handle types that are supported but not compatible with each other"; |
| } |
| |
| vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem); |
| |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.image = VK_NULL_HANDLE; |
| dedicated_info.buffer = buffer; |
| |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(&dedicated_info); |
| export_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &export_info); |
| |
| vkt::DeviceMemory memory_export(*m_device, alloc_info); |
| |
| VkMemoryGetFdInfoKHR mgfi = vku::InitStructHelper(); |
| mgfi.memory = memory_export; |
| mgfi.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| int fd; |
| vk::GetMemoryFdKHR(device(), &mgfi, &fd); |
| |
| buffer_info.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; |
| vkt::Buffer buffer2(*m_device, buffer_info, vkt::no_mem); |
| |
| dedicated_info.buffer = buffer2; |
| |
| VkImportMemoryFdInfoKHR import_info = vku::InitStructHelper(&dedicated_info); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| import_info.fd = fd; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryDedicatedAllocateInfo-buffer-01879"); |
| alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer2.MemoryRequirements(), 0, &import_info); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryFdBadFd) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| auto buffer_info = vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| if (!FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "Unable to find importable handle type"; |
| } |
| const auto compatible_types = GetCompatibleHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); |
| if ((VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT & compatible_types) == 0) { |
| GTEST_SKIP() << "Cannot find handle types that are supported but not compatible with each other"; |
| } |
| |
| vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem); |
| |
| VkImportMemoryFdInfoKHR import_info = vku::InitStructHelper(); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| import_info.fd = -1; // invalid |
| |
| m_errorMonitor->SetDesiredError("VUID-VkImportMemoryFdInfoKHR-handleType-00670"); |
| VkMemoryAllocateInfo alloc_info = |
| vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &import_info); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryFdHandleType) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| auto buffer_info = vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| if (!FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "Unable to find importable handle type"; |
| } |
| const auto compatible_types = GetCompatibleHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); |
| if ((VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT & compatible_types) == 0) { |
| GTEST_SKIP() << "Cannot find handle types that are supported but not compatible with each other"; |
| } |
| |
| vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem); |
| |
| VkImportMemoryFdInfoKHR import_info = vku::InitStructHelper(); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT; |
| import_info.fd = 1; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkImportMemoryFdInfoKHR-handleType-00669"); |
| VkMemoryAllocateInfo alloc_info = |
| vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &import_info); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryFdBufferSupport) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::protectedMemory); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| auto buffer_info = vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| buffer_info.flags = VK_BUFFER_CREATE_PROTECTED_BIT; |
| if (FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "Need buffer with no import support"; |
| } |
| |
| vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem); |
| |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.image = VK_NULL_HANDLE; |
| dedicated_info.buffer = buffer; |
| |
| VkImportMemoryFdInfoKHR import_info = vku::InitStructHelper(&dedicated_info); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| import_info.fd = 1; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkImportMemoryFdInfoKHR-handleType-09862"); |
| VkMemoryAllocateInfo alloc_info = |
| vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &import_info); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryFdImageSupport) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| auto image_info = vkt::Image::ImageCreateInfo2D(1024, 1, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT); |
| vkt::Image image(*m_device, image_info, vkt::no_mem); |
| |
| if (FindSupportedExternalMemoryHandleTypes(Gpu(), image_info, VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "Need image with no import support"; |
| } |
| |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.image = image; |
| dedicated_info.buffer = VK_NULL_HANDLE; |
| |
| VkImportMemoryFdInfoKHR import_info = vku::InitStructHelper(&dedicated_info); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| import_info.fd = 1; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkImportMemoryFdInfoKHR-handleType-09862"); |
| VkMemoryAllocateInfo alloc_info = |
| vkt::DeviceMemory::GetResourceAllocInfo(*m_device, image.MemoryRequirements(), 0, &import_info); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, GetMemoryHostHandleType) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPhysicalDeviceExternalMemoryHostPropertiesEXT memory_host_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(memory_host_props); |
| |
| VkDeviceSize alloc_size = memory_host_props.minImportedHostPointerAlignment; |
| void* host_memory = ::operator new((size_t)alloc_size, std::align_val_t(alloc_size)); |
| if (!host_memory) { |
| GTEST_SKIP() << "Can't allocate host memory"; |
| } |
| |
| VkMemoryHostPointerPropertiesEXT host_pointer_props = vku::InitStructHelper(); |
| m_errorMonitor->SetDesiredError("VUID-vkGetMemoryHostPointerPropertiesEXT-handleType-01752"); |
| vk::GetMemoryHostPointerPropertiesEXT(*m_device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, host_memory, |
| &host_pointer_props); |
| m_errorMonitor->VerifyFound(); |
| ::operator delete(host_memory, std::align_val_t(alloc_size)); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, GetMemoryHostAlignment) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPhysicalDeviceExternalMemoryHostPropertiesEXT memory_host_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(memory_host_props); |
| |
| VkDeviceSize alloc_size = memory_host_props.minImportedHostPointerAlignment; |
| VkDeviceSize bad_alloc_size = alloc_size / 4; |
| void *host_memory = ::operator new((size_t)bad_alloc_size, std::align_val_t(alloc_size)); |
| if (!host_memory) { |
| GTEST_SKIP() << "Can't allocate host memory"; |
| } |
| const VkDeviceSize host_pointer = reinterpret_cast<VkDeviceSize>(host_memory); |
| if (host_pointer % alloc_size == 0) { |
| ::operator delete(host_memory, std::align_val_t(bad_alloc_size)); |
| GTEST_SKIP() << "Can't create misaligned memory"; // when using ASAN |
| } |
| VkMemoryHostPointerPropertiesEXT host_pointer_props = vku::InitStructHelper(); |
| m_errorMonitor->SetDesiredError("VUID-vkGetMemoryHostPointerPropertiesEXT-pHostPointer-01753"); |
| vk::GetMemoryHostPointerPropertiesEXT(*m_device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, host_memory, |
| &host_pointer_props); |
| m_errorMonitor->VerifyFound(); |
| ::operator delete(host_memory, std::align_val_t(bad_alloc_size)); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryHostDedicated) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| VkPhysicalDeviceExternalMemoryHostPropertiesEXT memory_host_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(memory_host_props); |
| |
| VkDeviceSize alloc_size = memory_host_props.minImportedHostPointerAlignment; |
| void *host_memory = ::operator new((size_t)alloc_size, std::align_val_t(alloc_size)); |
| if (!host_memory) { |
| GTEST_SKIP() << "Can't allocate host memory"; |
| } |
| |
| VkMemoryHostPointerPropertiesEXT host_pointer_props = vku::InitStructHelper(); |
| vk::GetMemoryHostPointerPropertiesEXT(*m_device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, host_memory, |
| &host_pointer_props); |
| |
| const auto buffer_info = vkt::Buffer::CreateInfo(alloc_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem); |
| |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(); |
| dedicated_info.buffer = buffer; |
| dedicated_info.image = VK_NULL_HANDLE; |
| |
| VkImportMemoryHostPointerInfoEXT import_info = vku::InitStructHelper(&dedicated_info); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; |
| import_info.pHostPointer = host_memory; |
| |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&import_info); |
| alloc_info.allocationSize = alloc_size; |
| if (!m_device->Physical().SetMemoryType(host_pointer_props.memoryTypeBits, &alloc_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) { |
| ::operator delete(host_memory, std::align_val_t(alloc_size)); |
| GTEST_SKIP() << "Failed to set memory type."; |
| } |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-02806"); |
| VkDeviceMemory device_memory; |
| vk::AllocateMemory(*m_device, &alloc_info, nullptr, &device_memory); |
| m_errorMonitor->VerifyFound(); |
| |
| ::operator delete(host_memory, std::align_val_t(alloc_size)); |
| } |
| |
| TEST_F(NegativeExternalMemorySync, ImportMemoryHostMemoryIndex) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| VkPhysicalDeviceExternalMemoryHostPropertiesEXT memory_host_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(memory_host_props); |
| |
| VkDeviceSize alloc_size = memory_host_props.minImportedHostPointerAlignment; |
| void *host_memory = ::operator new((size_t)alloc_size, std::align_val_t(alloc_size)); |
| if (!host_memory) { |
| GTEST_SKIP() << "Can't allocate host memory"; |
| } |
| |
| VkMemoryHostPointerPropertiesEXT host_pointer_props = vku::InitStructHelper(); |
| vk::GetMemoryHostPointerPropertiesEXT(*m_device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, host_memory, |
| &host_pointer_props); |
| |
| VkImportMemoryHostPointerInfoEXT import_info = vku::InitStructHelper(); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; |
| import_info.pHostPointer = host_memory; |
| |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&import_info); |
| alloc_info.allocationSize = alloc_size; |
| |
| uint32_t unsupported_mem_type = |
| ((1 << m_device->Physical().memory_properties_.memoryTypeCount) - 1) & ~host_pointer_props.memoryTypeBits; |
| bool found_type = m_device->Physical().SetMemoryType(unsupported_mem_type, &alloc_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); |
| if (unsupported_mem_type == 0 || !found_type) { |
| ::operator delete(host_memory, std::align_val_t(alloc_size)); |
| GTEST_SKIP() << "Failed to find unsupported memory type."; |
| } |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-memoryTypeIndex-01744"); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| |
| ::operator delete(host_memory, std::align_val_t(alloc_size)); |
| } |
| |
| #ifdef VK_USE_PLATFORM_METAL_EXT |
| TEST_F(NegativeExternalMemorySync, ExportMetalObjects) { |
| TEST_DESCRIPTION("Test VK_EXT_metal_objects VUIDs"); |
| |
| AddRequiredExtensions(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_METAL_OBJECTS_EXTENSION_NAME); |
| AddOptionalExtensions(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| |
| RETURN_IF_SKIP(InitFramework()); |
| const bool ycbcr_conversion_extension = IsExtensionsEnabled(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME); |
| VkPhysicalDevicePortabilitySubsetFeaturesKHR portability_features = vku::InitStructHelper(); |
| auto features2 = GetPhysicalDeviceFeatures2(portability_features); |
| |
| if (ycbcr_conversion_extension) { |
| VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcr_features = vku::InitStructHelper(); |
| ycbcr_features.samplerYcbcrConversion = VK_TRUE; |
| portability_features.pNext = &ycbcr_features; |
| } |
| |
| RETURN_IF_SKIP(InitState(nullptr, &features2)); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| VkExportMetalObjectCreateInfoEXT metal_object_create_info = vku::InitStructHelper(); |
| auto instance_ci = GetInstanceCreateInfo(); |
| metal_object_create_info.exportObjectType = VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT; |
| metal_object_create_info.pNext = instance_ci.pNext; |
| instance_ci.pNext = &metal_object_create_info; |
| |
| VkInstance instance = {}; |
| m_errorMonitor->SetDesiredError("VUID-VkInstanceCreateInfo-pNext-06779"); |
| vk::CreateInstance(&instance_ci, nullptr, &instance); |
| m_errorMonitor->VerifyFound(); |
| metal_object_create_info.pNext = nullptr; |
| |
| VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(&metal_object_create_info); |
| alloc_info.allocationSize = 1024; |
| VkDeviceMemory memory; |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateInfo-pNext-06780"); |
| vk::AllocateMemory(device(), &alloc_info, nullptr, &memory); |
| m_errorMonitor->VerifyFound(); |
| |
| VkImageCreateInfo ici = vku::InitStructHelper(); |
| ici.imageType = VK_IMAGE_TYPE_2D; |
| ici.format = VK_FORMAT_B8G8R8A8_UNORM; |
| ici.extent = {128, 128, 1}; |
| ici.mipLevels = 1; |
| ici.arrayLayers = 1; |
| ici.samples = VK_SAMPLE_COUNT_1_BIT; |
| ici.tiling = VK_IMAGE_TILING_LINEAR; |
| ici.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |
| ici.pNext = &metal_object_create_info; |
| CreateImageTest(ici, "VUID-VkImageCreateInfo-pNext-06783"); |
| |
| VkImportMetalTextureInfoEXT import_metal_texture_info = vku::InitStructHelper(); |
| import_metal_texture_info.plane = VK_IMAGE_ASPECT_COLOR_BIT; |
| ici.pNext = &import_metal_texture_info; |
| ici.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; |
| CreateImageTest(ici, "VUID-VkImageCreateInfo-pNext-06784"); |
| |
| ici.format = VK_FORMAT_B8G8R8A8_UNORM; |
| import_metal_texture_info.plane = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| CreateImageTest(ici, "VUID-VkImageCreateInfo-pNext-06785"); |
| |
| ici.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; |
| import_metal_texture_info.plane = VK_IMAGE_ASPECT_PLANE_2_BIT; |
| CreateImageTest(ici, "VUID-VkImageCreateInfo-pNext-06786"); |
| |
| VkBufferCreateInfo buffer_create_info = vku::InitStructHelper(); |
| buffer_create_info.size = 1024; |
| buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; |
| |
| vkt::Buffer buffer(*m_device, buffer_create_info); |
| VkBufferViewCreateInfo buff_view_ci = vku::InitStructHelper(); |
| buff_view_ci.buffer = buffer; |
| buff_view_ci.format = VK_FORMAT_B8G8R8A8_UNORM; |
| buff_view_ci.range = VK_WHOLE_SIZE; |
| buff_view_ci.pNext = &metal_object_create_info; |
| CreateBufferViewTest(buff_view_ci, "VUID-VkBufferViewCreateInfo-pNext-06782"); |
| |
| vkt::Image image_obj(*m_device, 256, 256, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_STORAGE_BIT); |
| VkImageViewCreateInfo ivci = vku::InitStructHelper(); |
| ivci.image = image_obj; |
| ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; |
| ivci.format = VK_FORMAT_B8G8R8A8_UNORM; |
| ivci.subresourceRange.layerCount = 1; |
| ivci.subresourceRange.baseMipLevel = 0; |
| ivci.subresourceRange.levelCount = 1; |
| ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; |
| ivci.pNext = &metal_object_create_info; |
| CreateImageViewTest(ivci, "VUID-VkImageViewCreateInfo-pNext-06787"); |
| |
| VkSemaphoreCreateInfo sem_info = vku::InitStructHelper(); |
| sem_info.pNext = &metal_object_create_info; |
| VkSemaphore semaphore; |
| metal_object_create_info.exportObjectType = VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT; |
| m_errorMonitor->SetDesiredError("VUID-VkSemaphoreCreateInfo-pNext-06789"); |
| vk::CreateSemaphore(device(), &sem_info, NULL, &semaphore); |
| m_errorMonitor->VerifyFound(); |
| |
| VkEventCreateInfo event_info = vku::InitStructHelper(); |
| if (portability_features.events) { |
| event_info.pNext = &metal_object_create_info; |
| VkEvent event; |
| m_errorMonitor->SetDesiredError("VUID-VkEventCreateInfo-pNext-06790"); |
| vk::CreateEvent(device(), &event_info, nullptr, &event); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| VkExportMetalObjectsInfoEXT export_metal_objects_info = vku::InitStructHelper(); |
| VkExportMetalDeviceInfoEXT metal_device_info = vku::InitStructHelper(); |
| VkExportMetalCommandQueueInfoEXT metal_command_queue_info = vku::InitStructHelper(); |
| metal_command_queue_info.queue = m_default_queue->handle(); |
| export_metal_objects_info.pNext = &metal_device_info; |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06791"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| export_metal_objects_info.pNext = &metal_command_queue_info; |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06792"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| alloc_info.pNext = nullptr; |
| VkResult err = vk::AllocateMemory(device(), &alloc_info, nullptr, &memory); |
| ASSERT_EQ(VK_SUCCESS, err); |
| VkExportMetalBufferInfoEXT metal_buffer_info = vku::InitStructHelper(); |
| metal_buffer_info.memory = memory; |
| export_metal_objects_info.pNext = &metal_buffer_info; |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06793"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| vk::FreeMemory(device(), memory, nullptr); |
| |
| VkExportMetalObjectCreateInfoEXT export_metal_object_create_info = vku::InitStructHelper(); |
| export_metal_object_create_info.exportObjectType = VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT; |
| ici.pNext = &export_metal_object_create_info; |
| vkt::Image export_image_obj(*m_device, ici); |
| buff_view_ci.pNext = &export_metal_object_create_info; |
| vkt::BufferView export_buffer_view(*m_device, buff_view_ci); |
| VkExportMetalTextureInfoEXT metal_texture_info = vku::InitStructHelper(); |
| metal_texture_info.bufferView = export_buffer_view; |
| metal_texture_info.image = export_image_obj; |
| metal_texture_info.plane = VK_IMAGE_ASPECT_PLANE_0_BIT; |
| export_metal_objects_info.pNext = &metal_texture_info; |
| |
| // Only one of image, bufferView, imageView |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06794"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| // Image not created with struct in pNext |
| metal_texture_info.bufferView = VK_NULL_HANDLE; |
| metal_texture_info.image = image_obj; |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06795"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| metal_texture_info.image = VK_NULL_HANDLE; |
| auto image_view_ci = image_obj.BasicViewCreatInfo(); |
| vkt::ImageView image_view_no_struct(*m_device, image_view_ci); |
| metal_texture_info.imageView = image_view_no_struct; |
| // ImageView not created with struct in pNext |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06796"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| buff_view_ci.pNext = nullptr; |
| vkt::BufferView buffer_view_no_struct(*m_device, buff_view_ci); |
| metal_texture_info.imageView = VK_NULL_HANDLE; |
| metal_texture_info.bufferView = buffer_view_no_struct; |
| // BufferView not created with struct in pNext |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06797"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| metal_texture_info.bufferView = VK_NULL_HANDLE; |
| metal_texture_info.image = export_image_obj; |
| metal_texture_info.plane = VK_IMAGE_ASPECT_COLOR_BIT; |
| // metal_texture_info.plane not plane 0, 1 or 2 |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06798"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| ici.format = VK_FORMAT_B8G8R8A8_UNORM; |
| vkt::Image single_plane_export_image_obj(*m_device, ici); |
| metal_texture_info.plane = VK_IMAGE_ASPECT_PLANE_1_BIT; |
| metal_texture_info.image = single_plane_export_image_obj; |
| // metal_texture_info.plane not plane_0 for single plane image |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06799"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| image_view_ci.pNext = &export_metal_object_create_info; |
| export_metal_object_create_info.exportObjectType = VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT; |
| vkt::ImageView single_plane_export_image_view(*m_device, image_view_ci); |
| metal_texture_info.image = VK_NULL_HANDLE; |
| metal_texture_info.imageView = single_plane_export_image_view; |
| // metal_texture_info.plane not plane_0 for single plane imageView |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06801"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| VkExportMetalIOSurfaceInfoEXT metal_iosurface_info = vku::InitStructHelper(); |
| metal_iosurface_info.image = image_obj; |
| export_metal_objects_info.pNext = &metal_iosurface_info; |
| // metal_iosurface_info.image not created with struct in pNext |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06803"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| VkExportMetalSharedEventInfoEXT metal_shared_event_info = vku::InitStructHelper(); |
| export_metal_objects_info.pNext = &metal_shared_event_info; |
| // metal_shared_event_info event and semaphore both VK_NULL_HANDLE |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06804"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| sem_info.pNext = nullptr; |
| vkt::Semaphore semaphore_no_struct(*m_device, sem_info); |
| metal_shared_event_info.semaphore = semaphore_no_struct; |
| export_metal_objects_info.pNext = &metal_shared_event_info; |
| // Semaphore not created with struct in pNext |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06805"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| if (portability_features.events) { |
| event_info.pNext = nullptr; |
| vkt::Event event_no_struct(*m_device, event_info); |
| metal_shared_event_info.event = event_no_struct; |
| metal_shared_event_info.semaphore = VK_NULL_HANDLE; |
| // Event not created with struct in pNext |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06806"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| const VkFormat mp_format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; |
| if (FormatIsSupported(Gpu(), mp_format)) { |
| export_metal_object_create_info = vku::InitStructHelper(); |
| export_metal_object_create_info.exportObjectType = VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT; |
| ici.format = mp_format; |
| ici.tiling = VK_IMAGE_TILING_OPTIMAL; |
| ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT; |
| ici.pNext = &export_metal_object_create_info; |
| vkt::Image mp_image_obj(*m_device, ici); |
| |
| metal_texture_info.bufferView = VK_NULL_HANDLE; |
| metal_texture_info.imageView = VK_NULL_HANDLE; |
| metal_texture_info.image = mp_image_obj; |
| metal_texture_info.plane = VK_IMAGE_ASPECT_PLANE_2_BIT; |
| export_metal_objects_info.pNext = &metal_texture_info; |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06800"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| |
| if (ycbcr_conversion_extension) { |
| VkSamplerYcbcrConversionCreateInfo ycbcr_create_info = vku::InitStructHelper(); |
| ycbcr_create_info.format = mp_format; |
| ycbcr_create_info.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; |
| ycbcr_create_info.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; |
| ycbcr_create_info.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; |
| ycbcr_create_info.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| ycbcr_create_info.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; |
| ycbcr_create_info.chromaFilter = VK_FILTER_NEAREST; |
| ycbcr_create_info.forceExplicitReconstruction = false; |
| |
| VkSamplerYcbcrConversion conversion; |
| err = vk::CreateSamplerYcbcrConversionKHR(device(), &ycbcr_create_info, nullptr, &conversion); |
| ASSERT_EQ(VK_SUCCESS, err); |
| |
| VkSamplerYcbcrConversionInfo ycbcr_info = vku::InitStructHelper(); |
| ycbcr_info.conversion = conversion; |
| ycbcr_info.pNext = &export_metal_object_create_info; |
| ivci.image = mp_image_obj; |
| ivci.format = mp_format; |
| ivci.pNext = &ycbcr_info; |
| vkt::ImageView mp_image_view(*m_device, ivci); |
| metal_texture_info.image = VK_NULL_HANDLE; |
| metal_texture_info.imageView = mp_image_view; |
| m_errorMonitor->SetDesiredError("VUID-VkExportMetalObjectsInfoEXT-pNext-06802"); |
| vk::ExportMetalObjectsEXT(*m_device, &export_metal_objects_info); |
| m_errorMonitor->VerifyFound(); |
| vk::DestroySamplerYcbcrConversionKHR(device(), conversion, nullptr); |
| } |
| } |
| } |
| #endif // VK_USE_PLATFORM_METAL_EXT |
| |
| TEST_F(NegativeExternalMemorySync, ZeroInitializeFeature) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_ZERO_INITIALIZE_DEVICE_MEMORY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::zeroInitializeDeviceMemory); |
| AddRequiredExtensions(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); |
| // Required to pass in various memory flags without querying for corresponding extensions. |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| IgnoreHandleTypeError(m_errorMonitor); |
| |
| VkExternalMemoryBufferCreateInfo external_buffer_info = vku::InitStructHelper(); |
| external_buffer_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| auto buffer_info = vkt::Buffer::CreateInfo(1024, VK_BUFFER_USAGE_TRANSFER_DST_BIT, {}, &external_buffer_info); |
| if (!FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT)) { |
| GTEST_SKIP() << "Unable to find exportable handle type"; |
| } |
| if (!FindSupportedExternalMemoryHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) { |
| GTEST_SKIP() << "Unable to find importable handle type"; |
| } |
| const auto compatible_types = GetCompatibleHandleTypes(Gpu(), buffer_info, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); |
| if ((VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT & compatible_types) == 0) { |
| GTEST_SKIP() << "Cannot find handle types that are supported but not compatible with each other"; |
| } |
| |
| vkt::Buffer buffer(*m_device, buffer_info, vkt::no_mem); |
| |
| VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper(); |
| alloc_flags.flags = VK_MEMORY_ALLOCATE_ZERO_INITIALIZE_BIT_EXT; |
| |
| VkMemoryDedicatedAllocateInfo dedicated_info = vku::InitStructHelper(&alloc_flags); |
| dedicated_info.image = VK_NULL_HANDLE; |
| dedicated_info.buffer = buffer; |
| |
| VkExportMemoryAllocateInfo export_info = vku::InitStructHelper(&dedicated_info); |
| export_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| auto alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &export_info); |
| |
| vkt::DeviceMemory memory_export(*m_device, alloc_info); |
| |
| VkMemoryGetFdInfoKHR mgfi = vku::InitStructHelper(); |
| mgfi.memory = memory_export; |
| mgfi.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| |
| int fd; |
| vk::GetMemoryFdKHR(device(), &mgfi, &fd); |
| |
| VkImportMemoryFdInfoKHR import_info = vku::InitStructHelper(&dedicated_info); |
| import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; |
| import_info.fd = fd; |
| |
| alloc_info = vkt::DeviceMemory::GetResourceAllocInfo(*m_device, buffer.MemoryRequirements(), 0, &import_info); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkMemoryAllocateFlagsInfo-flags-10760"); |
| vkt::DeviceMemory memory_import(*m_device, alloc_info); |
| m_errorMonitor->VerifyFound(); |
| } |