[PATCH v10 [rebased] 2/4] vulkan-1/tests: Add tests for VK_KHR_external_memory_win32.
Zebediah Figura (she/her)
zfigura at codeweavers.com
Thu Jul 1 17:54:04 CDT 2021
On 7/1/21 5:46 PM, Georg Lehmann wrote:
>
>
> On 01.07.21 23:20, Zebediah Figura (she/her) wrote:
>> On 7/1/21 4:01 PM, Georg Lehmann wrote:
>>>
>>>
>>> On 01.07.21 21:59, Zebediah Figura (she/her) wrote:
>>>> On 6/25/21 1:57 PM, Derek Lesho wrote:
>>>>> Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
>>>>> ---
>>>>> v10:
>>>>> - Address comments
>>>>> - Minor adjustment to test_cross_process_resource parameters.
>>>>> ---
>>>>> dlls/vulkan-1/tests/vulkan.c | 401
>>>>> +++++++++++++++++++++++++++++++++++
>>>>> dlls/winevulkan/make_vulkan | 5 +-
>>>>> 2 files changed, 404 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/dlls/vulkan-1/tests/vulkan.c
>>>>> b/dlls/vulkan-1/tests/vulkan.c
>>>>> index f222c631232..fdf5716a914 100644
>>>>> --- a/dlls/vulkan-1/tests/vulkan.c
>>>>> +++ b/dlls/vulkan-1/tests/vulkan.c
>>>>> @@ -548,6 +548,375 @@ static void test_null_hwnd(VkInstance
>>>>> vk_instance, VkPhysicalDevice vk_physical_
>>>>> vkDestroySurfaceKHR(vk_instance, surface, NULL);
>>>>> }
>>>>> +uint32_t find_memory_type(VkPhysicalDevice vk_physical_device,
>>>>> VkMemoryPropertyFlagBits flags, uint32_t mask)
>>>>
>>>> Missing "static".
>>>>
>>>>> +{
>>>>> + VkPhysicalDeviceMemoryProperties properties = {0};
>>>>> + unsigned int i;
>>>>> +
>>>>> + vkGetPhysicalDeviceMemoryProperties(vk_physical_device,
>>>>> &properties);
>>>>> +
>>>>> + for(i = 0; i < properties.memoryTypeCount; i++)
>>>>> + {
>>>>> + if ((1u << i) & mask &&
>>>>> properties.memoryTypes[i].propertyFlags & flags)
>>>>> + return i;
>>>>> + }
>>>>> + return -1;
>>>>> +}
>>>>> +
>>>>> +static void
>>>>> test_cross_process_resource(VkPhysicalDeviceIDPropertiesKHR
>>>>> *device_id_properties, BOOL kmt, HANDLE handle)
>>>>> +{
>>>>> + char driver_uuid[VK_UUID_SIZE * 2 + 1], device_uuid[VK_UUID_SIZE
>>>>> * 2 + 1];
>>>>> + STARTUPINFOA si = { sizeof(si) };
>>>>> + PROCESS_INFORMATION info;
>>>>> + char **argv, buf[MAX_PATH];
>>>>> + unsigned int i;
>>>>> + BOOL res;
>>>>> +
>>>>> + for (i = 0; i < VK_UUID_SIZE; i++)
>>>>> + {
>>>>> + sprintf(&driver_uuid[i * 2], "%02X",
>>>>> device_id_properties->driverUUID[i]);
>>>>> + sprintf(&device_uuid[i * 2], "%02X",
>>>>> device_id_properties->deviceUUID[i]);
>>>>> + }
>>>>> + driver_uuid[i * 2] = 0;
>>>>> + device_uuid[i * 2] = 0;
>>>>> +
>>>>> + winetest_get_mainargs(&argv);
>>>>> + sprintf(buf, "\"%s\" vulkan resource %s %s %s %p", argv[0],
>>>>> driver_uuid, device_uuid,
>>>>> + kmt ? "kmt" :
>>>>> "nt", handle);
>>>>> + res = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0L, NULL, NULL,
>>>>> &si, &info);
>>>>> + ok(res, "CreateProcess failed: %u\n", GetLastError());
>>>>> + CloseHandle(info.hThread);
>>>>> +
>>>>> + wait_child_process(info.hProcess);
>>>>> +}
>>>>> +
>>>>> +static const char *test_external_memory_extensions[] =
>>>>> +{
>>>>> + "VK_KHR_external_memory_capabilities",
>>>>> + "VK_KHR_get_physical_device_properties2",
>>>>> +};
>>>>> +
>>>>> +static void test_external_memory(VkInstance vk_instance,
>>>>> VkPhysicalDevice vk_physical_device)
>>>>> +{
>>>>> + PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR
>>>>> pfn_vkGetPhysicalDeviceExternalBufferPropertiesKHR;
>>>>> + PFN_vkGetPhysicalDeviceProperties2
>>>>> pfn_vkGetPhysicalDeviceProperties2;
>>>>> + PFN_vkGetMemoryWin32HandleKHR pfn_vkGetMemoryWin32HandleKHR;
>>>>> + VkPhysicalDeviceExternalBufferInfoKHR external_buffer_info;
>>>>> + VkExternalBufferPropertiesKHR external_buffer_properties;
>>>>> + VkMemoryDedicatedAllocateInfoKHR dedicated_alloc_info;
>>>>> + VkPhysicalDeviceIDPropertiesKHR device_id_properties;
>>>>> + VkExportMemoryWin32HandleInfoKHR export_handle_info;
>>>>> + VkImportMemoryWin32HandleInfoKHR import_handle_info;
>>>>> + VkPhysicalDeviceProperties2KHR device_properties;
>>>>> + VkExportMemoryAllocateInfoKHR export_memory_info;
>>>>> + VkMemoryGetWin32HandleInfoKHR get_handle_info;
>>>>> + VkDeviceMemory vk_memory, vk_memory_import;
>>>>> + VkMemoryRequirements memory_requirements;
>>>>> + VkBufferCreateInfo buffer_create_info;
>>>>> + VkMemoryAllocateInfo alloc_info;
>>>>> + uint32_t queue_family_index;
>>>>> + SECURITY_ATTRIBUTES sa;
>>>>> + VkBuffer vk_buffer;
>>>>> + VkDevice vk_device;
>>>>> + HANDLE handle;
>>>>> + VkResult vr;
>>>>> + char **argv;
>>>>> + int argc;
>>>>> +
>>>>> + static const char *extensions[] =
>>>>> + {
>>>>> + "VK_KHR_dedicated_allocation",
>>>>> + "VK_KHR_external_memory",
>>>>> + "VK_KHR_external_memory_win32",
>>>>> + };
>>>>> +
>>>>> + pfn_vkGetPhysicalDeviceExternalBufferPropertiesKHR =
>>>>> + (void*) vkGetInstanceProcAddr(vk_instance,
>>>>> "vkGetPhysicalDeviceExternalBufferPropertiesKHR");
>>>>> +
>>>>> + pfn_vkGetPhysicalDeviceProperties2 =
>>>>> + (void*) vkGetInstanceProcAddr(vk_instance,
>>>>> "vkGetPhysicalDeviceProperties2KHR");
>>>>> +
>>>>> + if (pfn_vkGetPhysicalDeviceProperties2)
>>>>> + {
>>>>> + device_id_properties.sType =
>>>>> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR;
>>>>> + device_id_properties.pNext = NULL;
>>>>> +
>>>>> + device_properties.sType =
>>>>> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
>>>>> + device_properties.pNext = &device_id_properties;
>>>>> +
>>>>> + pfn_vkGetPhysicalDeviceProperties2(vk_physical_device,
>>>>> &device_properties);
>>>>> + }
>>>>> +
>>>>> + if ((vr = create_device(vk_physical_device,
>>>>> ARRAY_SIZE(extensions), extensions, NULL, &vk_device)))
>>>>> + {
>>>>> + skip("Failed to create device with external memory
>>>>> extensions, VkResult %d.\n", vr);
>>>>> + return;
>>>>> + }
>>>>> +
>>>>> + pfn_vkGetMemoryWin32HandleKHR = (void *)
>>>>> vkGetDeviceProcAddr(vk_device, "vkGetMemoryWin32HandleKHR");
>>>>> +
>>>>> + find_queue_family(vk_physical_device, VK_QUEUE_GRAPHICS_BIT,
>>>>> &queue_family_index);
>>>>> +
>>>>> + /* Most implementations only support exporting dedicated
>>>>> allocations */
>>>>> +
>>>>> + buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
>>>>> + buffer_create_info.pNext = NULL;
>>>>> + buffer_create_info.flags = 0;
>>>>> + buffer_create_info.size = 1;
>>>>> + buffer_create_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
>>>>> VK_BUFFER_USAGE_TRANSFER_DST_BIT;
>>>>
>>>> We aren't actually using it, though (although we could...)
>>>>
>>>
>>> The spec requires us to request some usage flags though.
>>
>> Ah, makes sense. I thought that might be the case; should probably have
>> checked the spec first...
>>
>>> I'm not sure if
>>> you imply that we should test if using the buffer actually work. If
>>> that's the case I'm inclined to disagree since that's already guaranteed
>>> by running on a conformant host vulkan driver.
>>
>> Not particularly. Like anything it wouldn't hurt (I really do want to
>> make sure that Wine doesn't have any chances to screw things up), but I
>> don't care strongly about it.
>>
>>>
>>>>> + buffer_create_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
>>>>> + buffer_create_info.queueFamilyIndexCount = 1;
>>>>> + buffer_create_info.pQueueFamilyIndices = &queue_family_index;
>>>>> + if ((vr = vkCreateBuffer(vk_device, &buffer_create_info, NULL,
>>>>> &vk_buffer)))
>>>>
>>>> Don't we need a VkExternalMemoryBufferCreateInfo structure here? From
>>>> the Vulkan 1.2 specification § 12.1:
>>>>
>>>> "A VkExternalMemoryBufferCreateInfo structure with a non-zero
>>>> handleTypes field must be included in the creation parameters for a
>>>> buffer that will be bound to memory that is either exported or
>>>> imported."
>>>>
>>>
>>> Yes indeed, so the buffer has to be created per handle type that we try
>>> and only if that type is supported.
>>>
>>>>> + {
>>>>> + skip("Failed to create generic buffer, VkResult %d.\n", vr);
>>>>> + vkDestroyDevice(vk_device, NULL);
>>>>> + return;
>>>>> + }
>>>>> +
>>>>> + dedicated_alloc_info.sType =
>>>>> VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
>>>>> + dedicated_alloc_info.pNext = NULL;
>>>>> + dedicated_alloc_info.image = VK_NULL_HANDLE;
>>>>> + dedicated_alloc_info.buffer = vk_buffer;
>>>>
>>>> Nitpick, but could you please move this down closer to where you use it?
>>>> I'm misled into thinking it's used for the
>>>> vkGetPhysicalDeviceExternalBufferPropertiesKHR() call.
>>>>
>>>>> +
>>>>> + external_buffer_info.sType =
>>>>> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR;
>>>>> + external_buffer_info.pNext = NULL;
>>>>> + external_buffer_info.flags = 0;
>>>>> + external_buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
>>>>> VK_BUFFER_USAGE_TRANSFER_DST_BIT;
>>>>> + external_buffer_info.handleType =
>>>>> VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
>>>>> +
>>>>> + memset(&external_buffer_properties, 0,
>>>>> sizeof(external_buffer_properties));
>>>>> + external_buffer_properties.sType =
>>>>> VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR;
>>>>> +
>>>>> +
>>>>> pfn_vkGetPhysicalDeviceExternalBufferPropertiesKHR(vk_physical_device,
>>>>> &external_buffer_info, &external_buffer_properties);
>>>>> +
>>>>> + vkGetBufferMemoryRequirements(vk_device, vk_buffer,
>>>>> &memory_requirements);
>>>>> +
>>>>> + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
>>>>> + alloc_info.allocationSize = memory_requirements.size;
>>>>> + alloc_info.memoryTypeIndex = find_memory_type(vk_physical_device,
>>>>> VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
>>>>> memory_requirements.memoryTypeBits);
>>>>> +
>>>>> + argc = winetest_get_mainargs(&argv);
>>>>> + if (argc > 3 && !strcmp(argv[2], "resource"))
>>>>> + {
>>>>> + sscanf(argv[6], "%p", &handle);
>>>>> +
>>>>> + import_handle_info.sType =
>>>>> VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
>>>>> + import_handle_info.pNext = &dedicated_alloc_info;
>>>>> + import_handle_info.handleType = strcmp(argv[5], "kmt") ?
>>>>> + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR :
>>>>> + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR;
>>>>> + import_handle_info.handle = handle;
>>>>> + import_handle_info.name = NULL;
>>>>> +
>>>>> + alloc_info.pNext = &import_handle_info;
>>>>> +
>>>>> + vr = vkAllocateMemory(vk_device, &alloc_info, NULL,
>>>>> &vk_memory);
>>>>> + ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult
>>>>> %d.\n", vr);
>>>>> +
>>>>> + vkFreeMemory(vk_device, vk_memory, NULL);
>>>>> + vkDestroyBuffer(vk_device, vk_buffer, NULL);
>>>>> + vkDestroyDevice(vk_device, NULL);
>>>>
>>>> Any reason not to include the by-name tests here?
>>>>
>>>> For that matter, you could add a helper function to test both in-process
>>>> and cross-process import.
>>>>
>>>>> +
>>>>> + return;
>>>>> + }
>>>>> +
>>>>> + if
>>>>> (!(external_buffer_properties.externalMemoryProperties.externalMemoryFeatures
>>>>>
>>>>> &
>>>>> +
>>>>> (VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR|VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR)))
>>>>>
>>>>>
>>>>
>>>> If we need it to be both exportable and importable, this won't do the
>>>> right thing. Same below.
>>>>
>>>>> + skip("With desired parameters, buffers are not exportable to
>>>>> and importable from an NT handle.\n");
>>>>> + else
>>>>> + {
>>>>> +
>>>>> ok(external_buffer_properties.externalMemoryProperties.compatibleHandleTypes
>>>>>
>>>>> & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
>>>>> + "Unexpected compatibleHandleTypes %#x.\n",
>>>>> external_buffer_properties.externalMemoryProperties.compatibleHandleTypes);
>>>>>
>>>>>
>>>>> +
>>>>> + export_memory_info.sType =
>>>>> VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
>>>>> + export_memory_info.pNext = &dedicated_alloc_info;
>>>>> + export_memory_info.handleTypes =
>>>>> VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
>>>>> +
>>>>> + sa.nLength = sizeof(sa);
>>>>> + sa.lpSecurityDescriptor = NULL;
>>>>> + sa.bInheritHandle = TRUE;
>>>>> +
>>>>> + export_handle_info.sType =
>>>>> VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
>>>>> + export_handle_info.pNext = &export_memory_info;
>>>>> + export_handle_info.name = L"wine_test_buffer_export_name";
>>>>> + export_handle_info.dwAccess = GENERIC_ALL;
>>>>> + export_handle_info.pAttributes = &sa;
>>>>> +
>>>>> + alloc_info.pNext = &export_handle_info;
>>>>> +
>>>>> + ok(alloc_info.memoryTypeIndex != -1, "Device local memory
>>>>> type index was not found.\n");
>>>>> +
>>>>> + vr = vkAllocateMemory(vk_device, &alloc_info, NULL,
>>>>> &vk_memory);
>>>>> + ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult
>>>>> %d.\n", vr);
>>>>> +
>>>>> + get_handle_info.sType =
>>>>> VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
>>>>> + get_handle_info.pNext = NULL;
>>>>> + get_handle_info.memory = vk_memory;
>>>>> + get_handle_info.handleType =
>>>>> VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
>>>>> +
>>>>> + vr = pfn_vkGetMemoryWin32HandleKHR(vk_device,
>>>>> &get_handle_info, &handle);
>>>>> + ok(vr == VK_SUCCESS, "vkGetMemoryWin32HandleKHR failed,
>>>>> VkResult %d.\n", vr);
>>>>> +
>>>>> + import_handle_info.sType =
>>>>> VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
>>>>> + import_handle_info.pNext = &dedicated_alloc_info;
>>>>> + import_handle_info.handleType =
>>>>> VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR;
>>>>> + import_handle_info.handle = handle;
>>>>> + import_handle_info.name = NULL;
>>>>> +
>>>>> + alloc_info.pNext = &import_handle_info;
>>>>> +
>>>>> + vr = vkAllocateMemory(vk_device, &alloc_info, NULL,
>>>>> &vk_memory_import);
>>>>> + ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult
>>>>> %d.\n", vr);
>>>>> + ok(vk_memory_import != vk_memory, "Expected new memory
>>>>> object.\n");
>>>>> +
>>>>> + vkFreeMemory(vk_device, vk_memory_import, NULL);
>>>>> +
>>>>> + import_handle_info.handle = NULL;
>>>>> + import_handle_info.name = L"wine_test_buffer_export_name";
>>>>> +
>>>>> + vr = vkAllocateMemory(vk_device, &alloc_info, NULL,
>>>>> &vk_memory_import);
>>>>> + ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult
>>>>> %d.\n", vr);
>>>>> + ok(vk_memory_import != vk_memory, "Expected new memory
>>>>> object.\n");
>>>>> +
>>>>> + vkFreeMemory(vk_device, vk_memory_import, NULL);
>>>>> +
>>>>> + if (pfn_vkGetPhysicalDeviceProperties2)
>>>>> + test_cross_process_resource(&device_id_properties, FALSE,
>>>>> handle);
>>>>> + else
>>>>> + skip("Skipping cross process shared resource test due to
>>>>> lack of VK_KHR_get_physical_device_properties2.\n");
>>>>> +
>>>>> + vkFreeMemory(vk_device, vk_memory, NULL);
>>>>> + CloseHandle(handle);
>>>>> + }
>>>>> +
>>>>> + external_buffer_info.handleType =
>>>>> VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR;
>>>>> +
>>>>> + memset(&external_buffer_properties, 0,
>>>>> sizeof(external_buffer_properties));
>>>>> + external_buffer_properties.sType =
>>>>> VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR;
>>>>> +
>>>>> +
>>>>> pfn_vkGetPhysicalDeviceExternalBufferPropertiesKHR(vk_physical_device,
>>>>> &external_buffer_info, &external_buffer_properties);
>>>>> +
>>>>> + if
>>>>> (!(external_buffer_properties.externalMemoryProperties.externalMemoryFeatures
>>>>>
>>>>> &
>>>>> +
>>>>> (VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR|VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR)))
>>>>>
>>>>>
>>>>> + skip("With desired parameters, buffers are not exportable to
>>>>> and importable from a KMT handle.\n");
>>>>> + else
>>>>> + {
>>>>> +
>>>>> ok(external_buffer_properties.externalMemoryProperties.compatibleHandleTypes
>>>>>
>>>>> & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
>>>>> + "Unexpected compatibleHandleTypes %#x.\n",
>>>>> external_buffer_properties.externalMemoryProperties.compatibleHandleTypes);
>>>>>
>>>>>
>>>>> +
>>>>> + export_memory_info.sType =
>>>>> VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
>>>>> + export_memory_info.pNext = &dedicated_alloc_info;
>>>>> + export_memory_info.handleTypes =
>>>>> VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR;
>>>>> +
>>>>> + alloc_info.pNext = &export_memory_info;
>>>>> +
>>>>> + ok(alloc_info.memoryTypeIndex != -1, "Device local memory
>>>>> type index was not found.\n");
>>>>> +
>>>>> + vr = vkAllocateMemory(vk_device, &alloc_info, NULL,
>>>>> &vk_memory);
>>>>> + ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult
>>>>> %d.\n", vr);
>>>>> +
>>>>> + get_handle_info.sType =
>>>>> VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
>>>>> + get_handle_info.pNext = NULL;
>>>>> + get_handle_info.memory = vk_memory;
>>>>> + get_handle_info.handleType =
>>>>> VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR;
>>>>> +
>>>>> + vr = pfn_vkGetMemoryWin32HandleKHR(vk_device,
>>>>> &get_handle_info, &handle);
>>>>> + ok(vr == VK_SUCCESS, "vkGetMemoryWin32HandleKHR failed,
>>>>> VkResult %d.\n", vr);
>>>>> +
>>>>> + import_handle_info.sType =
>>>>> VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
>>>>> + import_handle_info.pNext = &dedicated_alloc_info;
>>>>> + import_handle_info.handleType =
>>>>> VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR;
>>>>> + import_handle_info.handle = handle;
>>>>> + import_handle_info.name = NULL;
>>>>> +
>>>>> + alloc_info.pNext = &import_handle_info;
>>>>> +
>>>>> + vr = vkAllocateMemory(vk_device, &alloc_info, NULL,
>>>>> &vk_memory_import);
>>>>> + ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult
>>>>> %d.\n", vr);
>>>>> + ok(vk_memory_import != vk_memory, "Expected new memory
>>>>> object.\n");
>>>>> +
>>>>> + vkFreeMemory(vk_device, vk_memory_import, NULL);
>>>>> +
>>>>> + if (pfn_vkGetPhysicalDeviceProperties2)
>>>>> + test_cross_process_resource(&device_id_properties, TRUE,
>>>>> handle);
>>>>> + else
>>>>> + skip("Skipping cross process shared resource test due to
>>>>> lack of VK_KHR_get_physical_device_properties2.\n");
>>>>> +
>>>>> + vkFreeMemory(vk_device, vk_memory, NULL);
>>>>> + }
>>>>> +
>>>>> + vkDestroyBuffer(vk_device, vk_buffer, NULL);
>>>>> + vkDestroyDevice(vk_device, NULL);
>>>>> +}
>>>>> +
>>>>> +/* VK_KHR_get_physical_device_properties2 must be an included
>>>>> extension */
>>>>> +static void test_unique_device(uint8_t driver_uuid[VK_UUID_SIZE],
>>>>> uint8_t device_uuid[VK_UUID_SIZE],
>>>>> + uint32_t extension_count, const char * const
>>>>> *enabled_extensions,
>>>>> + void (*test_func_instance)(VkInstance, VkPhysicalDevice),
>>>>> void (*test_func)(VkPhysicalDevice))
>>>>
>>>> Could we instead use for_each_device_instance(), and match the UUID in
>>>> the callback?
>>>>
>>>> Also: I'm having some trouble finding this in the specification; could
>>>> you please point out where it says that the device and driver UUIDs have
>>>> to match?
>>>>
>>>
>>> 44.1 Additional Image Capabilities: Table 78. External memory handle
>>> types compatibility
>>
>> Thanks!
>>
>>>>> +{
>>>>> + PFN_vkGetPhysicalDeviceProperties2
>>>>> pfn_vkGetPhysicalDeviceProperties2;
>>>>> + VkPhysicalDeviceIDPropertiesKHR device_id_properties;
>>>>> + VkPhysicalDeviceProperties2KHR device_properties;
>>>>> + VkPhysicalDevice *vk_physical_devices;
>>>>> + VkInstance vk_instance;
>>>>> + unsigned int i;
>>>>> + uint32_t count;
>>>>> + VkResult vr;
>>>>> +
>>>>> + if ((vr = create_instance_skip(extension_count,
>>>>> enabled_extensions, &vk_instance)) < 0)
>>>>> + return;
>>>>> + ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr);
>>>>> +
>>>>> + pfn_vkGetPhysicalDeviceProperties2 =
>>>>> + (void*) vkGetInstanceProcAddr(vk_instance,
>>>>> "vkGetPhysicalDeviceProperties2KHR");
>>>>> + if (!pfn_vkGetPhysicalDeviceProperties2)
>>>>> + {
>>>>> + skip("Skipping cross process shared resource test due to lack
>>>>> of VK_KHR_get_physical_device_properties2.\n");
>>>>> + return;
>>>>> + }
>>>>> +
>>>>> + vr = vkEnumeratePhysicalDevices(vk_instance, &count, NULL);
>>>>> + if (vr || !count)
>>>>> + {
>>>>> + skip("No physical devices. VkResult %d.\n", vr);
>>>>> + vkDestroyInstance(vk_instance, NULL);
>>>>> + return;
>>>>> + }
>>>>> +
>>>>> + vk_physical_devices = heap_calloc(count,
>>>>> sizeof(*vk_physical_devices));
>>>>> + ok(!!vk_physical_devices, "Failed to allocated memory.\n");
>>>>> + vr = vkEnumeratePhysicalDevices(vk_instance, &count,
>>>>> vk_physical_devices);
>>>>> + ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr);
>>>>> +
>>>>> + for (i = 0; i < count; i++)
>>>>> + {
>>>>> + device_id_properties.sType =
>>>>> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR;
>>>>> + device_id_properties.pNext = NULL;
>>>>> +
>>>>> + device_properties.sType =
>>>>> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
>>>>> + device_properties.pNext = &device_id_properties;
>>>>> +
>>>>> + pfn_vkGetPhysicalDeviceProperties2(vk_physical_devices[i],
>>>>> &device_properties);
>>>>> +
>>>>> + if (!memcmp(device_id_properties.driverUUID, driver_uuid,
>>>>> VK_UUID_SIZE) &&
>>>>> + !memcmp(device_id_properties.deviceUUID, device_uuid,
>>>>> VK_UUID_SIZE))
>>>>> + {
>>>>> + if (test_func_instance)
>>>>> + test_func_instance(vk_instance,
>>>>> vk_physical_devices[i]);
>>>>> + else
>>>>> + test_func(vk_physical_devices[i]);
>>>>
>>>> This isn't new, but it strikes me as really awkward. Can't we just pass
>>>> a VkInstance to the callback and leave it unused?
>>>>
>>>>> +
>>>>> + break;
>>>>> + }
>>>>> + }
>>>>> + ok(i != count, "Failed to find matching physical device.\n");
>>>>> +
>>>>> + heap_free(vk_physical_devices);
>>>>> +
>>>>> + vkDestroyInstance(vk_instance, NULL);
>>>>> +}
>>>>> +
>>>>> static void for_each_device_instance(uint32_t extension_count, const
>>>>> char * const *enabled_extensions,
>>>>> void (*test_func_instance)(VkInstance, VkPhysicalDevice),
>>>>> void (*test_func)(VkPhysicalDevice))
>>>>> {
>>>>> @@ -594,6 +963,37 @@ static void for_each_device(void
>>>>> (*test_func)(VkPhysicalDevice))
>>>>> START_TEST(vulkan)
>>>>> {
>>>>> + unsigned int val;
>>>>> + unsigned int i;
>>>>> + char **argv;
>>>>> + int argc;
>>>>> +
>>>>> + argc = winetest_get_mainargs(&argv);
>>>>> +
>>>>> + if (argc > 3)
>>>>> + {
>>>>> + if (!strcmp(argv[2], "resource"))
>>>>> + {
>>>>> + uint8_t driver_uuid[VK_UUID_SIZE],
>>>>> device_uuid[VK_UUID_SIZE];
>>>>> +
>>>>> + ok(argc >= 7, "Missing launch arguments\n");
>>>>> +
>>>>> + for (i = 0; i < VK_UUID_SIZE; i++)
>>>>> + {
>>>>> + /* %02hhX overflows to write 4 bytes on win32 */
>>>>> + sscanf(&argv[3][i * 2], "%02X", &val);
>>>>> + driver_uuid[i] = val;
>>>>> +
>>>>> + sscanf(&argv[4][i * 2], "%02X", &val);
>>>>> + device_uuid[i] = val;
>>>>> + }
>>>>> +
>>>>> + test_unique_device(driver_uuid, device_uuid,
>>>>> + ARRAY_SIZE(test_external_memory_extensions),
>>>>> test_external_memory_extensions, test_external_memory, NULL);
>>>>> + return;
>>>>> + }
>>>>> + }
>>>>> +
>>>>> test_instance_version();
>>>>> for_each_device(enumerate_physical_device);
>>>>> test_enumerate_physical_device2();
>>>>> @@ -604,4 +1004,5 @@ START_TEST(vulkan)
>>>>> for_each_device(test_unsupported_device_extensions);
>>>>> for_each_device(test_private_data);
>>>>> for_each_device_instance(ARRAY_SIZE(test_null_hwnd_extensions),
>>>>> test_null_hwnd_extensions, test_null_hwnd, NULL);
>>>>> +
>>>>> for_each_device_instance(ARRAY_SIZE(test_external_memory_extensions),
>>>>> test_external_memory_extensions, test_external_memory, NULL);
>>>>> }
>>>>> diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
>>>>> index c46ef02dcb9..5c4c4f0fe26 100755
>>>>> --- a/dlls/winevulkan/make_vulkan
>>>>> +++ b/dlls/winevulkan/make_vulkan
>>>>> @@ -99,7 +99,6 @@ UNSUPPORTED_EXTENSIONS = [
>>>>> "VK_EXT_pipeline_creation_feedback",
>>>>> "VK_GOOGLE_display_timing",
>>>>> "VK_KHR_external_fence_win32",
>>>>> - "VK_KHR_external_memory_win32",
>>>>> "VK_KHR_external_semaphore_win32",
>>>>> # Relates to external_semaphore and needs type conversions in
>>>>> bitflags.
>>>>> "VK_KHR_shared_presentable_image", # Needs WSI work.
>>>>> @@ -127,7 +126,9 @@ UNSUPPORTED_EXTENSIONS = [
>>>>> # Either internal extensions which aren't present on the win32
>>>>> platform which
>>>>> # winevulkan may nonetheless use, or extensions we want to generate
>>>>> headers for
>>>>> # but not expose to applications (useful for test commits)
>>>>> -UNEXPOSED_EXTENSIONS = {}
>>>>> +UNEXPOSED_EXTENSIONS = {
>>>>> + "VK_KHR_external_memory_win32",
>>>>> +}
>>>>> # The Vulkan loader provides entry-points for core functionality and
>>>>> important
>>>>> # extensions. Based on vulkan-1.def this amounts to WSI extensions
>>>>> on 1.0.51.
>>>>>
>>>>
>>>> This doesn't look like it belongs in this patch.
>>>>
>>>
>>> In my opinion it does belong here, without it the necessary types,
>>> functions and enum values won't be generated in include/wine/vulkan.h
>>
>> Could we make it into a separate patch, then?
>
> I thought wine doesn't like changes that have no effect without an
> additional patch, but if you have no problem with that, ofc we can.
I think for headers it's fine to make it a separate patch. On reflection
I don't feel strongly, though.
More information about the wine-devel
mailing list