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.
This commit is contained in:
committed by
Sam Lantinga
parent
129627068f
commit
06bf8d1924
@@ -1269,6 +1269,7 @@ struct VulkanRenderer
|
|||||||
|
|
||||||
static bool VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
|
static bool VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
|
||||||
static bool VULKAN_INTERNAL_BeginCommandBuffer(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 void VULKAN_ReleaseWindow(SDL_GPURenderer *driverData, SDL_Window *window);
|
||||||
static bool VULKAN_Wait(SDL_GPURenderer *driverData);
|
static bool VULKAN_Wait(SDL_GPURenderer *driverData);
|
||||||
static bool VULKAN_WaitForFences(SDL_GPURenderer *driverData, bool waitAll, SDL_GPUFence *const *fences, Uint32 numFences);
|
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(
|
static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
|
||||||
VulkanRenderer *renderer,
|
VulkanRenderer *renderer,
|
||||||
bool transitionToDefaultLayout,
|
|
||||||
const SDL_GPUTextureCreateInfo *createinfo)
|
const SDL_GPUTextureCreateInfo *createinfo)
|
||||||
{
|
{
|
||||||
VkResult vulkanResult;
|
VkResult vulkanResult;
|
||||||
@@ -5882,21 +5882,6 @@ static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
|
|||||||
&nameInfo);
|
&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;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5963,7 +5948,6 @@ static void VULKAN_INTERNAL_CycleActiveTexture(
|
|||||||
// No texture is available, generate a new one.
|
// No texture is available, generate a new one.
|
||||||
texture = VULKAN_INTERNAL_CreateTexture(
|
texture = VULKAN_INTERNAL_CreateTexture(
|
||||||
renderer,
|
renderer,
|
||||||
false,
|
|
||||||
&container->header.info);
|
&container->header.info);
|
||||||
|
|
||||||
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
|
VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
|
||||||
@@ -6865,7 +6849,6 @@ static SDL_GPUTexture *VULKAN_CreateTexture(
|
|||||||
|
|
||||||
texture = VULKAN_INTERNAL_CreateTexture(
|
texture = VULKAN_INTERNAL_CreateTexture(
|
||||||
renderer,
|
renderer,
|
||||||
true,
|
|
||||||
createinfo);
|
createinfo);
|
||||||
|
|
||||||
if (texture == NULL) {
|
if (texture == NULL) {
|
||||||
@@ -6897,6 +6880,23 @@ static SDL_GPUTexture *VULKAN_CreateTexture(
|
|||||||
texture->container = container;
|
texture->container = container;
|
||||||
texture->containerIndex = 0;
|
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;
|
return (SDL_GPUTexture *)container;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10950,7 +10950,6 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|||||||
} else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) {
|
} else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) {
|
||||||
VulkanTexture *newTexture = VULKAN_INTERNAL_CreateTexture(
|
VulkanTexture *newTexture = VULKAN_INTERNAL_CreateTexture(
|
||||||
renderer,
|
renderer,
|
||||||
false,
|
|
||||||
¤tRegion->vulkanTexture->container->header.info);
|
¤tRegion->vulkanTexture->container->header.info);
|
||||||
|
|
||||||
if (newTexture == NULL) {
|
if (newTexture == NULL) {
|
||||||
|
|||||||
Reference in New Issue
Block a user