diff options
Diffstat (limited to 'thirdparty/vulkan/loader')
-rw-r--r-- | thirdparty/vulkan/loader/adapters.h | 80 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/dxgi_loader.c | 23 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/dxgi_loader.h | 8 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/extension_manual.c | 11 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/loader.c | 376 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/loader.h | 3 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/unknown_ext_chain_gas.S (renamed from thirdparty/vulkan/loader/unknown_ext_chain_gas.asm) | 12 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/vk_dispatch_table_helper.h | 21 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/vk_layer_dispatch_table.h | 13 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/vk_loader_extensions.c | 165 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/vk_loader_extensions.h | 1 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/vk_loader_platform.h | 39 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/wsi.c | 91 | ||||
-rw-r--r-- | thirdparty/vulkan/loader/wsi.h | 7 |
14 files changed, 764 insertions, 86 deletions
diff --git a/thirdparty/vulkan/loader/adapters.h b/thirdparty/vulkan/loader/adapters.h new file mode 100644 index 0000000000..ef97d66573 --- /dev/null +++ b/thirdparty/vulkan/loader/adapters.h @@ -0,0 +1,80 @@ +/* +* Copyright (c) 2019 The Khronos Group Inc. +* Copyright (c) 2019 Valve Corporation +* Copyright (c) 2019 LunarG, Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* Author: Lenny Komow <lenny@lunarg.com> +*/ + +typedef struct LoaderEnumAdapters2 { + ULONG adapter_count; + struct { + UINT handle; + LUID luid; + ULONG source_count; + BOOL present_move_regions_preferred; + } * adapters; +} LoaderEnumAdapters2; + +typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderEnumAdapters2)(const LoaderEnumAdapters2 *); + +typedef enum AdapterInfoType { + LOADER_QUERY_TYPE_REGISTRY = 48, +} AdapterInfoType; + +typedef struct LoaderQueryAdapterInfo { + UINT handle; + AdapterInfoType type; + VOID *private_data; + UINT private_data_size; +} LoaderQueryAdapterInfo; + +typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderQueryAdapterInfo)(const LoaderQueryAdapterInfo *); + +typedef enum LoaderQueryRegistryType { + LOADER_QUERY_REGISTRY_ADAPTER_KEY = 1, +} LoaderQueryRegistryType; + +typedef enum LoaderQueryRegistryStatus { + LOADER_QUERY_REGISTRY_STATUS_SUCCESS = 0, + LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW = 1, +} LoaderQueryRegistryStatus; + +typedef struct LoaderQueryRegistryFlags { + union { + struct { + UINT translate_path : 1; + UINT mutable_value : 1; + UINT reserved : 30; + }; + UINT value; + }; +} LoaderQueryRegistryFlags; + +typedef struct LoaderQueryRegistryInfo { + LoaderQueryRegistryType query_type; + LoaderQueryRegistryFlags query_flags; + WCHAR value_name[MAX_PATH]; + ULONG value_type; + ULONG physical_adapter_index; + ULONG output_value_size; + LoaderQueryRegistryStatus status; + union { + DWORD output_dword; + UINT64 output_qword; + WCHAR output_string[1]; + BYTE output_binary[1]; + }; +} LoaderQueryRegistryInfo; diff --git a/thirdparty/vulkan/loader/dxgi_loader.c b/thirdparty/vulkan/loader/dxgi_loader.c new file mode 100644 index 0000000000..c2a3fa5638 --- /dev/null +++ b/thirdparty/vulkan/loader/dxgi_loader.c @@ -0,0 +1,23 @@ +#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; +}
\ No newline at end of file diff --git a/thirdparty/vulkan/loader/dxgi_loader.h b/thirdparty/vulkan/loader/dxgi_loader.h new file mode 100644 index 0000000000..00daf08ed2 --- /dev/null +++ b/thirdparty/vulkan/loader/dxgi_loader.h @@ -0,0 +1,8 @@ +#ifndef DXGI_LOADER_H +#define DXGI_LOADER_H + +#include <dxgi1_2.h> + +HRESULT dyn_CreateDXGIFactory1(REFIID riid, void **ppFactory); + +#endif
\ No newline at end of file diff --git a/thirdparty/vulkan/loader/extension_manual.c b/thirdparty/vulkan/loader/extension_manual.c index 640db2f789..490496d7c7 100644 --- a/thirdparty/vulkan/loader/extension_manual.c +++ b/thirdparty/vulkan/loader/extension_manual.c @@ -58,6 +58,17 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2K uint8_t icd_index = phys_dev_term->icd_index; if (icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR != NULL) { + VkBaseOutStructure *pNext = (VkBaseOutStructure *)pSurfaceCapabilities->pNext; + while (pNext != NULL) { + if ((int)pNext->sType == VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR) { + // Not all ICDs may be supporting VK_KHR_surface_protected_capabilities + // Initialize VkSurfaceProtectedCapabilitiesKHR.supportsProtected to false and + // if an ICD supports protected surfaces, it will reset it to true accordingly. + ((VkSurfaceProtectedCapabilitiesKHR *)pNext)->supportsProtected = VK_FALSE; + } + pNext = (VkBaseOutStructure *)pNext->pNext; + } + // Pass the call to the driver, possibly unwrapping the ICD surface if (icd_surface->real_icd_surfaces != NULL && (void *)icd_surface->real_icd_surfaces[icd_index] != NULL) { VkPhysicalDeviceSurfaceInfo2KHR info_copy = *pSurfaceInfo; diff --git a/thirdparty/vulkan/loader/loader.c b/thirdparty/vulkan/loader/loader.c index 5e4de5e749..398c44bf9c 100644 --- a/thirdparty/vulkan/loader/loader.c +++ b/thirdparty/vulkan/loader/loader.c @@ -25,6 +25,12 @@ * */ +// This needs to be defined first, or else we'll get redefinitions on NTSTATUS values +#ifdef _WIN32 +#define UMDF_USING_NTSTATUS +#include <ntstatus.h> +#endif + #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif @@ -63,6 +69,9 @@ #include <cfgmgr32.h> #include <initguid.h> #include <devpkey.h> +#include <winternl.h> +#include "adapters.h" +#include "dxgi_loader.h" #endif // This is a CMake generated file with #defines for any functions/includes @@ -231,6 +240,10 @@ void *loader_device_heap_realloc(const struct loader_device *device, void *pMemo // Environment variables #if defined(__linux__) || defined(__APPLE__) +static inline bool IsHighIntegrity() { + return geteuid() != getuid() || getegid() != getgid(); +} + static inline char *loader_getenv(const char *name, const struct loader_instance *inst) { // No allocation of memory necessary for Linux, but we should at least touch // the inst pointer to get rid of compiler warnings. @@ -247,7 +260,7 @@ static inline char *loader_secure_getenv(const char *name, const struct loader_i // that can do damage. // This algorithm is derived from glibc code that sets an internal // variable (__libc_enable_secure) if the process is running under setuid or setgid. - return geteuid() != getuid() || getegid() != getgid() ? NULL : loader_getenv(name, inst); + return IsHighIntegrity() ? NULL : loader_getenv(name, inst); #else // Linux #ifdef HAVE_SECURE_GETENV @@ -274,6 +287,28 @@ static inline void loader_free_getenv(char *val, const struct loader_instance *i #elif defined(WIN32) +static inline bool IsHighIntegrity() { + HANDLE process_token; + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) { + // Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD. + uint8_t mandatory_label_buffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)]; + DWORD buffer_size; + if (GetTokenInformation(process_token, TokenIntegrityLevel, mandatory_label_buffer, sizeof(mandatory_label_buffer), + &buffer_size) != 0) { + const TOKEN_MANDATORY_LABEL *mandatory_label = (const TOKEN_MANDATORY_LABEL *)mandatory_label_buffer; + const DWORD sub_authority_count = *GetSidSubAuthorityCount(mandatory_label->Label.Sid); + const DWORD integrity_level = *GetSidSubAuthority(mandatory_label->Label.Sid, sub_authority_count - 1); + + CloseHandle(process_token); + return integrity_level > SECURITY_MANDATORY_MEDIUM_RID; + } + + CloseHandle(process_token); + } + + return false; +} + static inline char *loader_getenv(const char *name, const struct loader_instance *inst) { char *retVal; DWORD valSize; @@ -300,7 +335,10 @@ static inline char *loader_getenv(const char *name, const struct loader_instance } static inline char *loader_secure_getenv(const char *name, const struct loader_instance *inst) { - // No secure version for Windows as far as I know + if (IsHighIntegrity()) { + return NULL; + } + return loader_getenv(name, inst); } @@ -486,12 +524,11 @@ VKAPI_ATTR VkResult VKAPI_CALL vkSetDeviceDispatch(VkDevice device, void *object static bool loaderAddJsonEntry(const struct loader_instance *inst, char **reg_data, // list of JSON files PDWORD total_size, // size of reg_data - LPCTSTR key_name, // key name - used for debug prints - i.e. VulkanDriverName + LPCSTR key_name, // key name - used for debug prints - i.e. VulkanDriverName DWORD key_type, // key data type LPSTR json_path, // JSON string to add to the list reg_data DWORD json_size, // size in bytes of json_path VkResult *result) { - // Check for and ignore duplicates. if (*reg_data && strstr(*reg_data, json_path)) { // Success. The json_path is already in the list. @@ -542,8 +579,8 @@ static bool loaderAddJsonEntry(const struct loader_instance *inst, // This function looks for filename in given device handle, filename is then added to return list // function return true if filename was appended to reg_data list // If error occures result is updated with failure reason -bool loaderGetDeviceRegistryEntry(const struct loader_instance *inst, char **reg_data, PDWORD total_size, DEVINST dev_id, LPCTSTR value_name, VkResult *result) -{ +bool loaderGetDeviceRegistryEntry(const struct loader_instance *inst, char **reg_data, PDWORD total_size, DEVINST dev_id, + LPCSTR value_name, VkResult *result) { HKEY hkrKey = INVALID_HANDLE_VALUE; DWORD requiredSize, data_type; char *manifest_path = NULL; @@ -635,7 +672,8 @@ out: // // *reg_data contains a string list of filenames as pointer. // When done using the returned string list, the caller should free the pointer. -VkResult loaderGetDeviceRegistryFiles(const struct loader_instance *inst, char **reg_data, PDWORD reg_data_size, LPCTSTR value_name) { +VkResult loaderGetDeviceRegistryFiles(const struct loader_instance *inst, char **reg_data, PDWORD reg_data_size, + LPCSTR value_name) { static const wchar_t *softwareComponentGUID = L"{5c4c3332-344d-483c-8739-259e934c9cc8}"; static const wchar_t *displayGUID = L"{4d36e968-e325-11ce-bfc1-08002be10318}"; const ULONG flags = CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT; @@ -675,7 +713,7 @@ VkResult loaderGetDeviceRegistryFiles(const struct loader_instance *inst, char * for (wchar_t *deviceName = pDeviceNames; *deviceName; deviceName += wcslen(deviceName) + 1) { CONFIGRET status = CM_Locate_DevNodeW(&devID, deviceName, CM_LOCATE_DEVNODE_NORMAL); if (CR_SUCCESS != status) { - loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to open DevNode %s", + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to open DevNode %ls", deviceName); continue; } @@ -684,17 +722,17 @@ VkResult loaderGetDeviceRegistryFiles(const struct loader_instance *inst, char * if (CR_SUCCESS != status) { - loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to probe device status %s", + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: failed to probe device status %ls", deviceName); continue; } if ((ulStatus & DN_HAS_PROBLEM) && (ulProblem == CM_PROB_NEED_RESTART || ulProblem == DN_NEED_RESTART)) { loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, - "loaderGetDeviceRegistryFiles: device %s is pending reboot, skipping ...", deviceName); + "loaderGetDeviceRegistryFiles: device %ls is pending reboot, skipping ...", deviceName); continue; } - loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: opening device %s", deviceName); + loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "loaderGetDeviceRegistryFiles: opening device %ls", deviceName); if (loaderGetDeviceRegistryEntry(inst, reg_data, reg_data_size, devID, value_name, &result)) { found = true; @@ -716,7 +754,7 @@ VkResult loaderGetDeviceRegistryFiles(const struct loader_instance *inst, char * CM_Get_Device_IDW(childID, buffer, MAX_DEVICE_ID_LEN, 0); loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, - "loaderGetDeviceRegistryFiles: Opening child device %d - %s", childID, buffer); + "loaderGetDeviceRegistryFiles: Opening child device %d - %ls", childID, buffer); status = CM_Get_DevNode_Registry_PropertyW(childID, CM_DRP_CLASSGUID, NULL, &childGuid, &childGuidSize, 0); if (status != CR_SUCCESS) { @@ -768,6 +806,49 @@ static char *loader_get_next_path(char *path); // When done using the returned string list, the caller should free the pointer. VkResult loaderGetRegistryFiles(const struct loader_instance *inst, char *location, bool use_secondary_hive, char **reg_data, PDWORD reg_data_size) { + // This list contains all of the allowed ICDs. This allows us to verify that a device is actually present from the vendor + // specified. This does disallow other vendors, but any new driver should use the device-specific registries anyway. + static const struct { + const char *filename; + int vendor_id; + } known_drivers[] = { +#if defined(_WIN64) + { + .filename = "igvk64.json", + .vendor_id = 0x8086, + }, + { + .filename = "nv-vk64.json", + .vendor_id = 0x10de, + }, + { + .filename = "amd-vulkan64.json", + .vendor_id = 0x1002, + }, + { + .filename = "amdvlk64.json", + .vendor_id = 0x1002, + }, +#else + { + .filename = "igvk32.json", + .vendor_id = 0x8086, + }, + { + .filename = "nv-vk32.json", + .vendor_id = 0x10de, + }, + { + .filename = "amd-vulkan32.json", + .vendor_id = 0x1002, + }, + { + .filename = "amdvlk32.json", + .vendor_id = 0x1002, + }, +#endif + }; + LONG rtn_value; HKEY hive = DEFAULT_VK_REGISTRY_HIVE, key; DWORD access_flags; @@ -780,12 +861,25 @@ VkResult loaderGetRegistryFiles(const struct loader_instance *inst, char *locati DWORD value_size = sizeof(value); VkResult result = VK_SUCCESS; bool found = false; + IDXGIFactory1 *dxgi_factory = NULL; + bool is_driver = !strcmp(location, VK_DRIVERS_INFO_REGISTRY_LOC); if (NULL == reg_data) { result = VK_ERROR_INITIALIZATION_FAILED; goto out; } + if (is_driver) { + HRESULT hres = dyn_CreateDXGIFactory1(&IID_IDXGIFactory1, &dxgi_factory); + if (hres != S_OK) { + loader_log( + inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, + "loaderGetRegistryFiles: Failed to create dxgi factory for ICD registry verification. No ICDs will be added from " + "legacy registry locations"); + goto out; + } + } + while (*loc) { next = loader_get_next_path(loc); access_flags = KEY_QUERY_VALUE; @@ -820,9 +914,58 @@ VkResult loaderGetRegistryFiles(const struct loader_instance *inst, char *locati *reg_data = new_ptr; *reg_data_size *= 2; } + + // We've now found a json file. If this is an ICD, we still need to check if there is actually a device + // that matches this ICD loader_log( inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, "Located json file \"%s\" from registry \"%s\\%s\"", name, hive == DEFAULT_VK_REGISTRY_HIVE ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR, location); + if (is_driver) { + int i; + for (i = 0; i < sizeof(known_drivers) / sizeof(known_drivers[0]); ++i) { + if (!strcmp(name + strlen(name) - strlen(known_drivers[i].filename), known_drivers[i].filename)) { + break; + } + } + if (i == sizeof(known_drivers) / sizeof(known_drivers[0])) { + loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, + "Driver %s is not recognized as a known driver. It will be assumed to be active", name); + } else { + bool found_gpu = false; + for (int j = 0;; ++j) { + IDXGIAdapter1 *adapter; + HRESULT hres = dxgi_factory->lpVtbl->EnumAdapters1(dxgi_factory, j, &adapter); + if (hres == DXGI_ERROR_NOT_FOUND) { + break; + } else if (hres != S_OK) { + loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0, + "Failed to enumerate DXGI adapters at index %d. As a result, drivers may be skipped", j); + continue; + } + + DXGI_ADAPTER_DESC1 description; + hres = adapter->lpVtbl->GetDesc1(adapter, &description); + if (hres != S_OK) { + loader_log( + inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, + "Failed to get DXGI adapter information at index %d. As a result, drivers may be skipped", j); + continue; + } + + if (description.VendorId == known_drivers[i].vendor_id) { + found_gpu = true; + break; + } + } + + if (!found_gpu) { + loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, + "Dropping driver %s as no corresponduing DXGI adapter was found", name); + continue; + } + } + } + if (strlen(*reg_data) == 0) { // The list is emtpy. Add the first entry. (void)snprintf(*reg_data, name_size + 1, "%s", name); @@ -856,7 +999,8 @@ VkResult loaderGetRegistryFiles(const struct loader_instance *inst, char *locati } } } - name_size = 2048; + name_size = sizeof(name); + value_size = sizeof(value); } RegCloseKey(key); } @@ -875,6 +1019,9 @@ VkResult loaderGetRegistryFiles(const struct loader_instance *inst, char *locati } out: + if (is_driver && dxgi_factory != NULL) { + dxgi_factory->lpVtbl->Release(dxgi_factory); + } return result; } @@ -1635,7 +1782,7 @@ bool loaderImplicitLayerIsEnabled(const struct loader_instance *inst, const stru enable = true; } else { // Otherwise, only enable this layer if the enable environment variable is defined - env_value = loader_secure_getenv(prop->enable_env_var.name, inst); + env_value = loader_getenv(prop->enable_env_var.name, inst); if (env_value && !strcmp(prop->enable_env_var.value, env_value)) { enable = true; } @@ -1644,7 +1791,7 @@ bool loaderImplicitLayerIsEnabled(const struct loader_instance *inst, const stru // The disable_environment has priority over everything else. If it is defined, the layer is always // disabled. - env_value = loader_secure_getenv(prop->disable_env_var.name, inst); + env_value = loader_getenv(prop->disable_env_var.name, inst); if (env_value) { enable = false; } @@ -1906,7 +2053,8 @@ struct loader_icd_term *loader_get_icd_and_device(const VkDevice device, struct for (struct loader_device *dev = icd_term->logical_device_list; dev; dev = dev->next) // Value comparison of device prevents object wrapping by layers if (loader_get_dispatch(dev->icd_device) == loader_get_dispatch(device) || - loader_get_dispatch(dev->chain_device) == loader_get_dispatch(device)) { + (dev->chain_device != VK_NULL_HANDLE && + loader_get_dispatch(dev->chain_device) == loader_get_dispatch(device))) { *found_dev = dev; if (NULL != icd_index) { *icd_index = index; @@ -2287,6 +2435,12 @@ void loader_initialize(void) { .malloc_fn = loader_instance_tls_heap_alloc, .free_fn = loader_instance_tls_heap_free, }; cJSON_InitHooks(&alloc_fns); + +#if defined(_WIN32) + // 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"); +#endif } struct loader_data_files { @@ -3685,8 +3839,10 @@ static VkResult ReadDataFilesInSearchPaths(const struct loader_instance *inst, e search_path_size += DetermineDataFilePathSize(EXTRASYSCONFDIR, rel_size); #endif if (is_directory_list) { - search_path_size += DetermineDataFilePathSize(xdgdatahome, rel_size); - search_path_size += DetermineDataFilePathSize(home_root, rel_size); + if (!IsHighIntegrity()) { + search_path_size += DetermineDataFilePathSize(xdgdatahome, rel_size); + search_path_size += DetermineDataFilePathSize(home_root, rel_size); + } } #endif } @@ -3793,26 +3949,168 @@ out: } #ifdef _WIN32 +// Read manifest JSON files uing the Windows driver interface +static VkResult ReadManifestsFromD3DAdapters(const struct loader_instance *inst, char **reg_data, PDWORD reg_data_size, + const wchar_t *value_name) { + VkResult result = VK_INCOMPLETE; + LoaderEnumAdapters2 adapters = {.adapter_count = 0, .adapters = NULL}; + LoaderQueryRegistryInfo *full_info = NULL; + size_t full_info_size = 0; + char *json_path = NULL; + size_t json_path_size = 0; + + PFN_LoaderEnumAdapters2 fpLoaderEnumAdapters2 = + (PFN_LoaderEnumAdapters2)GetProcAddress(GetModuleHandle("gdi32.dll"), "D3DKMTEnumAdapters2"); + PFN_LoaderQueryAdapterInfo fpLoaderQueryAdapterInfo = + (PFN_LoaderQueryAdapterInfo)GetProcAddress(GetModuleHandle("gdi32.dll"), "D3DKMTQueryAdapterInfo"); + if (fpLoaderEnumAdapters2 == NULL || fpLoaderQueryAdapterInfo == NULL) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + + // Get all of the adapters + NTSTATUS status = fpLoaderEnumAdapters2(&adapters); + if (status == STATUS_SUCCESS && adapters.adapter_count > 0) { + adapters.adapters = loader_instance_heap_alloc(inst, sizeof(*adapters.adapters) * adapters.adapter_count, + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (adapters.adapters == NULL) { + goto out; + } + status = fpLoaderEnumAdapters2(&adapters); + } + if (status != STATUS_SUCCESS) { + goto out; + } + + // If that worked, we need to get the manifest file(s) for each adapter + for (ULONG i = 0; i < adapters.adapter_count; ++i) { + // The first query should just check if the field exists and how big it is + LoaderQueryRegistryInfo filename_info = { + .query_type = LOADER_QUERY_REGISTRY_ADAPTER_KEY, + .query_flags = + { + .translate_path = true, + }, + .value_type = REG_MULTI_SZ, + .physical_adapter_index = 0, + }; + wcsncpy(filename_info.value_name, value_name, sizeof(filename_info.value_name) / sizeof(DWORD)); + LoaderQueryAdapterInfo query_info = { + .handle = adapters.adapters[i].handle, + .type = LOADER_QUERY_TYPE_REGISTRY, + .private_data = &filename_info, + .private_data_size = sizeof(filename_info), + }; + status = fpLoaderQueryAdapterInfo(&query_info); + + // This error indicates that the type didn't match, so we'll try a REG_SZ + if (status != STATUS_SUCCESS) { + filename_info.value_type = REG_SZ; + status = fpLoaderQueryAdapterInfo(&query_info); + } + + if (status != STATUS_SUCCESS || filename_info.status != LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW) { + continue; + } + + while (status == STATUS_SUCCESS && + ((LoaderQueryRegistryInfo *)query_info.private_data)->status == LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW) { + bool needs_copy = (full_info == NULL); + size_t full_size = sizeof(LoaderQueryRegistryInfo) + filename_info.output_value_size; + void *buffer = + loader_instance_heap_realloc(inst, full_info, full_info_size, full_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (buffer == NULL) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + full_info = buffer; + full_info_size = full_size; + + if (needs_copy) { + memcpy(full_info, &filename_info, sizeof(LoaderQueryRegistryInfo)); + } + query_info.private_data = full_info; + query_info.private_data_size = (UINT)full_info_size; + status = fpLoaderQueryAdapterInfo(&query_info); + } + + if (status != STATUS_SUCCESS || full_info->status != LOADER_QUERY_REGISTRY_STATUS_SUCCESS) { + goto out; + } + + // Convert the wide string to a narrow string + void *buffer = loader_instance_heap_realloc(inst, json_path, json_path_size, full_info->output_value_size, + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (buffer == NULL) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + json_path = buffer; + json_path_size = full_info->output_value_size; + + // Iterate over each component string + for (const wchar_t *curr_path = full_info->output_string; curr_path[0] != '\0'; curr_path += wcslen(curr_path) + 1) { + WideCharToMultiByte(CP_UTF8, 0, curr_path, -1, json_path, (int)json_path_size, NULL, NULL); + + // Add the string to the output list + result = VK_SUCCESS; + loaderAddJsonEntry(inst, reg_data, reg_data_size, (LPCTSTR)L"EnumAdapters", REG_SZ, json_path, + (DWORD)strlen(json_path) + 1, &result); + if (result != VK_SUCCESS) { + goto out; + } + + // If this is a string and not a multi-string, we don't want to go throught the loop more than once + if (full_info->value_type == REG_SZ) { + break; + } + } + } + +out: + if (json_path != NULL) { + loader_instance_heap_free(inst, json_path); + } + if (full_info != NULL) { + loader_instance_heap_free(inst, full_info); + } + if (adapters.adapters != NULL) { + loader_instance_heap_free(inst, adapters.adapters); + } + + return result; +} + // Look for data files in the registry. static VkResult ReadDataFilesInRegistry(const struct loader_instance *inst, enum loader_data_files_type data_file_type, bool warn_if_not_present, char *registry_location, struct loader_data_files *out_files) { VkResult vk_result = VK_SUCCESS; bool is_icd = (data_file_type == LOADER_DATA_FILE_MANIFEST_ICD); - bool use_secondary_hive = data_file_type == LOADER_DATA_FILE_MANIFEST_LAYER; char *search_path = NULL; // These calls look at the PNP/Device section of the registry. VkResult regHKR_result = VK_SUCCESS; DWORD reg_size = 4096; if (!strncmp(registry_location, VK_DRIVERS_INFO_REGISTRY_LOC, sizeof(VK_DRIVERS_INFO_REGISTRY_LOC))) { - regHKR_result = loaderGetDeviceRegistryFiles(inst, &search_path, ®_size, LoaderPnpDriverRegistry()); + // If we're looking for drivers we need to try enumerating adapters + regHKR_result = ReadManifestsFromD3DAdapters(inst, &search_path, ®_size, LoaderPnpDriverRegistryWide()); + if (regHKR_result == VK_INCOMPLETE) { + regHKR_result = loaderGetDeviceRegistryFiles(inst, &search_path, ®_size, LoaderPnpDriverRegistry()); + } } else if (!strncmp(registry_location, VK_ELAYERS_INFO_REGISTRY_LOC, sizeof(VK_ELAYERS_INFO_REGISTRY_LOC))) { - regHKR_result = loaderGetDeviceRegistryFiles(inst, &search_path, ®_size, LoaderPnpELayerRegistry()); + regHKR_result = ReadManifestsFromD3DAdapters(inst, &search_path, ®_size, LoaderPnpELayerRegistryWide()); + if (regHKR_result == VK_INCOMPLETE) { + regHKR_result = loaderGetDeviceRegistryFiles(inst, &search_path, ®_size, LoaderPnpELayerRegistry()); + } } else if (!strncmp(registry_location, VK_ILAYERS_INFO_REGISTRY_LOC, sizeof(VK_ILAYERS_INFO_REGISTRY_LOC))) { - regHKR_result = loaderGetDeviceRegistryFiles(inst, &search_path, ®_size, LoaderPnpILayerRegistry()); + regHKR_result = ReadManifestsFromD3DAdapters(inst, &search_path, ®_size, LoaderPnpILayerRegistryWide()); + if (regHKR_result == VK_INCOMPLETE) { + regHKR_result = loaderGetDeviceRegistryFiles(inst, &search_path, ®_size, LoaderPnpILayerRegistry()); + } } // This call looks into the Khronos non-device specific section of the registry. + bool use_secondary_hive = (data_file_type == LOADER_DATA_FILE_MANIFEST_LAYER) && (!IsHighIntegrity()); VkResult reg_result = loaderGetRegistryFiles(inst, registry_location, use_secondary_hive, &search_path, ®_size); if ((VK_SUCCESS != reg_result && VK_SUCCESS != regHKR_result) || NULL == search_path) { @@ -4455,7 +4753,7 @@ void loaderScanForImplicitLayers(struct loader_instance *inst, struct loader_lay continue; } - res = loaderAddLayerProperties(inst, instance_layers, json, false, file_str); + res = loaderAddLayerProperties(inst, instance_layers, json, true, file_str); loader_instance_heap_free(inst, file_str); cJSON_Delete(json); @@ -4470,13 +4768,11 @@ void loaderScanForImplicitLayers(struct loader_instance *inst, struct loader_lay // actually present in the available layer list VerifyAllMetaLayers(inst, instance_layers, &override_layer_valid); - if (override_layer_valid) { - loaderRemoveLayersInBlacklist(inst, instance_layers); - if (NULL != inst) { + if (override_layer_valid || implicit_metalayer_present) { + loaderRemoveLayersNotInImplicitMetaLayers(inst, instance_layers); + if (override_layer_valid && inst != NULL) { inst->override_layer_present = true; } - } else if (implicit_metalayer_present) { - loaderRemoveLayersNotInImplicitMetaLayers(inst, instance_layers); } out: @@ -5098,7 +5394,7 @@ static void loaderAddEnvironmentLayers(struct loader_instance *inst, const enum struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list, const struct loader_layer_list *source_list) { char *next, *name; - char *layer_env = loader_secure_getenv(env_name, inst); + char *layer_env = loader_getenv(env_name, inst); if (layer_env == NULL) { goto out; } @@ -5981,16 +6277,18 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI // Get the driver version from vkEnumerateInstanceVersion uint32_t icd_version = VK_API_VERSION_1_0; - PFN_vkEnumerateInstanceVersion icd_enumerate_instance_version = (PFN_vkEnumerateInstanceVersion) - icd_term->scanned_icd->GetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion"); VkResult icd_result = VK_SUCCESS; - if (icd_enumerate_instance_version != NULL) { - icd_result = icd_enumerate_instance_version(&icd_version); - if (icd_result != VK_SUCCESS) { - icd_version = VK_API_VERSION_1_0; - loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "terminator_CreateInstance: ICD \"%s\" " - "vkEnumerateInstanceVersion returned error. The ICD will be treated as a 1.0 ICD", - icd_term->scanned_icd->lib_name); + if (icd_term->scanned_icd->api_version >= VK_API_VERSION_1_1) { + PFN_vkEnumerateInstanceVersion icd_enumerate_instance_version = (PFN_vkEnumerateInstanceVersion) + icd_term->scanned_icd->GetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion"); + if (icd_enumerate_instance_version != NULL) { + icd_result = icd_enumerate_instance_version(&icd_version); + if (icd_result != VK_SUCCESS) { + icd_version = VK_API_VERSION_1_0; + loader_log(ptr_instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "terminator_CreateInstance: ICD \"%s\" " + "vkEnumerateInstanceVersion returned error. The ICD will be treated as a 1.0 ICD", + icd_term->scanned_icd->lib_name); + } } } @@ -6942,7 +7240,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceVersion(const VkEnumerateInstanceVersionChain *chain, uint32_t* pApiVersion) { // NOTE: The Vulkan WG doesn't want us checking pApiVersion for NULL, but instead // prefers us crashing. - *pApiVersion = VK_MAKE_VERSION(loader_major_version, loader_minor_version, 0); + *pApiVersion = VK_MAKE_VERSION(loader_major_version, loader_minor_version, VK_HEADER_VERSION); return VK_SUCCESS; } diff --git a/thirdparty/vulkan/loader/loader.h b/thirdparty/vulkan/loader/loader.h index 36f04144bf..8d6b4c454a 100644 --- a/thirdparty/vulkan/loader/loader.h +++ b/thirdparty/vulkan/loader/loader.h @@ -333,6 +333,9 @@ struct loader_instance { bool wsi_ios_surface_enabled; #endif bool wsi_headless_surface_enabled; +#if defined(VK_USE_PLATFORM_METAL_EXT) + bool wsi_metal_surface_enabled; +#endif bool wsi_display_enabled; bool wsi_display_props2_enabled; }; diff --git a/thirdparty/vulkan/loader/unknown_ext_chain_gas.asm b/thirdparty/vulkan/loader/unknown_ext_chain_gas.S index aca92ea5b8..f847e1407d 100644 --- a/thirdparty/vulkan/loader/unknown_ext_chain_gas.asm +++ b/thirdparty/vulkan/loader/unknown_ext_chain_gas.S @@ -23,6 +23,12 @@ # VkPhysicalDevice or a dispatchable object it can unwrap the object, possibly overwriting the wrapped physical device, and then # jump to the next function in the call chain +#ifdef HAVE_CET_H +#include <cet.h> +#else +#define _CET_ENDBR +#endif + .intel_syntax noprefix .include "gen_defines.asm" @@ -31,6 +37,7 @@ .macro PhysDevExtTramp num .global vkPhysDevExtTramp\num vkPhysDevExtTramp\num: + _CET_ENDBR mov rax, [rdi] mov rdi, [rdi + PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] jmp [rax + (PHYS_DEV_OFFSET_INST_DISPATCH + (PTR_SIZE * \num))] @@ -39,6 +46,7 @@ vkPhysDevExtTramp\num: .macro PhysDevExtTermin num .global vkPhysDevExtTermin\num vkPhysDevExtTermin\num: + _CET_ENDBR mov rax, [rdi + ICD_TERM_OFFSET_PHYS_DEV_TERM] # Store the loader_icd_term* in rax cmp qword ptr [rax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num))], 0 # Check if the next function in the chain is NULL je terminError\num # Go to the error section if it is NULL @@ -60,6 +68,7 @@ terminError\num: .macro DevExtTramp num .global vkdev_ext\num vkdev_ext\num: + _CET_ENDBR mov rax, [rdi] # Dereference the handle to get the dispatch table jmp [rax + (EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * \num))] # Jump to the appropriate call chain .endm @@ -69,6 +78,7 @@ vkdev_ext\num: .macro PhysDevExtTramp num .global vkPhysDevExtTramp\num vkPhysDevExtTramp\num: + _CET_ENDBR mov eax, [esp + 4] # Load the wrapped VkPhysicalDevice into eax mov ecx, [eax + PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] # Load the unwrapped VkPhysicalDevice into ecx mov [esp + 4], ecx # Overwrite the wrapped VkPhysicalDevice with the unwrapped one (on the stack) @@ -79,6 +89,7 @@ vkPhysDevExtTramp\num: .macro PhysDevExtTermin num .global vkPhysDevExtTermin\num vkPhysDevExtTermin\num: + _CET_ENDBR mov ecx, [esp + 4] # Move the wrapped VkPhysicalDevice into ecx mov eax, [ecx + ICD_TERM_OFFSET_PHYS_DEV_TERM] # Store the loader_icd_term* in eax cmp dword ptr [eax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num))], 0 # Check if the next function in the chain is NULL @@ -102,6 +113,7 @@ terminError\num: .macro DevExtTramp num .global vkdev_ext\num vkdev_ext\num: + _CET_ENDBR mov eax, [esp + 4] # Dereference the handle to get the dispatch table jmp [eax + (EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * \num))] # Jump to the appropriate call chain .endm diff --git a/thirdparty/vulkan/loader/vk_dispatch_table_helper.h b/thirdparty/vulkan/loader/vk_dispatch_table_helper.h index 42e2a0756a..d934798db4 100644 --- a/thirdparty/vulkan/loader/vk_dispatch_table_helper.h +++ b/thirdparty/vulkan/loader/vk_dispatch_table_helper.h @@ -86,6 +86,12 @@ static VKAPI_ATTR VkResult VKAPI_CALL StubBindImageMemory2KHR(VkDevice device, u static VKAPI_ATTR void VKAPI_CALL StubGetDescriptorSetLayoutSupportKHR(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport) { }; static VKAPI_ATTR void VKAPI_CALL StubCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride) { }; static VKAPI_ATTR void VKAPI_CALL StubCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride) { }; +static VKAPI_ATTR VkResult VKAPI_CALL StubGetSemaphoreCounterValueKHR(VkDevice device, VkSemaphore semaphore, uint64_t* pValue) { return VK_SUCCESS; }; +static VKAPI_ATTR VkResult VKAPI_CALL StubWaitSemaphoresKHR(VkDevice device, const VkSemaphoreWaitInfoKHR* pWaitInfo, uint64_t timeout) { return VK_SUCCESS; }; +static VKAPI_ATTR VkResult VKAPI_CALL StubSignalSemaphoreKHR(VkDevice device, const VkSemaphoreSignalInfoKHR* pSignalInfo) { return VK_SUCCESS; }; +static VKAPI_ATTR VkResult VKAPI_CALL StubGetPipelineExecutablePropertiesKHR(VkDevice device, const VkPipelineInfoKHR* pPipelineInfo, uint32_t* pExecutableCount, VkPipelineExecutablePropertiesKHR* pProperties) { return VK_SUCCESS; }; +static VKAPI_ATTR VkResult VKAPI_CALL StubGetPipelineExecutableStatisticsKHR(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pStatisticCount, VkPipelineExecutableStatisticKHR* pStatistics) { return VK_SUCCESS; }; +static VKAPI_ATTR VkResult VKAPI_CALL StubGetPipelineExecutableInternalRepresentationsKHR(VkDevice device, const VkPipelineExecutableInfoKHR* pExecutableInfo, uint32_t* pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations) { return VK_SUCCESS; }; static VKAPI_ATTR VkResult VKAPI_CALL StubDebugMarkerSetObjectTagEXT(VkDevice device, const VkDebugMarkerObjectTagInfoEXT* pTagInfo) { return VK_SUCCESS; }; static VKAPI_ATTR VkResult VKAPI_CALL StubDebugMarkerSetObjectNameEXT(VkDevice device, const VkDebugMarkerObjectNameInfoEXT* pNameInfo) { return VK_SUCCESS; }; static VKAPI_ATTR void VKAPI_CALL StubCmdDebugMarkerBeginEXT(VkCommandBuffer commandBuffer, const VkDebugMarkerMarkerInfoEXT* pMarkerInfo) { }; @@ -179,6 +185,7 @@ static VKAPI_ATTR VkResult VKAPI_CALL StubReleaseFullScreenExclusiveModeEXT(VkDe #ifdef VK_USE_PLATFORM_WIN32_KHR static VKAPI_ATTR VkResult VKAPI_CALL StubGetDeviceGroupSurfacePresentModes2EXT(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes) { return VK_SUCCESS; }; #endif // VK_USE_PLATFORM_WIN32_KHR +static VKAPI_ATTR void VKAPI_CALL StubCmdSetLineStippleEXT(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern) { }; static VKAPI_ATTR void VKAPI_CALL StubResetQueryPoolEXT(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) { }; @@ -425,6 +432,18 @@ static inline void layer_init_device_dispatch_table(VkDevice device, VkLayerDisp if (table->CmdDrawIndirectCountKHR == nullptr) { table->CmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)StubCmdDrawIndirectCountKHR; } table->CmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR) gpa(device, "vkCmdDrawIndexedIndirectCountKHR"); if (table->CmdDrawIndexedIndirectCountKHR == nullptr) { table->CmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)StubCmdDrawIndexedIndirectCountKHR; } + table->GetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR) gpa(device, "vkGetSemaphoreCounterValueKHR"); + if (table->GetSemaphoreCounterValueKHR == nullptr) { table->GetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)StubGetSemaphoreCounterValueKHR; } + table->WaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR) gpa(device, "vkWaitSemaphoresKHR"); + if (table->WaitSemaphoresKHR == nullptr) { table->WaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR)StubWaitSemaphoresKHR; } + table->SignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR) gpa(device, "vkSignalSemaphoreKHR"); + if (table->SignalSemaphoreKHR == nullptr) { table->SignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)StubSignalSemaphoreKHR; } + table->GetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR) gpa(device, "vkGetPipelineExecutablePropertiesKHR"); + if (table->GetPipelineExecutablePropertiesKHR == nullptr) { table->GetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)StubGetPipelineExecutablePropertiesKHR; } + table->GetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR) gpa(device, "vkGetPipelineExecutableStatisticsKHR"); + if (table->GetPipelineExecutableStatisticsKHR == nullptr) { table->GetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR)StubGetPipelineExecutableStatisticsKHR; } + table->GetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR) gpa(device, "vkGetPipelineExecutableInternalRepresentationsKHR"); + if (table->GetPipelineExecutableInternalRepresentationsKHR == nullptr) { table->GetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)StubGetPipelineExecutableInternalRepresentationsKHR; } table->DebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT) gpa(device, "vkDebugMarkerSetObjectTagEXT"); if (table->DebugMarkerSetObjectTagEXT == nullptr) { table->DebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT)StubDebugMarkerSetObjectTagEXT; } table->DebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT) gpa(device, "vkDebugMarkerSetObjectNameEXT"); @@ -607,6 +626,8 @@ static inline void layer_init_device_dispatch_table(VkDevice device, VkLayerDisp table->GetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT) gpa(device, "vkGetDeviceGroupSurfacePresentModes2EXT"); if (table->GetDeviceGroupSurfacePresentModes2EXT == nullptr) { table->GetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)StubGetDeviceGroupSurfacePresentModes2EXT; } #endif // VK_USE_PLATFORM_WIN32_KHR + table->CmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT) gpa(device, "vkCmdSetLineStippleEXT"); + if (table->CmdSetLineStippleEXT == nullptr) { table->CmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)StubCmdSetLineStippleEXT; } table->ResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT) gpa(device, "vkResetQueryPoolEXT"); if (table->ResetQueryPoolEXT == nullptr) { table->ResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)StubResetQueryPoolEXT; } } diff --git a/thirdparty/vulkan/loader/vk_layer_dispatch_table.h b/thirdparty/vulkan/loader/vk_layer_dispatch_table.h index 0759f48825..1f0342dc49 100644 --- a/thirdparty/vulkan/loader/vk_layer_dispatch_table.h +++ b/thirdparty/vulkan/loader/vk_layer_dispatch_table.h @@ -470,6 +470,16 @@ typedef struct VkLayerDispatchTable_ { PFN_vkCmdDrawIndirectCountKHR CmdDrawIndirectCountKHR; PFN_vkCmdDrawIndexedIndirectCountKHR CmdDrawIndexedIndirectCountKHR; + // ---- VK_KHR_timeline_semaphore extension commands + PFN_vkGetSemaphoreCounterValueKHR GetSemaphoreCounterValueKHR; + PFN_vkWaitSemaphoresKHR WaitSemaphoresKHR; + PFN_vkSignalSemaphoreKHR SignalSemaphoreKHR; + + // ---- VK_KHR_pipeline_executable_properties extension commands + PFN_vkGetPipelineExecutablePropertiesKHR GetPipelineExecutablePropertiesKHR; + PFN_vkGetPipelineExecutableStatisticsKHR GetPipelineExecutableStatisticsKHR; + PFN_vkGetPipelineExecutableInternalRepresentationsKHR GetPipelineExecutableInternalRepresentationsKHR; + // ---- VK_EXT_debug_marker extension commands PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT; PFN_vkDebugMarkerSetObjectNameEXT DebugMarkerSetObjectNameEXT; @@ -631,6 +641,9 @@ typedef struct VkLayerDispatchTable_ { PFN_vkGetDeviceGroupSurfacePresentModes2EXT GetDeviceGroupSurfacePresentModes2EXT; #endif // VK_USE_PLATFORM_WIN32_KHR + // ---- VK_EXT_line_rasterization extension commands + PFN_vkCmdSetLineStippleEXT CmdSetLineStippleEXT; + // ---- VK_EXT_host_query_reset extension commands PFN_vkResetQueryPoolEXT ResetQueryPoolEXT; } VkLayerDispatchTable; diff --git a/thirdparty/vulkan/loader/vk_loader_extensions.c b/thirdparty/vulkan/loader/vk_loader_extensions.c index 80d80e6be6..c7a55cf11a 100644 --- a/thirdparty/vulkan/loader/vk_loader_extensions.c +++ b/thirdparty/vulkan/loader/vk_loader_extensions.c @@ -527,6 +527,16 @@ VKAPI_ATTR void VKAPI_CALL loader_init_device_extension_dispatch_table(struct lo table->CmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)gdpa(dev, "vkCmdDrawIndirectCountKHR"); table->CmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)gdpa(dev, "vkCmdDrawIndexedIndirectCountKHR"); + // ---- VK_KHR_timeline_semaphore extension commands + table->GetSemaphoreCounterValueKHR = (PFN_vkGetSemaphoreCounterValueKHR)gdpa(dev, "vkGetSemaphoreCounterValueKHR"); + table->WaitSemaphoresKHR = (PFN_vkWaitSemaphoresKHR)gdpa(dev, "vkWaitSemaphoresKHR"); + table->SignalSemaphoreKHR = (PFN_vkSignalSemaphoreKHR)gdpa(dev, "vkSignalSemaphoreKHR"); + + // ---- VK_KHR_pipeline_executable_properties extension commands + table->GetPipelineExecutablePropertiesKHR = (PFN_vkGetPipelineExecutablePropertiesKHR)gdpa(dev, "vkGetPipelineExecutablePropertiesKHR"); + table->GetPipelineExecutableStatisticsKHR = (PFN_vkGetPipelineExecutableStatisticsKHR)gdpa(dev, "vkGetPipelineExecutableStatisticsKHR"); + table->GetPipelineExecutableInternalRepresentationsKHR = (PFN_vkGetPipelineExecutableInternalRepresentationsKHR)gdpa(dev, "vkGetPipelineExecutableInternalRepresentationsKHR"); + // ---- VK_EXT_debug_marker extension commands table->DebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT)gdpa(dev, "vkDebugMarkerSetObjectTagEXT"); table->DebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)gdpa(dev, "vkDebugMarkerSetObjectNameEXT"); @@ -688,6 +698,9 @@ VKAPI_ATTR void VKAPI_CALL loader_init_device_extension_dispatch_table(struct lo table->GetDeviceGroupSurfacePresentModes2EXT = (PFN_vkGetDeviceGroupSurfacePresentModes2EXT)gdpa(dev, "vkGetDeviceGroupSurfacePresentModes2EXT"); #endif // VK_USE_PLATFORM_WIN32_KHR + // ---- VK_EXT_line_rasterization extension commands + table->CmdSetLineStippleEXT = (PFN_vkCmdSetLineStippleEXT)gdpa(dev, "vkCmdSetLineStippleEXT"); + // ---- VK_EXT_host_query_reset extension commands table->ResetQueryPoolEXT = (PFN_vkResetQueryPoolEXT)gdpa(dev, "vkResetQueryPoolEXT"); } @@ -1138,6 +1151,16 @@ VKAPI_ATTR void* VKAPI_CALL loader_lookup_device_dispatch_table(const VkLayerDis if (!strcmp(name, "CmdDrawIndirectCountKHR")) return (void *)table->CmdDrawIndirectCountKHR; if (!strcmp(name, "CmdDrawIndexedIndirectCountKHR")) return (void *)table->CmdDrawIndexedIndirectCountKHR; + // ---- VK_KHR_timeline_semaphore extension commands + if (!strcmp(name, "GetSemaphoreCounterValueKHR")) return (void *)table->GetSemaphoreCounterValueKHR; + if (!strcmp(name, "WaitSemaphoresKHR")) return (void *)table->WaitSemaphoresKHR; + if (!strcmp(name, "SignalSemaphoreKHR")) return (void *)table->SignalSemaphoreKHR; + + // ---- VK_KHR_pipeline_executable_properties extension commands + if (!strcmp(name, "GetPipelineExecutablePropertiesKHR")) return (void *)table->GetPipelineExecutablePropertiesKHR; + if (!strcmp(name, "GetPipelineExecutableStatisticsKHR")) return (void *)table->GetPipelineExecutableStatisticsKHR; + if (!strcmp(name, "GetPipelineExecutableInternalRepresentationsKHR")) return (void *)table->GetPipelineExecutableInternalRepresentationsKHR; + // ---- VK_EXT_debug_marker extension commands if (!strcmp(name, "DebugMarkerSetObjectTagEXT")) return (void *)table->DebugMarkerSetObjectTagEXT; if (!strcmp(name, "DebugMarkerSetObjectNameEXT")) return (void *)table->DebugMarkerSetObjectNameEXT; @@ -1299,6 +1322,9 @@ VKAPI_ATTR void* VKAPI_CALL loader_lookup_device_dispatch_table(const VkLayerDis if (!strcmp(name, "GetDeviceGroupSurfacePresentModes2EXT")) return (void *)table->GetDeviceGroupSurfacePresentModes2EXT; #endif // VK_USE_PLATFORM_WIN32_KHR + // ---- VK_EXT_line_rasterization extension commands + if (!strcmp(name, "CmdSetLineStippleEXT")) return (void *)table->CmdSetLineStippleEXT; + // ---- VK_EXT_host_query_reset extension commands if (!strcmp(name, "ResetQueryPoolEXT")) return (void *)table->ResetQueryPoolEXT; @@ -1885,6 +1911,62 @@ VKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirectCountKHR( } +// ---- VK_KHR_timeline_semaphore extension trampoline/terminators + +VKAPI_ATTR VkResult VKAPI_CALL GetSemaphoreCounterValueKHR( + VkDevice device, + VkSemaphore semaphore, + uint64_t* pValue) { + const VkLayerDispatchTable *disp = loader_get_dispatch(device); + return disp->GetSemaphoreCounterValueKHR(device, semaphore, pValue); +} + +VKAPI_ATTR VkResult VKAPI_CALL WaitSemaphoresKHR( + VkDevice device, + const VkSemaphoreWaitInfoKHR* pWaitInfo, + uint64_t timeout) { + const VkLayerDispatchTable *disp = loader_get_dispatch(device); + return disp->WaitSemaphoresKHR(device, pWaitInfo, timeout); +} + +VKAPI_ATTR VkResult VKAPI_CALL SignalSemaphoreKHR( + VkDevice device, + const VkSemaphoreSignalInfoKHR* pSignalInfo) { + const VkLayerDispatchTable *disp = loader_get_dispatch(device); + return disp->SignalSemaphoreKHR(device, pSignalInfo); +} + + +// ---- VK_KHR_pipeline_executable_properties extension trampoline/terminators + +VKAPI_ATTR VkResult VKAPI_CALL GetPipelineExecutablePropertiesKHR( + VkDevice device, + const VkPipelineInfoKHR* pPipelineInfo, + uint32_t* pExecutableCount, + VkPipelineExecutablePropertiesKHR* pProperties) { + const VkLayerDispatchTable *disp = loader_get_dispatch(device); + return disp->GetPipelineExecutablePropertiesKHR(device, pPipelineInfo, pExecutableCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL GetPipelineExecutableStatisticsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pStatisticCount, + VkPipelineExecutableStatisticKHR* pStatistics) { + const VkLayerDispatchTable *disp = loader_get_dispatch(device); + return disp->GetPipelineExecutableStatisticsKHR(device, pExecutableInfo, pStatisticCount, pStatistics); +} + +VKAPI_ATTR VkResult VKAPI_CALL GetPipelineExecutableInternalRepresentationsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR* pExecutableInfo, + uint32_t* pInternalRepresentationCount, + VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations) { + const VkLayerDispatchTable *disp = loader_get_dispatch(device); + return disp->GetPipelineExecutableInternalRepresentationsKHR(device, pExecutableInfo, pInternalRepresentationCount, pInternalRepresentations); +} + + // ---- VK_EXT_debug_marker extension trampoline/terminators VKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectTagEXT( @@ -3005,28 +3087,6 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateImagePipeSurfaceFUCHSIA( #endif // VK_USE_PLATFORM_FUCHSIA -// ---- VK_EXT_metal_surface extension trampoline/terminators - -#ifdef VK_USE_PLATFORM_METAL_EXT -VKAPI_ATTR VkResult VKAPI_CALL CreateMetalSurfaceEXT( - VkInstance instance, - const VkMetalSurfaceCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface) { -#error("Not implemented. Likely needs to be manually generated!"); - return disp->CreateMetalSurfaceEXT(instance, pCreateInfo, pAllocator, pSurface); -} - -VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT( - VkInstance instance, - const VkMetalSurfaceCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkSurfaceKHR* pSurface) { -#error("Not implemented. Likely needs to be manually generated!"); -} - -#endif // VK_USE_PLATFORM_METAL_EXT - // ---- VK_EXT_buffer_device_address extension trampoline/terminators VKAPI_ATTR VkDeviceAddress VKAPI_CALL GetBufferDeviceAddressEXT( @@ -3110,6 +3170,17 @@ VKAPI_ATTR VkResult VKAPI_CALL ReleaseFullScreenExclusiveModeEXT( #endif // VK_USE_PLATFORM_WIN32_KHR +// ---- VK_EXT_line_rasterization extension trampoline/terminators + +VKAPI_ATTR void VKAPI_CALL CmdSetLineStippleEXT( + VkCommandBuffer commandBuffer, + uint32_t lineStippleFactor, + uint16_t lineStipplePattern) { + const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer); + disp->CmdSetLineStippleEXT(commandBuffer, lineStippleFactor, lineStipplePattern); +} + + // ---- VK_EXT_host_query_reset extension trampoline/terminators VKAPI_ATTR void VKAPI_CALL ResetQueryPoolEXT( @@ -3406,6 +3477,34 @@ bool extension_instance_gpa(struct loader_instance *ptr_instance, const char *na return true; } + // ---- VK_KHR_timeline_semaphore extension commands + if (!strcmp("vkGetSemaphoreCounterValueKHR", name)) { + *addr = (void *)GetSemaphoreCounterValueKHR; + return true; + } + if (!strcmp("vkWaitSemaphoresKHR", name)) { + *addr = (void *)WaitSemaphoresKHR; + return true; + } + if (!strcmp("vkSignalSemaphoreKHR", name)) { + *addr = (void *)SignalSemaphoreKHR; + return true; + } + + // ---- VK_KHR_pipeline_executable_properties extension commands + if (!strcmp("vkGetPipelineExecutablePropertiesKHR", name)) { + *addr = (void *)GetPipelineExecutablePropertiesKHR; + return true; + } + if (!strcmp("vkGetPipelineExecutableStatisticsKHR", name)) { + *addr = (void *)GetPipelineExecutableStatisticsKHR; + return true; + } + if (!strcmp("vkGetPipelineExecutableInternalRepresentationsKHR", name)) { + *addr = (void *)GetPipelineExecutableInternalRepresentationsKHR; + return true; + } + // ---- VK_EXT_debug_marker extension commands if (!strcmp("vkDebugMarkerSetObjectTagEXT", name)) { *addr = (void *)DebugMarkerSetObjectTagEXT; @@ -3908,16 +4007,6 @@ bool extension_instance_gpa(struct loader_instance *ptr_instance, const char *na } #endif // VK_USE_PLATFORM_FUCHSIA - // ---- VK_EXT_metal_surface extension commands -#ifdef VK_USE_PLATFORM_METAL_EXT - if (!strcmp("vkCreateMetalSurfaceEXT", name)) { - *addr = (ptr_instance->enabled_known_extensions.ext_metal_surface == 1) - ? (void *)CreateMetalSurfaceEXT - : NULL; - return true; - } -#endif // VK_USE_PLATFORM_METAL_EXT - // ---- VK_EXT_buffer_device_address extension commands if (!strcmp("vkGetBufferDeviceAddressEXT", name)) { *addr = (void *)GetBufferDeviceAddressEXT; @@ -3962,6 +4051,12 @@ bool extension_instance_gpa(struct loader_instance *ptr_instance, const char *na } #endif // VK_USE_PLATFORM_WIN32_KHR + // ---- VK_EXT_line_rasterization extension commands + if (!strcmp("vkCmdSetLineStippleEXT", name)) { + *addr = (void *)CmdSetLineStippleEXT; + return true; + } + // ---- VK_EXT_host_query_reset extension commands if (!strcmp("vkResetQueryPoolEXT", name)) { *addr = (void *)ResetQueryPoolEXT; @@ -4037,12 +4132,6 @@ void extensions_create_instance(struct loader_instance *ptr_instance, const VkIn } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME)) { ptr_instance->enabled_known_extensions.fuchsia_imagepipe_surface = 1; #endif // VK_USE_PLATFORM_FUCHSIA - - // ---- VK_EXT_metal_surface extension commands -#ifdef VK_USE_PLATFORM_METAL_EXT - } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_METAL_SURFACE_EXTENSION_NAME)) { - ptr_instance->enabled_known_extensions.ext_metal_surface = 1; -#endif // VK_USE_PLATFORM_METAL_EXT } } } diff --git a/thirdparty/vulkan/loader/vk_loader_extensions.h b/thirdparty/vulkan/loader/vk_loader_extensions.h index 954e77448d..b08af33838 100644 --- a/thirdparty/vulkan/loader/vk_loader_extensions.h +++ b/thirdparty/vulkan/loader/vk_loader_extensions.h @@ -437,7 +437,6 @@ union loader_instance_extension_enables { uint8_t ext_display_surface_counter : 1; uint8_t ext_debug_utils : 1; uint8_t fuchsia_imagepipe_surface : 1; - uint8_t ext_metal_surface : 1; }; uint64_t padding[4]; }; diff --git a/thirdparty/vulkan/loader/vk_loader_platform.h b/thirdparty/vulkan/loader/vk_loader_platform.h index e405c21088..2ffda55367 100644 --- a/thirdparty/vulkan/loader/vk_loader_platform.h +++ b/thirdparty/vulkan/loader/vk_loader_platform.h @@ -207,7 +207,12 @@ static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_ static inline const char *LoaderPnpDriverRegistry() { BOOL is_wow; IsWow64Process(GetCurrentProcess(), &is_wow); - return is_wow ? (API_NAME "DriverNameWow") : (API_NAME "DriverName"); + return is_wow ? "VulkanDriverNameWow" : "VulkanDriverName"; +} +static inline const wchar_t *LoaderPnpDriverRegistryWide() { + BOOL is_wow; + IsWow64Process(GetCurrentProcess(), &is_wow); + return is_wow ? L"VulkanDriverNameWow" : L"VulkanDriverName"; } // Get the key for the plug 'n play explicit layer registry @@ -215,15 +220,25 @@ static inline const char *LoaderPnpDriverRegistry() { static inline const char *LoaderPnpELayerRegistry() { BOOL is_wow; IsWow64Process(GetCurrentProcess(), &is_wow); - return is_wow ? (API_NAME "ExplicitLayersWow") : (API_NAME "ExplicitLayers"); + return is_wow ? "VulkanExplicitLayersWow" : "VulkanExplicitLayers"; +} +static inline const wchar_t *LoaderPnpELayerRegistryWide() { + BOOL is_wow; + IsWow64Process(GetCurrentProcess(), &is_wow); + return is_wow ? L"VulkanExplicitLayersWow" : L"VulkanExplicitLayers"; } + // Get the key for the plug 'n play implicit layer registry // The string returned by this function should NOT be freed - static inline const char *LoaderPnpILayerRegistry() { BOOL is_wow; IsWow64Process(GetCurrentProcess(), &is_wow); - return is_wow ? (API_NAME "ImplicitLayersWow") : (API_NAME "ImplicitLayers"); + return is_wow ? "VulkanImplicitLayersWow" : "VulkanImplicitLayers"; +} +static inline const wchar_t *LoaderPnpILayerRegistryWide() { + BOOL is_wow; + IsWow64Process(GetCurrentProcess(), &is_wow); + return is_wow ? L"VulkanImplicitLayersWow" : L"VulkanImplicitLayers"; } #endif @@ -319,7 +334,23 @@ static char *loader_platform_get_proc_address_error(const char *name) { // Threads: typedef HANDLE loader_platform_thread; + +// __declspec(thread) is not supported by MinGW compiler (ignored with warning or +// cause erorr depending on compiler switches) +// +// __thread should be used instead +// +// __MINGW32__ defined for both 32 and 64 bit MinGW compilers, so it is enough to +// detect any (32 or 64) flawor of MinGW compiler. +// +// @note __GNUC__ could be used as a more generic way to detect _any_ +// GCC[-compitible] compiler on Windows, but this fix was tested +// only with MinGW, so keep it explicit at the moment. +#if defined(__MINGW32__) +#define THREAD_LOCAL_DECL __thread +#else #define THREAD_LOCAL_DECL __declspec(thread) +#endif // The once init functionality is not used when building a DLL on Windows. This is because there is no way to clean up the // resources allocated by anything allocated by once init. This isn't a problem for static libraries, but it is for dynamic diff --git a/thirdparty/vulkan/loader/wsi.c b/thirdparty/vulkan/loader/wsi.c index e9f573f072..f8d8e5374c 100644 --- a/thirdparty/vulkan/loader/wsi.c +++ b/thirdparty/vulkan/loader/wsi.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2015-2016 The Khronos Group Inc. - * Copyright (c) 2015-2016 Valve Corporation - * Copyright (c) 2015-2016 LunarG, Inc. + * Copyright (c) 2015-2016, 2019 The Khronos Group Inc. + * Copyright (c) 2015-2016, 2019 Valve Corporation + * Copyright (c) 2015-2016, 2019 LunarG, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ * Author: Jon Ashburn <jon@lunarg.com> * Author: Ian Elliott <ianelliott@google.com> * Author: Mark Lobodzinski <mark@lunarg.com> + * Author: Lenny Komow <lenny@lunarg.com> */ #ifndef _GNU_SOURCE @@ -60,9 +61,11 @@ void wsi_create_instance(struct loader_instance *ptr_instance, const VkInstanceC #ifdef VK_USE_PLATFORM_IOS_MVK ptr_instance->wsi_ios_surface_enabled = false; #endif // VK_USE_PLATFORM_IOS_MVK - ptr_instance->wsi_display_enabled = false; ptr_instance->wsi_display_props2_enabled = false; +#ifdef VK_USE_PLATFORM_METAL_EXT + ptr_instance->wsi_metal_surface_enabled = false; +#endif // VK_USE_PLATFORM_METAL_EXT for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) { @@ -115,6 +118,12 @@ void wsi_create_instance(struct loader_instance *ptr_instance, const VkInstanceC ptr_instance->wsi_headless_surface_enabled = true; continue; } +#if defined(VK_USE_PLATFORM_METAL_EXT) + if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_METAL_SURFACE_EXTENSION_NAME) == 0) { + ptr_instance->wsi_metal_surface_enabled = true; + continue; + } +#endif if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME) == 0) { ptr_instance->wsi_display_enabled = true; continue; @@ -1169,6 +1178,72 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateIOSSurfaceMVK(VkInstance instanc #endif // VK_USE_PLATFORM_IOS_MVK +#if defined(VK_USE_PLATFORM_METAL_EXT) + +LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT(VkInstance instance, + const VkMetalSurfaceCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkSurfaceKHR *pSurface) { + const VkLayerInstanceDispatchTable *disp = loader_get_instance_layer_dispatch(instance); + return disp->CreateMetalSurfaceEXT(instance, pCreateInfo, pAllocator, pSurface); +} + +VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { + VkResult result = VK_SUCCESS; + VkIcdSurface *icd_surface = NULL; + uint32_t i; + + // First, check to ensure the appropriate extension was enabled: + struct loader_instance *ptr_instance = loader_get_instance(instance); + if (!ptr_instance->wsi_metal_surface_enabled) { + loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "VK_EXT_metal_surface extension not enabled. vkCreateMetalSurfaceEXT will not be executed.\n"); + } + + // Next, if so, proceed with the implementation of this function: + icd_surface = AllocateIcdSurfaceStruct(ptr_instance, sizeof(icd_surface->metal_surf.base), sizeof(icd_surface->metal_surf)); + if (icd_surface == NULL) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + + icd_surface->metal_surf.base.platform = VK_ICD_WSI_PLATFORM_METAL; + icd_surface->metal_surf.pLayer = pCreateInfo->pLayer; + + // Loop through each ICD and determine if they need to create a surface + i = 0; + for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, ++i) { + if (icd_term->scanned_icd->interface_version >= ICD_VER_SUPPORTS_ICD_SURFACE_KHR) { + if (icd_term->dispatch.CreateMetalSurfaceEXT != NULL) { + result = icd_term->dispatch.CreateMetalSurfaceEXT(icd_term->instance, pCreateInfo, pAllocator, + &icd_surface->real_icd_surfaces[i]); + if (result != VK_SUCCESS) { + goto out; + } + } + } + } + *pSurface = (VkSurfaceKHR)icd_surface; + +out: + if (result != VK_SUCCESS && icd_surface != NULL) { + if (icd_surface->real_icd_surfaces != NULL) { + i = 0; + for (struct loader_icd_term *icd_term = ptr_instance->icd_terms; icd_term != NULL; icd_term = icd_term->next, ++i) { + if (icd_surface->real_icd_surfaces[i] == VK_NULL_HANDLE && icd_term->dispatch.DestroySurfaceKHR != NULL) { + icd_term->dispatch.DestroySurfaceKHR(icd_term->instance, icd_surface->real_icd_surfaces[i], pAllocator); + } + } + loader_instance_heap_free(ptr_instance, icd_surface->real_icd_surfaces); + } + loader_instance_heap_free(ptr_instance, icd_surface); + } + return result; +} + +#endif + // Functions for the VK_KHR_display instance extension: LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, @@ -1882,6 +1957,14 @@ bool wsi_swapchain_instance_gpa(struct loader_instance *ptr_instance, const char return true; } +#if defined(VK_USE_PLATFORM_METAL_EXT) + // Functions for the VK_MVK_macos_surface extension: + if (!strcmp("vkCreateMetalSurfaceEXT", name)) { + *addr = ptr_instance->wsi_metal_surface_enabled ? (void *)vkCreateMetalSurfaceEXT : NULL; + return true; + } +#endif // VK_USE_PLATFORM_METAL_EXT + // Functions for VK_KHR_display extension: if (!strcmp("vkGetPhysicalDeviceDisplayPropertiesKHR", name)) { *addr = ptr_instance->wsi_display_enabled ? (void *)vkGetPhysicalDeviceDisplayPropertiesKHR : NULL; diff --git a/thirdparty/vulkan/loader/wsi.h b/thirdparty/vulkan/loader/wsi.h index b09f168fda..3e44efa9e9 100644 --- a/thirdparty/vulkan/loader/wsi.h +++ b/thirdparty/vulkan/loader/wsi.h @@ -42,6 +42,9 @@ typedef struct { #ifdef VK_USE_PLATFORM_MACOS_MVK VkIcdSurfaceMacOS macos_surf; #endif // VK_USE_PLATFORM_MACOS_MVK +#ifdef VK_USE_PLATFORM_METAL_EXT + VkIcdSurfaceMetal metal_surf; +#endif // VK_USE_PLATFORM_METAL_EXT VkIcdSurfaceDisplay display_surf; VkIcdSurfaceHeadless headless_surf; }; @@ -126,6 +129,10 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance insta VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface); #endif +#if defined(VK_USE_PLATFORM_METAL_EXT) +VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface); +#endif VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPropertiesKHR *pProperties); |