295 lines
13 KiB
C++
295 lines
13 KiB
C++
/* Copyright (c) 2015-2016 The Khronos Group Inc.
|
|
* Copyright (c) 2015-2016 Valve Corporation
|
|
* Copyright (c) 2015-2016 LunarG, Inc.
|
|
* Copyright (C) 2015-2016 Google 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: Ian Elliott <ian@lunarg.com>
|
|
* Author: Ian Elliott <ianelliott@google.com>
|
|
*/
|
|
|
|
#ifndef SWAPCHAIN_H
|
|
#define SWAPCHAIN_H
|
|
|
|
#include "vulkan/vk_layer.h"
|
|
#include "vk_layer_config.h"
|
|
#include "vk_layer_logging.h"
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
|
|
using namespace std;
|
|
|
|
// Swapchain ERROR codes
|
|
enum SWAPCHAIN_ERROR {
|
|
SWAPCHAIN_INVALID_HANDLE, // Handle used that isn't currently valid
|
|
SWAPCHAIN_NULL_POINTER, // Pointer set to NULL, instead of being a valid pointer
|
|
SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, // Did not enable WSI extension, but called WSI function
|
|
SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN, // Called vkDestroyDevice() before vkDestroySwapchainKHR()
|
|
SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE, // Called vkCreateSwapchainKHR() with a pCreateInfo->surface that wasn't seen as supported
|
|
// by vkGetPhysicalDeviceSurfaceSupportKHR for the device
|
|
SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY, // Called vkCreateSwapchainKHR() without calling a query (e.g.
|
|
// vkGetPhysicalDeviceSurfaceCapabilitiesKHR())
|
|
SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, // Called vkCreateSwapchainKHR() with out-of-bounds minImageCount
|
|
SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS, // Called vkCreateSwapchainKHR() with out-of-bounds imageExtent
|
|
SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, // Called vkCreateSwapchainKHR() with imageExtent that doesn't match window's extent
|
|
SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, // Called vkCreateSwapchainKHR() with a non-supported preTransform
|
|
SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA, // Called vkCreateSwapchainKHR() with a non-supported compositeAlpha
|
|
SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS, // Called vkCreateSwapchainKHR() with a non-supported imageArrayLayers
|
|
SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, // Called vkCreateSwapchainKHR() with a non-supported imageUsageFlags
|
|
SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, // Called vkCreateSwapchainKHR() with a non-supported imageColorSpace
|
|
SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, // Called vkCreateSwapchainKHR() with a non-supported imageFormat
|
|
SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, // Called vkCreateSwapchainKHR() with a non-supported imageColorSpace
|
|
SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, // Called vkCreateSwapchainKHR() with a non-supported presentMode
|
|
SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE, // Called vkCreateSwapchainKHR() with a non-supported imageSharingMode
|
|
SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, // Called vkCreateSwapchainKHR() with bad values when imageSharingMode is
|
|
// VK_SHARING_MODE_CONCURRENT
|
|
SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES, // vkAcquireNextImageKHR() asked for more images than are available
|
|
SWAPCHAIN_BAD_BOOL, // VkBool32 that doesn't have value of VK_TRUE or VK_FALSE (e.g. is a non-zero form of true)
|
|
SWAPCHAIN_PRIOR_COUNT, // Query must be called first to get value of pCount, then called second time
|
|
SWAPCHAIN_INVALID_COUNT, // Second time a query called, the pCount value didn't match first time
|
|
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_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_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY, // vkGetDisplayPlaneSupportedDisplaysKHR should be called after querying
|
|
// device display plane properties
|
|
SWAPCHAIN_PLANE_INDEX_TOO_LARGE, // a planeIndex value is larger than what vkGetDisplayPlaneSupportedDisplaysKHR returns
|
|
};
|
|
|
|
// The following is for logging error messages:
|
|
const char * swapchain_layer_name = "Swapchain";
|
|
|
|
#define LAYER_NAME (char *) "Swapchain"
|
|
|
|
// NOTE: The following struct's/typedef's are for keeping track of
|
|
// info that is used for validating the WSI extensions.
|
|
|
|
// Forward declarations:
|
|
struct SwpInstance;
|
|
struct SwpSurface;
|
|
struct SwpPhysicalDevice;
|
|
struct SwpDevice;
|
|
struct SwpSwapchain;
|
|
struct SwpImage;
|
|
struct SwpQueue;
|
|
|
|
// Create one of these for each VkInstance:
|
|
struct SwpInstance {
|
|
// The actual handle for this VkInstance:
|
|
VkInstance instance;
|
|
|
|
// Remember the VkSurfaceKHR's that are created for this VkInstance:
|
|
unordered_map<VkSurfaceKHR, SwpSurface *> surfaces;
|
|
|
|
// When vkEnumeratePhysicalDevices is called, the VkPhysicalDevice's are
|
|
// remembered:
|
|
unordered_map<const void *, SwpPhysicalDevice *> physicalDevices;
|
|
|
|
// Set to true if VK_KHR_SURFACE_EXTENSION_NAME was enabled for this VkInstance:
|
|
bool surfaceExtensionEnabled;
|
|
|
|
// Set to true if VK_KHR_DISPLAY_EXTENSION_NAME was enabled for this VkInstance:
|
|
bool displayExtensionEnabled;
|
|
|
|
// TODO: Add additional booleans for platform-specific extensions:
|
|
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
|
// Set to true if VK_KHR_ANDROID_SURFACE_EXTENSION_NAME was enabled for this VkInstance:
|
|
bool androidSurfaceExtensionEnabled;
|
|
#endif // VK_USE_PLATFORM_ANDROID_KHR
|
|
#ifdef VK_USE_PLATFORM_MIR_KHR
|
|
// Set to true if VK_KHR_MIR_SURFACE_EXTENSION_NAME was enabled for this VkInstance:
|
|
bool mirSurfaceExtensionEnabled;
|
|
#endif // VK_USE_PLATFORM_MIR_KHR
|
|
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
|
// Set to true if VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME was enabled for this VkInstance:
|
|
bool waylandSurfaceExtensionEnabled;
|
|
#endif // VK_USE_PLATFORM_WAYLAND_KHR
|
|
#ifdef VK_USE_PLATFORM_WIN32_KHR
|
|
// Set to true if VK_KHR_WIN32_SURFACE_EXTENSION_NAME was enabled for this VkInstance:
|
|
bool win32SurfaceExtensionEnabled;
|
|
#endif // VK_USE_PLATFORM_WIN32_KHR
|
|
#ifdef VK_USE_PLATFORM_XCB_KHR
|
|
// Set to true if VK_KHR_XCB_SURFACE_EXTENSION_NAME was enabled for this VkInstance:
|
|
bool xcbSurfaceExtensionEnabled;
|
|
#endif // VK_USE_PLATFORM_XCB_KHR
|
|
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
|
// Set to true if VK_KHR_XLIB_SURFACE_EXTENSION_NAME was enabled for this VkInstance:
|
|
bool xlibSurfaceExtensionEnabled;
|
|
#endif // VK_USE_PLATFORM_XLIB_KHR
|
|
};
|
|
|
|
// Create one of these for each VkSurfaceKHR:
|
|
struct SwpSurface {
|
|
// The actual handle for this VkSurfaceKHR:
|
|
VkSurfaceKHR surface;
|
|
|
|
// VkInstance that this VkSurfaceKHR is associated with:
|
|
SwpInstance *pInstance;
|
|
|
|
// When vkCreateSwapchainKHR is called, the VkSwapchainKHR's are
|
|
// remembered:
|
|
unordered_map<VkSwapchainKHR, SwpSwapchain *> swapchains;
|
|
|
|
// 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:
|
|
struct SwpPhysicalDevice {
|
|
// The actual handle for this VkPhysicalDevice:
|
|
VkPhysicalDevice physicalDevice;
|
|
|
|
// Corresponding VkDevice (and info) to this VkPhysicalDevice:
|
|
SwpDevice *pDevice;
|
|
|
|
// VkInstance that this VkPhysicalDevice is associated with:
|
|
SwpInstance *pInstance;
|
|
|
|
// Records results of vkGetPhysicalDeviceQueueFamilyProperties()'s
|
|
// numOfQueueFamilies parameter when pQueueFamilyProperties is NULL:
|
|
bool gotQueueFamilyPropertyCount;
|
|
uint32_t numOfQueueFamilies;
|
|
|
|
// Record all surfaces that vkGetPhysicalDeviceSurfaceSupportKHR() was
|
|
// called for:
|
|
unordered_map<VkSurfaceKHR, SwpSurface *> supportedSurfaces;
|
|
|
|
// TODO: Record/use this info per-surface, not per-device, once a
|
|
// non-dispatchable surface object is added to WSI:
|
|
// Results of vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
|
|
bool gotSurfaceCapabilities;
|
|
VkSurfaceCapabilitiesKHR surfaceCapabilities;
|
|
|
|
// TODO: Record/use this info per-surface, not per-device, once a
|
|
// non-dispatchable surface object is added to WSI:
|
|
// Count and VkSurfaceFormatKHR's returned by vkGetPhysicalDeviceSurfaceFormatsKHR():
|
|
uint32_t surfaceFormatCount;
|
|
VkSurfaceFormatKHR *pSurfaceFormats;
|
|
|
|
// TODO: Record/use this info per-surface, not per-device, once a
|
|
// non-dispatchable surface object is added to WSI:
|
|
// Count and VkPresentModeKHR's returned by vkGetPhysicalDeviceSurfacePresentModesKHR():
|
|
uint32_t presentModeCount;
|
|
VkPresentModeKHR *pPresentModes;
|
|
|
|
// Count returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR():
|
|
uint32_t displayPlanePropertyCount;
|
|
bool gotDisplayPlanePropertyCount;
|
|
};
|
|
|
|
// Create one of these for each VkDevice within a VkInstance:
|
|
struct SwpDevice {
|
|
// The actual handle for this VkDevice:
|
|
VkDevice device;
|
|
|
|
// Corresponding VkPhysicalDevice (and info) to this VkDevice:
|
|
SwpPhysicalDevice *pPhysicalDevice;
|
|
|
|
// Set to true if VK_KHR_SWAPCHAIN_EXTENSION_NAME was enabled:
|
|
bool swapchainExtensionEnabled;
|
|
|
|
// Set to true if VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME was enabled:
|
|
bool displaySwapchainExtensionEnabled;
|
|
|
|
// 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:
|
|
struct SwpImage {
|
|
// The actual handle for this VkImage:
|
|
VkImage image;
|
|
|
|
// Corresponding VkSwapchainKHR (and info) to this VkImage:
|
|
SwpSwapchain *pSwapchain;
|
|
|
|
// true if application acquired this image from vkAcquireNextImageKHR(),
|
|
// and hasn't yet called vkQueuePresentKHR() for it; otherwise false:
|
|
bool acquiredByApp;
|
|
};
|
|
|
|
// Create one of these for each VkSwapchainKHR within a VkDevice:
|
|
struct SwpSwapchain {
|
|
// The actual handle for this VkSwapchainKHR:
|
|
VkSwapchainKHR swapchain;
|
|
|
|
// Corresponding VkDevice (and info) to this VkSwapchainKHR:
|
|
SwpDevice *pDevice;
|
|
|
|
// Corresponding VkSurfaceKHR to this VkSwapchainKHR:
|
|
SwpSurface *pSurface;
|
|
|
|
// When vkGetSwapchainImagesKHR is called, the VkImage's are
|
|
// remembered:
|
|
uint32_t imageCount;
|
|
unordered_map<int, SwpImage> images;
|
|
};
|
|
|
|
// 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 {
|
|
VkInstance instance;
|
|
|
|
debug_report_data *report_data;
|
|
std::vector<VkDebugReportCallbackEXT> logging_callback;
|
|
VkLayerDispatchTable *device_dispatch_table;
|
|
VkLayerInstanceDispatchTable *instance_dispatch_table;
|
|
|
|
// The following are for keeping track of the temporary callbacks that can
|
|
// be used in vkCreateInstance and vkDestroyInstance:
|
|
uint32_t num_tmp_callbacks;
|
|
VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos;
|
|
VkDebugReportCallbackEXT *tmp_callbacks;
|
|
|
|
// NOTE: The following are for keeping track of info that is used for
|
|
// validating the WSI extensions.
|
|
std::unordered_map<void *, SwpInstance> instanceMap;
|
|
std::unordered_map<VkSurfaceKHR, SwpSurface> surfaceMap;
|
|
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), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), num_tmp_callbacks(0),
|
|
tmp_dbg_create_infos(nullptr), tmp_callbacks(nullptr){};
|
|
};
|
|
|
|
#endif // SWAPCHAIN_H
|