Added SDL_EVENT_RENDER_DEVICE_LOST

This is sent when the device is lost and can't be recovered.

Also fixed the vulkan renderer so it returns errors appropriately and will log and break if debug mode is enabled.
This commit is contained in:
Sam Lantinga
2024-10-21 00:19:05 -07:00
parent 54e52d055f
commit 3d47877bb4
5 changed files with 266 additions and 212 deletions

View File

@@ -228,6 +228,7 @@ typedef enum SDL_EventType
/* Render events */ /* Render events */
SDL_EVENT_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */ SDL_EVENT_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
SDL_EVENT_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */ SDL_EVENT_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
SDL_EVENT_RENDER_DEVICE_LOST, /**< The device has been lost and can't be recovered. */
/* Reserved events for private platforms */ /* Reserved events for private platforms */
SDL_EVENT_PRIVATE0 = 0x4000, SDL_EVENT_PRIVATE0 = 0x4000,

View File

@@ -307,10 +307,9 @@ static void D3D11_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
static void D3D11_ReleaseAll(SDL_Renderer *renderer) static void D3D11_ReleaseAll(SDL_Renderer *renderer)
{ {
D3D11_RenderData *data = (D3D11_RenderData *)renderer->internal; D3D11_RenderData *data = (D3D11_RenderData *)renderer->internal;
SDL_Texture *texture = NULL;
// Release all textures // Release all textures
for (texture = renderer->textures; texture; texture = texture->next) { for (SDL_Texture *texture = renderer->textures; texture; texture = texture->next) {
D3D11_DestroyTexture(renderer, texture); D3D11_DestroyTexture(renderer, texture);
} }
@@ -982,39 +981,6 @@ static void D3D11_ReleaseMainRenderTargetView(SDL_Renderer *renderer)
SAFE_RELEASE(data->mainRenderTargetView); SAFE_RELEASE(data->mainRenderTargetView);
} }
static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer);
static HRESULT D3D11_HandleDeviceLost(SDL_Renderer *renderer)
{
HRESULT result = S_OK;
D3D11_ReleaseAll(renderer);
result = D3D11_CreateDeviceResources(renderer);
if (FAILED(result)) {
// D3D11_CreateDeviceResources will set the SDL error
D3D11_ReleaseAll(renderer);
return result;
}
result = D3D11_UpdateForWindowSizeChange(renderer);
if (FAILED(result)) {
// D3D11_UpdateForWindowSizeChange will set the SDL error
D3D11_ReleaseAll(renderer);
return result;
}
// Let the application know that the device has been reset
{
SDL_Event event;
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
event.common.timestamp = 0;
SDL_PushEvent(&event);
}
return S_OK;
}
// Initialize all resources that change when the window's size changes. // Initialize all resources that change when the window's size changes.
static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer) static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
{ {
@@ -1045,15 +1011,7 @@ static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
w, h, w, h,
DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
0); 0);
if (result == DXGI_ERROR_DEVICE_REMOVED) { if (FAILED(result)) {
// If the device was removed for any reason, a new device and swap chain will need to be created.
D3D11_HandleDeviceLost(renderer);
/* Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method
* and correctly set up the new device.
*/
goto done;
} else if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result); WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result);
goto done; goto done;
} }
@@ -1110,6 +1068,29 @@ done:
return result; return result;
} }
static bool D3D11_HandleDeviceLost(SDL_Renderer *renderer)
{
bool recovered = false;
D3D11_ReleaseAll(renderer);
if (SUCCEEDED(D3D11_CreateDeviceResources(renderer)) &&
SUCCEEDED(D3D11_CreateWindowSizeDependentResources(renderer))) {
recovered = true;
} else {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Renderer couldn't recover from device lost: %s\n", SDL_GetError());
D3D11_ReleaseAll(renderer);
}
// Let the application know that the device has been reset or lost
SDL_Event event;
event.type = recovered ? SDL_EVENT_RENDER_DEVICE_RESET : SDL_EVENT_RENDER_DEVICE_LOST;
event.common.timestamp = 0;
SDL_PushEvent(&event);
return recovered;
}
// This method is called when the window's size changes. // This method is called when the window's size changes.
static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer) static HRESULT D3D11_UpdateForWindowSizeChange(SDL_Renderer *renderer)
{ {
@@ -1164,6 +1145,10 @@ static bool D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
D3D11_TEXTURE2D_DESC textureDesc; D3D11_TEXTURE2D_DESC textureDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
if (!rendererData->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}
if (textureFormat == DXGI_FORMAT_UNKNOWN) { if (textureFormat == DXGI_FORMAT_UNKNOWN) {
return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified", return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
__FUNCTION__, texture->format); __FUNCTION__, texture->format);
@@ -2644,7 +2629,7 @@ static bool D3D11_RenderPresent(SDL_Renderer *renderer)
* must recreate all device resources. * must recreate all device resources.
*/ */
if (result == DXGI_ERROR_DEVICE_REMOVED) { if (result == DXGI_ERROR_DEVICE_REMOVED) {
if (SUCCEEDED(D3D11_HandleDeviceLost(renderer))) { if (D3D11_HandleDeviceLost(renderer)) {
SDL_SetError("Present failed, device lost"); SDL_SetError("Present failed, device lost");
} else { } else {
// Recovering from device lost failed, error is already set // Recovering from device lost failed, error is already set

View File

@@ -374,14 +374,13 @@ static void D3D12_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
static void D3D12_ReleaseAll(SDL_Renderer *renderer) static void D3D12_ReleaseAll(SDL_Renderer *renderer)
{ {
D3D12_RenderData *data = (D3D12_RenderData *)renderer->internal; D3D12_RenderData *data = (D3D12_RenderData *)renderer->internal;
SDL_Texture *texture = NULL;
SDL_PropertiesID props = SDL_GetRendererProperties(renderer); SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_D3D12_DEVICE_POINTER, NULL); SDL_SetPointerProperty(props, SDL_PROP_RENDERER_D3D12_DEVICE_POINTER, NULL);
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER, NULL); SDL_SetPointerProperty(props, SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER, NULL);
// Release all textures // Release all textures
for (texture = renderer->textures; texture; texture = texture->next) { for (SDL_Texture *texture = renderer->textures; texture; texture = texture->next) {
D3D12_DestroyTexture(renderer, texture); D3D12_DestroyTexture(renderer, texture);
} }
@@ -1326,40 +1325,6 @@ done:
} }
#endif #endif
static HRESULT D3D12_UpdateForWindowSizeChange(SDL_Renderer *renderer);
HRESULT
D3D12_HandleDeviceLost(SDL_Renderer *renderer)
{
HRESULT result = S_OK;
D3D12_ReleaseAll(renderer);
result = D3D12_CreateDeviceResources(renderer);
if (FAILED(result)) {
// D3D12_CreateDeviceResources will set the SDL error
D3D12_ReleaseAll(renderer);
return result;
}
result = D3D12_UpdateForWindowSizeChange(renderer);
if (FAILED(result)) {
// D3D12_UpdateForWindowSizeChange will set the SDL error
D3D12_ReleaseAll(renderer);
return result;
}
// Let the application know that the device has been reset
{
SDL_Event event;
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
event.common.timestamp = 0;
SDL_PushEvent(&event);
}
return S_OK;
}
// Initialize all resources that change when the window's size changes. // Initialize all resources that change when the window's size changes.
static HRESULT D3D12_CreateWindowSizeDependentResources(SDL_Renderer *renderer) static HRESULT D3D12_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
{ {
@@ -1398,15 +1363,7 @@ static HRESULT D3D12_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
w, h, w, h,
DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
data->swapFlags); data->swapFlags);
if (result == DXGI_ERROR_DEVICE_REMOVED) { if (FAILED(result)) {
// If the device was removed for any reason, a new device and swap chain will need to be created.
D3D12_HandleDeviceLost(renderer);
/* Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method
* and correctly set up the new device.
*/
goto done;
} else if (FAILED(result)) {
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result); WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result);
goto done; goto done;
} }
@@ -1486,6 +1443,29 @@ done:
return result; return result;
} }
static bool D3D12_HandleDeviceLost(SDL_Renderer *renderer)
{
bool recovered = false;
D3D12_ReleaseAll(renderer);
if (SUCCEEDED(D3D12_CreateDeviceResources(renderer)) &&
SUCCEEDED(D3D12_CreateWindowSizeDependentResources(renderer))) {
recovered = true;
} else {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Renderer couldn't recover from device lost: %s\n", SDL_GetError());
D3D12_ReleaseAll(renderer);
}
// Let the application know that the device has been reset or lost
SDL_Event event;
event.type = recovered ? SDL_EVENT_RENDER_DEVICE_RESET : SDL_EVENT_RENDER_DEVICE_LOST;
event.common.timestamp = 0;
SDL_PushEvent(&event);
return recovered;
}
// This method is called when the window's size changes. // This method is called when the window's size changes.
static HRESULT D3D12_UpdateForWindowSizeChange(SDL_Renderer *renderer) static HRESULT D3D12_UpdateForWindowSizeChange(SDL_Renderer *renderer)
{ {
@@ -1568,6 +1548,10 @@ static bool D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
D3D12_HEAP_PROPERTIES heapProps; D3D12_HEAP_PROPERTIES heapProps;
D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc; D3D12_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
if (!rendererData->d3dDevice) {
return SDL_SetError("Device lost and couldn't be recovered");
}
if (textureFormat == DXGI_FORMAT_UNKNOWN) { if (textureFormat == DXGI_FORMAT_UNKNOWN) {
return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified", __FUNCTION__, texture->format); return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified", __FUNCTION__, texture->format);
} }
@@ -3147,7 +3131,7 @@ static bool D3D12_RenderPresent(SDL_Renderer *renderer)
* must recreate all device resources. * must recreate all device resources.
*/ */
if (result == DXGI_ERROR_DEVICE_REMOVED) { if (result == DXGI_ERROR_DEVICE_REMOVED) {
if (SUCCEEDED(D3D12_HandleDeviceLost(renderer))) { if (D3D12_HandleDeviceLost(renderer)) {
SDL_SetError("Present failed, device lost"); SDL_SetError("Present failed, device lost");
} else { } else {
// Recovering from device lost failed, error is already set // Recovering from device lost failed, error is already set

View File

@@ -39,6 +39,20 @@
#include "../../video/SDL_pixels_c.h" #include "../../video/SDL_pixels_c.h"
#include "SDL_shaders_vulkan.h" #include "SDL_shaders_vulkan.h"
#define SET_ERROR_CODE(message, rc) \
if (SDL_GetHintBoolean(SDL_HINT_RENDER_VULKAN_DEBUG, false)) { \
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s: %s\n", message, SDL_Vulkan_GetResultString(rc)); \
SDL_TriggerBreakpoint(); \
} \
SDL_SetError("%s: %s", message, SDL_Vulkan_GetResultString(rc)) \
#define SET_ERROR_MESSAGE(message) \
if (SDL_GetHintBoolean(SDL_HINT_RENDER_VULKAN_DEBUG, false)) { \
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s\n", message); \
SDL_TriggerBreakpoint(); \
} \
SDL_SetError("%s", message) \
#define VULKAN_FUNCTIONS() \ #define VULKAN_FUNCTIONS() \
VULKAN_DEVICE_FUNCTION(vkAcquireNextImageKHR) \ VULKAN_DEVICE_FUNCTION(vkAcquireNextImageKHR) \
VULKAN_DEVICE_FUNCTION(vkAllocateCommandBuffers) \ VULKAN_DEVICE_FUNCTION(vkAllocateCommandBuffers) \
@@ -304,6 +318,7 @@ typedef struct
VkSurfaceFormatKHR *surfaceFormats; VkSurfaceFormatKHR *surfaceFormats;
bool recreateSwapchain; bool recreateSwapchain;
int vsync; int vsync;
SDL_PropertiesID create_props;
VkFramebuffer *framebuffers; VkFramebuffer *framebuffers;
VkRenderPass renderPasses[VULKAN_RENDERPASS_COUNT]; VkRenderPass renderPasses[VULKAN_RENDERPASS_COUNT];
@@ -474,6 +489,11 @@ static void VULKAN_DestroyAll(SDL_Renderer *renderer)
return; return;
} }
// Release all textures
for (SDL_Texture *texture = renderer->textures; texture; texture = texture->next) {
VULKAN_DestroyTexture(renderer, texture);
}
if (rendererData->waitDestStageMasks) { if (rendererData->waitDestStageMasks) {
SDL_free(rendererData->waitDestStageMasks); SDL_free(rendererData->waitDestStageMasks);
rendererData->waitDestStageMasks = NULL; rendererData->waitDestStageMasks = NULL;
@@ -489,6 +509,7 @@ static void VULKAN_DestroyAll(SDL_Renderer *renderer)
if (rendererData->surfaceFormats != NULL) { if (rendererData->surfaceFormats != NULL) {
SDL_free(rendererData->surfaceFormats); SDL_free(rendererData->surfaceFormats);
rendererData->surfaceFormats = NULL; rendererData->surfaceFormats = NULL;
rendererData->surfaceFormatsAllocatedCount = 0;
} }
if (rendererData->swapchainImages != NULL) { if (rendererData->swapchainImages != NULL) {
SDL_free(rendererData->swapchainImages); SDL_free(rendererData->swapchainImages);
@@ -564,12 +585,14 @@ static void VULKAN_DestroyAll(SDL_Renderer *renderer)
SDL_free(rendererData->renderingFinishedSemaphores); SDL_free(rendererData->renderingFinishedSemaphores);
rendererData->renderingFinishedSemaphores = NULL; rendererData->renderingFinishedSemaphores = NULL;
} }
if (rendererData->commandBuffers) {
vkFreeCommandBuffers(rendererData->device, rendererData->commandPool, rendererData->swapchainImageCount, rendererData->commandBuffers);
SDL_free(rendererData->commandBuffers);
rendererData->commandBuffers = NULL;
rendererData->currentCommandBuffer = VK_NULL_HANDLE;
rendererData->currentCommandBufferIndex = 0;
}
if (rendererData->commandPool) { if (rendererData->commandPool) {
if (rendererData->commandBuffers) {
vkFreeCommandBuffers(rendererData->device, rendererData->commandPool, rendererData->swapchainImageCount, rendererData->commandBuffers);
SDL_free(rendererData->commandBuffers);
rendererData->commandBuffers = NULL;
}
vkDestroyCommandPool(rendererData->device, rendererData->commandPool, NULL); vkDestroyCommandPool(rendererData->device, rendererData->commandPool, NULL);
rendererData->commandPool = VK_NULL_HANDLE; rendererData->commandPool = VK_NULL_HANDLE;
} }
@@ -584,7 +607,9 @@ static void VULKAN_DestroyAll(SDL_Renderer *renderer)
SDL_free(rendererData->descriptorPools[i]); SDL_free(rendererData->descriptorPools[i]);
} }
SDL_free(rendererData->descriptorPools); SDL_free(rendererData->descriptorPools);
rendererData->descriptorPools = NULL;
SDL_free(rendererData->numDescriptorPools); SDL_free(rendererData->numDescriptorPools);
rendererData->numDescriptorPools = NULL;
} }
for (uint32_t i = 0; i < NUM_SHADERS; i++) { for (uint32_t i = 0; i < NUM_SHADERS; i++) {
if (rendererData->vertexShaderModules[i] != VK_NULL_HANDLE) { if (rendererData->vertexShaderModules[i] != VK_NULL_HANDLE) {
@@ -608,6 +633,7 @@ static void VULKAN_DestroyAll(SDL_Renderer *renderer)
vkDestroyPipeline(rendererData->device, rendererData->pipelineStates[i].pipeline, NULL); vkDestroyPipeline(rendererData->device, rendererData->pipelineStates[i].pipeline, NULL);
} }
SDL_free(rendererData->pipelineStates); SDL_free(rendererData->pipelineStates);
rendererData->pipelineStates = NULL;
rendererData->pipelineStateCount = 0; rendererData->pipelineStateCount = 0;
if (rendererData->currentUploadBuffer) { if (rendererData->currentUploadBuffer) {
@@ -618,7 +644,9 @@ static void VULKAN_DestroyAll(SDL_Renderer *renderer)
SDL_free(rendererData->uploadBuffers[i]); SDL_free(rendererData->uploadBuffers[i]);
} }
SDL_free(rendererData->uploadBuffers); SDL_free(rendererData->uploadBuffers);
rendererData->uploadBuffers = NULL;
SDL_free(rendererData->currentUploadBuffer); SDL_free(rendererData->currentUploadBuffer);
rendererData->currentUploadBuffer = NULL;
} }
if (rendererData->constantBuffers) { if (rendererData->constantBuffers) {
@@ -630,8 +658,9 @@ static void VULKAN_DestroyAll(SDL_Renderer *renderer)
SDL_free(rendererData->constantBuffers[i]); SDL_free(rendererData->constantBuffers[i]);
} }
SDL_free(rendererData->constantBuffers); SDL_free(rendererData->constantBuffers);
SDL_free(rendererData->numConstantBuffers);
rendererData->constantBuffers = NULL; rendererData->constantBuffers = NULL;
SDL_free(rendererData->numConstantBuffers);
rendererData->numConstantBuffers = NULL;
} }
if (rendererData->device != VK_NULL_HANDLE && !rendererData->device_external) { if (rendererData->device != VK_NULL_HANDLE && !rendererData->device_external) {
@@ -670,7 +699,7 @@ static VkResult VULKAN_AllocateBuffer(VULKAN_RenderData *rendererData, VkDeviceS
bufferCreateInfo.usage = usage; bufferCreateInfo.usage = usage;
result = vkCreateBuffer(rendererData->device, &bufferCreateInfo, NULL, &bufferOut->buffer); result = vkCreateBuffer(rendererData->device, &bufferCreateInfo, NULL, &bufferOut->buffer);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateBuffer(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateBuffer()", result);
return result; return result;
} }
@@ -678,14 +707,13 @@ static VkResult VULKAN_AllocateBuffer(VULKAN_RenderData *rendererData, VkDeviceS
vkGetBufferMemoryRequirements(rendererData->device, bufferOut->buffer, &memoryRequirements); vkGetBufferMemoryRequirements(rendererData->device, bufferOut->buffer, &memoryRequirements);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyBuffer(rendererData, bufferOut); VULKAN_DestroyBuffer(rendererData, bufferOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetBufferMemoryRequirements(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetBufferMemoryRequirements()", result);
return result; return result;
} }
uint32_t memoryTypeIndex = 0; uint32_t memoryTypeIndex = 0;
if (!VULKAN_FindMemoryTypeIndex(rendererData, memoryRequirements.memoryTypeBits, requiredMemoryProps, desiredMemoryProps, &memoryTypeIndex)) { if (!VULKAN_FindMemoryTypeIndex(rendererData, memoryRequirements.memoryTypeBits, requiredMemoryProps, desiredMemoryProps, &memoryTypeIndex)) {
VULKAN_DestroyBuffer(rendererData, bufferOut); VULKAN_DestroyBuffer(rendererData, bufferOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "VULKAN_FindMemoryTypeIndex failed.\n");
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
@@ -696,20 +724,20 @@ static VkResult VULKAN_AllocateBuffer(VULKAN_RenderData *rendererData, VkDeviceS
result = vkAllocateMemory(rendererData->device, &memoryAllocateInfo, NULL, &bufferOut->deviceMemory); result = vkAllocateMemory(rendererData->device, &memoryAllocateInfo, NULL, &bufferOut->deviceMemory);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyBuffer(rendererData, bufferOut); VULKAN_DestroyBuffer(rendererData, bufferOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkAllocateMemory(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkAllocateMemory()", result);
return result; return result;
} }
result = vkBindBufferMemory(rendererData->device, bufferOut->buffer, bufferOut->deviceMemory, 0); result = vkBindBufferMemory(rendererData->device, bufferOut->buffer, bufferOut->deviceMemory, 0);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyBuffer(rendererData, bufferOut); VULKAN_DestroyBuffer(rendererData, bufferOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkBindBufferMemory(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkBindBufferMemory()", result);
return result; return result;
} }
result = vkMapMemory(rendererData->device, bufferOut->deviceMemory, 0, size, 0, &bufferOut->mappedBufferPtr); result = vkMapMemory(rendererData->device, bufferOut->deviceMemory, 0, size, 0, &bufferOut->mappedBufferPtr);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyBuffer(rendererData, bufferOut); VULKAN_DestroyBuffer(rendererData, bufferOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkMapMemory(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkMapMemory()", result);
return result; return result;
} }
bufferOut->size = size; bufferOut->size = size;
@@ -770,7 +798,7 @@ static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, SDL_Proper
result = vkCreateImage(rendererData->device, &imageCreateInfo, NULL, &imageOut->image); result = vkCreateImage(rendererData->device, &imageCreateInfo, NULL, &imageOut->image);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyImage(rendererData, imageOut); VULKAN_DestroyImage(rendererData, imageOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateImage(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateImage()", result);
return result; return result;
} }
@@ -778,14 +806,13 @@ static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, SDL_Proper
vkGetImageMemoryRequirements(rendererData->device, imageOut->image, &memoryRequirements); vkGetImageMemoryRequirements(rendererData->device, imageOut->image, &memoryRequirements);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyImage(rendererData, imageOut); VULKAN_DestroyImage(rendererData, imageOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetImageMemoryRequirements(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetImageMemoryRequirements()", result);
return result; return result;
} }
uint32_t memoryTypeIndex = 0; uint32_t memoryTypeIndex = 0;
if (!VULKAN_FindMemoryTypeIndex(rendererData, memoryRequirements.memoryTypeBits, 0, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memoryTypeIndex)) { if (!VULKAN_FindMemoryTypeIndex(rendererData, memoryRequirements.memoryTypeBits, 0, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memoryTypeIndex)) {
VULKAN_DestroyImage(rendererData, imageOut); VULKAN_DestroyImage(rendererData, imageOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "VULKAN_FindMemoryTypeIndex failed.\n");
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
@@ -796,13 +823,13 @@ static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, SDL_Proper
result = vkAllocateMemory(rendererData->device, &memoryAllocateInfo, NULL, &imageOut->deviceMemory); result = vkAllocateMemory(rendererData->device, &memoryAllocateInfo, NULL, &imageOut->deviceMemory);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyImage(rendererData, imageOut); VULKAN_DestroyImage(rendererData, imageOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkAllocateMemory(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkAllocateMemory()", result);
return result; return result;
} }
result = vkBindImageMemory(rendererData->device, imageOut->image, imageOut->deviceMemory, 0); result = vkBindImageMemory(rendererData->device, imageOut->image, imageOut->deviceMemory, 0);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyImage(rendererData, imageOut); VULKAN_DestroyImage(rendererData, imageOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkBindImageMemory(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkBindImageMemory()", result);
return result; return result;
} }
} else { } else {
@@ -831,7 +858,7 @@ static VkResult VULKAN_AllocateImage(VULKAN_RenderData *rendererData, SDL_Proper
result = vkCreateImageView(rendererData->device, &imageViewCreateInfo, NULL, &imageOut->imageView); result = vkCreateImageView(rendererData->device, &imageViewCreateInfo, NULL, &imageOut->imageView);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyImage(rendererData, imageOut); VULKAN_DestroyImage(rendererData, imageOut);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateImageView(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateImageView()", result);
return result; return result;
} }
@@ -880,9 +907,8 @@ static VkResult VULKAN_AcquireNextSwapchainImage(SDL_Renderer *renderer)
return result; return result;
} else if(result == VK_SUBOPTIMAL_KHR) { } else if(result == VK_SUBOPTIMAL_KHR) {
// Suboptimal, but we can contiue // Suboptimal, but we can contiue
} } else if (result != VK_SUCCESS) {
else if (result != VK_SUCCESS) { SET_ERROR_CODE("vkAcquireNextImageKHR()", result);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkAcquireNextImageKHR(): %s\n", SDL_Vulkan_GetResultString(result));
return result; return result;
} }
rendererData->currentImageAvailableSemaphore = rendererData->imageAvailableSemaphores[rendererData->currentCommandBufferIndex]; rendererData->currentImageAvailableSemaphore = rendererData->imageAvailableSemaphores[rendererData->currentCommandBufferIndex];
@@ -1258,11 +1284,14 @@ static VULKAN_PipelineState *VULKAN_CreatePipelineState(SDL_Renderer *renderer,
result = vkCreateGraphicsPipelines(rendererData->device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, NULL, &pipeline); result = vkCreateGraphicsPipelines(rendererData->device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, NULL, &pipeline);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateGraphicsPipelines(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateGraphicsPipelines()", result);
return NULL; return NULL;
} }
pipelineStates = (VULKAN_PipelineState *)SDL_realloc(rendererData->pipelineStates, (rendererData->pipelineStateCount + 1) * sizeof(*pipelineStates)); pipelineStates = (VULKAN_PipelineState *)SDL_realloc(rendererData->pipelineStates, (rendererData->pipelineStateCount + 1) * sizeof(*pipelineStates));
if (!pipelineStates) {
return NULL;
}
pipelineStates[rendererData->pipelineStateCount].shader = shader; pipelineStates[rendererData->pipelineStateCount].shader = shader;
pipelineStates[rendererData->pipelineStateCount].blendMode = blendMode; pipelineStates[rendererData->pipelineStateCount].blendMode = blendMode;
pipelineStates[rendererData->pipelineStateCount].topology = topology; pipelineStates[rendererData->pipelineStateCount].topology = topology;
@@ -1303,7 +1332,7 @@ static bool VULKAN_FindMemoryTypeIndex(VULKAN_RenderData *rendererData, uint32_t
} }
if (memoryTypeIndex >= rendererData->physicalDeviceMemoryProperties.memoryTypeCount) { if (memoryTypeIndex >= rendererData->physicalDeviceMemoryProperties.memoryTypeCount) {
SDL_SetError("[Vulkan] Unable to find memory type for allocation"); SET_ERROR_MESSAGE("Unable to find memory type for allocation");
return false; return false;
} }
*memoryTypeIndexOut = memoryTypeIndex; *memoryTypeIndexOut = memoryTypeIndex;
@@ -1323,7 +1352,6 @@ static VkResult VULKAN_CreateVertexBuffer(VULKAN_RenderData *rendererData, size_
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&rendererData->vertexBuffers[vbidx]); &rendererData->vertexBuffers[vbidx]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "VULKAN_AllocateBuffer(): %s\n", SDL_Vulkan_GetResultString(result));
return result; return result;
} }
return result; return result;
@@ -1332,12 +1360,11 @@ static VkResult VULKAN_CreateVertexBuffer(VULKAN_RenderData *rendererData, size_
static bool VULKAN_LoadGlobalFunctions(VULKAN_RenderData *rendererData) static bool VULKAN_LoadGlobalFunctions(VULKAN_RenderData *rendererData)
{ {
#define VULKAN_DEVICE_FUNCTION(name) #define VULKAN_DEVICE_FUNCTION(name)
#define VULKAN_GLOBAL_FUNCTION(name) \ #define VULKAN_GLOBAL_FUNCTION(name) \
name = (PFN_##name)rendererData->vkGetInstanceProcAddr(VK_NULL_HANDLE, #name); \ name = (PFN_##name)rendererData->vkGetInstanceProcAddr(VK_NULL_HANDLE, #name); \
if (!name) { \ if (!name) { \
SDL_LogError(SDL_LOG_CATEGORY_RENDER, \ SET_ERROR_MESSAGE("vkGetInstanceProcAddr(VK_NULL_HANDLE, \"" #name "\") failed"); \
"vkGetInstanceProcAddr(VK_NULL_HANDLE, \"" #name "\") failed\n"); \ return false; \
return false; \
} }
#define VULKAN_INSTANCE_FUNCTION(name) #define VULKAN_INSTANCE_FUNCTION(name)
#define VULKAN_OPTIONAL_INSTANCE_FUNCTION(name) #define VULKAN_OPTIONAL_INSTANCE_FUNCTION(name)
@@ -1359,9 +1386,8 @@ static bool VULKAN_LoadInstanceFunctions(VULKAN_RenderData *rendererData)
#define VULKAN_INSTANCE_FUNCTION(name) \ #define VULKAN_INSTANCE_FUNCTION(name) \
name = (PFN_##name)rendererData->vkGetInstanceProcAddr(rendererData->instance, #name); \ name = (PFN_##name)rendererData->vkGetInstanceProcAddr(rendererData->instance, #name); \
if (!name) { \ if (!name) { \
SDL_LogError(SDL_LOG_CATEGORY_RENDER, \ SET_ERROR_MESSAGE("vkGetInstanceProcAddr(instance, \"" #name "\") failed"); \
"vkGetInstanceProcAddr(instance, \"" #name "\") failed\n"); \ return false; \
return false; \
} }
#define VULKAN_OPTIONAL_INSTANCE_FUNCTION(name) \ #define VULKAN_OPTIONAL_INSTANCE_FUNCTION(name) \
name = (PFN_##name)rendererData->vkGetInstanceProcAddr(rendererData->instance, #name); name = (PFN_##name)rendererData->vkGetInstanceProcAddr(rendererData->instance, #name);
@@ -1379,11 +1405,10 @@ static bool VULKAN_LoadInstanceFunctions(VULKAN_RenderData *rendererData)
static bool VULKAN_LoadDeviceFunctions(VULKAN_RenderData *rendererData) static bool VULKAN_LoadDeviceFunctions(VULKAN_RenderData *rendererData)
{ {
#define VULKAN_DEVICE_FUNCTION(name) \ #define VULKAN_DEVICE_FUNCTION(name) \
name = (PFN_##name)vkGetDeviceProcAddr(rendererData->device, #name); \ name = (PFN_##name)vkGetDeviceProcAddr(rendererData->device, #name); \
if (!name) { \ if (!name) { \
SDL_LogError(SDL_LOG_CATEGORY_RENDER, \ SET_ERROR_MESSAGE("vkGetDeviceProcAddr(device, \"" #name "\") failed"); \
"vkGetDeviceProcAddr(device, \"" #name "\") failed\n"); \
return false; \ return false; \
} }
#define VULKAN_GLOBAL_FUNCTION(name) #define VULKAN_GLOBAL_FUNCTION(name)
@@ -1413,18 +1438,18 @@ static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
result = vkEnumeratePhysicalDevices(rendererData->instance, &physicalDeviceCount, NULL); result = vkEnumeratePhysicalDevices(rendererData->instance, &physicalDeviceCount, NULL);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkEnumeratePhysicalDevices(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkEnumeratePhysicalDevices()", result);
return result; return result;
} }
if (physicalDeviceCount == 0) { if (physicalDeviceCount == 0) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkEnumeratePhysicalDevices(): no physical devices\n"); SET_ERROR_MESSAGE("vkEnumeratePhysicalDevices(): no physical devices");
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
physicalDevices = (VkPhysicalDevice *)SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); physicalDevices = (VkPhysicalDevice *)SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
result = vkEnumeratePhysicalDevices(rendererData->instance, &physicalDeviceCount, physicalDevices); result = vkEnumeratePhysicalDevices(rendererData->instance, &physicalDeviceCount, physicalDevices);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_free(physicalDevices); SDL_free(physicalDevices);
SDL_LogError(SDL_LOG_CATEGORY_RENDER,"vkEnumeratePhysicalDevices(): %s\n",SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkEnumeratePhysicalDevices()", result);
return result; return result;
} }
rendererData->physicalDevice = NULL; rendererData->physicalDevice = NULL;
@@ -1475,7 +1500,7 @@ static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
SDL_free(physicalDevices); SDL_free(physicalDevices);
SDL_free(queueFamiliesProperties); SDL_free(queueFamiliesProperties);
SDL_free(deviceExtensions); SDL_free(deviceExtensions);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetPhysicalDeviceSurfaceSupportKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetPhysicalDeviceSurfaceSupportKHR()", result);
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
if (supported) { if (supported) {
@@ -1497,7 +1522,7 @@ static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
SDL_free(physicalDevices); SDL_free(physicalDevices);
SDL_free(queueFamiliesProperties); SDL_free(queueFamiliesProperties);
SDL_free(deviceExtensions); SDL_free(deviceExtensions);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkEnumerateDeviceExtensionProperties(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkEnumerateDeviceExtensionProperties()", result);
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
if (deviceExtensionCount == 0) { if (deviceExtensionCount == 0) {
@@ -1518,7 +1543,7 @@ static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
SDL_free(physicalDevices); SDL_free(physicalDevices);
SDL_free(queueFamiliesProperties); SDL_free(queueFamiliesProperties);
SDL_free(deviceExtensions); SDL_free(deviceExtensions);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkEnumerateDeviceExtensionProperties(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkEnumerateDeviceExtensionProperties()", result);
return result; return result;
} }
for (i = 0; i < deviceExtensionCount; i++) { for (i = 0; i < deviceExtensionCount; i++) {
@@ -1537,7 +1562,7 @@ static VkResult VULKAN_FindPhysicalDevice(VULKAN_RenderData *rendererData)
SDL_free(queueFamiliesProperties); SDL_free(queueFamiliesProperties);
SDL_free(deviceExtensions); SDL_free(deviceExtensions);
if (!rendererData->physicalDevice) { if (!rendererData->physicalDevice) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Vulkan: no viable physical devices found"); SET_ERROR_MESSAGE("No viable physical devices found");
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
return VK_SUCCESS; return VK_SUCCESS;
@@ -1551,7 +1576,7 @@ static VkResult VULKAN_GetSurfaceFormats(VULKAN_RenderData *rendererData)
NULL); NULL);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
rendererData->surfaceFormatsCount = 0; rendererData->surfaceFormatsCount = 0;
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetPhysicalDeviceSurfaceFormatsKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetPhysicalDeviceSurfaceFormatsKHR()", result);
return result; return result;
} }
if (rendererData->surfaceFormatsCount > rendererData->surfaceFormatsAllocatedCount) { if (rendererData->surfaceFormatsCount > rendererData->surfaceFormatsAllocatedCount) {
@@ -1565,7 +1590,7 @@ static VkResult VULKAN_GetSurfaceFormats(VULKAN_RenderData *rendererData)
rendererData->surfaceFormats); rendererData->surfaceFormats);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
rendererData->surfaceFormatsCount = 0; rendererData->surfaceFormatsCount = 0;
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetPhysicalDeviceSurfaceFormatsKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetPhysicalDeviceSurfaceFormatsKHR()", result);
return result; return result;
} }
@@ -1581,7 +1606,7 @@ static VkSemaphore VULKAN_CreateSemaphore(VULKAN_RenderData *rendererData)
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
result = vkCreateSemaphore(rendererData->device, &semaphoreCreateInfo, NULL, &semaphore); result = vkCreateSemaphore(rendererData->device, &semaphoreCreateInfo, NULL, &semaphore);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateSemaphore(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateSemaphore()", result);
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
} }
return semaphore; return semaphore;
@@ -1593,14 +1618,14 @@ static bool VULKAN_DeviceExtensionsFound(VULKAN_RenderData *rendererData, int ex
bool foundExtensions = true; bool foundExtensions = true;
VkResult result = vkEnumerateDeviceExtensionProperties(rendererData->physicalDevice, NULL, &extensionCount, NULL); VkResult result = vkEnumerateDeviceExtensionProperties(rendererData->physicalDevice, NULL, &extensionCount, NULL);
if (result != VK_SUCCESS ) { if (result != VK_SUCCESS ) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkEnumerateDeviceExtensionProperties(): %s.\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkEnumerateDeviceExtensionProperties()", result);
return false; return false;
} }
if (extensionCount > 0 ) { if (extensionCount > 0 ) {
VkExtensionProperties *extensionProperties = (VkExtensionProperties *)SDL_calloc(extensionCount, sizeof(VkExtensionProperties)); VkExtensionProperties *extensionProperties = (VkExtensionProperties *)SDL_calloc(extensionCount, sizeof(VkExtensionProperties));
result = vkEnumerateDeviceExtensionProperties(rendererData->physicalDevice, NULL, &extensionCount, extensionProperties); result = vkEnumerateDeviceExtensionProperties(rendererData->physicalDevice, NULL, &extensionCount, extensionProperties);
if (result != VK_SUCCESS ) { if (result != VK_SUCCESS ) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkEnumerateDeviceExtensionProperties): %s.\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkEnumerateDeviceExtensionProperties()", result);
SDL_free(extensionProperties); SDL_free(extensionProperties);
return false; return false;
} }
@@ -1626,14 +1651,14 @@ static bool VULKAN_InstanceExtensionFound(VULKAN_RenderData *rendererData, const
uint32_t extensionCount; uint32_t extensionCount;
VkResult result = vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL); VkResult result = vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL);
if (result != VK_SUCCESS ) { if (result != VK_SUCCESS ) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkEnumerateInstanceExtensionProperties( NULL, ... ): %s.\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkEnumerateInstanceExtensionProperties()", result);
return false; return false;
} }
if (extensionCount > 0 ) { if (extensionCount > 0 ) {
VkExtensionProperties *extensionProperties = (VkExtensionProperties *)SDL_calloc(extensionCount, sizeof(VkExtensionProperties)); VkExtensionProperties *extensionProperties = (VkExtensionProperties *)SDL_calloc(extensionCount, sizeof(VkExtensionProperties));
result = vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensionProperties); result = vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensionProperties);
if (result != VK_SUCCESS ) { if (result != VK_SUCCESS ) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkEnumerateInstanceExtensionProperties( NULL, ... ): %s.\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkEnumerateInstanceExtensionProperties()", result);
SDL_free(extensionProperties); SDL_free(extensionProperties);
return false; return false;
} }
@@ -1693,7 +1718,7 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
const char *validationLayerName[] = { SDL_VULKAN_VALIDATION_LAYER_NAME }; const char *validationLayerName[] = { SDL_VULKAN_VALIDATION_LAYER_NAME };
if (!SDL_Vulkan_LoadLibrary(NULL)) { if (!SDL_Vulkan_LoadLibrary(NULL)) {
SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "SDL_Vulkan_LoadLibrary failed." ); SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "SDL_Vulkan_LoadLibrary failed" );
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
vkGetInstanceProcAddr = device ? (PFN_vkGetInstanceProcAddr)device->vulkan_config.vkGetInstanceProcAddr : NULL; vkGetInstanceProcAddr = device ? (PFN_vkGetInstanceProcAddr)device->vulkan_config.vkGetInstanceProcAddr : NULL;
@@ -1714,7 +1739,7 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
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) { if (!rendererData->supportsEXTSwapchainColorspace) {
SDL_SetError("[Vulkan] Using HDR output but %s not supported", VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME); SDL_SetError("Using HDR output but %s not supported", VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
} }
@@ -1755,7 +1780,7 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
result = vkCreateInstance(&instanceCreateInfo, NULL, &rendererData->instance); result = vkCreateInstance(&instanceCreateInfo, NULL, &rendererData->instance);
SDL_free((void *)instanceExtensionsCopy); SDL_free((void *)instanceExtensionsCopy);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateInstance(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateInstance()", result);
return result; return result;
} }
} }
@@ -1773,7 +1798,7 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
} else { } else {
if (!device->Vulkan_CreateSurface || !device->Vulkan_CreateSurface(device, renderer->window, rendererData->instance, NULL, &rendererData->surface)) { if (!device->Vulkan_CreateSurface || !device->Vulkan_CreateSurface(device, renderer->window, rendererData->instance, NULL, &rendererData->surface)) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Vulkan_CreateSurface() failed.\n"); SET_ERROR_MESSAGE("Vulkan_CreateSurface() failed");
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
} }
@@ -1842,7 +1867,7 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
result = vkCreateDevice(rendererData->physicalDevice, &deviceCreateInfo, NULL, &rendererData->device); result = vkCreateDevice(rendererData->physicalDevice, &deviceCreateInfo, NULL, &rendererData->device);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateDevice(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateDevice()", result);
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
return result; return result;
} }
@@ -1869,7 +1894,7 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
result = vkCreateCommandPool(rendererData->device, &commandPoolCreateInfo, NULL, &rendererData->commandPool); result = vkCreateCommandPool(rendererData->device, &commandPoolCreateInfo, NULL, &rendererData->commandPool);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateCommandPool(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateCommandPool()", result);
return result; return result;
} }
@@ -1887,14 +1912,14 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
result = vkCreateShaderModule(rendererData->device, &shaderModuleCreateInfo, NULL, &rendererData->vertexShaderModules[i]); result = vkCreateShaderModule(rendererData->device, &shaderModuleCreateInfo, NULL, &rendererData->vertexShaderModules[i]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateShaderModule(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateShaderModule()", result);
return result; return result;
} }
VULKAN_GetPixelShader(shader, &shaderModuleCreateInfo.pCode, &shaderModuleCreateInfo.codeSize); VULKAN_GetPixelShader(shader, &shaderModuleCreateInfo.pCode, &shaderModuleCreateInfo.codeSize);
result = vkCreateShaderModule(rendererData->device, &shaderModuleCreateInfo, NULL, &rendererData->fragmentShaderModules[i]); result = vkCreateShaderModule(rendererData->device, &shaderModuleCreateInfo, NULL, &rendererData->fragmentShaderModules[i]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateShaderModule(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateShaderModule()", result);
return result; return result;
} }
} }
@@ -1903,7 +1928,6 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
result = VULKAN_CreateDescriptorSetAndPipelineLayout(rendererData, VK_NULL_HANDLE, &rendererData->descriptorSetLayout, &rendererData->pipelineLayout); result = VULKAN_CreateDescriptorSetAndPipelineLayout(rendererData, VK_NULL_HANDLE, &rendererData->descriptorSetLayout, &rendererData->pipelineLayout);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "VULKAN_CreateDescriptorSetAndPipelineLayout(): %s\n", SDL_Vulkan_GetResultString(result));
return result; return result;
} }
@@ -1942,7 +1966,7 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert
result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &rendererData->samplers[i]); result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &rendererData->samplers[i]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateSampler(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateSampler()", result);
return result; return result;
} }
} }
@@ -2013,14 +2037,14 @@ static VkResult VULKAN_CreateFramebuffersAndRenderPasses(SDL_Renderer *renderer,
result = vkCreateRenderPass(rendererData->device, &renderPassCreateInfo, NULL, &renderPasses[VULKAN_RENDERPASS_LOAD]); result = vkCreateRenderPass(rendererData->device, &renderPassCreateInfo, NULL, &renderPasses[VULKAN_RENDERPASS_LOAD]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateRenderPass(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateRenderPass()", result);
return result; return result;
} }
attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
result = vkCreateRenderPass(rendererData->device, &renderPassCreateInfo, NULL, &renderPasses[VULKAN_RENDERPASS_CLEAR]); result = vkCreateRenderPass(rendererData->device, &renderPassCreateInfo, NULL, &renderPasses[VULKAN_RENDERPASS_CLEAR]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateRenderPass(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateRenderPass()", result);
return result; return result;
} }
@@ -2037,7 +2061,7 @@ static VkResult VULKAN_CreateFramebuffersAndRenderPasses(SDL_Renderer *renderer,
framebufferCreateInfo.pAttachments = &imageViews[i]; framebufferCreateInfo.pAttachments = &imageViews[i];
result = vkCreateFramebuffer(rendererData->device, &framebufferCreateInfo, NULL, &framebuffers[i]); result = vkCreateFramebuffer(rendererData->device, &framebufferCreateInfo, NULL, &framebuffers[i]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateFramebuffer(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateFramebuffer()", result);
return result; return result;
} }
} }
@@ -2050,7 +2074,7 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal; VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(rendererData->physicalDevice, rendererData->surface, &rendererData->surfaceCapabilities); VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(rendererData->physicalDevice, rendererData->surface, &rendererData->surfaceCapabilities);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR()", result);
return result; return result;
} }
@@ -2071,6 +2095,13 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
SDL_free(rendererData->fences); SDL_free(rendererData->fences);
rendererData->fences = NULL; rendererData->fences = NULL;
} }
if (rendererData->commandBuffers) {
vkResetCommandPool(rendererData->device, rendererData->commandPool, 0);
SDL_free(rendererData->commandBuffers);
rendererData->commandBuffers = NULL;
rendererData->currentCommandBuffer = VK_NULL_HANDLE;
rendererData->currentCommandBufferIndex = 0;
}
if (rendererData->framebuffers) { if (rendererData->framebuffers) {
for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) { for (uint32_t i = 0; i < rendererData->swapchainImageCount; i++) {
if (rendererData->framebuffers[i] != VK_NULL_HANDLE) { if (rendererData->framebuffers[i] != VK_NULL_HANDLE) {
@@ -2192,14 +2223,14 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
uint32_t presentModeCount = 0; uint32_t presentModeCount = 0;
result = vkGetPhysicalDeviceSurfacePresentModesKHR(rendererData->physicalDevice, rendererData->surface, &presentModeCount, NULL); result = vkGetPhysicalDeviceSurfacePresentModesKHR(rendererData->physicalDevice, rendererData->surface, &presentModeCount, NULL);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetPhysicalDeviceSurfacePresentModesKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetPhysicalDeviceSurfacePresentModesKHR()", result);
return result; return result;
} }
if (presentModeCount > 0) { if (presentModeCount > 0) {
VkPresentModeKHR *presentModes = (VkPresentModeKHR *)SDL_calloc(presentModeCount, sizeof(VkPresentModeKHR)); VkPresentModeKHR *presentModes = (VkPresentModeKHR *)SDL_calloc(presentModeCount, sizeof(VkPresentModeKHR));
result = vkGetPhysicalDeviceSurfacePresentModesKHR(rendererData->physicalDevice, rendererData->surface, &presentModeCount, presentModes); result = vkGetPhysicalDeviceSurfacePresentModesKHR(rendererData->physicalDevice, rendererData->surface, &presentModeCount, presentModes);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetPhysicalDeviceSurfacePresentModesKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetPhysicalDeviceSurfacePresentModesKHR()", result);
SDL_free(presentModes); SDL_free(presentModes);
return result; return result;
} }
@@ -2234,7 +2265,6 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
} }
} }
VkSwapchainCreateInfoKHR swapchainCreateInfo = { 0 }; VkSwapchainCreateInfoKHR swapchainCreateInfo = { 0 };
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainCreateInfo.surface = rendererData->surface; swapchainCreateInfo.surface = rendererData->surface;
@@ -2258,7 +2288,7 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
rendererData->swapchain = VK_NULL_HANDLE; rendererData->swapchain = VK_NULL_HANDLE;
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateSwapchainKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateSwapchainKHR()", result);
return result; return result;
} }
@@ -2267,7 +2297,7 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
result = vkGetSwapchainImagesKHR(rendererData->device, rendererData->swapchain, &rendererData->swapchainImageCount, NULL); result = vkGetSwapchainImagesKHR(rendererData->device, rendererData->swapchain, &rendererData->swapchainImageCount, NULL);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
rendererData->swapchainImageCount = 0; rendererData->swapchainImageCount = 0;
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetSwapchainImagesKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetSwapchainImagesKHR()", result);
return result; return result;
} }
@@ -2280,7 +2310,7 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
SDL_free(rendererData->swapchainImages); SDL_free(rendererData->swapchainImages);
rendererData->swapchainImages = NULL; rendererData->swapchainImages = NULL;
rendererData->swapchainImageCount = 0; rendererData->swapchainImageCount = 0;
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkGetSwapchainImagesKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkGetSwapchainImagesKHR()", result);
return result; return result;
} }
@@ -2308,7 +2338,7 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
result = vkCreateImageView(rendererData->device, &imageViewCreateInfo, NULL, &rendererData->swapchainImageViews[i]); result = vkCreateImageView(rendererData->device, &imageViewCreateInfo, NULL, &rendererData->swapchainImageViews[i]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateImageView(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateImageView()", result);
return result; return result;
} }
rendererData->swapchainImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED; rendererData->swapchainImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -2321,17 +2351,11 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
commandBufferAllocateInfo.commandPool = rendererData->commandPool; commandBufferAllocateInfo.commandPool = rendererData->commandPool;
commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
commandBufferAllocateInfo.commandBufferCount = rendererData->swapchainImageCount; commandBufferAllocateInfo.commandBufferCount = rendererData->swapchainImageCount;
if (rendererData->commandBuffers != NULL) {
vkResetCommandPool(rendererData->device, rendererData->commandPool, 0);
SDL_free(rendererData->commandBuffers);
rendererData->currentCommandBuffer = VK_NULL_HANDLE;
rendererData->currentCommandBufferIndex = 0;
}
rendererData->commandBuffers = (VkCommandBuffer *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkCommandBuffer)); rendererData->commandBuffers = (VkCommandBuffer *)SDL_calloc(rendererData->swapchainImageCount, sizeof(VkCommandBuffer));
result = vkAllocateCommandBuffers(rendererData->device, &commandBufferAllocateInfo, rendererData->commandBuffers); result = vkAllocateCommandBuffers(rendererData->device, &commandBufferAllocateInfo, rendererData->commandBuffers);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkAllocateCommandBuffers(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkAllocateCommandBuffers()", result);
return result; return result;
} }
@@ -2344,7 +2368,7 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
result = vkCreateFence(rendererData->device, &fenceCreateInfo, NULL, &rendererData->fences[i]); result = vkCreateFence(rendererData->device, &fenceCreateInfo, NULL, &rendererData->fences[i]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateFence(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateFence()", result);
return result; return result;
} }
} }
@@ -2367,7 +2391,7 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
rendererData->renderPasses); rendererData->renderPasses);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "VULKAN_CreateFramebuffersAndRenderPasses(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("VULKAN_CreateFramebuffersAndRenderPasses()", result);
return result; return result;
} }
@@ -2425,7 +2449,6 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
&rendererData->constantBuffers[i][0]); &rendererData->constantBuffers[i][0]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
VULKAN_DestroyAll(renderer); VULKAN_DestroyAll(renderer);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "VULKAN_AllocateBuffer(): %s\n", SDL_Vulkan_GetResultString(result));
return result; return result;
} }
} }
@@ -2466,6 +2489,30 @@ static VkResult VULKAN_CreateWindowSizeDependentResources(SDL_Renderer *renderer
return result; return result;
} }
static bool VULKAN_HandleDeviceLost(SDL_Renderer *renderer)
{
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
bool recovered = false;
VULKAN_DestroyAll(renderer);
if (VULKAN_CreateDeviceResources(renderer, rendererData->create_props) == VK_SUCCESS &&
VULKAN_CreateWindowSizeDependentResources(renderer) == VK_SUCCESS) {
recovered = true;
} else {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Renderer couldn't recover from device lost: %s\n", SDL_GetError());
VULKAN_DestroyAll(renderer);
}
// Let the application know that the device has been reset or lost
SDL_Event event;
event.type = recovered ? SDL_EVENT_RENDER_DEVICE_RESET : SDL_EVENT_RENDER_DEVICE_LOST;
event.common.timestamp = 0;
SDL_PushEvent(&event);
return recovered;
}
// This method is called when the window's size changes. // This method is called when the window's size changes.
static VkResult VULKAN_UpdateForWindowSizeChange(SDL_Renderer *renderer) static VkResult VULKAN_UpdateForWindowSizeChange(SDL_Renderer *renderer)
{ {
@@ -2514,6 +2561,11 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
uint32_t width = texture->w; uint32_t width = texture->w;
uint32_t height = texture->h; uint32_t height = texture->h;
VkComponentMapping imageViewSwizzle = rendererData->identitySwizzle; VkComponentMapping imageViewSwizzle = rendererData->identitySwizzle;
if (!rendererData->device) {
return SDL_SetError("Device lost and couldn't be recovered");
}
if (textureFormat == VK_FORMAT_UNDEFINED) { if (textureFormat == VK_FORMAT_UNDEFINED) {
return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified", __FUNCTION__, texture->format); return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified", __FUNCTION__, texture->format);
} }
@@ -2541,7 +2593,7 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
// Check that we have VK_KHR_sampler_ycbcr_conversion support // Check that we have VK_KHR_sampler_ycbcr_conversion support
if (!rendererData->supportsKHRSamplerYCbCrConversion) { if (!rendererData->supportsKHRSamplerYCbCrConversion) {
return SDL_SetError("[Vulkan] YUV textures require a Vulkan device that supports VK_KHR_sampler_ycbcr_conversion"); return SDL_SetError("YUV textures require a Vulkan device that supports VK_KHR_sampler_ycbcr_conversion");
} }
VkSamplerYcbcrConversionCreateInfoKHR samplerYcbcrConversionCreateInfo = { 0 }; VkSamplerYcbcrConversionCreateInfoKHR samplerYcbcrConversionCreateInfo = { 0 };
@@ -2574,7 +2626,7 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
} }
break; break;
default: default:
return SDL_SetError("[Vulkan] Unsupported Ycbcr colorspace: %d", SDL_COLORSPACEMATRIX(texture->colorspace)); return SDL_SetError("Unsupported Ycbcr colorspace: %d", SDL_COLORSPACEMATRIX(texture->colorspace));
} }
samplerYcbcrConversionCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; samplerYcbcrConversionCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
samplerYcbcrConversionCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; samplerYcbcrConversionCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
@@ -2617,7 +2669,8 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
result = vkCreateSamplerYcbcrConversionKHR(rendererData->device, &samplerYcbcrConversionCreateInfo, NULL, &textureData->samplerYcbcrConversion); result = vkCreateSamplerYcbcrConversionKHR(rendererData->device, &samplerYcbcrConversionCreateInfo, NULL, &textureData->samplerYcbcrConversion);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return SDL_SetError("[Vulkan] vkCreateSamplerYcbcrConversionKHR %s", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateSamplerYcbcrConversionKHR()", result);
return false;
} }
// Also create VkSampler object which we will need to pass to the PSO as an immutable sampler // Also create VkSampler object which we will need to pass to the PSO as an immutable sampler
@@ -2641,14 +2694,14 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
samplerCreateInfo.pNext = &samplerYcbcrConversionInfo; samplerCreateInfo.pNext = &samplerYcbcrConversionInfo;
result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &textureData->samplerYcbcr); result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &textureData->samplerYcbcr);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return SDL_SetError("[Vulkan] vkCreateSampler %s", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateSampler()", result);
return false;
} }
// Allocate special descriptor set layout with samplerYcbcr baked as an immutable sampler // Allocate special descriptor set layout with samplerYcbcr baked as an immutable sampler
result = VULKAN_CreateDescriptorSetAndPipelineLayout(rendererData, textureData->samplerYcbcr, result = VULKAN_CreateDescriptorSetAndPipelineLayout(rendererData, textureData->samplerYcbcr, &textureData->descriptorSetLayoutYcbcr, &textureData->pipelineLayoutYcbcr);
&textureData->descriptorSetLayoutYcbcr, &textureData->pipelineLayoutYcbcr);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
return SDL_SetError("[Vulkan] VULKAN_CreateDescriptorSetAndPipelineLayout %s", SDL_Vulkan_GetResultString(result)); return false;
} }
} }
#endif #endif
@@ -2662,7 +2715,7 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
result = VULKAN_AllocateImage(rendererData, create_props, width, height, textureFormat, usage, imageViewSwizzle, textureData->samplerYcbcrConversion, &textureData->mainImage); result = VULKAN_AllocateImage(rendererData, create_props, width, height, textureFormat, usage, imageViewSwizzle, textureData->samplerYcbcrConversion, &textureData->mainImage);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "VULKAN_AllocateImage(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("VULKAN_AllocateImage()", result);
return false; return false;
} }
@@ -2679,7 +2732,7 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
&textureData->mainFramebuffer, &textureData->mainFramebuffer,
textureData->mainRenderpasses); textureData->mainRenderpasses);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "VULKAN_CreateFramebuffersAndRenderPasses(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("VULKAN_CreateFramebuffersAndRenderPasses()", result);
return false; return false;
} }
} }
@@ -2738,14 +2791,14 @@ static void VULKAN_DestroyTexture(SDL_Renderer *renderer,
texture->internal = NULL; texture->internal = NULL;
} }
static VkResult VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, VkImage image, VkFormat format, int plane, int x, int y, int w, int h, const void *pixels, int pitch, VkImageLayout *imageLayout) static bool VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, VkImage image, VkFormat format, int plane, int x, int y, int w, int h, const void *pixels, int pitch, VkImageLayout *imageLayout)
{ {
VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(format); VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(format);
VkDeviceSize length = w * pixelSize; VkDeviceSize length = w * pixelSize;
VkDeviceSize uploadBufferSize = length * h; VkDeviceSize uploadBufferSize = length * h;
const Uint8 *src; const Uint8 *src;
Uint8 *dst; Uint8 *dst;
VkResult result; VkResult rc;
int planeCount = VULKAN_VkFormatGetNumPlanes(format); int planeCount = VULKAN_VkFormatGetNumPlanes(format);
VULKAN_EnsureCommandBuffer(rendererData); VULKAN_EnsureCommandBuffer(rendererData);
@@ -2753,14 +2806,14 @@ static VkResult VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, Vk
int currentUploadBufferIndex = rendererData->currentUploadBuffer[rendererData->currentCommandBufferIndex]; int currentUploadBufferIndex = rendererData->currentUploadBuffer[rendererData->currentCommandBufferIndex];
VULKAN_Buffer *uploadBuffer = &rendererData->uploadBuffers[rendererData->currentCommandBufferIndex][currentUploadBufferIndex]; VULKAN_Buffer *uploadBuffer = &rendererData->uploadBuffers[rendererData->currentCommandBufferIndex][currentUploadBufferIndex];
result = VULKAN_AllocateBuffer(rendererData, uploadBufferSize, rc = VULKAN_AllocateBuffer(rendererData, uploadBufferSize,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
uploadBuffer); uploadBuffer);
if (result != VK_SUCCESS) { if (rc != VK_SUCCESS) {
return result; return false;
} }
src = (const Uint8 *)pixels; src = (const Uint8 *)pixels;
@@ -2797,8 +2850,7 @@ static VkResult VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, Vk
region.imageSubresource.mipLevel = 0; region.imageSubresource.mipLevel = 0;
if (planeCount <= 1) { if (planeCount <= 1) {
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
} } else {
else {
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << plane; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << plane;
} }
region.imageOffset.x = x; region.imageOffset.x = x;
@@ -2827,7 +2879,7 @@ static VkResult VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, Vk
VULKAN_IssueBatch(rendererData); VULKAN_IssueBatch(rendererData);
} }
return VK_SUCCESS; return true;
} }
@@ -2931,7 +2983,7 @@ static bool VULKAN_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
{ {
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal; VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal; VULKAN_TextureData *textureData = (VULKAN_TextureData *)texture->internal;
VkResult result; VkResult rc;
if (!textureData) { if (!textureData) {
return SDL_SetError("Texture is not currently available"); return SDL_SetError("Texture is not currently available");
} }
@@ -2943,15 +2995,15 @@ static bool VULKAN_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(textureData->mainImage.format); VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(textureData->mainImage.format);
VkDeviceSize length = rect->w * pixelSize; VkDeviceSize length = rect->w * pixelSize;
VkDeviceSize stagingBufferSize = length * rect->h; VkDeviceSize stagingBufferSize = length * rect->h;
result = VULKAN_AllocateBuffer(rendererData, rc = VULKAN_AllocateBuffer(rendererData,
stagingBufferSize, stagingBufferSize,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&textureData->stagingBuffer); &textureData->stagingBuffer);
if (result != VK_SUCCESS) { if (rc != VK_SUCCESS) {
return SDL_SetError("[Vulkan] VULKAN_AllocateBuffer with result %s", SDL_Vulkan_GetResultString(result)); return false;
} }
/* Make note of where the staging texture will be written to /* Make note of where the staging texture will be written to
@@ -3334,7 +3386,7 @@ static VkDescriptorPool VULKAN_AllocateDescriptorPool(VULKAN_RenderData *rendere
descriptorPoolCreateInfo.maxSets = SDL_VULKAN_MAX_DESCRIPTOR_SETS; descriptorPoolCreateInfo.maxSets = SDL_VULKAN_MAX_DESCRIPTOR_SETS;
result = vkCreateDescriptorPool(rendererData->device, &descriptorPoolCreateInfo, NULL, &descriptorPool); result = vkCreateDescriptorPool(rendererData->device, &descriptorPoolCreateInfo, NULL, &descriptorPool);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_SetError("[Vulkan] Unable to allocate descriptor pool vkCreateDescrptorPool: %s", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateDescrptorPool()", result);
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
} }
@@ -3369,7 +3421,7 @@ static VkResult VULKAN_CreateDescriptorSetAndPipelineLayout(VULKAN_RenderData *r
descriptorSetLayoutCreateInfo.pBindings = layoutBindings; descriptorSetLayoutCreateInfo.pBindings = layoutBindings;
result = vkCreateDescriptorSetLayout(rendererData->device, &descriptorSetLayoutCreateInfo, NULL, descriptorSetLayoutOut); result = vkCreateDescriptorSetLayout(rendererData->device, &descriptorSetLayoutCreateInfo, NULL, descriptorSetLayoutOut);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateDescriptorSetLayout(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreateDescriptorSetLayout()", result);
return result; return result;
} }
@@ -3386,7 +3438,7 @@ static VkResult VULKAN_CreateDescriptorSetAndPipelineLayout(VULKAN_RenderData *r
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange; pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantRange;
result = vkCreatePipelineLayout(rendererData->device, &pipelineLayoutCreateInfo, NULL, pipelineLayoutOut); result = vkCreatePipelineLayout(rendererData->device, &pipelineLayoutCreateInfo, NULL, pipelineLayoutOut);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreatePipelineLayout(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkCreatePipelineLayout()", result);
return result; return result;
} }
@@ -3420,7 +3472,7 @@ static VkDescriptorSet VULKAN_AllocateDescriptorSet(SDL_Renderer *renderer, VULK
result = vkAllocateDescriptorSets(rendererData->device, &descriptorSetAllocateInfo, &descriptorSet); result = vkAllocateDescriptorSets(rendererData->device, &descriptorSetAllocateInfo, &descriptorSet);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
// This should not fail - we are allocating from the front of the descriptor set // This should not fail - we are allocating from the front of the descriptor set
SDL_SetError("[Vulkan] Unable to allocate descriptor set"); SDL_SetError("Unable to allocate descriptor set");
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
} }
rendererData->currentDescriptorPoolIndex = currentDescriptorPoolIndex; rendererData->currentDescriptorPoolIndex = currentDescriptorPoolIndex;
@@ -3536,7 +3588,7 @@ static bool VULKAN_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand
} }
if (!rendererData->currentPipelineState) { if (!rendererData->currentPipelineState) {
return SDL_SetError("[Vulkan] Unable to create required pipeline state"); return SDL_SetError("Unable to create required pipeline state");
} }
vkCmdBindPipeline(rendererData->currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, rendererData->currentPipelineState->pipeline); vkCmdBindPipeline(rendererData->currentCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, rendererData->currentPipelineState->pipeline);
@@ -3597,9 +3649,7 @@ static bool VULKAN_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&newConstantBuffer); &newConstantBuffer);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_SetError("[Vulkan] Could not allocate new memory for constant buffer" );
return false; return false;
} }
@@ -3722,6 +3772,10 @@ static bool VULKAN_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cm
VULKAN_DrawStateCache stateCache; VULKAN_DrawStateCache stateCache;
SDL_memset(&stateCache, 0, sizeof(stateCache)); SDL_memset(&stateCache, 0, sizeof(stateCache));
if (!rendererData->device) {
return SDL_SetError("Device lost and couldn't be recovered");
}
if (rendererData->recreateSwapchain) { if (rendererData->recreateSwapchain) {
if (VULKAN_UpdateForWindowSizeChange(renderer) != VK_SUCCESS) { if (VULKAN_UpdateForWindowSizeChange(renderer) != VK_SUCCESS) {
return false; return false;
@@ -3884,7 +3938,6 @@ static SDL_Surface* VULKAN_RenderReadPixels(SDL_Renderer *renderer, const SDL_Re
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&readbackBuffer) != VK_SUCCESS) { &readbackBuffer) != VK_SUCCESS) {
SDL_SetError("[Vulkan] Failed to allocate buffer for readback");
return NULL; return NULL;
} }
@@ -3987,8 +4040,12 @@ static bool VULKAN_RenderPresent(SDL_Renderer *renderer)
{ {
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal; VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
VkResult result = VK_SUCCESS; VkResult result = VK_SUCCESS;
if (rendererData->currentCommandBuffer) {
if (!rendererData->device) {
return SDL_SetError("Device lost and couldn't be recovered");
}
if (rendererData->currentCommandBuffer) {
rendererData->currentPipelineState = VK_NULL_HANDLE; rendererData->currentPipelineState = VK_NULL_HANDLE;
rendererData->viewportDirty = true; rendererData->viewportDirty = true;
@@ -4005,7 +4062,7 @@ static bool VULKAN_RenderPresent(SDL_Renderer *renderer)
result = vkResetFences(rendererData->device, 1, &rendererData->fences[rendererData->currentCommandBufferIndex]); result = vkResetFences(rendererData->device, 1, &rendererData->fences[rendererData->currentCommandBufferIndex]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkResetFences(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkResetFences()", result);
return false; return false;
} }
@@ -4040,13 +4097,20 @@ static bool VULKAN_RenderPresent(SDL_Renderer *renderer)
} }
result = vkQueueSubmit(rendererData->graphicsQueue, 1, &submitInfo, rendererData->fences[rendererData->currentCommandBufferIndex]); result = vkQueueSubmit(rendererData->graphicsQueue, 1, &submitInfo, rendererData->fences[rendererData->currentCommandBufferIndex]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkQueueSubmit(): %s\n", SDL_Vulkan_GetResultString(result)); if (result == VK_ERROR_DEVICE_LOST) {
if (VULKAN_HandleDeviceLost(renderer)) {
SDL_SetError("Present failed, device lost");
} else {
// Recovering from device lost failed, error is already set
}
} else {
SET_ERROR_CODE("vkQueueSubmit()", result);
}
return false; return false;
} }
rendererData->currentCommandBuffer = VK_NULL_HANDLE; rendererData->currentCommandBuffer = VK_NULL_HANDLE;
rendererData->currentImageAvailableSemaphore = VK_NULL_HANDLE; rendererData->currentImageAvailableSemaphore = VK_NULL_HANDLE;
VkPresentInfoKHR presentInfo = { 0 }; VkPresentInfoKHR presentInfo = { 0 };
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1; presentInfo.waitSemaphoreCount = 1;
@@ -4056,7 +4120,7 @@ static bool VULKAN_RenderPresent(SDL_Renderer *renderer)
presentInfo.pImageIndices = &rendererData->currentSwapchainImageIndex; presentInfo.pImageIndices = &rendererData->currentSwapchainImageIndex;
result = vkQueuePresentKHR(rendererData->presentQueue, &presentInfo); result = vkQueuePresentKHR(rendererData->presentQueue, &presentInfo);
if ((result != VK_SUCCESS) && (result != VK_ERROR_OUT_OF_DATE_KHR) && (result != VK_ERROR_SURFACE_LOST_KHR) && (result != VK_SUBOPTIMAL_KHR )) { if ((result != VK_SUCCESS) && (result != VK_ERROR_OUT_OF_DATE_KHR) && (result != VK_ERROR_SURFACE_LOST_KHR) && (result != VK_SUBOPTIMAL_KHR )) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkQueuePresentKHR(): %s\n", SDL_Vulkan_GetResultString(result)); SET_ERROR_CODE("vkQueuePresentKHR()", result);
return false; return false;
} }
@@ -4065,7 +4129,15 @@ static bool VULKAN_RenderPresent(SDL_Renderer *renderer)
// Wait for previous time this command buffer was submitted, will be N frames ago // Wait for previous time this command buffer was submitted, will be N frames ago
result = vkWaitForFences(rendererData->device, 1, &rendererData->fences[rendererData->currentCommandBufferIndex], VK_TRUE, UINT64_MAX); result = vkWaitForFences(rendererData->device, 1, &rendererData->fences[rendererData->currentCommandBufferIndex], VK_TRUE, UINT64_MAX);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkWaitForFences(): %s\n", SDL_Vulkan_GetResultString(result)); if (result == VK_ERROR_DEVICE_LOST) {
if (VULKAN_HandleDeviceLost(renderer)) {
SDL_SetError("Present failed, device lost");
} else {
// Recovering from device lost failed, error is already set
}
} else {
SET_ERROR_CODE("vkWaitForFences()", result);
}
return false; return false;
} }
@@ -4118,6 +4190,13 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD
rendererData->identitySwizzle.b = VK_COMPONENT_SWIZZLE_IDENTITY; rendererData->identitySwizzle.b = VK_COMPONENT_SWIZZLE_IDENTITY;
rendererData->identitySwizzle.a = VK_COMPONENT_SWIZZLE_IDENTITY; rendererData->identitySwizzle.a = VK_COMPONENT_SWIZZLE_IDENTITY;
// Save the create props in case we need to recreate on device lost
rendererData->create_props = SDL_CreateProperties();
if (!SDL_CopyProperties(create_props, rendererData->create_props)) {
SDL_free(rendererData);
return false;
}
renderer->WindowEvent = VULKAN_WindowEvent; renderer->WindowEvent = VULKAN_WindowEvent;
renderer->SupportsBlendMode = VULKAN_SupportsBlendMode; renderer->SupportsBlendMode = VULKAN_SupportsBlendMode;
renderer->CreateTexture = VULKAN_CreateTexture; renderer->CreateTexture = VULKAN_CreateTexture;
@@ -4161,7 +4240,9 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD
// Initialize Vulkan resources // Initialize Vulkan resources
if (VULKAN_CreateDeviceResources(renderer, create_props) != VK_SUCCESS) { if (VULKAN_CreateDeviceResources(renderer, create_props) != VK_SUCCESS) {
return false; return false;
} else if (VULKAN_CreateWindowSizeDependentResources(renderer) != VK_SUCCESS) { }
if (VULKAN_CreateWindowSizeDependentResources(renderer) != VK_SUCCESS) {
return false; return false;
} }

View File

@@ -1880,11 +1880,14 @@ void SDLTest_PrintEvent(const SDL_Event *event)
event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure); event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
break; break;
case SDL_EVENT_RENDER_TARGETS_RESET:
SDL_Log("SDL EVENT: render targets reset");
break;
case SDL_EVENT_RENDER_DEVICE_RESET: case SDL_EVENT_RENDER_DEVICE_RESET:
SDL_Log("SDL EVENT: render device reset"); SDL_Log("SDL EVENT: render device reset");
break; break;
case SDL_EVENT_RENDER_TARGETS_RESET: case SDL_EVENT_RENDER_DEVICE_LOST:
SDL_Log("SDL EVENT: render targets reset"); SDL_Log("SDL EVENT: render device lost");
break; break;
case SDL_EVENT_TERMINATING: case SDL_EVENT_TERMINATING: