1346 lines
69 KiB
C
1346 lines
69 KiB
C
/*
|
|
* Copyright (c) 2015-2017 The Khronos Group Inc.
|
|
* Copyright (c) 2015-2017 Valve Corporation
|
|
* Copyright (c) 2015-2017 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: Mark Young <marky@lunarg.com>
|
|
* Author: Lenny Komow <lenny@lunarg.com>
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "vk_loader_platform.h"
|
|
#include "loader.h"
|
|
#include "vk_loader_extensions.h"
|
|
#include <vulkan/vk_icd.h>
|
|
#include "wsi.h"
|
|
#include "debug_report.h"
|
|
|
|
// ---- Manually added trampoline/terminator functions
|
|
|
|
// These functions, for whatever reason, require more complex changes than
|
|
// can easily be automatically generated.
|
|
VkResult setupLoaderTrampPhysDevGroups(VkInstance instance);
|
|
VkResult setupLoaderTermPhysDevGroups(struct loader_instance *inst);
|
|
|
|
// ---- VK_KHX_device_group extension trampoline/terminators
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDeviceGroupsKHX(
|
|
VkInstance instance, uint32_t *pPhysicalDeviceGroupCount,
|
|
VkPhysicalDeviceGroupPropertiesKHX *pPhysicalDeviceGroupProperties) {
|
|
VkResult res = VK_SUCCESS;
|
|
uint32_t count;
|
|
uint32_t i;
|
|
struct loader_instance *inst = NULL;
|
|
|
|
loader_platform_thread_lock_mutex(&loader_lock);
|
|
|
|
inst = loader_get_instance(instance);
|
|
if (NULL == inst) {
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
|
|
if (NULL == pPhysicalDeviceGroupCount) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"vkEnumeratePhysicalDeviceGroupsKHX: Received NULL pointer for physical "
|
|
"device group count return value.");
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
|
|
VkResult setup_res = setupLoaderTrampPhysDevGroups(instance);
|
|
if (VK_SUCCESS != setup_res) {
|
|
res = setup_res;
|
|
goto out;
|
|
}
|
|
|
|
count = inst->phys_dev_group_count_tramp;
|
|
|
|
// Wrap the PhysDev object for loader usage, return wrapped objects
|
|
if (NULL != pPhysicalDeviceGroupProperties) {
|
|
if (inst->phys_dev_group_count_tramp > *pPhysicalDeviceGroupCount) {
|
|
loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkEnumeratePhysicalDeviceGroupsKHX: Trimming device group count down"
|
|
" by application request from %d to %d physical device groups",
|
|
inst->phys_dev_group_count_tramp, *pPhysicalDeviceGroupCount);
|
|
count = *pPhysicalDeviceGroupCount;
|
|
res = VK_INCOMPLETE;
|
|
}
|
|
for (i = 0; i < count; i++) {
|
|
memcpy(&pPhysicalDeviceGroupProperties[i], inst->phys_dev_groups_tramp[i],
|
|
sizeof(VkPhysicalDeviceGroupPropertiesKHX));
|
|
}
|
|
}
|
|
|
|
*pPhysicalDeviceGroupCount = count;
|
|
|
|
out:
|
|
|
|
loader_platform_thread_unlock_mutex(&loader_lock);
|
|
return res;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroupsKHX(
|
|
VkInstance instance, uint32_t *pPhysicalDeviceGroupCount,
|
|
VkPhysicalDeviceGroupPropertiesKHX *pPhysicalDeviceGroupProperties) {
|
|
struct loader_instance *inst = (struct loader_instance *)instance;
|
|
VkResult res = VK_SUCCESS;
|
|
|
|
// Always call the setup loader terminator physical device groups because they may
|
|
// have changed at any point.
|
|
res = setupLoaderTermPhysDevGroups(inst);
|
|
if (VK_SUCCESS != res) {
|
|
goto out;
|
|
}
|
|
|
|
uint32_t copy_count = inst->phys_dev_group_count_term;
|
|
if (NULL != pPhysicalDeviceGroupProperties) {
|
|
if (copy_count > *pPhysicalDeviceGroupCount) {
|
|
copy_count = *pPhysicalDeviceGroupCount;
|
|
res = VK_INCOMPLETE;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < copy_count; i++) {
|
|
memcpy(&pPhysicalDeviceGroupProperties[i], inst->phys_dev_groups_term[i],
|
|
sizeof(VkPhysicalDeviceGroupPropertiesKHX));
|
|
}
|
|
}
|
|
|
|
*pPhysicalDeviceGroupCount = copy_count;
|
|
|
|
out:
|
|
|
|
return res;
|
|
}
|
|
|
|
// ---- VK_NV_external_memory_capabilities extension trampoline/terminators
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
GetPhysicalDeviceExternalImageFormatPropertiesNV(
|
|
VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
|
|
VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
|
|
VkExternalMemoryHandleTypeFlagsNV externalHandleType,
|
|
VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
|
|
return disp->GetPhysicalDeviceExternalImageFormatPropertiesNV(
|
|
unwrapped_phys_dev, format, type, tiling, usage, flags,
|
|
externalHandleType, pExternalImageFormatProperties);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV(
|
|
VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
|
|
VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
|
|
VkExternalMemoryHandleTypeFlagsNV externalHandleType,
|
|
VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
|
|
struct loader_physical_device_term *phys_dev_term =
|
|
(struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (!icd_term->dispatch.GetPhysicalDeviceExternalImageFormatPropertiesNV) {
|
|
if (externalHandleType) {
|
|
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
|
}
|
|
|
|
if (!icd_term->dispatch.GetPhysicalDeviceImageFormatProperties) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
pExternalImageFormatProperties->externalMemoryFeatures = 0;
|
|
pExternalImageFormatProperties->exportFromImportedHandleTypes = 0;
|
|
pExternalImageFormatProperties->compatibleHandleTypes = 0;
|
|
|
|
return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(
|
|
phys_dev_term->phys_dev, format, type, tiling, usage, flags,
|
|
&pExternalImageFormatProperties->imageFormatProperties);
|
|
}
|
|
|
|
return icd_term->dispatch.GetPhysicalDeviceExternalImageFormatPropertiesNV(
|
|
phys_dev_term->phys_dev, format, type, tiling, usage, flags,
|
|
externalHandleType, pExternalImageFormatProperties);
|
|
}
|
|
|
|
// ---- VK_KHR_get_physical_device_properties2 extension trampoline/terminators
|
|
|
|
VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR *pFeatures) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
disp->GetPhysicalDeviceFeatures2KHR(unwrapped_phys_dev, pFeatures);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice,
|
|
VkPhysicalDeviceFeatures2KHR *pFeatures) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceFeatures2KHR != NULL) {
|
|
// Pass the call to the driver
|
|
icd_term->dispatch.GetPhysicalDeviceFeatures2KHR(phys_dev_term->phys_dev, pFeatures);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceFeatures2KHR: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceFeatures",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
// Write to the VkPhysicalDeviceFeatures2KHR struct
|
|
icd_term->dispatch.GetPhysicalDeviceFeatures(phys_dev_term->phys_dev, &pFeatures->features);
|
|
|
|
void *pNext = pFeatures->pNext;
|
|
while (pNext != NULL) {
|
|
switch (*(VkStructureType *)pNext) {
|
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX: {
|
|
// Skip the check if VK_KHX_multiview is enabled because it's a device extension
|
|
// Write to the VkPhysicalDeviceMultiviewFeaturesKHX struct
|
|
VkPhysicalDeviceMultiviewFeaturesKHX *multiview_features = pNext;
|
|
multiview_features->multiview = VK_FALSE;
|
|
multiview_features->multiviewGeometryShader = VK_FALSE;
|
|
multiview_features->multiviewTessellationShader = VK_FALSE;
|
|
|
|
pNext = multiview_features->pNext;
|
|
break;
|
|
}
|
|
default: {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceFeatures2KHR: Emulation found unrecognized structure type in pFeatures->pNext - "
|
|
"this struct will be ignored");
|
|
|
|
struct VkStructureHeader *header = pNext;
|
|
pNext = (void *)header->pNext;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice,
|
|
VkPhysicalDeviceProperties2KHR *pProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
disp->GetPhysicalDeviceProperties2KHR(unwrapped_phys_dev, pProperties);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice,
|
|
VkPhysicalDeviceProperties2KHR *pProperties) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceProperties2KHR != NULL) {
|
|
// Pass the call to the driver
|
|
icd_term->dispatch.GetPhysicalDeviceProperties2KHR(phys_dev_term->phys_dev, pProperties);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceProperties2KHR: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceProperties",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
// Write to the VkPhysicalDeviceProperties2KHR struct
|
|
icd_term->dispatch.GetPhysicalDeviceProperties(phys_dev_term->phys_dev, &pProperties->properties);
|
|
|
|
void *pNext = pProperties->pNext;
|
|
while (pNext != NULL) {
|
|
switch (*(VkStructureType *)pNext) {
|
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR: {
|
|
VkPhysicalDeviceIDPropertiesKHR *id_properties = pNext;
|
|
|
|
// Verify that "VK_KHR_external_memory_capabilities" is enabled
|
|
if (icd_term->this_instance->enabled_known_extensions.khr_external_memory_capabilities) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceProperties2KHR: Emulation cannot generate unique IDs for struct "
|
|
"VkPhysicalDeviceIDPropertiesKHR - setting IDs to zero instead");
|
|
|
|
// Write to the VkPhysicalDeviceIDPropertiesKHR struct
|
|
memset(id_properties->deviceUUID, 0, VK_UUID_SIZE);
|
|
memset(id_properties->driverUUID, 0, VK_UUID_SIZE);
|
|
id_properties->deviceLUIDValid = VK_FALSE;
|
|
}
|
|
|
|
pNext = id_properties->pNext;
|
|
break;
|
|
}
|
|
default: {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceProperties2KHR: Emulation found unrecognized structure type in "
|
|
"pProperties->pNext - this struct will be ignored");
|
|
|
|
struct VkStructureHeader *header = pNext;
|
|
pNext = (void *)header->pNext;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceFormatProperties2KHR(VkPhysicalDevice physicalDevice, VkFormat format,
|
|
VkFormatProperties2KHR *pFormatProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
disp->GetPhysicalDeviceFormatProperties2KHR(unwrapped_phys_dev, format, pFormatProperties);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties2KHR(VkPhysicalDevice physicalDevice, VkFormat format,
|
|
VkFormatProperties2KHR *pFormatProperties) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceFormatProperties2KHR != NULL) {
|
|
// Pass the call to the driver
|
|
icd_term->dispatch.GetPhysicalDeviceFormatProperties2KHR(phys_dev_term->phys_dev, format, pFormatProperties);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(
|
|
icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceFormatProperties2KHR: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceFormatProperties",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
// Write to the VkFormatProperties2KHR struct
|
|
icd_term->dispatch.GetPhysicalDeviceFormatProperties(phys_dev_term->phys_dev, format, &pFormatProperties->formatProperties);
|
|
|
|
if (pFormatProperties->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceFormatProperties2KHR: Emulation found unrecognized structure type in "
|
|
"pFormatProperties->pNext - this struct will be ignored");
|
|
}
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceImageFormatProperties2KHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
|
|
VkImageFormatProperties2KHR *pImageFormatProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
return disp->GetPhysicalDeviceImageFormatProperties2KHR(unwrapped_phys_dev, pImageFormatInfo, pImageFormatProperties);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties2KHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
|
|
VkImageFormatProperties2KHR *pImageFormatProperties) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceImageFormatProperties2KHR != NULL) {
|
|
// Pass the call to the driver
|
|
return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties2KHR(phys_dev_term->phys_dev, pImageFormatInfo,
|
|
pImageFormatProperties);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceImageFormatProperties2KHR: Emulating call in ICD \"%s\" using "
|
|
"vkGetPhysicalDeviceImageFormatProperties",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
// If there is more info in either pNext, then this is unsupported
|
|
if (pImageFormatInfo->pNext != NULL || pImageFormatProperties->pNext != NULL) {
|
|
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
|
}
|
|
|
|
// Write to the VkImageFormatProperties2KHR struct
|
|
return icd_term->dispatch.GetPhysicalDeviceImageFormatProperties(
|
|
phys_dev_term->phys_dev, pImageFormatInfo->format, pImageFormatInfo->type, pImageFormatInfo->tiling,
|
|
pImageFormatInfo->usage, pImageFormatInfo->flags, &pImageFormatProperties->imageFormatProperties);
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice,
|
|
uint32_t *pQueueFamilyPropertyCount,
|
|
VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
disp->GetPhysicalDeviceQueueFamilyProperties2KHR(unwrapped_phys_dev, pQueueFamilyPropertyCount, pQueueFamilyProperties);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties2KHR(
|
|
VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties2KHR != NULL) {
|
|
// Pass the call to the driver
|
|
icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties2KHR(phys_dev_term->phys_dev, pQueueFamilyPropertyCount,
|
|
pQueueFamilyProperties);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceQueueFamilyProperties2KHR: Emulating call in ICD \"%s\" using "
|
|
"vkGetPhysicalDeviceQueueFamilyProperties",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
if (pQueueFamilyProperties == NULL || *pQueueFamilyPropertyCount == 0) {
|
|
// Write to pQueueFamilyPropertyCount
|
|
icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount, NULL);
|
|
} else {
|
|
// Allocate a temporary array for the output of the old function
|
|
VkQueueFamilyProperties *properties = loader_stack_alloc(*pQueueFamilyPropertyCount * sizeof(VkQueueFamilyProperties));
|
|
if (properties == NULL) {
|
|
*pQueueFamilyPropertyCount = 0;
|
|
loader_log(
|
|
icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceQueueFamilyProperties2KHR: Out of memory - Failed to allocate array for loader emulation.");
|
|
return;
|
|
}
|
|
|
|
icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties(phys_dev_term->phys_dev, pQueueFamilyPropertyCount,
|
|
properties);
|
|
for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; ++i) {
|
|
// Write to the VkQueueFamilyProperties2KHR struct
|
|
memcpy(&pQueueFamilyProperties[i].queueFamilyProperties, &properties[i], sizeof(VkQueueFamilyProperties));
|
|
|
|
if (pQueueFamilyProperties[i].pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceQueueFamilyProperties2KHR: Emulation found unrecognized structure type in "
|
|
"pQueueFamilyProperties[%d].pNext - this struct will be ignored",
|
|
i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceMemoryProperties2KHR(VkPhysicalDevice physicalDevice,
|
|
VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
disp->GetPhysicalDeviceMemoryProperties2KHR(unwrapped_phys_dev, pMemoryProperties);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties2KHR(
|
|
VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceMemoryProperties2KHR != NULL) {
|
|
// Pass the call to the driver
|
|
icd_term->dispatch.GetPhysicalDeviceMemoryProperties2KHR(phys_dev_term->phys_dev, pMemoryProperties);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(
|
|
icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceMemoryProperties2KHR: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceMemoryProperties",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
// Write to the VkPhysicalDeviceMemoryProperties2KHR struct
|
|
icd_term->dispatch.GetPhysicalDeviceMemoryProperties(phys_dev_term->phys_dev, &pMemoryProperties->memoryProperties);
|
|
|
|
if (pMemoryProperties->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceMemoryProperties2KHR: Emulation found unrecognized structure type in "
|
|
"pMemoryProperties->pNext - this struct will be ignored");
|
|
}
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceSparseImageFormatProperties2KHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR *pFormatInfo, uint32_t *pPropertyCount,
|
|
VkSparseImageFormatProperties2KHR *pProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
disp->GetPhysicalDeviceSparseImageFormatProperties2KHR(unwrapped_phys_dev, pFormatInfo, pPropertyCount, pProperties);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperties2KHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR *pFormatInfo, uint32_t *pPropertyCount,
|
|
VkSparseImageFormatProperties2KHR *pProperties) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties2KHR != NULL) {
|
|
// Pass the call to the driver
|
|
icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties2KHR(phys_dev_term->phys_dev, pFormatInfo, pPropertyCount,
|
|
pProperties);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSparseImageFormatProperties2KHR: Emulating call in ICD \"%s\" using "
|
|
"vkGetPhysicalDeviceSparseImageFormatProperties",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
if (pFormatInfo->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSparseImageFormatProperties2KHR: Emulation found unrecognized structure type in "
|
|
"pFormatInfo->pNext - this struct will be ignored");
|
|
}
|
|
|
|
if (pProperties == NULL || *pPropertyCount == 0) {
|
|
// Write to pPropertyCount
|
|
icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(
|
|
phys_dev_term->phys_dev, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage,
|
|
pFormatInfo->tiling, pPropertyCount, NULL);
|
|
} else {
|
|
// Allocate a temporary array for the output of the old function
|
|
VkSparseImageFormatProperties *properties =
|
|
loader_stack_alloc(*pPropertyCount * sizeof(VkSparseImageMemoryRequirements));
|
|
if (properties == NULL) {
|
|
*pPropertyCount = 0;
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSparseImageFormatProperties2KHR: Out of memory - Failed to allocate array for "
|
|
"loader emulation.");
|
|
return;
|
|
}
|
|
|
|
icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties(
|
|
phys_dev_term->phys_dev, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage,
|
|
pFormatInfo->tiling, pPropertyCount, properties);
|
|
for (uint32_t i = 0; i < *pPropertyCount; ++i) {
|
|
// Write to the VkSparseImageFormatProperties2KHR struct
|
|
memcpy(&pProperties[i].properties, &properties[i], sizeof(VkSparseImageFormatProperties));
|
|
|
|
if (pProperties[i].pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSparseImageFormatProperties2KHR: Emulation found unrecognized structure type in "
|
|
"pProperties[%d].pNext - this struct will be ignored",
|
|
i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---- VK_KHR_get_surface_capabilities2 extension trampoline/terminators
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,
|
|
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
|
|
VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
return disp->GetPhysicalDeviceSurfaceCapabilities2KHR(unwrapped_phys_dev, pSurfaceInfo, pSurfaceCapabilities);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2KHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
|
|
VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
VkIcdSurface *icd_surface = (VkIcdSurface *)(pSurfaceInfo->surface);
|
|
uint8_t icd_index = phys_dev_term->icd_index;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR != NULL) {
|
|
// 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;
|
|
info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
|
|
return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, &info_copy,
|
|
pSurfaceCapabilities);
|
|
} else {
|
|
return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev_term->phys_dev, pSurfaceInfo,
|
|
pSurfaceCapabilities);
|
|
}
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSurfaceCapabilities2KHR: Emulating call in ICD \"%s\" using "
|
|
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
if (pSurfaceInfo->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSurfaceCapabilities2KHR: Emulation found unrecognized structure type in "
|
|
"pSurfaceInfo->pNext - this struct will be ignored");
|
|
}
|
|
|
|
// Write to the VkSurfaceCapabilities2KHR struct
|
|
VkSurfaceKHR surface = pSurfaceInfo->surface;
|
|
if (icd_surface->real_icd_surfaces != NULL && (void *)icd_surface->real_icd_surfaces[icd_index] != NULL) {
|
|
surface = icd_surface->real_icd_surfaces[icd_index];
|
|
}
|
|
VkResult res = icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, surface,
|
|
&pSurfaceCapabilities->surfaceCapabilities);
|
|
|
|
if (pSurfaceCapabilities->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSurfaceCapabilities2KHR: Emulation found unrecognized structure type in "
|
|
"pSurfaceCapabilities->pNext - this struct will be ignored");
|
|
}
|
|
return res;
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
|
|
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
|
|
uint32_t *pSurfaceFormatCount,
|
|
VkSurfaceFormat2KHR *pSurfaceFormats) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
return disp->GetPhysicalDeviceSurfaceFormats2KHR(unwrapped_phys_dev, pSurfaceInfo, pSurfaceFormatCount, pSurfaceFormats);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
|
|
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
|
|
uint32_t *pSurfaceFormatCount,
|
|
VkSurfaceFormat2KHR *pSurfaceFormats) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
VkIcdSurface *icd_surface = (VkIcdSurface *)(pSurfaceInfo->surface);
|
|
uint8_t icd_index = phys_dev_term->icd_index;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR != NULL) {
|
|
// 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;
|
|
info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
|
|
return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, &info_copy, pSurfaceFormatCount,
|
|
pSurfaceFormats);
|
|
} else {
|
|
return icd_term->dispatch.GetPhysicalDeviceSurfaceFormats2KHR(phys_dev_term->phys_dev, pSurfaceInfo,
|
|
pSurfaceFormatCount, pSurfaceFormats);
|
|
}
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSurfaceFormats2KHR: Emulating call in ICD \"%s\" using vkGetPhysicalDeviceSurfaceFormatsKHR",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
if (pSurfaceInfo->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSurfaceFormats2KHR: Emulation found unrecognized structure type in pSurfaceInfo->pNext "
|
|
"- this struct will be ignored");
|
|
}
|
|
|
|
VkSurfaceKHR surface = pSurfaceInfo->surface;
|
|
if (icd_surface->real_icd_surfaces != NULL && (void *)icd_surface->real_icd_surfaces[icd_index] != NULL) {
|
|
surface = icd_surface->real_icd_surfaces[icd_index];
|
|
}
|
|
|
|
if (*pSurfaceFormatCount == 0 || pSurfaceFormats == NULL) {
|
|
// Write to pSurfaceFormatCount
|
|
return icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface, pSurfaceFormatCount,
|
|
NULL);
|
|
} else {
|
|
// Allocate a temporary array for the output of the old function
|
|
VkSurfaceFormatKHR *formats = loader_stack_alloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
|
|
if (formats == NULL) {
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
|
|
VkResult res = icd_term->dispatch.GetPhysicalDeviceSurfaceFormatsKHR(phys_dev_term->phys_dev, surface,
|
|
pSurfaceFormatCount, formats);
|
|
for (uint32_t i = 0; i < *pSurfaceFormatCount; ++i) {
|
|
pSurfaceFormats[i].surfaceFormat = formats[i];
|
|
if (pSurfaceFormats[i].pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSurfaceFormats2KHR: Emulation found unrecognized structure type in "
|
|
"pSurfaceFormats[%d].pNext - this struct will be ignored",
|
|
i);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---- VK_EXT_display_surface_counter extension trampoline/terminators
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
|
|
VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
return disp->GetPhysicalDeviceSurfaceCapabilities2EXT(unwrapped_phys_dev, surface, pSurfaceCapabilities);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfaceCapabilities2EXT(
|
|
VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
VkIcdSurface *icd_surface = (VkIcdSurface *)(surface);
|
|
uint8_t icd_index = phys_dev_term->icd_index;
|
|
|
|
// Unwrap the surface if needed
|
|
VkSurfaceKHR unwrapped_surface = surface;
|
|
if (icd_surface->real_icd_surfaces != NULL && (void *)icd_surface->real_icd_surfaces[icd_index] != NULL) {
|
|
unwrapped_surface = icd_surface->real_icd_surfaces[icd_index];
|
|
}
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT != NULL) {
|
|
// Pass the call to the driver
|
|
return icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilities2EXT(phys_dev_term->phys_dev, unwrapped_surface,
|
|
pSurfaceCapabilities);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSurfaceCapabilities2EXT: Emulating call in ICD \"%s\" using "
|
|
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
VkSurfaceCapabilitiesKHR surface_caps;
|
|
VkResult res =
|
|
icd_term->dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev_term->phys_dev, unwrapped_surface, &surface_caps);
|
|
pSurfaceCapabilities->minImageCount = surface_caps.minImageCount;
|
|
pSurfaceCapabilities->maxImageCount = surface_caps.maxImageCount;
|
|
pSurfaceCapabilities->currentExtent = surface_caps.currentExtent;
|
|
pSurfaceCapabilities->minImageExtent = surface_caps.minImageExtent;
|
|
pSurfaceCapabilities->maxImageExtent = surface_caps.maxImageExtent;
|
|
pSurfaceCapabilities->maxImageArrayLayers = surface_caps.maxImageArrayLayers;
|
|
pSurfaceCapabilities->supportedTransforms = surface_caps.supportedTransforms;
|
|
pSurfaceCapabilities->currentTransform = surface_caps.currentTransform;
|
|
pSurfaceCapabilities->supportedCompositeAlpha = surface_caps.supportedCompositeAlpha;
|
|
pSurfaceCapabilities->supportedUsageFlags = surface_caps.supportedUsageFlags;
|
|
pSurfaceCapabilities->supportedSurfaceCounters = 0;
|
|
|
|
if (pSurfaceCapabilities->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceSurfaceCapabilities2EXT: Emulation found unrecognized structure type in "
|
|
"pSurfaceCapabilities->pNext - this struct will be ignored");
|
|
}
|
|
|
|
return res;
|
|
}
|
|
}
|
|
|
|
// ---- VK_EXT_direct_mode_display extension trampoline/terminators
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
return disp->ReleaseDisplayEXT(unwrapped_phys_dev, display);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.ReleaseDisplayEXT == NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"ICD \"%s\" associated with VkPhysicalDevice does not support vkReleaseDisplayEXT - Consequently, the call is "
|
|
"invalid because it should not be possible to acquire a display on this device",
|
|
icd_term->scanned_icd->lib_name);
|
|
}
|
|
return icd_term->dispatch.ReleaseDisplayEXT(phys_dev_term->phys_dev, display);
|
|
}
|
|
|
|
// ---- VK_EXT_acquire_xlib_display extension trampoline/terminators
|
|
|
|
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
|
VKAPI_ATTR VkResult VKAPI_CALL AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, VkDisplayKHR display) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
return disp->AcquireXlibDisplayEXT(unwrapped_phys_dev, dpy, display);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL terminator_AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy,
|
|
VkDisplayKHR display) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.AcquireXlibDisplayEXT != NULL) {
|
|
// Pass the call to the driver
|
|
return icd_term->dispatch.AcquireXlibDisplayEXT(phys_dev_term->phys_dev, dpy, display);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkAcquireXLibDisplayEXT: Emulating call in ICD \"%s\" by returning error", icd_term->scanned_icd->lib_name);
|
|
|
|
// Fail for the unsupported command
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
|
|
VkDisplayKHR *pDisplay) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
return disp->GetRandROutputDisplayEXT(unwrapped_phys_dev, dpy, rrOutput, pDisplay);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
|
|
VkDisplayKHR *pDisplay) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetRandROutputDisplayEXT != NULL) {
|
|
// Pass the call to the driver
|
|
return icd_term->dispatch.GetRandROutputDisplayEXT(phys_dev_term->phys_dev, dpy, rrOutput, pDisplay);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetRandROutputDisplayEXT: Emulating call in ICD \"%s\" by returning null display",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
// Return a null handle to indicate this can't be done
|
|
*pDisplay = VK_NULL_HANDLE;
|
|
return VK_SUCCESS;
|
|
}
|
|
}
|
|
|
|
#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
|
|
|
|
// ---- VK_KHR_external_memory_capabilities extension trampoline/terminators
|
|
|
|
VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceExternalBufferPropertiesKHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfoKHR *pExternalBufferInfo,
|
|
VkExternalBufferPropertiesKHR *pExternalBufferProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
disp->GetPhysicalDeviceExternalBufferPropertiesKHR(unwrapped_phys_dev, pExternalBufferInfo, pExternalBufferProperties);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalBufferPropertiesKHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfoKHR *pExternalBufferInfo,
|
|
VkExternalBufferPropertiesKHR *pExternalBufferProperties) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceExternalBufferPropertiesKHR) {
|
|
// Pass the call to the driver
|
|
icd_term->dispatch.GetPhysicalDeviceExternalBufferPropertiesKHR(phys_dev_term->phys_dev, pExternalBufferInfo,
|
|
pExternalBufferProperties);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceExternalBufferPropertiesKHR: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
|
|
|
|
if (pExternalBufferInfo->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceExternalBufferPropertiesKHR: Emulation found unrecognized structure type in "
|
|
"pExternalBufferInfo->pNext - this struct will be ignored");
|
|
}
|
|
|
|
// Fill in everything being unsupported
|
|
memset(&pExternalBufferProperties->externalMemoryProperties, 0, sizeof(VkExternalMemoryPropertiesKHR));
|
|
|
|
if (pExternalBufferProperties->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceExternalBufferPropertiesKHR: Emulation found unrecognized structure type in "
|
|
"pExternalBufferProperties->pNext - this struct will be ignored");
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---- VK_KHR_external_semaphore_capabilities extension trampoline/terminators
|
|
|
|
VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceExternalSemaphorePropertiesKHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfoKHR *pExternalSemaphoreInfo,
|
|
VkExternalSemaphorePropertiesKHR *pExternalSemaphoreProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
disp->GetPhysicalDeviceExternalSemaphorePropertiesKHR(unwrapped_phys_dev, pExternalSemaphoreInfo, pExternalSemaphoreProperties);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalSemaphorePropertiesKHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfoKHR *pExternalSemaphoreInfo,
|
|
VkExternalSemaphorePropertiesKHR *pExternalSemaphoreProperties) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceExternalSemaphorePropertiesKHR != NULL) {
|
|
// Pass the call to the driver
|
|
icd_term->dispatch.GetPhysicalDeviceExternalSemaphorePropertiesKHR(phys_dev_term->phys_dev, pExternalSemaphoreInfo,
|
|
pExternalSemaphoreProperties);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceExternalSemaphorePropertiesKHR: Emulating call in ICD \"%s\"",
|
|
icd_term->scanned_icd->lib_name);
|
|
|
|
if (pExternalSemaphoreInfo->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceExternalSemaphorePropertiesKHR: Emulation found unrecognized structure type in "
|
|
"pExternalSemaphoreInfo->pNext - this struct will be ignored");
|
|
}
|
|
|
|
// Fill in everything being unsupported
|
|
pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
|
|
pExternalSemaphoreProperties->compatibleHandleTypes = 0;
|
|
pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
|
|
|
|
if (pExternalSemaphoreProperties->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceExternalSemaphorePropertiesKHR: Emulation found unrecognized structure type in "
|
|
"pExternalSemaphoreProperties->pNext - this struct will be ignored");
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---- VK_KHR_external_fence_capabilities extension trampoline/terminators
|
|
|
|
VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceExternalFencePropertiesKHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfoKHR *pExternalFenceInfo,
|
|
VkExternalFencePropertiesKHR *pExternalFenceProperties) {
|
|
const VkLayerInstanceDispatchTable *disp;
|
|
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
|
|
disp = loader_get_instance_layer_dispatch(physicalDevice);
|
|
disp->GetPhysicalDeviceExternalFencePropertiesKHR(unwrapped_phys_dev, pExternalFenceInfo, pExternalFenceProperties);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalFencePropertiesKHR(
|
|
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfoKHR *pExternalFenceInfo,
|
|
VkExternalFencePropertiesKHR *pExternalFenceProperties) {
|
|
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
|
|
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
|
|
|
|
if (icd_term->dispatch.GetPhysicalDeviceExternalFencePropertiesKHR != NULL) {
|
|
// Pass the call to the driver
|
|
icd_term->dispatch.GetPhysicalDeviceExternalFencePropertiesKHR(phys_dev_term->phys_dev, pExternalFenceInfo,
|
|
pExternalFenceProperties);
|
|
} else {
|
|
// Emulate the call
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceExternalFencePropertiesKHR: Emulating call in ICD \"%s\"", icd_term->scanned_icd->lib_name);
|
|
|
|
if (pExternalFenceInfo->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceExternalFencePropertiesKHR: Emulation found unrecognized structure type in "
|
|
"pExternalFenceInfo->pNext - this struct will be ignored");
|
|
}
|
|
|
|
// Fill in everything being unsupported
|
|
pExternalFenceProperties->exportFromImportedHandleTypes = 0;
|
|
pExternalFenceProperties->compatibleHandleTypes = 0;
|
|
pExternalFenceProperties->externalFenceFeatures = 0;
|
|
|
|
if (pExternalFenceProperties->pNext != NULL) {
|
|
loader_log(icd_term->this_instance, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
|
|
"vkGetPhysicalDeviceExternalFencePropertiesKHR: Emulation found unrecognized structure type in "
|
|
"pExternalFenceProperties->pNext - this struct will be ignored");
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---- Helper functions
|
|
|
|
VkResult setupLoaderTrampPhysDevGroups(VkInstance instance) {
|
|
VkResult res = VK_SUCCESS;
|
|
struct loader_instance *inst;
|
|
uint32_t total_count = 0;
|
|
VkPhysicalDeviceGroupPropertiesKHX **new_phys_dev_groups = NULL;
|
|
VkPhysicalDeviceGroupPropertiesKHX *local_phys_dev_groups = NULL;
|
|
|
|
inst = loader_get_instance(instance);
|
|
if (NULL == inst) {
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
|
|
// Setup the trampoline loader physical devices. This will actually
|
|
// call down and setup the terminator loader physical devices during the
|
|
// process.
|
|
VkResult setup_res = setupLoaderTrampPhysDevs(instance);
|
|
if (setup_res != VK_SUCCESS && setup_res != VK_INCOMPLETE) {
|
|
res = setup_res;
|
|
goto out;
|
|
}
|
|
|
|
// Query how many physical device groups there
|
|
res = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroupsKHX(instance, &total_count, NULL);
|
|
if (res != VK_SUCCESS) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTrampPhysDevGroups: Failed during dispatch call of "
|
|
"\'EnumeratePhysicalDeviceGroupsKHX\' to lower layers or "
|
|
"loader to get count.");
|
|
goto out;
|
|
}
|
|
|
|
// Create an array for the new physical device groups, which will be stored
|
|
// in the instance for the trampoline code.
|
|
new_phys_dev_groups = (VkPhysicalDeviceGroupPropertiesKHX **)loader_instance_heap_alloc(
|
|
inst, total_count * sizeof(VkPhysicalDeviceGroupPropertiesKHX *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
|
|
if (NULL == new_phys_dev_groups) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTrampPhysDevGroups: Failed to allocate new physical device"
|
|
" group array of size %d",
|
|
total_count);
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
memset(new_phys_dev_groups, 0, total_count * sizeof(VkPhysicalDeviceGroupPropertiesKHX *));
|
|
|
|
// Create a temporary array (on the stack) to keep track of the
|
|
// returned VkPhysicalDevice values.
|
|
local_phys_dev_groups = loader_stack_alloc(sizeof(VkPhysicalDeviceGroupPropertiesKHX) * total_count);
|
|
if (NULL == local_phys_dev_groups) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTrampPhysDevGroups: Failed to allocate local "
|
|
"physical device group array of size %d",
|
|
total_count);
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
// Initialize the memory to something valid
|
|
memset(local_phys_dev_groups, 0, sizeof(VkPhysicalDeviceGroupPropertiesKHX) * total_count);
|
|
for (uint32_t group = 0; group < total_count; group++) {
|
|
local_phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX;
|
|
local_phys_dev_groups[group].pNext = NULL;
|
|
local_phys_dev_groups[group].subsetAllocation = false;
|
|
}
|
|
|
|
// Call down and get the content
|
|
res = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroupsKHX(instance, &total_count, local_phys_dev_groups);
|
|
if (VK_SUCCESS != res) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTrampPhysDevGroups: Failed during dispatch call of "
|
|
"\'EnumeratePhysicalDeviceGroupsKHX\' to lower layers or "
|
|
"loader to get content.");
|
|
goto out;
|
|
}
|
|
|
|
// Replace all the physical device IDs with the proper loader values
|
|
for (uint32_t group = 0; group < total_count; group++) {
|
|
for (uint32_t group_gpu = 0; group_gpu < local_phys_dev_groups[group].physicalDeviceCount; group_gpu++) {
|
|
bool found = false;
|
|
for (uint32_t tramp_gpu = 0; tramp_gpu < inst->phys_dev_count_tramp; tramp_gpu++) {
|
|
if (local_phys_dev_groups[group].physicalDevices[group_gpu] == inst->phys_devs_tramp[tramp_gpu]->phys_dev) {
|
|
local_phys_dev_groups[group].physicalDevices[group_gpu] = (VkPhysicalDevice)inst->phys_devs_tramp[tramp_gpu];
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTrampPhysDevGroups: Failed to find GPU %d in group %d"
|
|
" returned by \'EnumeratePhysicalDeviceGroupsKHX\' in list returned"
|
|
" by \'EnumeratePhysicalDevices\'", group_gpu, group);
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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++) {
|
|
// 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_tramp; old_idx++) {
|
|
if (local_phys_dev_groups[new_idx].physicalDeviceCount == inst->phys_dev_groups_tramp[old_idx]->physicalDeviceCount) {
|
|
bool found_all_gpus = true;
|
|
for (uint32_t old_gpu = 0; old_gpu < inst->phys_dev_groups_tramp[old_idx]->physicalDeviceCount; old_gpu++) {
|
|
bool found_gpu = false;
|
|
for (uint32_t new_gpu = 0; new_gpu < local_phys_dev_groups[new_idx].physicalDeviceCount; new_gpu++) {
|
|
if (local_phys_dev_groups[new_idx].physicalDevices[new_gpu] == inst->phys_dev_groups_tramp[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[new_idx] = inst->phys_dev_groups_tramp[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] = (VkPhysicalDeviceGroupPropertiesKHX *)loader_instance_heap_alloc(
|
|
inst, sizeof(VkPhysicalDeviceGroupPropertiesKHX), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
|
|
if (NULL == new_phys_dev_groups[new_idx]) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTrampPhysDevGroups: Failed to allocate "
|
|
"physical device group trampoline object %d",
|
|
new_idx);
|
|
total_count = new_idx;
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
memcpy(new_phys_dev_groups[new_idx], &local_phys_dev_groups[new_idx],
|
|
sizeof(VkPhysicalDeviceGroupPropertiesKHX));
|
|
}
|
|
}
|
|
|
|
out:
|
|
|
|
if (VK_SUCCESS != res) {
|
|
if (NULL != new_phys_dev_groups) {
|
|
for (uint32_t i = 0; i < total_count; i++) {
|
|
loader_instance_heap_free(inst, new_phys_dev_groups[i]);
|
|
}
|
|
loader_instance_heap_free(inst, new_phys_dev_groups);
|
|
}
|
|
total_count = 0;
|
|
} else {
|
|
// Free everything that didn't carry over to the new array of
|
|
// physical device groups
|
|
if (NULL != inst->phys_dev_groups_tramp) {
|
|
for (uint32_t i = 0; i < inst->phys_dev_group_count_tramp; i++) {
|
|
bool found = false;
|
|
for (uint32_t j = 0; j < total_count; j++) {
|
|
if (inst->phys_dev_groups_tramp[i] == new_phys_dev_groups[j]) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
loader_instance_heap_free(inst, inst->phys_dev_groups_tramp[i]);
|
|
}
|
|
}
|
|
loader_instance_heap_free(inst, inst->phys_dev_groups_tramp);
|
|
}
|
|
|
|
// Swap in the new physical device group list
|
|
inst->phys_dev_group_count_tramp = total_count;
|
|
inst->phys_dev_groups_tramp = new_phys_dev_groups;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
VkResult setupLoaderTermPhysDevGroups(struct loader_instance *inst) {
|
|
VkResult res = VK_SUCCESS;
|
|
struct loader_icd_term *icd_term;
|
|
uint32_t total_count = 0;
|
|
uint32_t cur_icd_group_count = 0;
|
|
VkPhysicalDeviceGroupPropertiesKHX **new_phys_dev_groups = NULL;
|
|
VkPhysicalDeviceGroupPropertiesKHX *local_phys_dev_groups = NULL;
|
|
|
|
if (0 == inst->phys_dev_count_term) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTermPhysDevGroups: Loader failed to setup physical "
|
|
"device terminator info before calling \'EnumeratePhysicalDeviceGroupsKHX\'.");
|
|
assert(false);
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
|
|
// For each ICD, query the number of physical device groups, 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++) {
|
|
cur_icd_group_count = 0;
|
|
if (NULL == icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHX) {
|
|
// Treat each ICD's GPU as it's own group if the extension isn't supported
|
|
res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &cur_icd_group_count, NULL);
|
|
if (res != VK_SUCCESS) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTermPhysDevGroups: Failed during dispatch call of "
|
|
"\'EnumeratePhysicalDevices\' to ICD %d to get plain phys dev count.",
|
|
icd_idx);
|
|
goto out;
|
|
}
|
|
} else {
|
|
// Query the actual group info
|
|
res = icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHX(icd_term->instance, &cur_icd_group_count, NULL);
|
|
if (res != VK_SUCCESS) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTermPhysDevGroups: Failed during dispatch call of "
|
|
"\'EnumeratePhysicalDeviceGroupsKHX\' to ICD %d to get count.",
|
|
icd_idx);
|
|
goto out;
|
|
}
|
|
}
|
|
total_count += cur_icd_group_count;
|
|
}
|
|
|
|
// Create an array for the new physical device groups, which will be stored
|
|
// in the instance for the Terminator code.
|
|
new_phys_dev_groups = (VkPhysicalDeviceGroupPropertiesKHX **)loader_instance_heap_alloc(
|
|
inst, total_count * sizeof(VkPhysicalDeviceGroupPropertiesKHX *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
|
|
if (NULL == new_phys_dev_groups) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTermPhysDevGroups: Failed to allocate new physical device"
|
|
" group array of size %d",
|
|
total_count);
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
memset(new_phys_dev_groups, 0, total_count * sizeof(VkPhysicalDeviceGroupPropertiesKHX *));
|
|
|
|
// Create a temporary array (on the stack) to keep track of the
|
|
// returned VkPhysicalDevice values.
|
|
local_phys_dev_groups = loader_stack_alloc(sizeof(VkPhysicalDeviceGroupPropertiesKHX) * total_count);
|
|
if (NULL == local_phys_dev_groups) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTermPhysDevGroups: Failed to allocate local "
|
|
"physical device group array of size %d",
|
|
total_count);
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
// Initialize the memory to something valid
|
|
memset(local_phys_dev_groups, 0, sizeof(VkPhysicalDeviceGroupPropertiesKHX) * total_count);
|
|
for (uint32_t group = 0; group < total_count; group++) {
|
|
local_phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHX;
|
|
local_phys_dev_groups[group].pNext = NULL;
|
|
local_phys_dev_groups[group].subsetAllocation = false;
|
|
}
|
|
|
|
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;
|
|
|
|
if (NULL == icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHX) {
|
|
VkPhysicalDevice* phys_dev_array = loader_stack_alloc(sizeof(VkPhysicalDevice) * count_this_time);
|
|
if (NULL == phys_dev_array) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTermPhysDevGroups: Failed to allocate local "
|
|
"physical device array of size %d",
|
|
count_this_time);
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
|
|
res = icd_term->dispatch.EnumeratePhysicalDevices(icd_term->instance, &count_this_time, phys_dev_array);
|
|
if (res != VK_SUCCESS) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTermPhysDevGroups: Failed during dispatch call of "
|
|
"\'EnumeratePhysicalDevices\' to ICD %d to get plain phys dev count.",
|
|
icd_idx);
|
|
goto out;
|
|
}
|
|
|
|
// Add each GPU as it's own group
|
|
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];
|
|
}
|
|
|
|
} else {
|
|
res = icd_term->dispatch.EnumeratePhysicalDeviceGroupsKHX(icd_term->instance, &count_this_time, &local_phys_dev_groups[cur_icd_group_count]);
|
|
if (VK_SUCCESS != res) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTermPhysDevGroups: Failed during dispatch call of "
|
|
"\'EnumeratePhysicalDeviceGroupsKHX\' to ICD %d to get content.",
|
|
icd_idx);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
cur_icd_group_count += count_this_time;
|
|
}
|
|
|
|
// Replace all the physical device IDs with the proper loader values
|
|
for (uint32_t group = 0; group < total_count; group++) {
|
|
for (uint32_t group_gpu = 0; group_gpu < local_phys_dev_groups[group].physicalDeviceCount; group_gpu++) {
|
|
bool found = false;
|
|
for (uint32_t term_gpu = 0; term_gpu < inst->phys_dev_count_term; term_gpu++) {
|
|
if (local_phys_dev_groups[group].physicalDevices[group_gpu] == inst->phys_devs_term[term_gpu]->phys_dev) {
|
|
local_phys_dev_groups[group].physicalDevices[group_gpu] = (VkPhysicalDevice)inst->phys_devs_term[term_gpu];
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
|
|
"setupLoaderTermPhysDevGroups: Failed to find GPU %d in group %d"
|
|
" returned by \'EnumeratePhysicalDeviceGroupsKHX\' in list returned"
|
|
" by \'EnumeratePhysicalDevices\'", group_gpu, group);
|
|
res = VK_ERROR_INITIALIZATION_FAILED;
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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++) {
|
|
// 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) {
|
|
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 < local_phys_dev_groups[new_idx].physicalDeviceCount; new_gpu++) {
|
|
if (local_phys_dev_groups[new_idx].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[new_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] = (VkPhysicalDeviceGroupPropertiesKHX *)loader_instance_heap_alloc(
|
|
inst, sizeof(VkPhysicalDeviceGroupPropertiesKHX), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
|
|
if (NULL == new_phys_dev_groups[new_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;
|
|
res = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
goto out;
|
|
}
|
|
memcpy(new_phys_dev_groups[new_idx], &local_phys_dev_groups[new_idx],
|
|
sizeof(VkPhysicalDeviceGroupPropertiesKHX));
|
|
}
|
|
}
|
|
|
|
out:
|
|
|
|
if (VK_SUCCESS != res) {
|
|
if (NULL != new_phys_dev_groups) {
|
|
for (uint32_t i = 0; i < total_count; i++) {
|
|
loader_instance_heap_free(inst, new_phys_dev_groups[i]);
|
|
}
|
|
loader_instance_heap_free(inst, new_phys_dev_groups);
|
|
}
|
|
total_count = 0;
|
|
} else {
|
|
// Free everything that didn't carry over to the new array of
|
|
// physical device groups
|
|
if (NULL != inst->phys_dev_groups_term) {
|
|
for (uint32_t i = 0; i < inst->phys_dev_group_count_term; i++) {
|
|
bool found = false;
|
|
for (uint32_t j = 0; j < total_count; j++) {
|
|
if (inst->phys_dev_groups_term[i] == new_phys_dev_groups[j]) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
loader_instance_heap_free(inst, inst->phys_dev_groups_term[i]);
|
|
}
|
|
}
|
|
loader_instance_heap_free(inst, inst->phys_dev_groups_term);
|
|
}
|
|
|
|
// Swap in the new physical device group list
|
|
inst->phys_dev_group_count_term = total_count;
|
|
inst->phys_dev_groups_term = new_phys_dev_groups;
|
|
}
|
|
|
|
return res;
|
|
}
|