pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
+ pDisp->GetDeviceQueue = (PFN_vkGetDeviceQueue) gpa(device, "vkGetDeviceQueue");
SwpPhysicalDevice *pPhysicalDevice = &my_instance_data->physicalDeviceMap[physicalDevice];
if (pPhysicalDevice) {
layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
- pDisp->GetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties) gpa(instance, "vkGetPhysicalDeviceQueueFamilyProperties");
#ifdef VK_USE_PLATFORM_ANDROID_KHR
pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR) gpa(instance, "vkCreateAndroidSurfaceKHR");
#endif // VK_USE_PLATFORM_ANDROID_KHR
if (pPhysicalDevice &&
pQueueFamilyPropertyCount && !pQueueFamilyProperties) {
pPhysicalDevice->gotQueueFamilyPropertyCount = true;
- pPhysicalDevice->pQueueFamilyPropertyCount =
+ pPhysicalDevice->numOfQueueFamilies =
*pQueueFamilyPropertyCount;
}
}
my_data->surfaceMap[*pSurface].pInstance = pInstance;
my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
(pAllocator != NULL);
+ my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
+ my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
// Point to the associated SwpInstance:
pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
}
my_data->surfaceMap[*pSurface].pInstance = pInstance;
my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
(pAllocator != NULL);
+ my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
+ my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
// Point to the associated SwpInstance:
pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
}
__FUNCTION__, VK_KHR_MIR_SURFACE_EXTENSION_NAME);
}
if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
- (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) {
+ (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
pPhysicalDevice,
"VkPhysicalDevice",
queueFamilyIndex,
- pPhysicalDevice->pQueueFamilyPropertyCount);
+ pPhysicalDevice->numOfQueueFamilies);
}
if (VK_FALSE == skipCall) {
my_data->surfaceMap[*pSurface].pInstance = pInstance;
my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
(pAllocator != NULL);
+ my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
+ my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
// Point to the associated SwpInstance:
pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
}
__FUNCTION__, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
}
if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
- (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) {
+ (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
pPhysicalDevice,
"VkPhysicalDevice",
queueFamilyIndex,
- pPhysicalDevice->pQueueFamilyPropertyCount);
+ pPhysicalDevice->numOfQueueFamilies);
}
if (VK_FALSE == skipCall) {
my_data->surfaceMap[*pSurface].pInstance = pInstance;
my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
(pAllocator != NULL);
+ my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
+ my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
// Point to the associated SwpInstance:
pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
}
__FUNCTION__, VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
}
if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
- (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) {
+ (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
pPhysicalDevice,
"VkPhysicalDevice",
queueFamilyIndex,
- pPhysicalDevice->pQueueFamilyPropertyCount);
+ pPhysicalDevice->numOfQueueFamilies);
}
if (VK_FALSE == skipCall) {
my_data->surfaceMap[*pSurface].pInstance = pInstance;
my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
(pAllocator != NULL);
+ my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
+ my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
// Point to the associated SwpInstance:
pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
}
__FUNCTION__, VK_KHR_XCB_SURFACE_EXTENSION_NAME);
}
if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
- (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) {
+ (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
pPhysicalDevice,
"VkPhysicalDevice",
queueFamilyIndex,
- pPhysicalDevice->pQueueFamilyPropertyCount);
+ pPhysicalDevice->numOfQueueFamilies);
}
if (VK_FALSE == skipCall) {
my_data->surfaceMap[*pSurface].pInstance = pInstance;
my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
(pAllocator != NULL);
+ my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
+ my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
// Point to the associated SwpInstance:
pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
}
__FUNCTION__, VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
}
if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
- (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) {
+ (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
pPhysicalDevice,
"VkPhysicalDevice",
queueFamilyIndex,
- pPhysicalDevice->pQueueFamilyPropertyCount);
+ pPhysicalDevice->numOfQueueFamilies);
}
if (VK_FALSE == skipCall) {
"%s() called even though the %s extension was not enabled for this VkInstance.",
__FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
}
- if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
- (queueFamilyIndex >= pPhysicalDevice->pQueueFamilyPropertyCount)) {
+ if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
+ skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
+ pPhysicalDevice,
+ "VkPhysicalDevice",
+ SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES,
+ "%s() called before calling the "
+ "vkGetPhysicalDeviceQueueFamilyProperties "
+ "function.",
+ __FUNCTION__);
+ } else if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
+ (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
pPhysicalDevice,
"VkPhysicalDevice",
queueFamilyIndex,
- pPhysicalDevice->pQueueFamilyPropertyCount);
+ pPhysicalDevice->numOfQueueFamilies);
}
if (!pSupported) {
skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
// Record the result of this query:
- pPhysicalDevice->queueFamilyIndexSupport[queueFamilyIndex] =
- surface;
- pPhysicalDevice->surfaceSupport[surface] =
- queueFamilyIndex;
- // TODO: We need to compare this with the actual queue used for
- // presentation, to ensure it was advertised to the application as
- // supported for presentation.
+ SwpInstance *pInstance = pPhysicalDevice->pInstance;
+ SwpSurface *pSurface =
+ (pInstance) ? pInstance->surfaces[surface] : NULL;
+ if (pSurface) {
+ pPhysicalDevice->supportedSurfaces[surface] = pSurface;
+ if (!pSurface->numQueueFamilyIndexSupport) {
+ if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
+ pSurface->pQueueFamilyIndexSupport = (VkBool32 *)
+ malloc(pPhysicalDevice->numOfQueueFamilies *
+ sizeof(VkBool32));
+ if (pSurface->pQueueFamilyIndexSupport != NULL) {
+ pSurface->numQueueFamilyIndexSupport =
+ pPhysicalDevice->numOfQueueFamilies;
+ }
+ }
+ }
+ if (pSurface->numQueueFamilyIndexSupport) {
+ pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] =
+ *pSupported;
+ }
+ }
}
return result;
// Validate pCreateInfo->surface to make sure that
// vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
// surface:
- uint32_t queueFamilyIndex = pPhysicalDevice->surfaceSupport[pCreateInfo->surface];
- if (!queueFamilyIndex) {
+ SwpSurface *pSurface =
+ ((pPhysicalDevice) ?
+ pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
+ if (!pSurface) {
skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
"%s() called with pCreateInfo->surface that "
SwpDevice *pDevice = &my_data->deviceMap[device];
my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
- pDevice->swapchains[*pSwapchain] =
- &my_data->swapchainMap[*pSwapchain];
+ if (pDevice) {
+ pDevice->swapchains[*pSwapchain] =
+ &my_data->swapchainMap[*pSwapchain];
+ }
my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
my_data->swapchainMap[*pSwapchain].imageCount = 0;
my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate =
// sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
// of that sname:VkSemaphore that won't be consumed by any other wait on that
// semaphore
-// - Ensure that the queue is active, and is one of the queueFamilyIndex's
-// that was returned by a previuos query.
// - Record/update the state of the swapchain, in case an error occurs
// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
VkResult result = VK_SUCCESS;
__FUNCTION__, index);
}
}
+ SwpQueue *pQueue = &my_data->queueMap[queue];
+ SwpSurface *pSurface = pSwapchain->pSurface;
+ if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
+ uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
+ // Note: the 1st test is to ensure queueFamilyIndex is in range,
+ // and the 2nd test is the validation check:
+ if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
+ (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
+ skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
+ pPresentInfo->pSwapchains[i],
+ "VkSwapchainKHR",
+ SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE,
+ "%s() called with a swapchain whose "
+ "surface is not supported for "
+ "presention on this device with the "
+ "queueFamilyIndex (i.e. %d) of the "
+ "given queue.",
+ __FUNCTION__, queueFamilyIndex);
+ }
+ }
}
}
return VK_ERROR_VALIDATION_FAILED_EXT;
}
+VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(
+ VkDevice device,
+ uint32_t queueFamilyIndex,
+ uint32_t queueIndex,
+ VkQueue* pQueue)
+{
+ VkBool32 skipCall = VK_FALSE;
+ layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
+ if (VK_FALSE == skipCall) {
+ // Call down the call chain:
+ my_data->device_dispatch_table->GetDeviceQueue(
+ device, queueFamilyIndex, queueIndex, pQueue);
+
+ // Remember the queue's handle, and link it to the device:
+ SwpDevice *pDevice = &my_data->deviceMap[device];
+ my_data->queueMap[&pQueue].queue = *pQueue;
+ if (pDevice) {
+ pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
+ }
+ my_data->queueMap[&pQueue].pDevice = pDevice;
+ my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
+ }
+}
+
+
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
VkInstance instance,
const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
if (!strcmp("vkQueuePresentKHR", funcName))
return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
}
+ if (!strcmp("vkGetDeviceQueue", funcName))
+ return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue);
if (pDisp->GetDeviceProcAddr == NULL)
return NULL;
return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
+ if (!strcmp(funcName, "vkGetPhysicalDeviceQueueFamilyProperties"))
+ return (PFN_vkVoidFunction) vkGetPhysicalDeviceQueueFamilyProperties;
if (instance == VK_NULL_HANDLE) {
return NULL;
return addr;
}
- if (!strcmp("vkGetPhysicalDeviceQueueFamilyProperties", funcName))
- return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceQueueFamilyProperties);
#ifdef VK_USE_PLATFORM_ANDROID_KHR
if (my_data->instanceMap.size() != 0 &&
my_data->instanceMap[instance].androidSurfaceExtensionEnabled)
SWAPCHAIN_WRONG_STYPE, // The sType for a struct has the wrong value
SWAPCHAIN_WRONG_NEXT, // The pNext for a struct is not NULL
SWAPCHAIN_ZERO_VALUE, // A value should be non-zero
- SWAPCHAIN_QUEUE_FAMILY_INDEX_TOO_LARGE, // A queueFamilyIndex value is not less than pQueueFamilyPropertyCount returned by vkGetPhysicalDeviceQueueFamilyProperties()
SWAPCHAIN_INCOMPATIBLE_ALLOCATOR, // pAllocator must be compatible (i.e. NULL or not) when object is created and destroyed
+ SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, // A function using a queueFamilyIndex was called before vkGetPhysicalDeviceQueueFamilyProperties() was called
+ SWAPCHAIN_QUEUE_FAMILY_INDEX_TOO_LARGE, // A queueFamilyIndex value is not less than pQueueFamilyPropertyCount returned by vkGetPhysicalDeviceQueueFamilyProperties()
+ SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, // A surface is not supported by a given queueFamilyIndex, as seen by vkGetPhysicalDeviceSurfaceSupportKHR()
} SWAPCHAIN_ERROR;
struct _SwpDevice;
struct _SwpSwapchain;
struct _SwpImage;
+struct _SwpQueue;
typedef _SwpInstance SwpInstance;
typedef _SwpSurface SwpSurface;;
typedef _SwpDevice SwpDevice;
typedef _SwpSwapchain SwpSwapchain;
typedef _SwpImage SwpImage;
+typedef _SwpQueue SwpQueue;
// Create one of these for each VkInstance:
struct _SwpInstance {
// 'true' if pAllocator was non-NULL when vkCreate*SurfaceKHR was called:
bool usedAllocatorToCreate;
+
+ // Value of pQueueFamilyPropertyCount that was returned by the
+ // vkGetPhysicalDeviceQueueFamilyProperties() function:
+ uint32_t numQueueFamilyIndexSupport;
+ // Array of VkBool32's that is intialized by the
+ // vkGetPhysicalDeviceSurfaceSupportKHR() function. First call for a given
+ // surface allocates and initializes this array to false for all
+ // queueFamilyIndex's (and sets numQueueFamilyIndexSupport to non-zero).
+ // All calls set the entry for a given queueFamilyIndex:
+ VkBool32 *pQueueFamilyIndexSupport;
};
// Create one of these for each VkPhysicalDevice within a VkInstance:
SwpInstance *pInstance;
// Records results of vkGetPhysicalDeviceQueueFamilyProperties()'s
- // pQueueFamilyPropertyCount parameter when pQueueFamilyProperties is NULL:
+ // numOfQueueFamilies parameter when pQueueFamilyProperties is NULL:
bool gotQueueFamilyPropertyCount;
- uint32_t pQueueFamilyPropertyCount;
+ uint32_t numOfQueueFamilies;
- // Record all supported queueFamilyIndex-surface pairs that support
- // presenting with WSI swapchains:
- unordered_map<uint32_t, VkSurfaceKHR> queueFamilyIndexSupport;
-
- // Record all supported surface-queueFamilyIndex pairs that support
- // presenting with WSI swapchains:
- unordered_map<VkSurfaceKHR, uint32_t> surfaceSupport;
+ // Record all surfaces that vkGetPhysicalDeviceSurfaceSupportKHR() was
+ // called for:
+ unordered_map<const void*, SwpSurface*> supportedSurfaces;
// TODO: Record/use this info per-surface, not per-device, once a
// non-dispatchable surface object is added to WSI:
// When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are
// remembered:
unordered_map<VkSwapchainKHR, SwpSwapchain*> swapchains;
+
+ // When vkGetDeviceQueue is called, the VkQueue's are remembered:
+ unordered_map<VkQueue, SwpQueue*> queues;
};
// Create one of these for each VkImage within a VkSwapchainKHR:
bool usedAllocatorToCreate;
};
+// Create one of these for each VkQueue within a VkDevice:
+struct _SwpQueue {
+ // The actual handle for this VkQueue:
+ VkQueue queue;
+
+ // Corresponding VkDevice (and info) to this VkSwapchainKHR:
+ SwpDevice *pDevice;
+
+ // Which queueFamilyIndex this VkQueue is associated with:
+ uint32_t queueFamilyIndex;
+};
+
struct layer_data {
debug_report_data *report_data;
std::vector<VkDebugReportCallbackEXT> logging_callback;
std::unordered_map<void *, SwpPhysicalDevice> physicalDeviceMap;
std::unordered_map<void *, SwpDevice> deviceMap;
std::unordered_map<VkSwapchainKHR, SwpSwapchain> swapchainMap;
+ std::unordered_map<void *, SwpQueue> queueMap;
layer_data() :
report_data(nullptr),