From 06bf8d1924c982c7cb750dd8eea40e4482a7c0ac Mon Sep 17 00:00:00 2001 From: William Horvath Date: Fri, 13 Feb 2026 09:17:13 -0800 Subject: [PATCH] gpu_vulkan: Set texture container before transitioning to default barrier state. Avoids a null dereference of currentRegion->vulkanTexture->container in DefragmentMemory: } else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) { ... ¤tRegion->vulkanTexture->container->header.info ... (among others) by not "VULKAN_Submit"ting (and thus adding it to the defrag pool) before setting the container. Although rare (defrag almost never ran), this crash happened in a real-world application. --- src/gpu/vulkan/SDL_gpu_vulkan.c | 37 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c index 5cb0dbdc2f..f1fe1f3ac1 100644 --- a/src/gpu/vulkan/SDL_gpu_vulkan.c +++ b/src/gpu/vulkan/SDL_gpu_vulkan.c @@ -1269,6 +1269,7 @@ struct VulkanRenderer static bool VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer); static bool VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer); +static void VULKAN_ReleaseTexture(SDL_GPURenderer *driverData, SDL_GPUTexture *texture); static void VULKAN_ReleaseWindow(SDL_GPURenderer *driverData, SDL_Window *window); static bool VULKAN_Wait(SDL_GPURenderer *driverData); static bool VULKAN_WaitForFences(SDL_GPURenderer *driverData, bool waitAll, SDL_GPUFence *const *fences, Uint32 numFences); @@ -5654,7 +5655,6 @@ static void VULKAN_PopDebugGroup( static VulkanTexture *VULKAN_INTERNAL_CreateTexture( VulkanRenderer *renderer, - bool transitionToDefaultLayout, const SDL_GPUTextureCreateInfo *createinfo) { VkResult vulkanResult; @@ -5882,21 +5882,6 @@ static VulkanTexture *VULKAN_INTERNAL_CreateTexture( &nameInfo); } - if (transitionToDefaultLayout) { - // Let's transition to the default barrier state, because for some reason Vulkan doesn't let us do that with initialLayout. - VulkanCommandBuffer *barrierCommandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer); - VULKAN_INTERNAL_TextureTransitionToDefaultUsage( - renderer, - barrierCommandBuffer, - VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED, - texture); - VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture); - if (!VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer)) { - VULKAN_INTERNAL_DestroyTexture(renderer, texture); - return NULL; - } - } - return texture; } @@ -5963,7 +5948,6 @@ static void VULKAN_INTERNAL_CycleActiveTexture( // No texture is available, generate a new one. texture = VULKAN_INTERNAL_CreateTexture( renderer, - false, &container->header.info); VULKAN_INTERNAL_TextureTransitionToDefaultUsage( @@ -6865,7 +6849,6 @@ static SDL_GPUTexture *VULKAN_CreateTexture( texture = VULKAN_INTERNAL_CreateTexture( renderer, - true, createinfo); if (texture == NULL) { @@ -6897,6 +6880,23 @@ static SDL_GPUTexture *VULKAN_CreateTexture( texture->container = container; texture->containerIndex = 0; + // Let's transition to the default barrier state, because for some reason Vulkan doesn't let us do that with initialLayout. + // Only do this after "container" is set, so the texture + // is fully initialized before any Submit that could trigger defrag. + { + VulkanCommandBuffer *barrierCommandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GPURenderer *)renderer); + VULKAN_INTERNAL_TextureTransitionToDefaultUsage( + renderer, + barrierCommandBuffer, + VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED, + texture); + VULKAN_INTERNAL_TrackTexture(barrierCommandBuffer, texture); + if (!VULKAN_Submit((SDL_GPUCommandBuffer *)barrierCommandBuffer)) { + VULKAN_ReleaseTexture((SDL_GPURenderer *)renderer, (SDL_GPUTexture *)container); + return NULL; + } + } + return (SDL_GPUTexture *)container; } @@ -10950,7 +10950,6 @@ static bool VULKAN_INTERNAL_DefragmentMemory( } else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) { VulkanTexture *newTexture = VULKAN_INTERNAL_CreateTexture( renderer, - false, ¤tRegion->vulkanTexture->container->header.info); if (newTexture == NULL) {