loader: Add support for debug report
diff --git a/layers/layers_msg.h b/layers/layers_msg.h
index 88208f9..a5e90de 100644
--- a/layers/layers_msg.h
+++ b/layers/layers_msg.h
@@ -62,6 +62,8 @@
pNewDbgFuncNode->msgFlags = msgFlags;
pNewDbgFuncNode->pUserData = pUserData;
pNewDbgFuncNode->pNext = g_pDbgFunctionHead;
+
+ /* TODO: This should be a per-instance resource */
g_pDbgFunctionHead = pNewDbgFuncNode;
} else {
free(pNewDbgFuncNode);
@@ -94,10 +96,27 @@
return result;
}
+static void* msg_callback_get_proc_addr(
+ const char *funcName)
+{
+ if (!g_DEBUG_REPORT) {
+ return NULL;
+ }
+
+ if (!strcmp(funcName, "vkDbgCreateMsgCallback")) {
+ return (void *) vkDbgCreateMsgCallback;
+ }
+ if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) {
+ return (void *) vkDbgDestroyMsgCallback;
+ }
+
+ return NULL;
+}
+
// Utility function to handle reporting
// If callbacks are enabled, use them, otherwise use printf
static void layerCbMsg(
- VkFlags msgFlags,
+ VkFlags msgFlags,
VkObjectType objectType,
VkObject srcObject,
size_t location,
@@ -122,65 +141,4 @@
}
pTrav = pTrav->pNext;
}
-#if 0
- if (g_debugAction & (VK_DBG_LAYER_ACTION_LOG_MSG | VK_DBG_LAYER_ACTION_CALLBACK)) {
- if (msgFlags & VK_DBG_REPORT_ERROR_BIT) {
- if (g_reportFlags <= VK_DBG_LAYER_LEVEL_ERROR) {
- if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG) {
- fprintf(g_logFile, "{%s}ERROR : %s\n", pLayerPrefix, pMsg);
- fflush(g_logFile);
- }
- if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK) {
- while (pTrav) {
- pTrav->pfnMsgCallback(msgFlags,
- objectType, srcObject,
- location,
- msgCode,
- pLayerPrefix,
- pMsg,
- pTrav->pUserData);
- pTrav = pTrav->pNext;
- }
- }
- }
- }
- switch (msgType) {
- case VK_DBG_REPORT_ERROR_BIT:
- break;
- case VK_DBG_MSG_WARNING:
- if (g_reportFlags <= VK_DBG_LAYER_LEVEL_WARN) {
- if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG)
- fprintf(g_logFile, "{%s}WARN : %s\n", pLayerPrefix, pMsg);
- if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK)
- while (pTrav) {
- pTrav->pfnMsgCallback(msgType, validationLevel, srcObject, location, msgCode, pMsg, pTrav->pUserData);
- pTrav = pTrav->pNext;
- }
- }
- break;
- case VK_DBG_MSG_PERF_WARNING:
- if (g_reportFlags <= VK_DBG_LAYER_LEVEL_PERF_WARN) {
- if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG)
- fprintf(g_logFile, "{%s}PERF_WARN : %s\n", pLayerPrefix, pMsg);
- if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK)
- while (pTrav) {
- pTrav->pfnMsgCallback(msgType, validationLevel, srcObject, location, msgCode, pMsg, pTrav->pUserData);
- pTrav = pTrav->pNext;
- }
- }
- break;
- default:
- if (g_reportFlags <= VK_DBG_LAYER_LEVEL_INFO) {
- if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG)
- fprintf(g_logFile, "{%s}INFO : %s\n", pLayerPrefix, pMsg);
- if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK)
- while (pTrav) {
- pTrav->pfnMsgCallback(msgType, validationLevel, srcObject, location, msgCode, pMsg, pTrav->pUserData);
- pTrav = pTrav->pNext;
- }
- }
- break;
- }
- }
-#endif
}
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index 3898a54..85af9c2 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -863,6 +863,25 @@
return res;
}
+VkResult VKAPI vkCreateInstance(
+ const VkInstanceCreateInfo* pCreateInfo,
+ VkInstance* pInstance)
+{
+ loader_platform_thread_once(&g_initOnce, initMemTracker);
+ /*
+ * For layers, the pInstance has already been filled out
+ * by the loader so that dispatch table is available.
+ */
+ initInstanceTable((const VkBaseLayerObject *) (*pInstance));
+
+ VkResult result = instance_dispatch_table(*pInstance)->CreateInstance(pCreateInfo, pInstance);
+
+ if (result == VK_SUCCESS) {
+ enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions);
+ }
+ return result;
+}
+
VK_LAYER_EXPORT VkResult VKAPI vkCreateDevice(
VkPhysicalDevice gpu,
const VkDeviceCreateInfo *pCreateInfo,
@@ -922,13 +941,19 @@
uint32_t version;
const char * const name;
};
-#define MEM_TRACKER_LAYER_EXT_ARRAY_SIZE 1
+#define MEM_TRACKER_LAYER_EXT_ARRAY_SIZE 2
static const VkExtensionProperties mtExts[MEM_TRACKER_LAYER_EXT_ARRAY_SIZE] = {
{
VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
"MemTracker",
0x10,
- "Sample layer: MemTracker",
+ "Validation layer: MemTracker",
+ },
+ {
+ VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
+ "Validation",
+ 0x10,
+ "Validation layer: MemTracker",
}
};
@@ -971,6 +996,45 @@
return VK_SUCCESS;
}
+VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(
+ VkPhysicalDevice physical_device,
+ VkExtensionInfoType infoType,
+ uint32_t extensionIndex,
+ size_t *pDataSize,
+ void *pData)
+{
+ uint32_t *count;
+
+ if (pDataSize == NULL) {
+ return VK_ERROR_INVALID_POINTER;
+ }
+
+ switch (infoType) {
+ case VK_EXTENSION_INFO_TYPE_COUNT:
+ *pDataSize = sizeof(uint32_t);
+ if (pData == NULL) {
+ return VK_SUCCESS;
+ }
+ count = (uint32_t *) pData;
+ *count = MEM_TRACKER_LAYER_EXT_ARRAY_SIZE;
+ break;
+ case VK_EXTENSION_INFO_TYPE_PROPERTIES:
+ *pDataSize = sizeof(VkExtensionProperties);
+ if (pData == NULL) {
+ return VK_SUCCESS;
+ }
+ if (extensionIndex >= MEM_TRACKER_LAYER_EXT_ARRAY_SIZE) {
+ return VK_ERROR_INVALID_VALUE;
+ }
+ memcpy((VkExtensionProperties *) pData, &mtExts[extensionIndex], sizeof(VkExtensionProperties));
+ break;
+ default:
+ return VK_ERROR_INVALID_VALUE;
+ }
+
+ return VK_SUCCESS;
+}
+
VK_LAYER_EXPORT VkResult VKAPI vkGetDeviceQueue(
VkDevice device,
uint32_t queueNodeIndex,
@@ -1252,6 +1316,10 @@
uint32_t fenceCount,
VkFence *pFences)
{
+ /*
+ * TODO: Shouldn't we check for error conditions before passing down the chain?
+ * What if reason result is not VK_SUCCESS is something we could report as a validation error?
+ */
VkResult result = device_dispatch_table(device)->ResetFences(device, fenceCount, pFences);
if (VK_SUCCESS == result) {
loader_platform_thread_lock_mutex(&globalLock);
@@ -2151,6 +2219,8 @@
VkDevice dev,
const char *funcName)
{
+ void *fptr;
+
if (dev == NULL) {
return NULL;
}
@@ -2296,7 +2366,11 @@
return (void*) vkDestroySwapChainWSI;
if (!strcmp(funcName, "vkGetSwapChainInfoWSI"))
return (void*) vkGetSwapChainInfoWSI;
- else
+
+ fptr = msg_callback_get_proc_addr(funcName);
+ if (fptr)
+ return fptr;
+
{
VkLayerDispatchTable **ppDisp = (VkLayerDispatchTable **) dev;
VkLayerDispatchTable* pTable = tableMap[*ppDisp];
@@ -2310,6 +2384,7 @@
VkInstance instance,
const char *funcName)
{
+ void *fptr;
if (instance == NULL) {
return NULL;
}
@@ -2324,9 +2399,15 @@
if (!strcmp(funcName, "vkDestroyInstance"))
return (void *) vkDestroyInstance;
+ if (!strcmp(funcName, "vkCreateInstance"))
+ return (void*) vkCreateInstance;
if (!strcmp(funcName, "vkCreateDevice"))
return (void*) vkCreateDevice;
- else
+
+ fptr = msg_callback_get_proc_addr(funcName);
+ if (fptr)
+ return fptr;
+
{
VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) instance;
VkLayerInstanceDispatchTable* pTable = tableInstanceMap[*ppDisp];
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index a27d54e..fa8f316 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -193,6 +193,10 @@
VK_LAYER_EXPORT VkResult VKAPI vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance)
{
+ /* TODO: shouldn't we have initInstanceDispatch here? */
+ loader_platform_thread_once(&initOnce, initParamChecker);
+ initInstanceTable((const VkBaseLayerObject *) (*pInstance));
+
PreCreateInstance(pCreateInfo->pAppInfo, pCreateInfo->pAllocCb);
VkResult result = instance_dispatch_table(*pInstance)->CreateInstance(pCreateInfo, pInstance);
PostCreateInstance(result, pCreateInfo, pInstance);
@@ -327,13 +331,19 @@
return result;
}
-#define PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE 1
+#define PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE 2
static const VkExtensionProperties pcExts[PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE] = {
{
VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
"ParamChecker",
0x10,
"Sample layer: ParamChecker",
+ },
+ {
+ VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
+ "Validation",
+ 0x10,
+ "Sample layer: ParamChecker",
}
};
@@ -379,8 +389,33 @@
size_t* pDataSize,
void* pData)
{
- VkResult result = instance_dispatch_table(gpu)->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex, pDataSize, pData);
- return result;
+ /* This entrypoint is NOT going to init it's own dispatch table since loader calls here early */
+ uint32_t *count;
+
+ if (pDataSize == NULL)
+ return VK_ERROR_INVALID_POINTER;
+
+ switch (infoType) {
+ case VK_EXTENSION_INFO_TYPE_COUNT:
+ *pDataSize = sizeof(uint32_t);
+ if (pData == NULL)
+ return VK_SUCCESS;
+ count = (uint32_t *) pData;
+ *count = PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE;
+ break;
+ case VK_EXTENSION_INFO_TYPE_PROPERTIES:
+ *pDataSize = sizeof(VkExtensionProperties);
+ if (pData == NULL)
+ return VK_SUCCESS;
+ if (extensionIndex >= PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE)
+ return VK_ERROR_INVALID_VALUE;
+ memcpy((VkExtensionProperties *) pData, &pcExts[extensionIndex], sizeof(VkExtensionProperties));
+ break;
+ default:
+ return VK_ERROR_INVALID_VALUE;
+ };
+
+ return VK_SUCCESS;
}
VK_LAYER_EXPORT VkResult VKAPI vkGetDeviceQueue(VkDevice device, uint32_t queueNodeIndex, uint32_t queueIndex, VkQueue* pQueue)
diff --git a/loader/loader.c b/loader/loader.c
index fd23465..b55ddcf 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -69,7 +69,7 @@
.GetPhysicalDeviceInfo = loader_GetPhysicalDeviceInfo,
.CreateDevice = loader_CreateDevice,
.GetGlobalExtensionInfo = vkGetGlobalExtensionInfo,
- .GetPhysicalDeviceExtensionInfo = loader_GetPhysicalDeviceExtensionInfo,
+ .GetPhysicalDeviceExtensionInfo = vkGetPhysicalDeviceExtensionInfo,
.GetMultiDeviceCompatibility = loader_GetMultiDeviceCompatibility,
.GetDisplayInfoWSI = loader_GetDisplayInfoWSI,
.DbgCreateMsgCallback = loader_DbgCreateMsgCallback,
@@ -302,6 +302,52 @@
return;
}
+static void get_physical_device_layer_extensions(
+ struct loader_instance *ptr_instance,
+ VkPhysicalDevice physical_device,
+ const uint32_t layer_index,
+ struct loader_extension_list *ext_list)
+{
+ uint32_t i, count;
+ size_t siz = sizeof(count);
+ VkResult res;
+ loader_platform_dl_handle lib_handle;
+ PFN_vkGetPhysicalDeviceExtensionInfo fp_get;
+ struct loader_extension_property ext_props;
+
+ if (!loader.scanned_layers[layer_index].physical_device_extensions_supported) {
+ return;
+ }
+
+ ext_props.origin = VK_EXTENSION_ORIGIN_LAYER;
+ ext_props.lib_name = loader.scanned_layers[layer_index].lib_name;
+ char funcStr[256];
+ snprintf(funcStr, 256, "%sGetPhysicalDeviceExtensionInfo", ext_props.info.name);
+ lib_handle = loader_add_layer_lib("device", &ext_props);
+ fp_get = (PFN_vkGetPhysicalDeviceExtensionInfo) loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceExtensionInfo");
+ if (fp_get) {
+ res = fp_get(physical_device, VK_EXTENSION_INFO_TYPE_COUNT, 0, &siz, &count);
+ if (res == VK_SUCCESS) {
+ siz = sizeof(VkExtensionProperties);
+ for (i = 0; i < count; i++) {
+ memset(&ext_props, 0, sizeof(ext_props));
+ res = fp_get(physical_device, VK_EXTENSION_INFO_TYPE_PROPERTIES, i, &siz, &ext_props.info);
+ if (res == VK_SUCCESS && (ext_props.info.sType == VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES)) {
+ ext_props.hosted = false;
+ ext_props.origin = VK_EXTENSION_ORIGIN_LAYER;
+ ext_props.lib_name = loader.scanned_layers[layer_index].lib_name;
+ loader_add_to_ext_list(ext_list, 1, &ext_props);
+ }
+ }
+ } else {
+ loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting physical device extension info count from Layer %s", ext_props.lib_name);
+ }
+ }
+
+ loader_remove_layer_lib(ptr_instance, &ext_props);
+ return;
+}
+
static bool loader_init_ext_list(struct loader_extension_list *ext_info)
{
ext_info->capacity = 32 * sizeof(struct loader_extension_property);
@@ -490,6 +536,7 @@
loader_platform_dl_handle handle;
void *fp_create_inst;
void *fp_get_global_ext_info;
+ void *fp_get_device_ext_info;
struct loader_scanned_icds *new_node;
// Used to call: dlopen(filename, RTLD_LAZY);
@@ -509,6 +556,7 @@
LOOKUP(fp_create_inst, CreateInstance);
LOOKUP(fp_get_global_ext_info, GetGlobalExtensionInfo);
+ LOOKUP(fp_get_device_ext_info, GetPhysicalDeviceExtensionInfo);
#undef LOOKUP
new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds)
@@ -522,6 +570,7 @@
new_node->CreateInstance = fp_create_inst;
new_node->GetGlobalExtensionInfo = fp_get_global_ext_info;
loader_init_ext_list(&new_node->global_extension_list);
+ loader_init_ext_list(&new_node->device_extension_list);
new_node->next = loader.scanned_icd_list;
new_node->lib_name = (char *) (new_node + 1);
@@ -794,6 +843,12 @@
VK_EXTENSION_ORIGIN_LAYER,
&loader.scanned_layers[count].global_extension_list);
+ fp_get_ext = loader_platform_get_proc_address(handle,
+ "vkGetPhysicalDeviceExtensionInfo");
+ if (fp_get_ext) {
+ loader.scanned_layers[count].physical_device_extensions_supported = true;
+ }
+
count++;
loader_platform_close_library(handle);
}
@@ -880,8 +935,8 @@
/* Have already loaded this library, just increment ref count */
loader.loaded_layer_lib_list[i].ref_count++;
loader_log(VK_DBG_REPORT_INFO_BIT, 0,
- "Inserting %s layer %s from library %s", chain_type,
- ext_prop->info.name, ext_prop->lib_name);
+ "%s Chain: Increment layer reference count for layer library %s",
+ chain_type, ext_prop->lib_name);
return loader.loaded_layer_lib_list[i].lib_handle;
}
}
@@ -896,7 +951,7 @@
my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count];
- /* NOTE: We require that the extension property to be immutable */
+ /* NOTE: We require that the extension property be immutable */
my_lib->lib_name = ext_prop->lib_name;
my_lib->ref_count = 0;
my_lib->lib_handle = NULL;
@@ -907,8 +962,8 @@
return NULL;
} else {
loader_log(VK_DBG_REPORT_INFO_BIT, 0,
- "Inserting %s layer %s from library %s", chain_type,
- ext_prop->info.name, ext_prop->lib_name);
+ "Chain: %s: Loading layer library %s",
+ chain_type, ext_prop->lib_name);
}
loader.loaded_layer_lib_count++;
loader.loaded_layer_lib_list = new_layer_lib_list;
@@ -941,9 +996,15 @@
my_lib->ref_count--;
inst->layer_count--;
if (my_lib->ref_count > 0) {
+ loader_log(VK_DBG_REPORT_INFO_BIT, 0,
+ "Decrement reference count for layer library %s", ext_prop->lib_name);
return;
}
+ loader_platform_close_library(my_lib->lib_handle);
+ loader_log(VK_DBG_REPORT_INFO_BIT, 0,
+ "Unloading layer library %s", ext_prop->lib_name);
+
/* Need to remove unused library from list */
new_layer_lib_list = malloc((loader.loaded_layer_lib_count - 1) * sizeof(struct loader_lib_info));
if (!new_layer_lib_list) {
@@ -961,6 +1022,7 @@
memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1],
sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1));
}
+
free(loader.loaded_layer_lib_list);
loader.loaded_layer_lib_count--;
loader.loaded_layer_lib_list = new_layer_lib_list;
@@ -1133,6 +1195,10 @@
continue;
}
+ loader_log(VK_DBG_REPORT_INFO_BIT, 0,
+ "Insert instance layer library %s for extension: %s",
+ ext_prop->lib_name, ext_prop->info.name);
+
layer_idx--;
}
@@ -1141,6 +1207,14 @@
return inst->layer_count;
}
+void loader_activate_instance_layer_extensions(struct loader_instance *inst)
+{
+
+ loader_init_instance_extension_dispatch_table(inst->disp,
+ inst->disp->GetInstanceProcAddr,
+ (VkInstance) inst->wrappedInstance);
+}
+
void loader_enable_device_layers(struct loader_icd *icd, uint32_t gpu_index)
{
if (icd == NULL)
@@ -1220,6 +1294,10 @@
continue;
}
+ loader_log(VK_DBG_REPORT_INFO_BIT, 0,
+ "Insert device layer library %s for extension: %s",
+ ext_prop->lib_name, ext_prop->info.name);
+
layer_idx--;
}
@@ -1315,79 +1393,142 @@
return VK_SUCCESS;
}
+VkResult loader_init_physical_device_info(
+ struct loader_instance *ptr_instance)
+{
+ struct loader_icd *icd;
+ uint32_t n, count = 0;
+ VkResult res = VK_ERROR_UNKNOWN;
+
+ icd = ptr_instance->icds;
+ while (icd) {
+ res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
+ if (res != VK_SUCCESS)
+ return res;
+ icd->gpu_count = n;
+ count += n;
+ icd = icd->next;
+ }
+
+ ptr_instance->total_gpu_count = count;
+
+ VkPhysicalDevice* gpus;
+ gpus = malloc( sizeof(VkPhysicalDevice) * count);
+ if (!gpus) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ icd = ptr_instance->icds;
+ while (icd) {
+ VkBaseLayerObject * wrapped_gpus;
+ PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
+
+ n = icd->gpu_count;
+ res = icd->EnumeratePhysicalDevices(
+ icd->instance,
+ &n,
+ gpus);
+ if (res == VK_SUCCESS && n) {
+ wrapped_gpus = (VkBaseLayerObject*) malloc(n *
+ sizeof(VkBaseLayerObject));
+ if (!wrapped_gpus) {
+ /* TODO: Add cleanup code here */
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ icd->gpus = wrapped_gpus;
+ icd->loader_dispatch = (VkLayerDispatchTable *) malloc(n *
+ sizeof(VkLayerDispatchTable));
+ for (unsigned int i = 0; i < n; i++) {
+ (wrapped_gpus + i)->baseObject = gpus[i];
+ (wrapped_gpus + i)->pGPA = get_proc_addr;
+ (wrapped_gpus + i)->nextObject = gpus[i];
+
+ loader_init_device_dispatch_table(icd->loader_dispatch + i,
+ get_proc_addr, gpus[i], gpus[i]);
+
+ loader_init_dispatch(gpus[i], ptr_instance->disp);
+
+ if (!loader_init_ext_list(&icd->device_extension_cache[i])) {
+ /* TODO: Add cleanup code here */
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ if (res == VK_SUCCESS && icd->GetPhysicalDeviceExtensionInfo) {
+ size_t data_size;
+ uint32_t extension_count;
+
+ data_size = sizeof(extension_count);
+ res = icd->GetPhysicalDeviceExtensionInfo(gpus[i], VK_EXTENSION_INFO_TYPE_COUNT, 0, &data_size, &extension_count);
+ if (data_size == sizeof(extension_count) && res == VK_SUCCESS) {
+ struct loader_extension_property ext_props;
+
+ /* Gather all the ICD extensions */
+ for (uint32_t extension_id = 0; extension_id < extension_count; extension_id++) {
+ data_size = sizeof(VkExtensionProperties);
+ res = icd->GetPhysicalDeviceExtensionInfo(gpus[i], VK_EXTENSION_INFO_TYPE_PROPERTIES,
+ extension_id, &data_size, &ext_props.info);
+ if (data_size == sizeof(VkExtensionProperties) && res == VK_SUCCESS) {
+ ext_props.hosted = false;
+ ext_props.origin = VK_EXTENSION_ORIGIN_ICD;
+ ext_props.lib_name = icd->scanned_icds->lib_name;
+ loader_add_to_ext_list(&icd->device_extension_cache[i], 1, &ext_props);
+ }
+ }
+
+ // Traverse layers list adding non-duplicate extensions to the list
+ for (uint32_t l = 0; l < loader.scanned_layer_count; l++) {
+ get_physical_device_layer_extensions(ptr_instance, gpus[i], l, &icd->device_extension_cache[i]);
+ }
+ }
+ }
+
+ if (res != VK_SUCCESS) {
+ /* clean up any extension lists previously created before this request failed */
+ for (uint32_t j = 0; j < i; j++) {
+ loader_destroy_ext_list(&icd->device_extension_cache[i]);
+ }
+ return res;
+ }
+ }
+
+ count += n;
+ }
+
+ icd = icd->next;
+ }
+
+ return VK_SUCCESS;
+}
+
VkResult loader_EnumeratePhysicalDevices(
VkInstance instance,
uint32_t* pPhysicalDeviceCount,
VkPhysicalDevice* pPhysicalDevices)
{
+ uint32_t index = 0;
struct loader_instance *ptr_instance = (struct loader_instance *) instance;
- struct loader_icd *icd;
- uint32_t n, count = 0;
- VkResult res = VK_ERROR_UNKNOWN;
+ struct loader_icd *icd = ptr_instance->icds;
- //in spirit of VK don't error check on the instance parameter
- icd = ptr_instance->icds;
- if (pPhysicalDevices == NULL) {
- while (icd) {
- res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL);
- if (res != VK_SUCCESS)
- return res;
- icd->gpu_count = n;
- count += n;
- icd = icd->next;
- }
-
- ptr_instance->total_gpu_count = count;
-
- } else
- {
- VkPhysicalDevice* gpus;
- if (*pPhysicalDeviceCount < ptr_instance->total_gpu_count)
- return VK_ERROR_INVALID_VALUE;
- gpus = malloc( sizeof(VkPhysicalDevice) * *pPhysicalDeviceCount);
- if (!gpus)
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- while (icd) {
- VkBaseLayerObject * wrapped_gpus;
- PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr;
-
- n = *pPhysicalDeviceCount;
- res = icd->EnumeratePhysicalDevices(
- icd->instance,
- &n,
- gpus);
- if (res == VK_SUCCESS && n) {
- wrapped_gpus = (VkBaseLayerObject*) malloc(n *
- sizeof(VkBaseLayerObject));
- icd->gpus = wrapped_gpus;
- icd->gpu_count = n;
- icd->loader_dispatch = (VkLayerDispatchTable *) malloc(n *
- sizeof(VkLayerDispatchTable));
- for (unsigned int i = 0; i < n; i++) {
- (wrapped_gpus + i)->baseObject = gpus[i];
- (wrapped_gpus + i)->pGPA = get_proc_addr;
- (wrapped_gpus + i)->nextObject = gpus[i];
- memcpy(pPhysicalDevices + count, gpus, sizeof(*pPhysicalDevices));
- loader_init_device_dispatch_table(icd->loader_dispatch + i,
- get_proc_addr, gpus[i], gpus[i]);
-
- loader_init_dispatch(gpus[i], ptr_instance->disp);
- }
-
- count += n;
-
- if (count >= *pPhysicalDeviceCount) {
- break;
- }
- }
-
- icd = icd->next;
- }
+ /* TODO: How do we only do this once? */
+ if (ptr_instance->total_gpu_count == 0) {
+ loader_init_physical_device_info(ptr_instance);
}
- *pPhysicalDeviceCount = count;
+ *pPhysicalDeviceCount = ptr_instance->total_gpu_count;
+ if (!pPhysicalDevices) {
+ return VK_SUCCESS;
+ }
- return (count > 0) ? VK_SUCCESS : res;
+ while (icd) {
+ assert((index + icd->gpu_count) <= *pPhysicalDeviceCount);
+ for (uint32_t i = 0; i < icd->gpu_count; i++) {
+ memcpy(&pPhysicalDevices[index], &icd->gpus[i].baseObject, sizeof(VkPhysicalDevice));
+ }
+ index += icd->gpu_count;
+ icd = icd->next;
+ }
+
+ return VK_SUCCESS;
}
VkResult loader_GetPhysicalDeviceInfo(
@@ -1572,7 +1713,8 @@
return VK_SUCCESS;
}
-VkResult loader_GetPhysicalDeviceExtensionInfo(
+
+LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(
VkPhysicalDevice gpu,
VkExtensionInfoType infoType,
uint32_t extensionIndex,
@@ -1580,14 +1722,35 @@
void* pData)
{
uint32_t gpu_index;
+ uint32_t *count;
struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu, &gpu_index);
- VkResult res = VK_ERROR_INITIALIZATION_FAILED;
- if (icd->GetPhysicalDeviceExtensionInfo)
- res = icd->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex,
- pDataSize, pData);
+ if (pDataSize == NULL)
+ return VK_ERROR_INVALID_POINTER;
- return res;
+ switch (infoType) {
+ case VK_EXTENSION_INFO_TYPE_COUNT:
+ *pDataSize = sizeof(uint32_t);
+ if (pData == NULL)
+ return VK_SUCCESS;
+ count = (uint32_t *) pData;
+ *count = icd->device_extension_cache[gpu_index].count;
+ break;
+ case VK_EXTENSION_INFO_TYPE_PROPERTIES:
+ *pDataSize = sizeof(VkExtensionProperties);
+ if (pData == NULL)
+ return VK_SUCCESS;
+ if (extensionIndex >= icd->device_extension_cache[gpu_index].count)
+ return VK_ERROR_INVALID_VALUE;
+ memcpy((VkExtensionProperties *) pData,
+ &icd->device_extension_cache[gpu_index].list[extensionIndex],
+ sizeof(VkExtensionProperties));
+ break;
+ default:
+ return VK_ERROR_INVALID_VALUE;
+ };
+
+ return VK_SUCCESS;
}
VkResult loader_GetMultiDeviceCompatibility(
diff --git a/loader/loader.h b/loader/loader.h
index 8b427b5..2d3b067 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -69,16 +69,14 @@
char *lib_name;
/* cache of global extensions for a specific layer */
-// uint32_t global_extension_count;
-// struct loader_extension_property *global_extensions;
struct loader_extension_list global_extension_list;
+ bool physical_device_extensions_supported;
/*
* cache of device extensions for a specific layer,
* filled in at CreateInstance time
*/
- uint32_t device_ext_count;
- struct loader_extension_property *device_ext_list;
+ struct loader_extension_list physical_device_extension_list;
};
struct loader_icd {
@@ -105,6 +103,13 @@
uint32_t app_extension_count[MAX_GPUS_FOR_LAYER];
VkExtensionProperties *app_extension_props[MAX_GPUS_FOR_LAYER];
+ /*
+ * Fill in the cache of available extensions from all layers that
+ * operate with this physical device.
+ * This cache will be used to satisfy calls to GetPhysicalDeviceExtensionInfo
+ */
+ struct loader_extension_list device_extension_cache[MAX_GPUS_FOR_LAYER];
+
struct loader_extension_list enabled_device_extensions[MAX_GPUS_FOR_LAYER];
};
@@ -238,8 +243,7 @@
* cache of device extensions for specific ICD,
* filled in at CreateInstance time
*/
- uint32_t device_extension_count;
- struct loader_extension_property *device_extensions;
+ struct loader_extension_list device_extension_list;
};
static inline void loader_set_dispatch(VkObject obj, const void *data)
@@ -312,7 +316,6 @@
uint32_t extensionIndex,
size_t* pDataSize,
void* pData);
-#endif
VkResult loader_GetPhysicalDeviceExtensionInfo(
VkPhysicalDevice gpu,
@@ -320,6 +323,7 @@
uint32_t extensionIndex,
size_t* pDataSize,
void* pData);
+#endif
VkResult loader_GetMultiDeviceCompatibility(
VkPhysicalDevice gpu0,
@@ -343,7 +347,15 @@
void layer_lib_scan(void);
void loader_coalesce_extensions(void);
+static loader_platform_dl_handle loader_add_layer_lib(
+ const char *chain_type,
+ struct loader_extension_property *ext_prop);
+static void loader_remove_layer_lib(
+ struct loader_instance *inst,
+ struct loader_extension_property *ext_prop);
+
struct loader_icd * loader_get_icd(const VkBaseLayerObject *gpu,
uint32_t *gpu_index);
uint32_t loader_activate_instance_layers(struct loader_instance *inst);
+void loader_activate_instance_layer_extensions(struct loader_instance *inst);
#endif /* LOADER_H */
diff --git a/loader/table_ops.h b/loader/table_ops.h
index 93131b1..e4c39f2 100644
--- a/loader/table_ops.h
+++ b/loader/table_ops.h
@@ -387,7 +387,13 @@
table->GetPhysicalDeviceExtensionInfo = (PFN_vkGetPhysicalDeviceExtensionInfo) gpa(inst, "vkGetPhysicalDeviceExtensionInfo");
table->GetMultiDeviceCompatibility = (PFN_vkGetMultiDeviceCompatibility) gpa(inst, "vkGetMultiDeviceCompatibility");
table->GetDisplayInfoWSI = (PFN_vkGetDisplayInfoWSI) gpa(inst, "vkGetDisplayInfoWSI");
+}
+static inline void loader_init_instance_extension_dispatch_table(
+ VkLayerInstanceDispatchTable *table,
+ PFN_vkGetInstanceProcAddr gpa,
+ VkInstance inst)
+{
table->DbgCreateMsgCallback = (PFN_vkDbgCreateMsgCallback) gpa(inst, "vkDbgCreateMsgCallback");
table->DbgDestroyMsgCallback = (PFN_vkDbgDestroyMsgCallback) gpa(inst, "vkDbgDestroyMsgCallback");
}
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 8503971..d22df04 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -120,6 +120,14 @@
res = ptr_instance->disp->CreateInstance(pCreateInfo, pInstance);
+ /*
+ * Finally have the layers in place and everyone has seen
+ * the CreateInstance command go by. This allows the layer's
+ * GetInstanceProcAddr functions to return valid extension functions
+ * if enabled.
+ */
+ loader_activate_instance_layer_extensions(ptr_instance);
+
return res;
}
@@ -199,31 +207,6 @@
return res;
}
-#if 0 //TODO get working on layer instance chain
-LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(
- VkExtensionInfoType infoType,
- uint32_t extensionIndex,
- size_t* pDataSize,
- void* pData)
-{
- return instance_disp.GetGlobalExtensionInfo(infoType, extensionIndex, pDataSize, pData);
-}
-#endif
-
-LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(
- VkPhysicalDevice gpu,
- VkExtensionInfoType infoType,
- uint32_t extensionIndex,
- size_t* pDataSize,
- void* pData)
-{
- const VkLayerInstanceDispatchTable *disp;
-
- disp = loader_get_instance_dispatch(gpu);
-
- return disp->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex, pDataSize, pData);
-}
-
LOADER_EXPORT VkResult VKAPI vkGetDeviceQueue(VkDevice device, uint32_t queueNodeIndex, uint32_t queueIndex, VkQueue* pQueue)
{
const VkLayerDispatchTable *disp;
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 5c69e3c..e9cf958 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -152,6 +152,13 @@
std::vector<const char *> device_extension_names;
instance_extension_names.push_back(DEBUG_REPORT_EXTENSION_NAME);
+ instance_extension_names.push_back("MemTracker");
+ instance_extension_names.push_back("ObjectTracker");
+ instance_extension_names.push_back("Threading");
+
+ device_extension_names.push_back("MemTracker");
+ device_extension_names.push_back("ObjectTracker");
+ device_extension_names.push_back("Threading");
// Force layer output level to be >= WARNING so that we catch those messages but ignore others
setLayerOptionEnum("MemTrackerReportLevel", "VK_DBG_LAYER_LEVEL_WARNING");
@@ -806,34 +813,6 @@
}
#endif
#if OBJECT_TRACKER_TESTS
-TEST_F(VkLayerTest, WaitForUnsubmittedFence)
-{
- vk_testing::Fence testFence;
- VkFlags msgFlags;
- std::string msgString;
- VkFenceCreateInfo fenceInfo = {};
- fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceInfo.pNext = NULL;
-
- ASSERT_NO_FATAL_FAILURE(InitState());
- testFence.init(*m_device, fenceInfo);
- m_errorMonitor->ClearState();
- vkGetFenceStatus(m_device->device(),testFence.obj());
- msgFlags = m_errorMonitor->GetState(&msgString);
- ASSERT_TRUE(msgFlags & VK_DBG_REPORT_ERROR_BIT) << "Did not receive an error asking for status of unsubmitted fence";
- if (!strstr(msgString.c_str(),"Status Requested for Unsubmitted Fence")) {
- FAIL() << "Error received was not Status Requested for Unsubmitted Fence";
- }
-
- VkFence fences[1] = {testFence.obj()};
- m_errorMonitor->ClearState();
- vkWaitForFences(m_device->device(), 1, fences, VK_TRUE, 0);
- msgFlags = m_errorMonitor->GetState(&msgString);
- ASSERT_TRUE(msgFlags & VK_DBG_REPORT_ERROR_BIT) << "Did not receive an error for waiting for unsubmitted fence";
- if (!strstr(msgString.c_str(),"Waiting for Unsubmitted Fence")) {
- FAIL() << "Error received was not 'Waiting for Unsubmitted Fence'";
- }
-}
TEST_F(VkLayerTest, GetObjectInfoMismatchedType)
{
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index a658bbe..f206d06 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -120,7 +120,7 @@
VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
dbgFunction,
userData,
- &m_msgCallback);
+ &m_globalMsgCallback);
ASSERT_VK_SUCCESS(err);
}
}
@@ -149,6 +149,18 @@
// ASSERT_NE(obj_name, (PFN_vkDbgCreateMsgCallback) NULL) << "Did not get function pointer for DbgCreateMsgCallback";
// obj_name()
m_device = new VkDeviceObj(0, objs[0], device_extensions);
+
+ /* Now register callback on device */
+ if (0) {
+ if (m_dbgCreateMsgCallback) {
+ err = m_dbgCreateMsgCallback(this->inst,
+ VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
+ dbgFunction,
+ userData,
+ &m_devMsgCallback);
+ ASSERT_VK_SUCCESS(err);
+ }
+ }
m_device->get_device_queue();
m_depthStencil = new VkDepthStencilObj();
diff --git a/tests/vkrenderframework.h b/tests/vkrenderframework.h
index 024bdba..e761001 100644
--- a/tests/vkrenderframework.h
+++ b/tests/vkrenderframework.h
@@ -129,7 +129,8 @@
VkDepthStencilObj *m_depthStencil;
VkMemoryRefManager m_mem_ref_mgr;
PFN_vkDbgCreateMsgCallback m_dbgCreateMsgCallback;
- VkDbgMsgCallback m_msgCallback;
+ VkDbgMsgCallback m_globalMsgCallback;
+ VkDbgMsgCallback m_devMsgCallback;
/*
* SetUp and TearDown are called by the Google Test framework
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index c1d6fdc..d3488f6 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -33,7 +33,7 @@
import vk_helper
def proto_is_global(proto):
- if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name == "CreateInstance" or proto.name == "GetGlobalExtensionInfo" or proto.name == "GetDisplayInfoWSI":
+ if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name == "CreateInstance" or proto.name == "GetGlobalExtensionInfo" or proto.name == "GetPhysicalDeviceExtensionInfo" or proto.name == "GetDisplayInfoWSI":
return True
else:
return False
@@ -175,15 +175,32 @@
def _gen_layer_get_global_extension_info(self, layer="Generic"):
ggei_body = []
- ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 1')
- ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
- ggei_body.append(' {')
- ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
- ggei_body.append(' "%s",' % layer)
- ggei_body.append(' 0x10,')
- ggei_body.append(' "layer: %s",' % layer)
- ggei_body.append(' }')
- ggei_body.append('};')
+ if layer == 'APIDump':
+ ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 1')
+ ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
+ ggei_body.append(' {')
+ ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
+ ggei_body.append(' "%s",' % layer)
+ ggei_body.append(' 0x10,')
+ ggei_body.append(' "layer: %s",' % layer)
+ ggei_body.append(' }')
+ ggei_body.append('};')
+ else:
+ ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 2')
+ ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {')
+ ggei_body.append(' {')
+ ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
+ ggei_body.append(' "%s",' % layer)
+ ggei_body.append(' 0x10,')
+ ggei_body.append(' "layer: %s",' % layer)
+ ggei_body.append(' },')
+ ggei_body.append(' {')
+ ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,')
+ ggei_body.append(' "Validation",')
+ ggei_body.append(' 0x10,')
+ ggei_body.append(' "layer: %s",' % layer)
+ ggei_body.append(' }')
+ ggei_body.append('};')
ggei_body.append('')
ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)')
ggei_body.append('{')
@@ -215,6 +232,39 @@
ggei_body.append('}')
return "\n".join(ggei_body)
+ def _gen_layer_get_physical_device_extension_info(self, layer="Generic"):
+ ggei_body = []
+ ggei_body.append('')
+ ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(VkPhysicalDevice physicalDevice, VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)')
+ ggei_body.append('{')
+ ggei_body.append(' uint32_t *count;')
+ ggei_body.append('')
+ ggei_body.append(' if (pDataSize == NULL)')
+ ggei_body.append(' return VK_ERROR_INVALID_POINTER;')
+ ggei_body.append('')
+ ggei_body.append(' switch (infoType) {')
+ ggei_body.append(' case VK_EXTENSION_INFO_TYPE_COUNT:')
+ ggei_body.append(' *pDataSize = sizeof(uint32_t);')
+ ggei_body.append(' if (pData == NULL)')
+ ggei_body.append(' return VK_SUCCESS;')
+ ggei_body.append(' count = (uint32_t *) pData;')
+ ggei_body.append(' *count = LAYER_EXT_ARRAY_SIZE;')
+ ggei_body.append(' break;')
+ ggei_body.append(' case VK_EXTENSION_INFO_TYPE_PROPERTIES:')
+ ggei_body.append(' *pDataSize = sizeof(VkExtensionProperties);')
+ ggei_body.append(' if (pData == NULL)')
+ ggei_body.append(' return VK_SUCCESS;')
+ ggei_body.append(' if (extensionIndex >= LAYER_EXT_ARRAY_SIZE)')
+ ggei_body.append(' return VK_ERROR_INVALID_VALUE;')
+ ggei_body.append(' memcpy((VkExtensionProperties *) pData, &layerExts[extensionIndex], sizeof(VkExtensionProperties));')
+ ggei_body.append(' break;')
+ ggei_body.append(' default:')
+ ggei_body.append(' return VK_ERROR_INVALID_VALUE;')
+ ggei_body.append(' };')
+ ggei_body.append(' return VK_SUCCESS;')
+ ggei_body.append('}')
+ return "\n".join(ggei_body)
+
def _generate_dispatch_entrypoints(self, qual=""):
if qual:
qual += " "
@@ -236,6 +286,8 @@
funcs.append('/* CreateDevice HERE */')
elif 'GetGlobalExtensionInfo' == proto.name:
intercept = self._gen_layer_get_global_extension_info(self.layer_name)
+ elif 'GetPhysicalDeviceExtensionInfo' == proto.name:
+ intercept = self._gen_layer_get_physical_device_extension_info(self.layer_name)
if intercept is not None:
funcs.append(intercept)
intercepted.append(proto)
@@ -538,7 +590,7 @@
gen_header.append('}')
return "\n".join(gen_header)
def generate_intercept(self, proto, qual):
- if proto.name in [ 'GetGlobalExtensionInfo' ]:
+ if proto.name in [ 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo' ]:
# use default version
return None
decl = proto.c_func(prefix="vk", attr="VKAPI")
@@ -812,7 +864,7 @@
return "\n".join(func_body)
def generate_intercept(self, proto, qual):
- if proto.name in [ 'GetGlobalExtensionInfo']:
+ if proto.name in [ 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo']:
return None
decl = proto.c_func(prefix="vk", attr="VKAPI")
ret_val = ''
@@ -1250,7 +1302,7 @@
return "\n".join(header_txt)
def generate_intercept(self, proto, qual):
- if proto.name in [ 'DbgCreateMsgCallback', 'GetGlobalExtensionInfo' ]:
+ if proto.name in [ 'DbgCreateMsgCallback', 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo' ]:
# use default version
return None