[PATCH v10 [rebased] 2/4] vulkan-1/tests: Add tests for VK_KHR_external_memory_win32.

Georg Lehmann dadschoorse at gmail.com
Thu Jul 1 17:46:05 CDT 2021



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.



More information about the wine-devel mailing list