|
|
@@ -641,6 +641,11 @@ struct VulkanTexture
|
|
|
VkImageAspectFlags aspectFlags;
|
|
|
Uint32 depth; // used for cleanup only
|
|
|
|
|
|
+ // used to avoid indirection on barriers
|
|
|
+ Uint32 levelCount;
|
|
|
+ Uint32 layerCount;
|
|
|
+ SDL_GPUTextureType type;
|
|
|
+
|
|
|
// FIXME: It'd be nice if we didn't have to have this on the texture...
|
|
|
SDL_GPUTextureUsageFlags usage; // used for defrag transitions only.
|
|
|
|
|
|
@@ -2723,12 +2728,16 @@ static void VULKAN_INTERNAL_BufferMemoryBarrier(
|
|
|
buffer->transitioned = true;
|
|
|
}
|
|
|
|
|
|
-static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
|
|
|
+static void VULKAN_INTERNAL_TextureMemoryBarrier(
|
|
|
VulkanRenderer *renderer,
|
|
|
VulkanCommandBuffer *commandBuffer,
|
|
|
VulkanTextureUsageMode sourceUsageMode,
|
|
|
VulkanTextureUsageMode destinationUsageMode,
|
|
|
- VulkanTextureSubresource *textureSubresource)
|
|
|
+ Uint32 baseLevel,
|
|
|
+ Uint32 levelCount,
|
|
|
+ Uint32 baseLayer,
|
|
|
+ Uint32 layerCount,
|
|
|
+ VulkanTexture *texture)
|
|
|
{
|
|
|
VkPipelineStageFlags srcStages = 0;
|
|
|
VkPipelineStageFlags dstStages = 0;
|
|
|
@@ -2742,21 +2751,12 @@ static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
|
|
|
memoryBarrier.newLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
- memoryBarrier.image = textureSubresource->parent->image;
|
|
|
- memoryBarrier.subresourceRange.aspectMask = textureSubresource->parent->aspectFlags;
|
|
|
- memoryBarrier.subresourceRange.baseMipLevel = textureSubresource->level;
|
|
|
- memoryBarrier.subresourceRange.levelCount = 1;
|
|
|
- memoryBarrier.subresourceRange.baseArrayLayer = textureSubresource->layer;
|
|
|
- memoryBarrier.subresourceRange.layerCount = 1;
|
|
|
-
|
|
|
- // VK_KHR_maintenance9 adds the ability to independently transition arbitrary subsets of slices in a 3D texture
|
|
|
- // but otherwise it is not necessarily supported by the driver.
|
|
|
- // As a workaround we have to transition the whole texture instead of just the subresource.
|
|
|
- // If VK_KHR_maintenance9 becomes widely supported, this can be removed.
|
|
|
- // See https://docs.vulkan.org/features/latest/features/proposals/VK_KHR_maintenance9.html#_barriers_with_2d_array_compatible_3d_images
|
|
|
- if (textureSubresource->parent->container->header.info.type == SDL_GPU_TEXTURETYPE_3D) {
|
|
|
- memoryBarrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
|
|
- }
|
|
|
+ memoryBarrier.image = texture->image;
|
|
|
+ memoryBarrier.subresourceRange.aspectMask = texture->aspectFlags;
|
|
|
+ memoryBarrier.subresourceRange.baseMipLevel = baseLevel;
|
|
|
+ memoryBarrier.subresourceRange.levelCount = levelCount;
|
|
|
+ memoryBarrier.subresourceRange.baseArrayLayer = baseLayer;
|
|
|
+ memoryBarrier.subresourceRange.layerCount = layerCount;
|
|
|
|
|
|
if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED) {
|
|
|
srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
|
@@ -2853,6 +2853,56 @@ static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
|
|
|
&memoryBarrier);
|
|
|
}
|
|
|
|
|
|
+// Transitions the entire texture with a single barrier call.
|
|
|
+static void VULKAN_INTERNAL_FullTextureMemoryBarrier(
|
|
|
+ VulkanRenderer *renderer,
|
|
|
+ VulkanCommandBuffer *commandBuffer,
|
|
|
+ VulkanTextureUsageMode sourceUsageMode,
|
|
|
+ VulkanTextureUsageMode destinationUsageMode,
|
|
|
+ VulkanTexture *texture)
|
|
|
+{
|
|
|
+ VULKAN_INTERNAL_TextureMemoryBarrier(
|
|
|
+ renderer,
|
|
|
+ commandBuffer,
|
|
|
+ sourceUsageMode,
|
|
|
+ destinationUsageMode,
|
|
|
+ 0,
|
|
|
+ texture->levelCount,
|
|
|
+ 0,
|
|
|
+ texture->layerCount,
|
|
|
+ texture);
|
|
|
+}
|
|
|
+
|
|
|
+static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
|
|
|
+ VulkanRenderer *renderer,
|
|
|
+ VulkanCommandBuffer *commandBuffer,
|
|
|
+ VulkanTextureUsageMode sourceUsageMode,
|
|
|
+ VulkanTextureUsageMode destinationUsageMode,
|
|
|
+ VulkanTextureSubresource *textureSubresource)
|
|
|
+{
|
|
|
+ Uint32 layerCount = 1;
|
|
|
+
|
|
|
+ // VK_KHR_maintenance9 adds the ability to independently transition arbitrary subsets of slices in a 3D texture
|
|
|
+ // but otherwise it is not necessarily supported by the driver.
|
|
|
+ // As a workaround we have to transition the whole texture instead of just the subresource.
|
|
|
+ // If VK_KHR_maintenance9 becomes widely supported, this can be removed.
|
|
|
+ // See https://docs.vulkan.org/features/latest/features/proposals/VK_KHR_maintenance9.html#_barriers_with_2d_array_compatible_3d_images
|
|
|
+ if (textureSubresource->parent->type == SDL_GPU_TEXTURETYPE_3D) {
|
|
|
+ layerCount = VK_REMAINING_ARRAY_LAYERS;
|
|
|
+ }
|
|
|
+
|
|
|
+ VULKAN_INTERNAL_TextureMemoryBarrier(
|
|
|
+ renderer,
|
|
|
+ commandBuffer,
|
|
|
+ sourceUsageMode,
|
|
|
+ destinationUsageMode,
|
|
|
+ textureSubresource->level,
|
|
|
+ 1,
|
|
|
+ textureSubresource->layer,
|
|
|
+ layerCount,
|
|
|
+ textureSubresource->parent);
|
|
|
+}
|
|
|
+
|
|
|
static VulkanBufferUsageMode VULKAN_INTERNAL_DefaultBufferUsageMode(
|
|
|
VulkanBuffer *buffer)
|
|
|
{
|
|
|
@@ -2950,13 +3000,12 @@ static void VULKAN_INTERNAL_TextureTransitionFromDefaultUsage(
|
|
|
VulkanTextureUsageMode destinationUsageMode,
|
|
|
VulkanTexture *texture)
|
|
|
{
|
|
|
- for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
|
|
|
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
|
|
|
- renderer,
|
|
|
- commandBuffer,
|
|
|
- destinationUsageMode,
|
|
|
- &texture->subresources[i]);
|
|
|
- }
|
|
|
+ VULKAN_INTERNAL_FullTextureMemoryBarrier(
|
|
|
+ renderer,
|
|
|
+ commandBuffer,
|
|
|
+ VULKAN_INTERNAL_DefaultTextureUsageMode(texture),
|
|
|
+ destinationUsageMode,
|
|
|
+ texture);
|
|
|
}
|
|
|
|
|
|
static void VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
|
|
|
@@ -2979,14 +3028,12 @@ static void VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
|
|
|
VulkanTextureUsageMode sourceUsageMode,
|
|
|
VulkanTexture *texture)
|
|
|
{
|
|
|
- // FIXME: could optimize this barrier
|
|
|
- for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
|
|
|
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
|
|
|
- renderer,
|
|
|
- commandBuffer,
|
|
|
- sourceUsageMode,
|
|
|
- &texture->subresources[i]);
|
|
|
- }
|
|
|
+ VULKAN_INTERNAL_FullTextureMemoryBarrier(
|
|
|
+ renderer,
|
|
|
+ commandBuffer,
|
|
|
+ sourceUsageMode,
|
|
|
+ VULKAN_INTERNAL_DefaultTextureUsageMode(texture),
|
|
|
+ texture);
|
|
|
}
|
|
|
|
|
|
// Resource Disposal
|
|
|
@@ -5738,6 +5785,9 @@ static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
|
|
|
texture->swizzle = SwizzleForSDLFormat(createinfo->format);
|
|
|
texture->depth = depth;
|
|
|
texture->usage = createinfo->usage;
|
|
|
+ texture->levelCount = createinfo->num_levels;
|
|
|
+ texture->layerCount = (createinfo->type == SDL_GPU_TEXTURETYPE_3D) ? 1 : createinfo->layer_count_or_depth;
|
|
|
+ texture->type = createinfo->type;
|
|
|
SDL_SetAtomicInt(&texture->referenceCount, 0);
|
|
|
|
|
|
if (IsDepthFormat(createinfo->format)) {
|
|
|
@@ -6959,7 +7009,9 @@ static SDL_GPUTexture *VULKAN_CreateTexture(
|
|
|
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;
|
|
|
@@ -8402,7 +8454,6 @@ static void VULKAN_BindComputeStorageTextures(
|
|
|
VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
|
|
|
textureContainer->activeTexture);
|
|
|
|
|
|
-
|
|
|
VULKAN_INTERNAL_TrackTexture(
|
|
|
vulkanCommandBuffer,
|
|
|
textureContainer->activeTexture);
|
|
|
@@ -11119,24 +11170,26 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|
|
}
|
|
|
|
|
|
SDL_GPUTextureCreateInfo info = currentRegion->vulkanTexture->container->header.info;
|
|
|
+
|
|
|
+ VULKAN_INTERNAL_TextureTransitionFromDefaultUsage(
|
|
|
+ renderer,
|
|
|
+ commandBuffer,
|
|
|
+ VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
|
|
|
+ currentRegion->vulkanTexture);
|
|
|
+
|
|
|
+ VULKAN_INTERNAL_FullTextureMemoryBarrier(
|
|
|
+ renderer,
|
|
|
+ commandBuffer,
|
|
|
+ VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
|
|
|
+ VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
|
|
|
+ newTexture
|
|
|
+ );
|
|
|
+
|
|
|
+ // Can only copy one mip level at a time
|
|
|
for (Uint32 subresourceIndex = 0; subresourceIndex < currentRegion->vulkanTexture->subresourceCount; subresourceIndex += 1) {
|
|
|
- // copy subresource if necessary
|
|
|
VulkanTextureSubresource *srcSubresource = ¤tRegion->vulkanTexture->subresources[subresourceIndex];
|
|
|
VulkanTextureSubresource *dstSubresource = &newTexture->subresources[subresourceIndex];
|
|
|
|
|
|
- VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
|
|
|
- renderer,
|
|
|
- commandBuffer,
|
|
|
- VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
|
|
|
- srcSubresource);
|
|
|
-
|
|
|
- VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
|
|
|
- renderer,
|
|
|
- commandBuffer,
|
|
|
- VULKAN_TEXTURE_USAGE_MODE_UNINITIALIZED,
|
|
|
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
|
|
|
- dstSubresource);
|
|
|
-
|
|
|
VkImageCopy imageCopy;
|
|
|
imageCopy.srcOffset.x = 0;
|
|
|
imageCopy.srcOffset.y = 0;
|
|
|
@@ -11165,16 +11218,16 @@ static bool VULKAN_INTERNAL_DefragmentMemory(
|
|
|
1,
|
|
|
&imageCopy);
|
|
|
|
|
|
- VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
|
|
|
- renderer,
|
|
|
- commandBuffer,
|
|
|
- VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
|
|
|
- dstSubresource);
|
|
|
-
|
|
|
VULKAN_INTERNAL_TrackTexture(commandBuffer, srcSubresource->parent);
|
|
|
VULKAN_INTERNAL_TrackTexture(commandBuffer, dstSubresource->parent);
|
|
|
}
|
|
|
|
|
|
+ VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
|
|
|
+ renderer,
|
|
|
+ commandBuffer,
|
|
|
+ VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
|
|
|
+ newTexture);
|
|
|
+
|
|
|
// re-point original container to new texture
|
|
|
newTexture->container = currentRegion->vulkanTexture->container;
|
|
|
newTexture->containerIndex = currentRegion->vulkanTexture->containerIndex;
|