Hello community, here is the log from the commit of package vulkan-loader for openSUSE:Factory checked in at 2020-09-05 23:57:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/vulkan-loader (Old) and /work/SRC/openSUSE:Factory/.vulkan-loader.new.3399 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "vulkan-loader" Sat Sep 5 23:57:09 2020 rev:26 rq:831292 version:1.2.151 Changes: -------- --- /work/SRC/openSUSE:Factory/vulkan-loader/vulkan-loader.changes 2020-08-12 10:55:57.784727401 +0200 +++ /work/SRC/openSUSE:Factory/.vulkan-loader.new.3399/vulkan-loader.changes 2020-09-05 23:57:17.459100263 +0200 @@ -1,0 +2,6 @@ +Wed Aug 19 07:30:26 UTC 2020 - Jan Engelhardt <[email protected]> + +- Update to release 1.2.151 + * Fixed crash in device enumeration + +------------------------------------------------------------------- Old: ---- v1.2.148.tar.gz New: ---- v1.2.151.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ vulkan-loader.spec ++++++ --- /var/tmp/diff_new_pack.sbNyu8/_old 2020-09-05 23:57:20.331101702 +0200 +++ /var/tmp/diff_new_pack.sbNyu8/_new 2020-09-05 23:57:20.335101704 +0200 @@ -18,7 +18,7 @@ %define lname libvulkan1 Name: vulkan-loader -Version: 1.2.148 +Version: 1.2.151 Release: 0 Summary: Reference ICD loader for Vulkan License: Apache-2.0 ++++++ v1.2.148.tar.gz -> v1.2.151.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vulkan-Loader-1.2.148/.appveyor.yml new/Vulkan-Loader-1.2.151/.appveyor.yml --- old/Vulkan-Loader-1.2.148/.appveyor.yml 2020-07-20 20:36:53.000000000 +0200 +++ new/Vulkan-Loader-1.2.151/.appveyor.yml 2020-08-17 19:41:19.000000000 +0200 @@ -12,7 +12,7 @@ max_jobs: 4 os: - - Visual Studio 2015 + - Visual Studio 2017 environment: PYTHON_PATH: "C:/Python35" @@ -47,7 +47,7 @@ - echo Generating CMake files for %PLATFORM% - mkdir build - cd build - - cmake -A %PLATFORM% -C../external/helper.cmake .. + - cmake -A %PLATFORM% -DCMAKE_SYSTEM_VERSION=10.0.18362 -C../external/helper.cmake .. - echo Building platform=%PLATFORM% configuration=%CONFIGURATION% platform: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vulkan-Loader-1.2.148/README.md new/Vulkan-Loader-1.2.151/README.md --- old/Vulkan-Loader-1.2.148/README.md 2020-07-20 20:36:53.000000000 +0200 +++ new/Vulkan-Loader-1.2.151/README.md 2020-08-17 19:41:19.000000000 +0200 @@ -58,8 +58,6 @@ This work is released as open source under a Apache-style license from Khronos including a Khronos copyright. -See COPYRIGHT.txt for a full list of licenses used in this repository. - ## Acknowledgements While this project has been developed primarily by LunarG, Inc., there are many other diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vulkan-Loader-1.2.148/loader/CMakeLists.txt new/Vulkan-Loader-1.2.151/loader/CMakeLists.txt --- old/Vulkan-Loader-1.2.148/loader/CMakeLists.txt 2020-07-20 20:36:53.000000000 +0200 +++ new/Vulkan-Loader-1.2.151/loader/CMakeLists.txt 2020-08-17 19:41:19.000000000 +0200 @@ -183,7 +183,7 @@ endif() if(WIN32) - add_library(loader-norm OBJECT ${NORMAL_LOADER_SRCS} dirent_on_windows.c dxgi_loader.c) + add_library(loader-norm OBJECT ${NORMAL_LOADER_SRCS} dirent_on_windows.c) target_compile_options(loader-norm PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_DBG}>") target_compile_options(loader-norm PUBLIC ${MSVC_LOADER_COMPILE_OPTIONS}) target_include_directories(loader-norm PRIVATE "$<TARGET_PROPERTY:Vulkan::Headers,INTERFACE_INCLUDE_DIRECTORIES>") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vulkan-Loader-1.2.148/loader/LoaderAndLayerInterface.md new/Vulkan-Loader-1.2.151/loader/LoaderAndLayerInterface.md --- old/Vulkan-Loader-1.2.148/loader/LoaderAndLayerInterface.md 2020-07-20 20:36:53.000000000 +0200 +++ new/Vulkan-Loader-1.2.151/loader/LoaderAndLayerInterface.md 2020-08-17 19:41:19.000000000 +0200 @@ -49,13 +49,14 @@ * [ICD Vulkan Entry Point Discovery](#icd-vulkan-entry-point-discovery) * [ICD API Version](#icd-api-version) * [ICD Unknown Physical Device Extensions](#icd-unknown-physical-device-extensions) + * [Physical Device Sorting](#physical-device-sorting) * [ICD Dispatchable Object Creation](#icd-dispatchable-object-creation) * [Handling KHR Surface Objects in WSI Extensions](#handling-khr-surface-objects-in-wsi-extensions) * [Loader and ICD Interface Negotiation](#loader-and-icd-interface-negotiation) * [Table of Debug Environment Variables](#table-of-debug-environment-variables) * [Glossary of Terms](#glossary-of-terms) - + ## Overview Vulkan is a layered architecture, made up of the following elements: @@ -191,7 +192,7 @@ * `vkBeginCommandBuffer` * `vkCreateEvent` -You can query Vulkan Device functions using either `vkGetInstanceProcAddr` or +You can query Vulkan Device functions using either `vkGetInstanceProcAddr` or `vkGetDeviceProcAddr`. If you choose to use `vkGetInstanceProcAddr`, it will have an additional level built into the call chain, which will reduce performance slightly. However, the function pointer returned can be used for @@ -268,7 +269,7 @@ Device call chains are created at `vkCreateDevice` and are generally simpler because they deal with only a single device and the ICD can always be the -*terminator* of the chain. +*terminator* of the chain.  @@ -298,7 +299,7 @@ * [WSI Extensions](#wsi-extensions) * [Unknown Extensions](#unknown-extensions) - + #### Interfacing with Vulkan Functions There are several ways you can interface with Vulkan functions through the loader. @@ -369,7 +370,7 @@ The answer comes in how the call chain of Instance functions are implemented versus the call chain of a Device functions. Remember, a [Vulkan Instance is a -high-level construct used to provide Vulkan system-level +high-level construct used to provide Vulkan system-level information](#instance-related-objects). Because of this, Instance functions need to be broadcast to every available ICD on the system. The following diagram shows an approximate @@ -692,7 +693,7 @@ - VK_KHR_swapchain - VK_KHR_display -In addition, each of the following OS targets for the loader support +In addition, each of the following OS targets for the loader support target-specific extensions: | Windowing System | Extensions available | @@ -798,9 +799,9 @@ * [Layer Library API Version 2](#layer-library-api-version-2) * [Layer Library API Version 1](#layer-library-api-version-1) * [Layer Library API Version 0](#layer-library-api-version-0) - - + + #### Layer Discovery As mentioned in the @@ -1381,7 +1382,7 @@ pfnNextGetInstanceProcAddr(NULL, "vkCreateInstance"). - For CreateDevice get the next entity's `vkCreateDevice` by calling the "pfnNextGetInstanceProcAddr": - pfnNextGetInstanceProcAddr(NULL, "vkCreateDevice"). + pfnNextGetInstanceProcAddr(instance, "vkCreateDevice"), passing the already created instance handle. - Advanced the linked list to the next node: pLayerInfo = pLayerInfo->pNext. - Call down the chain either `vkCreateDevice` or `vkCreateInstance` - Initialize your layer dispatch table by calling the next entity's @@ -1432,13 +1433,14 @@ #### Example Code for CreateDevice ```cpp -VkResult +VkResult vkCreateDevice( VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { + VkInstance instance = GetInstanceFromPhysicalDevice(gpu); VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); @@ -1447,7 +1449,7 @@ PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; PFN_vkCreateDevice fpCreateDevice = - (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice"); + (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance, "vkCreateDevice"); if (fpCreateDevice == NULL) { return VK_ERROR_INITIALIZATION_FAILED; } @@ -1471,6 +1473,8 @@ return VK_SUCCESS; } ``` +In this case the function `GetInstanceFromPhysicalDevice` is called to get the instance handle. +In practice, this would be done by any method a layer chooses to get an instance handle from the physical device. #### Meta-layers @@ -1489,7 +1493,7 @@ 4. The loader will automatically collate all instance and device extensions in a meta-layer's component layers, and report them as the meta-layer's properties to the application when queried. - + Restrictions to defining and using a meta-layer are: 1. A Meta-layer Manifest file **must** be a properly formatted that contains one or more component layers. @@ -1497,7 +1501,7 @@ be used. 4. All component layers **must be** at the same Vulkan API major and minor version for the meta-layer to be used. - + The ordering of a meta-layer's component layers in the instance or device call-chain is simple: * The first layer listed will be the layer closest to the application. @@ -1606,7 +1610,7 @@ ##### Associating Private Data with Vulkan Objects Within a Layer A layer may want to associate its own private data with one or more Vulkan -objects. Two common methods to do this are hash maps and object wrapping. +objects. Two common methods to do this are hash maps and object wrapping. ###### Wrapping @@ -2310,7 +2314,7 @@ * "library\_path" * "api\_version" - + ### ICD Vulkan Entry Point Discovery The Vulkan symbols exported by an ICD must not clash with the loader's exported @@ -2327,11 +2331,11 @@ ``` This function has very similar semantics to `vkGetInstanceProcAddr`. -`vk_icdGetInstanceProcAddr` returns valid function pointers for all the +`vk_icdGetInstanceProcAddr` returns valid function pointers for all the global-level and instance-level Vulkan functions, and also for `vkGetDeviceProcAddr`. Global-level functions are those which contain no dispatchable object as the first parameter, such as `vkCreateInstance` and -`vkEnumerateInstanceExtensionProperties`. The ICD must support querying +`vkEnumerateInstanceExtensionProperties`. The ICD must support querying global-level entry points by calling `vk_icdGetInstanceProcAddr` with a NULL `VkInstance` parameter. Instance-level functions are those that have either `VkInstance`, or `VkPhysicalDevice` as the first parameter dispatchable object. @@ -2345,7 +2349,7 @@ All other Vulkan entry points must either: * NOT be exported directly from the ICD library * or NOT use the official Vulkan function names if they are exported - + This requirement is for ICD libraries that include other functionality (such as OpenGL) and thus could be loaded by the application prior to when the Vulkan loader library is loaded by the @@ -2471,6 +2475,35 @@ attempting to use the commands. +### Physical Device Sorting + +When an application selects a GPU to use, it must enumerate physical devices or physical device groups. +These API functions do not specify which order the physical devices or physical device groups will be presented in. +On Windows, the loader will attempt to sort these objects so that the system preference will be listed first. +This mechanism does not force an application to use any particular GPU — it merely changes the order in which they are presented. + +This mechanism requires that an ICD implement version 6 of the loader/ICD interface. +Version 6 of this interface defines a new method that the ICD may provide on Windows: + +```c +VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices); +``` + +This function takes an adapter LUID as input, and enumerates all Vulkan physical devices that are associated with that LUID. +This works in the same way as other Vulkan enumerations — if `pPhysicalDevices` is `NULL`, then the count will be provided. +Otherwise, the physical devices associated with the queried adapter will be provided. +The function must provide multiple physical devices when the LUID referes to a linked adapter. +This allows the loader to translate the adapter into Vulkan physical device groups. + +While the loader attempts to match the system's preference for GPU ordering, there are some limitations. +Because this feature requires a new ICD interface, only physical devices from ICDs that support this function will be sorted. +All unsorted physical devices will be listed at the end of the list, in an indeterminate order. +Furthermore, only physical devices that correspond to an adapter may be sorted. +This means that a software implementation would likely not be sorted. +Finally, this API only applies to Windows systems and will only work on versions of Windows 10 that support GPU selection through the OS. +Other platforms may be included in the future, but they will require separate platform-specific interfaces. + + ### ICD Dispatchable Object Creation As previously covered, the loader requires dispatch tables to be accessible @@ -2486,7 +2519,7 @@ pointer. * **NOTE:** For any C\++ ICD's that implement VK objects directly as C\++ classes: - * The C\++ compiler may put a vtable at offset zero if your class is + * The C\++ compiler may put a vtable at offset zero if your class is non-POD due to the use of a virtual function. * In this case use a regular C structure (see below). 3. The loader checks for a magic value (ICD\_LOADER\_MAGIC) in all the created @@ -2511,7 +2544,7 @@ return newObj; } ``` - + ### Handling KHR Surface Objects in WSI Extensions @@ -2639,6 +2672,11 @@ `vk_icdGetInstanceProcAddr` first, it supports at least version 1. Otherwise, the loader only supports version 0. +##### Loader Version 6 Interface Requirements + +Version 6 provides a mechanism to allow the loader to sort physical devices. +The loader will only attempt to sort physical devices on an ICD if version 6 of the interface is supported. +This version provides the `vk_icdEnumerateAdapterPhysicalDevices` function defined earlier in this document. ##### Loader Version 5 Interface Requirements @@ -2763,7 +2801,7 @@ | VK_LAYER_PATH | Override the loader's standard Layer library search folders and use the provided delimited folders to search for layer Manifest files. | `export VK_LAYER_PATH=<path_a>:<path_b>`<br/><br/>`set VK_LAYER_PATH=<path_a>;<path_b>` | | VK_LOADER_DISABLE_INST_EXT_FILTER | Disable the filtering out of instance extensions that the loader doesn't know about. This will allow applications to enable instance extensions exposed by ICDs but that the loader has no support for. **NOTE:** This may cause the loader or application to crash. | `export VK_LOADER_DISABLE_INST_EXT_FILTER=1`<br/><br/>`set VK_LOADER_DISABLE_INST_EXT_FILTER=1` | | VK_LOADER_DEBUG | Enable loader debug messages. Options are:<br/>- error (only errors)<br/>- warn (warnings and errors)<br/>- info (info, warning, and errors)<br/> - debug (debug + all before) <br/> -all (report out all messages) | `export VK_LOADER_DEBUG=all`<br/><br/>`set VK_LOADER_DEBUG=warn` | - + ## Glossary of Terms | Field Name | Field Value | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vulkan-Loader-1.2.148/loader/dxgi_loader.c new/Vulkan-Loader-1.2.151/loader/dxgi_loader.c --- old/Vulkan-Loader-1.2.148/loader/dxgi_loader.c 2020-07-20 20:36:53.000000000 +0200 +++ new/Vulkan-Loader-1.2.151/loader/dxgi_loader.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,23 +0,0 @@ -#include "dxgi_loader.h" - -#include <strsafe.h> - -static HMODULE load_dxgi_module() { - TCHAR systemPath[MAX_PATH] = ""; - GetSystemDirectory(systemPath, MAX_PATH); - StringCchCat(systemPath, MAX_PATH, TEXT("\\dxgi.dll")); - - return LoadLibrary(systemPath); -} - -typedef HRESULT (APIENTRY *PFN_CreateDXGIFactory1)(REFIID riid, void **ppFactory); - -HRESULT dyn_CreateDXGIFactory1(REFIID riid, void **ppFactory) { - PFN_CreateDXGIFactory1 fpCreateDXGIFactory1 = - (PFN_CreateDXGIFactory1)GetProcAddress(load_dxgi_module(), "CreateDXGIFactory1"); - - if (fpCreateDXGIFactory1 != NULL) - return fpCreateDXGIFactory1(riid, ppFactory); - - return DXGI_ERROR_NOT_FOUND; -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vulkan-Loader-1.2.148/loader/dxgi_loader.h new/Vulkan-Loader-1.2.151/loader/dxgi_loader.h --- old/Vulkan-Loader-1.2.148/loader/dxgi_loader.h 2020-07-20 20:36:53.000000000 +0200 +++ new/Vulkan-Loader-1.2.151/loader/dxgi_loader.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,8 +0,0 @@ -#ifndef DXGI_LOADER_H -#define DXGI_LOADER_H - -#include <dxgi1_2.h> - -HRESULT dyn_CreateDXGIFactory1(REFIID riid, void **ppFactory); - -#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vulkan-Loader-1.2.148/loader/loader.c new/Vulkan-Loader-1.2.151/loader/loader.c --- old/Vulkan-Loader-1.2.148/loader/loader.c 2020-07-20 20:36:53.000000000 +0200 +++ new/Vulkan-Loader-1.2.151/loader/loader.c 2020-08-17 19:41:19.000000000 +0200 @@ -70,8 +70,12 @@ #include <initguid.h> #include <devpkey.h> #include <winternl.h> +#include <strsafe.h> +#include <dxgi1_6.h> #include "adapters.h" -#include "dxgi_loader.h" + +typedef HRESULT (APIENTRY *PFN_CreateDXGIFactory1)(REFIID riid, void **ppFactory); +static PFN_CreateDXGIFactory1 fpCreateDXGIFactory1; #endif // This is a CMake generated file with #defines for any functions/includes @@ -884,7 +888,7 @@ } if (is_driver) { - HRESULT hres = dyn_CreateDXGIFactory1(&IID_IDXGIFactory1, &dxgi_factory); + HRESULT hres = fpCreateDXGIFactory1(&IID_IDXGIFactory1, &dxgi_factory); if (hres != S_OK) { loader_log( inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, @@ -1962,9 +1966,10 @@ // Search the source_list for any layer with a name that matches the given name and a type // that matches the given type. Add all matching layers to the target_list. // Do not add if found loader_layer_properties is already on the target_list. -void loaderAddLayerNameToList(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags, - const struct loader_layer_list *source_list, struct loader_layer_list *target_list, - struct loader_layer_list *expanded_target_list) { +VkResult loaderAddLayerNameToList(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags, + const struct loader_layer_list *source_list, struct loader_layer_list *target_list, + struct loader_layer_list *expanded_target_list) { + VkResult res = VK_SUCCESS; bool found = false; for (uint32_t i = 0; i < source_list->count; i++) { struct loader_layer_properties *source_prop = &source_list->list[i]; @@ -1985,9 +1990,17 @@ } } if (!found) { - loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "loaderAddLayerNameToList: Failed to find layer name %s to activate", - name); + if (strcmp(name, "VK_LAYER_LUNARG_standard_validation")) { + loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, + "loaderAddLayerNameToList: Failed to find layer name %s to activate", name); + } else { + res = VK_ERROR_LAYER_NOT_PRESENT; + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "Layer VK_LAYER_LUNARG_standard_validation has been changed to VK_LAYER_KHRONOS_validation. Please use the " + "new version of the layer."); + } } + return res; } static VkExtensionProperties *get_extension_property(const char *name, const struct loader_extension_list *list) { @@ -2288,6 +2301,9 @@ PFN_vkGetInstanceProcAddr fp_get_proc_addr; PFN_GetPhysicalDeviceProcAddr fp_get_phys_dev_proc_addr = NULL; PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version; +#if defined(VK_USE_PLATFORM_WIN32_KHR) + PFN_vk_icdEnumerateAdapterPhysicalDevices fp_enum_dxgi_adapter_phys_devs = NULL; +#endif struct loader_scanned_icd *new_scanned_icd; uint32_t interface_vers; VkResult res = VK_SUCCESS; @@ -2374,6 +2390,11 @@ goto out; } fp_get_phys_dev_proc_addr = loader_platform_get_proc_address(handle, "vk_icdGetPhysicalDeviceProcAddr"); +#if defined(VK_USE_PLATFORM_WIN32_KHR) + if (interface_vers >= 6) { + fp_enum_dxgi_adapter_phys_devs = loader_platform_get_proc_address(handle, "vk_icdEnumerateAdapterPhysicalDevices"); + } +#endif } // check for enough capacity @@ -2399,6 +2420,9 @@ new_scanned_icd->GetPhysicalDeviceProcAddr = fp_get_phys_dev_proc_addr; new_scanned_icd->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props; new_scanned_icd->CreateInstance = fp_create_inst; +#if defined(VK_USE_PLATFORM_WIN32_KHR) + new_scanned_icd->EnumerateAdapterPhysicalDevices = fp_enum_dxgi_adapter_phys_devs; +#endif new_scanned_icd->interface_version = interface_vers; new_scanned_icd->lib_name = (char *)loader_instance_heap_alloc(inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); @@ -2481,6 +2505,13 @@ // This is needed to ensure that newer APIs are available right away // and not after the first call that has been statically linked LoadLibrary("gdi32.dll"); + + TCHAR systemPath[MAX_PATH] = ""; + GetSystemDirectory(systemPath, MAX_PATH); + StringCchCat(systemPath, MAX_PATH, TEXT("\\dxgi.dll")); + HMODULE dxgi_module = LoadLibrary(systemPath); + fpCreateDXGIFactory1 = dxgi_module == NULL ? NULL : + (PFN_CreateDXGIFactory1)GetProcAddress(dxgi_module, "CreateDXGIFactory1"); #endif } @@ -2782,6 +2813,9 @@ if (prop->blacklist_layer_names != NULL) { loader_instance_heap_free(inst, prop->blacklist_layer_names); } + if (prop->override_paths != NULL) { + loader_instance_heap_free(inst, prop->override_paths); + } // Remove the current invalid meta-layer from the layer list. Use memmove since we are // overlapping the source and destination addresses. @@ -4925,6 +4959,7 @@ res = loaderAddLayerProperties(inst, instance_layers, json, true, file_str); loader_instance_heap_free(inst, file_str); + manifest_files.filename_list[i] = NULL; cJSON_Delete(json); if (VK_ERROR_OUT_OF_HOST_MEMORY == res) { @@ -4949,6 +4984,11 @@ if (NULL != override_paths) { loader_instance_heap_free(inst, override_paths); } + for (uint32_t i = 0; i < manifest_files.count; i++) { + if (NULL != manifest_files.filename_list[i]) { + loader_instance_heap_free(inst, manifest_files.filename_list[i]); + } + } if (NULL != manifest_files.filename_list) { loader_instance_heap_free(inst, manifest_files.filename_list); } @@ -5585,9 +5625,11 @@ // Get the layer name(s) from the env_name environment variable. If layer is found in // search_list then add it to layer_list. But only add it to layer_list if type_flags matches. -static void loaderAddEnvironmentLayers(struct loader_instance *inst, const enum layer_type_flags type_flags, const char *env_name, - struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list, - const struct loader_layer_list *source_list) { +static VkResult loaderAddEnvironmentLayers(struct loader_instance *inst, const enum layer_type_flags type_flags, + const char *env_name, struct loader_layer_list *target_list, + struct loader_layer_list *expanded_target_list, + const struct loader_layer_list *source_list) { + VkResult res = VK_SUCCESS; char *next, *name; char *layer_env = loader_getenv(env_name, inst); if (layer_env == NULL) { @@ -5601,7 +5643,10 @@ while (name && *name) { next = loader_get_next_path(name); - loaderAddLayerNameToList(inst, name, type_flags, source_list, target_list, expanded_target_list); + res = loaderAddLayerNameToList(inst, name, type_flags, source_list, target_list, expanded_target_list); + if (res != VK_SUCCESS) { + goto out; + } name = next; } @@ -5611,7 +5656,7 @@ loader_free_getenv(layer_env, inst); } - return; + return res; } VkResult loaderEnableInstanceLayers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo, @@ -5640,8 +5685,11 @@ loaderAddImplicitLayers(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, instance_layers); // Add any layers specified via environment variable next - loaderAddEnvironmentLayers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, "VK_INSTANCE_LAYERS", &inst->app_activated_layer_list, - &inst->expanded_activated_layer_list, instance_layers); + err = loaderAddEnvironmentLayers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, "VK_INSTANCE_LAYERS", &inst->app_activated_layer_list, + &inst->expanded_activated_layer_list, instance_layers); + if (err != VK_SUCCESS) { + goto out; + } // Add layers specified by the application err = loaderAddLayerNamesToList(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, @@ -5663,6 +5711,7 @@ } } +out: return err; } @@ -5985,28 +6034,46 @@ } } + VkLoaderFeatureFlags feature_flags = 0; +#if defined(_WIN32) + IDXGIFactory6* dxgi_factory = NULL; + HRESULT hres = fpCreateDXGIFactory1(&IID_IDXGIFactory6, &dxgi_factory); + if (hres == S_OK) { + feature_flags |= VK_LOADER_FEATURE_PHYSICAL_DEVICE_SORTING; + dxgi_factory->lpVtbl->Release(dxgi_factory); + } +#endif + PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)next_gipa(*created_instance, "vkCreateInstance"); if (fpCreateInstance) { - VkLayerInstanceCreateInfo create_info_disp; - - create_info_disp.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; - create_info_disp.function = VK_LOADER_DATA_CALLBACK; - - create_info_disp.u.pfnSetInstanceLoaderData = vkSetInstanceDispatch; - - create_info_disp.pNext = loader_create_info.pNext; - loader_create_info.pNext = &create_info_disp; - - VkLayerInstanceCreateInfo create_info_disp2; - - create_info_disp2.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO; - create_info_disp2.function = VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK; - - create_info_disp2.u.layerDevice.pfnLayerCreateDevice = loader_layer_create_device; - create_info_disp2.u.layerDevice.pfnLayerDestroyDevice = loader_layer_destroy_device; - - create_info_disp2.pNext = loader_create_info.pNext; - loader_create_info.pNext = &create_info_disp2; + const VkLayerInstanceCreateInfo instance_dispatch = { + .sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO, + .pNext = loader_create_info.pNext, + .function = VK_LOADER_DATA_CALLBACK, + .u = { + .pfnSetInstanceLoaderData = vkSetInstanceDispatch, + }, + }; + const VkLayerInstanceCreateInfo device_callback = { + .sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO, + .pNext = &instance_dispatch, + .function = VK_LOADER_LAYER_CREATE_DEVICE_CALLBACK, + .u = { + .layerDevice = { + .pfnLayerCreateDevice = loader_layer_create_device, + .pfnLayerDestroyDevice = loader_layer_destroy_device, + }, + }, + }; + const VkLayerInstanceCreateInfo loader_features = { + .sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO, + .pNext = &device_callback, + .function = VK_LOADER_FEATURES, + .u = { + .loaderFeatures = feature_flags, + }, + }; + loader_create_info.pNext = &loader_features; res = fpCreateInstance(&loader_create_info, pAllocator, created_instance); } else { @@ -6247,8 +6314,11 @@ // Build the lists of active layers (including metalayers) and expanded layers (with metalayers resolved to their components) loaderAddImplicitLayers(inst, &active_layers, &expanded_layers, instance_layers); - loaderAddEnvironmentLayers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, ENABLED_LAYERS_ENV, &active_layers, &expanded_layers, - instance_layers); + res = loaderAddEnvironmentLayers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, ENABLED_LAYERS_ENV, &active_layers, &expanded_layers, + instance_layers); + if (res != VK_SUCCESS) { + goto out; + } res = loaderAddLayerNamesToList(inst, &active_layers, &expanded_layers, pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames, instance_layers); if (VK_SUCCESS != res) { @@ -6980,11 +7050,136 @@ return res; } +struct LoaderSortedPhysicalDevice { + uint32_t device_count; + VkPhysicalDevice* physical_devices; + uint32_t icd_index; + struct loader_icd_term* icd_term; +}; + +// This function allocates an array in sorted_devices which must be freed by the caller if not null +VkResult ReadSortedPhysicalDevices(struct loader_instance *inst, struct LoaderSortedPhysicalDevice **sorted_devices, uint32_t* sorted_count) +{ + VkResult res = VK_SUCCESS; + uint32_t sorted_alloc = 0; + struct loader_icd_term* icd_term = NULL; + +#if defined(_WIN32) + IDXGIFactory6* dxgi_factory = NULL; + HRESULT hres = fpCreateDXGIFactory1(&IID_IDXGIFactory6, &dxgi_factory); + if (hres != S_OK) { + loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Failed to create DXGI factory 6. Physical devices will not be sorted"); + } + else { + sorted_alloc = 16; + *sorted_devices = loader_instance_heap_alloc(inst, sorted_alloc * sizeof(struct LoaderSortedPhysicalDevice), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (*sorted_devices == NULL) { + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + + memset(*sorted_devices, 0, sorted_alloc * sizeof(struct LoaderSortedPhysicalDevice)); + + *sorted_count = 0; + for (uint32_t i = 0; ; ++i) { + IDXGIAdapter1* adapter; + hres = dxgi_factory->lpVtbl->EnumAdapterByGpuPreference(dxgi_factory, i, DXGI_GPU_PREFERENCE_UNSPECIFIED, &IID_IDXGIAdapter1, &adapter); + if (hres == DXGI_ERROR_NOT_FOUND) { + break; // No more adapters + } + else if (hres != S_OK) { + loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Failed to enumerate adapters by GPU preference at index %u. This adapter will not be sorted", i); + break; + } + + DXGI_ADAPTER_DESC1 description; + hres = adapter->lpVtbl->GetDesc1(adapter, &description); + if (hres != S_OK) { + loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Failed to get adapter LUID index %u. This adapter will not be sorted", i); + continue; + } + + if (sorted_alloc <= i) { + uint32_t old_size = sorted_alloc * sizeof(struct LoaderSortedPhysicalDevice); + *sorted_devices = loader_instance_heap_realloc(inst, *sorted_devices, old_size, 2 * old_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (*sorted_devices == NULL) { + adapter->lpVtbl->Release(adapter); + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + sorted_alloc *= 2; + } + struct LoaderSortedPhysicalDevice *sorted_array = *sorted_devices; + sorted_array[*sorted_count].device_count = 0; + sorted_array[*sorted_count].physical_devices = NULL; + //*sorted_count = i; + + icd_term = inst->icd_terms; + for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) { + // This is the new behavior, which cannot be run unless the ICD provides EnumerateAdapterPhysicalDevices + if (icd_term->scanned_icd->EnumerateAdapterPhysicalDevices == NULL) { + continue; + } + + uint32_t count; + VkResult vkres = icd_term->scanned_icd->EnumerateAdapterPhysicalDevices(icd_term->instance, description.AdapterLuid, &count, NULL); + if (vkres == VK_ERROR_INCOMPATIBLE_DRIVER) { + continue; // This driver doesn't support the adapter + } + else if (vkres != VK_SUCCESS) { + loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Failed to convert DXGI adapter into Vulkan physical device with unexpected error code"); + continue; + } + + // Get the actual physical devices + if (0 != count) + { + do { + sorted_array[*sorted_count].physical_devices = loader_instance_heap_realloc(inst, sorted_array[*sorted_count].physical_devices, sorted_array[*sorted_count].device_count * sizeof(VkPhysicalDevice), count * sizeof(VkPhysicalDevice), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (sorted_array[*sorted_count].physical_devices == NULL) { + res = VK_ERROR_OUT_OF_HOST_MEMORY; + break; + } + sorted_array[*sorted_count].device_count = count; + } while (vkres = icd_term->scanned_icd->EnumerateAdapterPhysicalDevices(icd_term->instance, description.AdapterLuid, &count, sorted_array[*sorted_count].physical_devices) == VK_INCOMPLETE); + } + + if (vkres != VK_SUCCESS) { + loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, "Failed to convert DXGI adapter into Vulkan physical device"); + continue; + } + else if (res == VK_ERROR_OUT_OF_HOST_MEMORY) { + goto out; + } + inst->total_gpu_count += (sorted_array[*sorted_count].device_count = count); + sorted_array[*sorted_count].icd_index = icd_idx; + sorted_array[*sorted_count].icd_term = icd_term; + ++(*sorted_count); + } + + adapter->lpVtbl->Release(adapter); + } + + dxgi_factory->lpVtbl->Release(dxgi_factory); + } + +out: +#endif + + if (*sorted_count == 0 && *sorted_devices != NULL) { + loader_instance_heap_free(inst, *sorted_devices); + *sorted_devices = NULL; + } + return res; +} + VkResult setupLoaderTermPhysDevs(struct loader_instance *inst) { VkResult res = VK_SUCCESS; struct loader_icd_term *icd_term; struct loader_phys_dev_per_icd *icd_phys_dev_array = NULL; struct loader_physical_device_term **new_phys_devs = NULL; + struct LoaderSortedPhysicalDevice *sorted_phys_dev_array = NULL; + uint32_t sorted_count = 0; inst->total_gpu_count = 0; @@ -7001,11 +7196,28 @@ goto out; } memset(icd_phys_dev_array, 0, sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count); - icd_term = inst->icd_terms; + + // Get the physical devices supported by platform sorting mechanism into a separate list + res = ReadSortedPhysicalDevices(inst, &sorted_phys_dev_array, &sorted_count); + if (VK_SUCCESS != res) { + goto out; + } // For each ICD, query the number of physical devices, and then get an // internal value for those physical devices. + icd_term = inst->icd_terms; for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) { + icd_phys_dev_array[icd_idx].count = 0; + icd_phys_dev_array[icd_idx].phys_devs = NULL; + icd_phys_dev_array[icd_idx].this_icd_term = NULL; + + // This is the legacy behavior which should be skipped if EnumerateAdapterPhysicalDevices is available +#if defined(VK_USE_PLATFORM_WIN32_KHR) + if (icd_term->scanned_icd->EnumerateAdapterPhysicalDevices != NULL) { + continue; + } +#endif + res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &icd_phys_dev_array[icd_idx].count, NULL); if (VK_SUCCESS != res) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, @@ -7058,6 +7270,49 @@ // Copy or create everything to fill the new array of physical devices uint32_t idx = 0; + +#if defined(_WIN32) + // Copy over everything found through sorted enumeration + for (uint32_t i = 0; i < sorted_count; ++i) { + for (uint32_t j = 0; j < sorted_phys_dev_array[i].device_count; ++i) { + + // Check if this physical device is already in the old buffer + if (NULL != inst->phys_devs_term) { + for (uint32_t old_idx = 0; old_idx < inst->phys_dev_count_term; old_idx++) { + if (sorted_phys_dev_array[i].physical_devices[j] == inst->phys_devs_term[old_idx]->phys_dev) { + new_phys_devs[idx] = inst->phys_devs_term[old_idx]; + break; + } + } + } + + // If this physical device isn't in the old buffer, then we need to create it. + if (NULL == new_phys_devs[idx]) { + new_phys_devs[idx] = loader_instance_heap_alloc(inst, sizeof(struct loader_physical_device_term), + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (NULL == new_phys_devs[idx]) { + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "setupLoaderTermPhysDevs: Failed to allocate " + "physical device terminator object %d", + idx); + inst->total_gpu_count = idx; + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + + loader_set_dispatch((void *)new_phys_devs[idx], inst->disp); + new_phys_devs[idx]->this_icd_term = sorted_phys_dev_array[i].icd_term; + new_phys_devs[idx]->icd_index = (uint8_t)(sorted_phys_dev_array[i].icd_index); + new_phys_devs[idx]->phys_dev = sorted_phys_dev_array[i].physical_devices[j]; + } + + // Increment the count of new physical devices + idx++; + } + } +#endif + + // Copy over everything found through EnumeratePhysicalDevices for (uint32_t icd_idx = 0; icd_idx < inst->total_icd_count; icd_idx++) { for (uint32_t pd_idx = 0; pd_idx < icd_phys_dev_array[icd_idx].count; pd_idx++) { // Check if this physical device is already in the old buffer @@ -7129,6 +7384,15 @@ inst->phys_devs_term = new_phys_devs; } + if (sorted_phys_dev_array != NULL) { + for (uint32_t i = 0; i < sorted_count; ++i) { + if (sorted_phys_dev_array[i].device_count > 0 && sorted_phys_dev_array[i].physical_devices != NULL) { + loader_instance_heap_free(inst, sorted_phys_dev_array[i].physical_devices); + } + } + loader_instance_heap_free(inst, sorted_phys_dev_array); + } + return res; } @@ -7632,7 +7896,10 @@ uint32_t cur_icd_group_count = 0; VkPhysicalDeviceGroupPropertiesKHR **new_phys_dev_groups = NULL; VkPhysicalDeviceGroupPropertiesKHR *local_phys_dev_groups = NULL; + bool *local_phys_dev_group_sorted = NULL; PFN_vkEnumeratePhysicalDeviceGroups fpEnumeratePhysicalDeviceGroups = NULL; + struct LoaderSortedPhysicalDevice* sorted_phys_dev_array = NULL; + uint32_t sorted_count = 0; if (0 == inst->phys_dev_count_term) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, @@ -7696,7 +7963,8 @@ // Create a temporary array (on the stack) to keep track of the // returned VkPhysicalDevice values. local_phys_dev_groups = loader_stack_alloc(sizeof(VkPhysicalDeviceGroupProperties) * total_count); - if (NULL == local_phys_dev_groups) { + local_phys_dev_group_sorted = loader_stack_alloc(sizeof(bool) * total_count); + if (NULL == local_phys_dev_groups || NULL == local_phys_dev_group_sorted) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "setupLoaderTermPhysDevGroups: Failed to allocate local " "physical device group array of size %d", @@ -7706,17 +7974,31 @@ } // Initialize the memory to something valid memset(local_phys_dev_groups, 0, sizeof(VkPhysicalDeviceGroupProperties) * total_count); + memset(local_phys_dev_group_sorted, 0, sizeof(bool) * total_count); for (uint32_t group = 0; group < total_count; group++) { local_phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR; local_phys_dev_groups[group].pNext = NULL; local_phys_dev_groups[group].subsetAllocation = false; } + // Get the physical devices supported by platform sorting mechanism into a separate list + res = ReadSortedPhysicalDevices(inst, &sorted_phys_dev_array, &sorted_count); + if (VK_SUCCESS != res) { + goto out; + } + cur_icd_group_count = 0; icd_term = inst->icd_terms; for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) { uint32_t count_this_time = total_count - cur_icd_group_count; + // Check if this group can be sorted +#if defined(VK_USE_PLATFORM_WIN32_KHR) + bool icd_sorted = icd_term->scanned_icd->EnumerateAdapterPhysicalDevices != NULL; +#else + bool icd_sorted = false; +#endif + // Get the function pointer to use to call into the ICD. This could be the core or KHR version if (inst->enabled_known_extensions.khr_device_group_creation) { fpEnumeratePhysicalDeviceGroups = icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHR; @@ -7748,10 +8030,14 @@ for (uint32_t indiv_gpu = 0; indiv_gpu < count_this_time; indiv_gpu++) { local_phys_dev_groups[indiv_gpu + cur_icd_group_count].physicalDeviceCount = 1; local_phys_dev_groups[indiv_gpu + cur_icd_group_count].physicalDevices[0] = phys_dev_array[indiv_gpu]; + local_phys_dev_group_sorted[indiv_gpu + cur_icd_group_count] = icd_sorted; } } else { res = fpEnumeratePhysicalDeviceGroups(icd_term->instance, &count_this_time, &local_phys_dev_groups[cur_icd_group_count]); + for (uint32_t group = 0; group < count_this_time; ++group) { + local_phys_dev_group_sorted[group + cur_icd_group_count] = icd_sorted; + } if (VK_SUCCESS != res) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "setupLoaderTermPhysDevGroups: Failed during dispatch call of " @@ -7786,8 +8072,87 @@ } } + uint32_t idx = 0; + +#if defined(_WIN32) + // Copy over everything found through sorted enumeration + for (uint32_t i = 0; i < sorted_count; ++i) { + + // Find the VkPhysicalDeviceGroupProperties object in local_phys_dev_groups + VkPhysicalDeviceGroupProperties *group_properties = NULL; + for (uint32_t group = 0; group < total_count; group++) { + if (sorted_phys_dev_array[i].device_count != local_phys_dev_groups[group].physicalDeviceCount) { + continue; + } + + bool match = true; + for (uint32_t group_gpu = 0; group_gpu < local_phys_dev_groups[group].physicalDeviceCount; group_gpu++) { + if (sorted_phys_dev_array[i].physical_devices[group_gpu] != ((struct loader_physical_device_term*) local_phys_dev_groups[group].physicalDevices[group_gpu])->phys_dev) { + match = false; + break; + } + } + + if (match) { + group_properties = &local_phys_dev_groups[group]; + } + } + + // Check if this physical device group with the same contents is already in the old buffer + for (uint32_t old_idx = 0; old_idx < inst->phys_dev_group_count_term; old_idx++) { + if (NULL != group_properties && group_properties->physicalDeviceCount == inst->phys_dev_groups_term[old_idx]->physicalDeviceCount) { + bool found_all_gpus = true; + for (uint32_t old_gpu = 0; old_gpu < inst->phys_dev_groups_term[old_idx]->physicalDeviceCount; old_gpu++) { + bool found_gpu = false; + for (uint32_t new_gpu = 0; new_gpu < group_properties->physicalDeviceCount; new_gpu++) { + if (group_properties->physicalDevices[new_gpu] == inst->phys_dev_groups_term[old_idx]->physicalDevices[old_gpu]) { + found_gpu = true; + break; + } + } + + if (!found_gpu) { + found_all_gpus = false; + break; + } + } + if (!found_all_gpus) { + continue; + } + else { + new_phys_dev_groups[idx] = inst->phys_dev_groups_term[old_idx]; + break; + } + } + } + + // If this physical device group isn't in the old buffer, create it + if (group_properties != NULL && NULL == new_phys_dev_groups[idx]) { + new_phys_dev_groups[idx] = (VkPhysicalDeviceGroupPropertiesKHR*)loader_instance_heap_alloc( + inst, sizeof(VkPhysicalDeviceGroupPropertiesKHR), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (NULL == new_phys_dev_groups[idx]) { + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "setupLoaderTermPhysDevGroups: Failed to allocate " + "physical device group Terminator object %d", + idx); + total_count = idx; + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + memcpy(new_phys_dev_groups[idx], group_properties, sizeof(VkPhysicalDeviceGroupPropertiesKHR)); + } + + ++idx; + } +#endif + // Copy or create everything to fill the new array of physical device groups for (uint32_t new_idx = 0; new_idx < total_count; new_idx++) { + // Skip groups which have been included through sorting + if (local_phys_dev_group_sorted[new_idx] || local_phys_dev_groups[new_idx].physicalDeviceCount == 0) { + continue; + } + // Check if this physical device group with the same contents is already in the old buffer for (uint32_t old_idx = 0; old_idx < inst->phys_dev_group_count_term; old_idx++) { if (local_phys_dev_groups[new_idx].physicalDeviceCount == inst->phys_dev_groups_term[old_idx]->physicalDeviceCount) { @@ -7809,28 +8174,30 @@ if (!found_all_gpus) { continue; } else { - new_phys_dev_groups[new_idx] = inst->phys_dev_groups_term[old_idx]; + new_phys_dev_groups[idx] = inst->phys_dev_groups_term[old_idx]; break; } } } // If this physical device group isn't in the old buffer, create it - if (NULL == new_phys_dev_groups[new_idx]) { - new_phys_dev_groups[new_idx] = (VkPhysicalDeviceGroupPropertiesKHR *)loader_instance_heap_alloc( + if (NULL == new_phys_dev_groups[idx]) { + new_phys_dev_groups[idx] = (VkPhysicalDeviceGroupPropertiesKHR *)loader_instance_heap_alloc( inst, sizeof(VkPhysicalDeviceGroupPropertiesKHR), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (NULL == new_phys_dev_groups[new_idx]) { + if (NULL == new_phys_dev_groups[idx]) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "setupLoaderTermPhysDevGroups: Failed to allocate " "physical device group Terminator object %d", - new_idx); - total_count = new_idx; + idx); + total_count = idx; res = VK_ERROR_OUT_OF_HOST_MEMORY; goto out; } - memcpy(new_phys_dev_groups[new_idx], &local_phys_dev_groups[new_idx], + memcpy(new_phys_dev_groups[idx], &local_phys_dev_groups[new_idx], sizeof(VkPhysicalDeviceGroupPropertiesKHR)); } + + ++idx; } out: @@ -7867,6 +8234,15 @@ inst->phys_dev_groups_term = new_phys_dev_groups; } + if (sorted_phys_dev_array != NULL) { + for (uint32_t i = 0; i < sorted_count; ++i) { + if (sorted_phys_dev_array[i].device_count > 0 && sorted_phys_dev_array[i].physical_devices != NULL) { + loader_instance_heap_free(inst, sorted_phys_dev_array[i].physical_devices); + } + } + loader_instance_heap_free(inst, sorted_phys_dev_array); + } + return res; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vulkan-Loader-1.2.148/loader/loader.h new/Vulkan-Loader-1.2.151/loader/loader.h --- old/Vulkan-Loader-1.2.148/loader/loader.h 2020-07-20 20:36:53.000000000 +0200 +++ new/Vulkan-Loader-1.2.151/loader/loader.h 2020-08-17 19:41:19.000000000 +0200 @@ -387,6 +387,9 @@ PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr; PFN_vkCreateInstance CreateInstance; PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; +#if defined(VK_USE_PLATFORM_WIN32_KHR) + PFN_vk_icdEnumerateAdapterPhysicalDevices EnumerateAdapterPhysicalDevices; +#endif }; static inline struct loader_instance *loader_instance(VkInstance instance) { return (struct loader_instance *)instance; } @@ -476,9 +479,9 @@ void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list); void loaderDestroyLayerList(const struct loader_instance *inst, struct loader_device *device, struct loader_layer_list *layer_list); void loaderDeleteLayerListAndProperties(const struct loader_instance *inst, struct loader_layer_list *layer_list); -void loaderAddLayerNameToList(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags, - const struct loader_layer_list *source_list, struct loader_layer_list *target_list, - struct loader_layer_list *expanded_target_list); +VkResult loaderAddLayerNameToList(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags, + const struct loader_layer_list *source_list, struct loader_layer_list *target_list, + struct loader_layer_list *expanded_target_list); void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list); VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list); void loaderScanForLayers(struct loader_instance *inst, struct loader_layer_list *instance_layers); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Vulkan-Loader-1.2.148/scripts/known_good.json new/Vulkan-Loader-1.2.151/scripts/known_good.json --- old/Vulkan-Loader-1.2.148/scripts/known_good.json 2020-07-20 20:36:53.000000000 +0200 +++ new/Vulkan-Loader-1.2.151/scripts/known_good.json 2020-08-17 19:41:19.000000000 +0200 @@ -6,7 +6,7 @@ "sub_dir" : "Vulkan-Headers", "build_dir" : "Vulkan-Headers/build", "install_dir" : "Vulkan-Headers/build/install", - "commit" : "v1.2.148" + "commit" : "v1.2.151" } ], "install_names" : {
