Allow using an external Vulkan device with the vulkan renderer

This commit is contained in:
Sam Lantinga 2024-02-27 18:51:08 -08:00
parent e03746b25f
commit 614630df69
2 changed files with 173 additions and 83 deletions

View File

@ -250,6 +250,15 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co
* - `SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN`: true if you want * - `SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN`: true if you want
* present synchronized with the refresh rate * present synchronized with the refresh rate
* *
* With the vulkan renderer:
*
* - `SDL_PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER`: the VkInstance to use with the renderer, optional.
* - `SDL_PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER`: the VkSurfaceKHR to use with the renderer, optional.
* - `SDL_PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER`: the VkPhysicalDevice to use with the renderer, optional.
* - `SDL_PROP_RENDERER_CREATE_VULKAN_DEVICE_POINTER`: the VkDevice to use with the renderer, optional.
* - `SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER`: the queue family index used for rendering.
* - `SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER`: the queue family index used for presentation.
*
* \param props the properties to use * \param props the properties to use
* \returns a valid rendering context or NULL if there was an error; call * \returns a valid rendering context or NULL if there was an error; call
* SDL_GetError() for more information. * SDL_GetError() for more information.
@ -263,11 +272,17 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co
*/ */
extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_PropertiesID props); extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_PropertiesID props);
#define SDL_PROP_RENDERER_CREATE_NAME_STRING "name" #define SDL_PROP_RENDERER_CREATE_NAME_STRING "name"
#define SDL_PROP_RENDERER_CREATE_WINDOW_POINTER "window" #define SDL_PROP_RENDERER_CREATE_WINDOW_POINTER "window"
#define SDL_PROP_RENDERER_CREATE_SURFACE_POINTER "surface" #define SDL_PROP_RENDERER_CREATE_SURFACE_POINTER "surface"
#define SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER "output_colorspace" #define SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER "output_colorspace"
#define SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN "present_vsync" #define SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN "present_vsync"
#define SDL_PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER "vulkan.instance"
#define SDL_PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER "vulkan.surface"
#define SDL_PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER "vulkan.physical_device"
#define SDL_PROP_RENDERER_CREATE_VULKAN_DEVICE_POINTER "vulkan.device"
#define SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER "vulkan.graphics_queue_family_index"
#define SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER "vulkan.present_queue_family_index"
/** /**
* Create a 2D software rendering context for a surface. * Create a 2D software rendering context for a surface.
@ -354,15 +369,33 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend
* that can be displayed, in terms of the SDR white point. When HDR is not * that can be displayed, in terms of the SDR white point. When HDR is not
* enabled, this will be 1.0. This property can change dynamically when * enabled, this will be 1.0. This property can change dynamically when
* SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent. * SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent.
*
* With the direct3d renderer:
*
* - `SDL_PROP_RENDERER_D3D9_DEVICE_POINTER`: the IDirect3DDevice9 associated * - `SDL_PROP_RENDERER_D3D9_DEVICE_POINTER`: the IDirect3DDevice9 associated
* with the renderer * with the renderer
*
* With the direct3d11 renderer:
*
* - `SDL_PROP_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device associated * - `SDL_PROP_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device associated
* with the renderer * with the renderer
*
* With the direct3d12 renderer:
*
* - `SDL_PROP_RENDERER_D3D12_DEVICE_POINTER`: the ID3D12Device associated * - `SDL_PROP_RENDERER_D3D12_DEVICE_POINTER`: the ID3D12Device associated
* with the renderer * with the renderer
* - `SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER`: the ID3D12CommandQueue * - `SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER`: the ID3D12CommandQueue
* associated with the renderer * associated with the renderer
* *
* With the vulkan renderer:
*
* - `SDL_PROP_RENDERER_VULKAN_INSTANCE_POINTER`: the VkInstance associated with the renderer
* - `SDL_PROP_RENDERER_VULKAN_SURFACE_NUMBER`: the VkSurfaceKHR associated with the renderer
* - `SDL_PROP_RENDERER_VULKAN_PHYSICAL_DEVICE_POINTER`: the VkPhysicalDevice associated with the renderer
* - `SDL_PROP_RENDERER_VULKAN_DEVICE_POINTER`: the VkDevice associated with the renderer
* - `SDL_PROP_RENDERER_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER`: the queue family index used for rendering
* - `SDL_PROP_RENDERER_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER`: the queue family index used for presentation
*
* \param renderer the rendering context * \param renderer the rendering context
* \returns a valid property ID on success or 0 on failure; call * \returns a valid property ID on success or 0 on failure; call
* SDL_GetError() for more information. * SDL_GetError() for more information.
@ -374,17 +407,23 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend
*/ */
extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer *renderer); extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer *renderer);
#define SDL_PROP_RENDERER_NAME_STRING "SDL.renderer.name" #define SDL_PROP_RENDERER_NAME_STRING "SDL.renderer.name"
#define SDL_PROP_RENDERER_WINDOW_POINTER "SDL.renderer.window" #define SDL_PROP_RENDERER_WINDOW_POINTER "SDL.renderer.window"
#define SDL_PROP_RENDERER_SURFACE_POINTER "SDL.renderer.surface" #define SDL_PROP_RENDERER_SURFACE_POINTER "SDL.renderer.surface"
#define SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER "SDL.renderer.output_colorspace" #define SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER "SDL.renderer.output_colorspace"
#define SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN "SDL.renderer.HDR_enabled" #define SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN "SDL.renderer.HDR_enabled"
#define SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT "SDL.renderer.SDR_white_point" #define SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT "SDL.renderer.SDR_white_point"
#define SDL_PROP_RENDERER_HDR_HEADROOM_FLOAT "SDL.renderer.HDR_headroom" #define SDL_PROP_RENDERER_HDR_HEADROOM_FLOAT "SDL.renderer.HDR_headroom"
#define SDL_PROP_RENDERER_D3D9_DEVICE_POINTER "SDL.renderer.d3d9.device" #define SDL_PROP_RENDERER_D3D9_DEVICE_POINTER "SDL.renderer.d3d9.device"
#define SDL_PROP_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device" #define SDL_PROP_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device"
#define SDL_PROP_RENDERER_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.device" #define SDL_PROP_RENDERER_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.device"
#define SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER "SDL.renderer.d3d12.command_queue" #define SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER "SDL.renderer.d3d12.command_queue"
#define SDL_PROP_RENDERER_VULKAN_INSTANCE_POINTER "SDL.renderer.vulkan.instance"
#define SDL_PROP_RENDERER_VULKAN_SURFACE_NUMBER "SDL.renderer.vulkan.surface"
#define SDL_PROP_RENDERER_VULKAN_PHYSICAL_DEVICE_POINTER "SDL.renderer.vulkan.physical_device"
#define SDL_PROP_RENDERER_VULKAN_DEVICE_POINTER "SDL.renderer.vulkan.device"
#define SDL_PROP_RENDERER_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER "SDL.renderer.vulkan.graphics_queue_family_index"
#define SDL_PROP_RENDERER_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER "SDL.renderer.vulkan.present_queue_family_index"
/** /**
* Get the output size in pixels of a rendering context. * Get the output size in pixels of a rendering context.

View File

@ -270,7 +270,9 @@ typedef struct
{ {
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
VkInstance instance; VkInstance instance;
SDL_bool instance_external;
VkSurfaceKHR surface; VkSurfaceKHR surface;
SDL_bool surface_external;
VkPhysicalDevice physicalDevice; VkPhysicalDevice physicalDevice;
VkPhysicalDeviceProperties physicalDeviceProperties; VkPhysicalDeviceProperties physicalDeviceProperties;
VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
@ -278,6 +280,7 @@ typedef struct
VkQueue graphicsQueue; VkQueue graphicsQueue;
VkQueue presentQueue; VkQueue presentQueue;
VkDevice device; VkDevice device;
SDL_bool device_external;
uint32_t graphicsQueueFamilyIndex; uint32_t graphicsQueueFamilyIndex;
uint32_t presentQueueFamilyIndex; uint32_t presentQueueFamilyIndex;
VkSwapchainKHR swapchain; VkSwapchainKHR swapchain;
@ -567,15 +570,15 @@ static void VULKAN_DestroyAll(SDL_Renderer *renderer)
rendererData->constantBuffers = NULL; rendererData->constantBuffers = NULL;
} }
if (rendererData->device != VK_NULL_HANDLE) { if (rendererData->device != VK_NULL_HANDLE && !rendererData->device_external) {
vkDestroyDevice(rendererData->device, NULL); vkDestroyDevice(rendererData->device, NULL);
rendererData->device = VK_NULL_HANDLE; rendererData->device = VK_NULL_HANDLE;
} }
if (rendererData->surface != VK_NULL_HANDLE) { if (rendererData->surface != VK_NULL_HANDLE && !rendererData->surface_external) {
vkDestroySurfaceKHR(rendererData->instance, rendererData->surface, NULL); vkDestroySurfaceKHR(rendererData->instance, rendererData->surface, NULL);
rendererData->surface = VK_NULL_HANDLE; rendererData->surface = VK_NULL_HANDLE;
} }
if (rendererData->instance != VK_NULL_HANDLE) { if (rendererData->instance != VK_NULL_HANDLE && !rendererData->instance_external) {
vkDestroyInstance(rendererData->instance, NULL); vkDestroyInstance(rendererData->instance, NULL);
rendererData->instance = VK_NULL_HANDLE; rendererData->instance = VK_NULL_HANDLE;
} }
@ -1524,7 +1527,7 @@ static SDL_bool VULKAN_ValidationLayersFound()
} }
/* Create resources that depend on the device. */ /* Create resources that depend on the device. */
static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer) static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_PropertiesID create_props)
{ {
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->driverdata; VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->driverdata;
SDL_VideoDevice *device = SDL_GetVideoDevice(); SDL_VideoDevice *device = SDL_GetVideoDevice();
@ -1549,46 +1552,53 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer)
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
/* Create VkInstance */ /* Check for colorspace extension */
VkInstanceCreateInfo instanceCreateInfo = { 0 };
VkApplicationInfo appInfo = { 0 };
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.apiVersion = VK_API_VERSION_1_0;
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pApplicationInfo = &appInfo;
char const* const* instanceExtensions = SDL_Vulkan_GetInstanceExtensions(&instanceCreateInfo.enabledExtensionCount);
rendererData->supportsEXTSwapchainColorspace = VK_FALSE;
if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR || if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR ||
renderer->output_colorspace == SDL_COLORSPACE_HDR10) { renderer->output_colorspace == SDL_COLORSPACE_HDR10) {
rendererData->supportsEXTSwapchainColorspace = VULKAN_InstanceExtensionFound(rendererData, VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME); rendererData->supportsEXTSwapchainColorspace = VULKAN_InstanceExtensionFound(rendererData, VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
if (rendererData->supportsEXTSwapchainColorspace == SDL_FALSE) { if (!rendererData->supportsEXTSwapchainColorspace) {
return SDL_SetError("[Vulkan] Using HDR output but %s not supported.", VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME); return SDL_SetError("[Vulkan] Using HDR output but %s not supported.", VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
} }
} }
char **instanceExtensionsCopy = SDL_calloc(sizeof(const char *), instanceCreateInfo.enabledExtensionCount + 1);
for (uint32_t i = 0; i < instanceCreateInfo.enabledExtensionCount; i++) { /* Create VkInstance */
instanceExtensionsCopy[i] = SDL_strdup(instanceExtensions[i]); rendererData->instance = (VkInstance)SDL_GetProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER, NULL);
} if (rendererData->instance) {
if (rendererData->supportsEXTSwapchainColorspace) { rendererData->instance_external = SDL_TRUE;
instanceExtensionsCopy[instanceCreateInfo.enabledExtensionCount] = SDL_strdup(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME); } else {
instanceCreateInfo.enabledExtensionCount++; VkInstanceCreateInfo instanceCreateInfo = { 0 };
} VkApplicationInfo appInfo = { 0 };
instanceCreateInfo.ppEnabledExtensionNames = (const char* const*) instanceExtensionsCopy; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
if (createDebug && VULKAN_ValidationLayersFound()) { appInfo.apiVersion = VK_API_VERSION_1_0;
instanceCreateInfo.ppEnabledLayerNames = validationLayerName; instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.enabledLayerCount = 1; instanceCreateInfo.pApplicationInfo = &appInfo;
} char const *const *instanceExtensions = SDL_Vulkan_GetInstanceExtensions(&instanceCreateInfo.enabledExtensionCount);
result = vkCreateInstance(&instanceCreateInfo, NULL, &rendererData->instance);
if (result != VK_SUCCESS) { char **instanceExtensionsCopy = SDL_calloc(sizeof(const char *), instanceCreateInfo.enabledExtensionCount + 1);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateInstance(): %s\n", SDL_Vulkan_GetResultString(result)); for (uint32_t i = 0; i < instanceCreateInfo.enabledExtensionCount; i++) {
return result; instanceExtensionsCopy[i] = SDL_strdup(instanceExtensions[i]);
}
if (rendererData->supportsEXTSwapchainColorspace) {
instanceExtensionsCopy[instanceCreateInfo.enabledExtensionCount] = SDL_strdup(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
instanceCreateInfo.enabledExtensionCount++;
}
instanceCreateInfo.ppEnabledExtensionNames = (const char *const *)instanceExtensionsCopy;
if (createDebug && VULKAN_ValidationLayersFound()) {
instanceCreateInfo.ppEnabledLayerNames = validationLayerName;
instanceCreateInfo.enabledLayerCount = 1;
}
result = vkCreateInstance(&instanceCreateInfo, NULL, &rendererData->instance);
if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateInstance(): %s\n", SDL_Vulkan_GetResultString(result));
return result;
}
for (uint32_t i = 0; i < instanceCreateInfo.enabledExtensionCount; i++) {
SDL_free(instanceExtensionsCopy[i]);
}
SDL_free(instanceExtensionsCopy);
} }
for (uint32_t i = 0; i < instanceCreateInfo.enabledExtensionCount; i++) {
SDL_free(instanceExtensionsCopy[i]);
}
SDL_free(instanceExtensionsCopy);
/* Load instance Vulkan functions */ /* Load instance Vulkan functions */
if (VULKAN_LoadInstanceFunctions(rendererData) != 0) { if (VULKAN_LoadInstanceFunctions(rendererData) != 0) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
@ -1596,45 +1606,78 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer)
} }
/* Create Vulkan surface */ /* Create Vulkan surface */
if (!device->Vulkan_CreateSurface || !device->Vulkan_CreateSurface(device, renderer->window, rendererData->instance, NULL, &rendererData->surface)) { rendererData->surface = (VkSurfaceKHR)SDL_GetNumberProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER, 0);
VULKAN_DestroyAll(renderer); if (rendererData->surface) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Vulkan_CreateSurface() failed.\n"); rendererData->surface_external = SDL_TRUE;
return VK_ERROR_UNKNOWN; } else {
if (!device->Vulkan_CreateSurface || !device->Vulkan_CreateSurface(device, renderer->window, rendererData->instance, NULL, &rendererData->surface)) {
VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Vulkan_CreateSurface() failed.\n");
return VK_ERROR_UNKNOWN;
}
} }
/* Choose Vulkan physical device */ /* Choose Vulkan physical device */
if (VULKAN_FindPhysicalDevice(rendererData) != VK_SUCCESS) { rendererData->physicalDevice = (VkPhysicalDevice)SDL_GetProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER, NULL);
VULKAN_DestroyAll(renderer); if (rendererData->physicalDevice) {
return VK_ERROR_UNKNOWN; vkGetPhysicalDeviceMemoryProperties(rendererData->physicalDevice, &rendererData->physicalDeviceMemoryProperties);
vkGetPhysicalDeviceFeatures(rendererData->physicalDevice, &rendererData->physicalDeviceFeatures);
} else {
if (VULKAN_FindPhysicalDevice(rendererData) != VK_SUCCESS) {
VULKAN_DestroyAll(renderer);
return VK_ERROR_UNKNOWN;
}
}
if (SDL_HasProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER)) {
rendererData->graphicsQueueFamilyIndex = (uint32_t)SDL_GetNumberProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER, 0);
}
if (SDL_HasProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER)) {
rendererData->presentQueueFamilyIndex = (uint32_t)SDL_GetNumberProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER, 0);
} }
/* Create Vulkan device */ /* Create Vulkan device */
VkDeviceQueueCreateInfo deviceQueueCreateInfo[1] = { { 0 } }; rendererData->device = (VkDevice)SDL_GetProperty(create_props, SDL_PROP_RENDERER_CREATE_VULKAN_DEVICE_POINTER, NULL);
static const float queuePriority[] = { 1.0f }; if (rendererData->device) {
VkDeviceCreateInfo deviceCreateInfo = { 0 }; rendererData->device_external = SDL_TRUE;
static const char *const deviceExtensionNames[] = { } else {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = { { 0 }, { 0 } };
}; static const float queuePriority[] = { 1.0f };
VkDeviceCreateInfo deviceCreateInfo = { 0 };
static const char *const deviceExtensionNames[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
deviceQueueCreateInfo->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceQueueCreateInfo->queueFamilyIndex = rendererData->graphicsQueueFamilyIndex; deviceCreateInfo.queueCreateInfoCount = 0;
deviceQueueCreateInfo->queueCount = 1; deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo;
deviceQueueCreateInfo->pQueuePriorities = &queuePriority[0]; deviceCreateInfo.pEnabledFeatures = NULL;
deviceCreateInfo.enabledExtensionCount = SDL_arraysize(deviceExtensionNames);
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames;
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceQueueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
deviceCreateInfo.queueCreateInfoCount = 1; deviceQueueCreateInfo[0].queueFamilyIndex = rendererData->graphicsQueueFamilyIndex;
deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo; deviceQueueCreateInfo[0].queueCount = 1;
deviceCreateInfo.pEnabledFeatures = NULL; deviceQueueCreateInfo[0].pQueuePriorities = queuePriority;
deviceCreateInfo.enabledExtensionCount = SDL_arraysize(deviceExtensionNames); ++deviceCreateInfo.queueCreateInfoCount;
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames;
result = vkCreateDevice(rendererData->physicalDevice, &deviceCreateInfo, NULL, &rendererData->device); if (rendererData->presentQueueFamilyIndex != rendererData->graphicsQueueFamilyIndex) {
if (result != VK_SUCCESS) { deviceQueueCreateInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateDevice(): %s\n", SDL_Vulkan_GetResultString(result)); deviceQueueCreateInfo[1].queueFamilyIndex = rendererData->presentQueueFamilyIndex;
VULKAN_DestroyAll(renderer); deviceQueueCreateInfo[1].queueCount = 1;
return result; deviceQueueCreateInfo[1].pQueuePriorities = queuePriority;
++deviceCreateInfo.queueCreateInfoCount;
}
result = vkCreateDevice(rendererData->physicalDevice, &deviceCreateInfo, NULL, &rendererData->device);
if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateDevice(): %s\n", SDL_Vulkan_GetResultString(result));
VULKAN_DestroyAll(renderer);
return result;
}
} }
if(VULKAN_LoadDeviceFunctions(rendererData) != 0) { if (VULKAN_LoadDeviceFunctions(rendererData) != 0) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
@ -1789,6 +1832,14 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer)
} }
} }
SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
SDL_SetProperty(props, SDL_PROP_RENDERER_VULKAN_INSTANCE_POINTER, rendererData->instance);
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_SURFACE_NUMBER, (Sint64)rendererData->surface);
SDL_SetProperty(props, SDL_PROP_RENDERER_VULKAN_PHYSICAL_DEVICE_POINTER, rendererData->physicalDevice);
SDL_SetProperty(props, SDL_PROP_RENDERER_VULKAN_DEVICE_POINTER, rendererData->device);
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER, rendererData->graphicsQueueFamilyIndex);
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER, rendererData->presentQueueFamilyIndex);
return VK_SUCCESS; return VK_SUCCESS;
} }
@ -3880,8 +3931,8 @@ SDL_Renderer *VULKAN_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_
*/ */
renderer->window = window; renderer->window = window;
/* Initialize Direct3D resources */ /* Initialize Vulkan resources */
if (VULKAN_CreateDeviceResources(renderer) != VK_SUCCESS) { if (VULKAN_CreateDeviceResources(renderer, create_props) != VK_SUCCESS) {
VULKAN_DestroyRenderer(renderer); VULKAN_DestroyRenderer(renderer);
return NULL; return NULL;
} }