diff --git a/include/Refresh.h b/include/Refresh.h index eda971e..a07fbc7 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -141,15 +141,14 @@ typedef enum REFRESH_DepthFormat REFRESH_DEPTHFORMAT_D32_SFLOAT_S8_UINT } REFRESH_DepthFormat; -typedef enum REFRESH_TextureLayout +typedef enum REFRESH_TextureUsageFlagBits { - REFRESH_TEXTURELAYOUT_READ, - REFRESH_TEXTURELAYOUT_COLOR_TARGET, - REFRESH_TEXTURELAYOUT_DEPTHSTENCIL_TARGET, - REFRESH_TEXTURELAYOUT_VERTEX_SAMPLER, - REFRESH_TEXTURELAYOUT_FRAGMENT_SAMPLER, - REFRESH_TEXTURELAYOUT_WRITE -} REFRESH_TextureLayout; + REFRESH_TEXTUREUSAGE_VERTEX_SAMPLER_BIT = 0x00000001, + REFRESH_TEXTUREUSAGE_FRAGMENT_SAMPLER_BIT = 0x00000002, + REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT = 0x00000004 +} REFRESH_TextureUsageFlagBits; + +typedef uint32_t REFRESH_TextureUsageFlags; typedef enum REFRESH_SampleCount { @@ -733,8 +732,9 @@ REFRESHAPI REFRESH_ShaderModule* REFRESH_CreateShaderModule( * format: The pixel format of the texture data. * width: The width of the texture image. * height: The height of the texture image. - * levelCount: The number of mipmap levels to allocate. - * + * levelCount: The number of mipmap levels to allocate. + * usageFlags: Specifies how the texture will be used. + * * Returns an allocated REFRESH_Texture* object. Note that the contents of * the texture are undefined until SetData is called. */ @@ -744,7 +744,7 @@ REFRESHAPI REFRESH_Texture* REFRESH_CreateTexture2D( uint32_t width, uint32_t height, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ); /* Creates a 3D texture. @@ -754,6 +754,7 @@ REFRESHAPI REFRESH_Texture* REFRESH_CreateTexture2D( * height: The height of the texture image. * depth: The depth of the texture image. * levelCount: The number of mipmap levels to allocate. + * usageFlags: Specifies how the texture will be used. * * Returns an allocated REFRESH_Texture* object. Note that the contents of * the texture are undefined until SetData is called. @@ -765,7 +766,7 @@ REFRESHAPI REFRESH_Texture* REFRESH_CreateTexture3D( uint32_t height, uint32_t depth, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ); /* Creates a texture cube. @@ -773,7 +774,8 @@ REFRESHAPI REFRESH_Texture* REFRESH_CreateTexture3D( * format: The pixel format of the texture data. * size: The length of the cube side. * levelCount: The number of mipmap levels to allocate. - * + * usageFlags: Specifies how the texture will be used. + * * Returns an allocated REFRESH_Texture* object. Note that the contents of * the texture are undefined until SetData is called. */ @@ -782,7 +784,7 @@ REFRESHAPI REFRESH_Texture* REFRESH_CreateTextureCube( REFRESH_SurfaceFormat format, uint32_t size, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ); /* Creates a color target. @@ -1263,24 +1265,6 @@ REFRESHAPI void REFRESH_BindIndexBuffer( REFRESH_IndexElementSize indexElementSize ); -/* Transitions */ - -/* Performs a texture layout transition. - * Texture layouts must be transitioned for different texture use cases. - * - * NOTE: It is an error to perform a layout transition in a render pass. - * - * layout: The layout to transition to. - * pTextures: A pointer to an array of textures to transition. - * textureCount: The number of textures in the array to transition. - */ -REFRESHAPI void REFRESH_TextureLayoutTransition( - REFRESH_Device *device, - REFRESH_TextureLayout layout, - REFRESH_Texture **pTextures, - uint32_t textureCount -); - /* Submission/Presentation */ /* Queues an image to be presented to the screen. diff --git a/src/Refresh.c b/src/Refresh.c index a37e848..a361238 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -281,7 +281,7 @@ REFRESH_Texture* REFRESH_CreateTexture2D( uint32_t width, uint32_t height, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ) { NULL_RETURN_NULL(device); return device->CreateTexture2D( @@ -290,7 +290,7 @@ REFRESH_Texture* REFRESH_CreateTexture2D( width, height, levelCount, - canBeRenderTarget + usageFlags ); } @@ -301,7 +301,7 @@ REFRESH_Texture* REFRESH_CreateTexture3D( uint32_t height, uint32_t depth, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ) { NULL_RETURN_NULL(device); return device->CreateTexture3D( @@ -311,7 +311,7 @@ REFRESH_Texture* REFRESH_CreateTexture3D( height, depth, levelCount, - canBeRenderTarget + usageFlags ); } @@ -320,7 +320,7 @@ REFRESH_Texture* REFRESH_CreateTextureCube( REFRESH_SurfaceFormat format, uint32_t size, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ) { NULL_RETURN_NULL(device); return device->CreateTextureCube( @@ -328,7 +328,7 @@ REFRESH_Texture* REFRESH_CreateTextureCube( format, size, levelCount, - canBeRenderTarget + usageFlags ); } @@ -811,21 +811,6 @@ void REFRESH_BindIndexBuffer( ); } -void REFRESH_TextureLayoutTransition( - REFRESH_Device *device, - REFRESH_TextureLayout layout, - REFRESH_Texture **pTextures, - uint32_t textureCount -) { - NULL_RETURN(device); - device->TextureLayoutTransition( - device->driverData, - layout, - pTextures, - textureCount - ); -} - void REFRESH_QueuePresent( REFRESH_Device *device, REFRESH_TextureSlice* textureSlice, diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index e0a17b2..1dfb5a2 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -239,7 +239,7 @@ struct REFRESH_Device uint32_t width, uint32_t height, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ); REFRESH_Texture* (*CreateTexture3D)( @@ -249,7 +249,7 @@ struct REFRESH_Device uint32_t height, uint32_t depth, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ); REFRESH_Texture* (*CreateTextureCube)( @@ -257,7 +257,7 @@ struct REFRESH_Device REFRESH_SurfaceFormat format, uint32_t size, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ); REFRESH_ColorTarget* (*CreateColorTarget)( @@ -493,13 +493,6 @@ struct REFRESH_Device REFRESH_IndexElementSize indexElementSize ); - void (*TextureLayoutTransition)( - REFRESH_Renderer *driverData, - REFRESH_TextureLayout layout, - REFRESH_Texture **pTextures, - uint32_t textureCount - ); - void(*QueuePresent)( REFRESH_Renderer *driverData, REFRESH_TextureSlice *textureSlice, @@ -562,7 +555,6 @@ struct REFRESH_Device ASSIGN_DRIVER_FUNC(BindGraphicsPipeline, name) \ ASSIGN_DRIVER_FUNC(BindVertexBuffers, name) \ ASSIGN_DRIVER_FUNC(BindIndexBuffer, name) \ - ASSIGN_DRIVER_FUNC(TextureLayoutTransition, name) \ ASSIGN_DRIVER_FUNC(QueuePresent, name) \ ASSIGN_DRIVER_FUNC(Submit, name) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 8b1f615..f68d7a3 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -699,6 +699,7 @@ typedef struct VulkanTexture uint32_t levelCount; VkFormat format; VulkanResourceAccessType resourceAccessType; + REFRESH_TextureUsageFlags usageFlags; } VulkanTexture; typedef struct VulkanDepthStencilTexture @@ -1009,6 +1010,7 @@ typedef struct VulkanRenderer uint32_t numActiveCommands; VulkanGraphicsPipeline *currentGraphicsPipeline; + VulkanFramebuffer *currentFramebuffer; SamplerDescriptorSetLayoutHashTable samplerDescriptorSetLayoutHashTable; PipelineLayoutHashTable pipelineLayoutHashTable; @@ -3743,7 +3745,8 @@ static uint8_t VULKAN_INTERNAL_CreateTexture( VkImageAspectFlags aspectMask, VkImageTiling tiling, VkImageType imageType, - VkImageUsageFlags usage, + VkImageUsageFlags imageUsageFlags, + REFRESH_TextureUsageFlags textureUsageFlags, VulkanTexture *texture ) { VkResult vulkanResult; @@ -3755,6 +3758,13 @@ static uint8_t VULKAN_INTERNAL_CreateTexture( uint8_t layerCount = isCube ? 6 : 1; VkComponentMapping swizzle = IDENTITY_SWIZZLE; + if ((textureUsageFlags & REFRESH_TEXTUREUSAGE_VERTEX_SAMPLER_BIT) && + (textureUsageFlags & REFRESH_TEXTUREUSAGE_FRAGMENT_SAMPLER_BIT)) + { + REFRESH_LogError("Cannot use a texture for both vertex and fragment sampling."); + return 0; + } + if (isCube) { imageCreateFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; @@ -3776,7 +3786,7 @@ static uint8_t VULKAN_INTERNAL_CreateTexture( imageCreateInfo.arrayLayers = layerCount; imageCreateInfo.samples = samples; imageCreateInfo.tiling = tiling; - imageCreateInfo.usage = usage; + imageCreateInfo.usage = imageUsageFlags; // FIXME: would this interfere with pixel data sharing? imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageCreateInfo.queueFamilyIndexCount = 0; @@ -3876,6 +3886,7 @@ static uint8_t VULKAN_INTERNAL_CreateTexture( texture->levelCount = levelCount; texture->layerCount = layerCount; texture->resourceAccessType = RESOURCE_ACCESS_NONE; + texture->usageFlags = textureUsageFlags; return 1; } @@ -4009,19 +4020,19 @@ static REFRESH_Texture* VULKAN_CreateTexture2D( uint32_t width, uint32_t height, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanTexture *result; - uint32_t usageFlags = ( + VkImageUsageFlags imageUsageFlags = ( VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT ); - if (canBeRenderTarget) + if (usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT) { - usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; } result = (VulkanTexture*) SDL_malloc(sizeof(VulkanTexture)); @@ -4038,6 +4049,7 @@ static REFRESH_Texture* VULKAN_CreateTexture2D( VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_TYPE_2D, + imageUsageFlags, usageFlags, result ); @@ -4052,19 +4064,19 @@ static REFRESH_Texture* VULKAN_CreateTexture3D( uint32_t height, uint32_t depth, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanTexture *result; - uint32_t usageFlags = ( + VkImageUsageFlags imageUsageFlags = ( VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT ); - if (canBeRenderTarget) + if (usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT) { - usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; } result = (VulkanTexture*) SDL_malloc(sizeof(VulkanTexture)); @@ -4081,6 +4093,7 @@ static REFRESH_Texture* VULKAN_CreateTexture3D( VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_TYPE_3D, + imageUsageFlags, usageFlags, result ); @@ -4093,19 +4106,19 @@ static REFRESH_Texture* VULKAN_CreateTextureCube( REFRESH_SurfaceFormat format, uint32_t size, uint32_t levelCount, - uint8_t canBeRenderTarget + REFRESH_TextureUsageFlags usageFlags ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanTexture *result; - uint32_t usageFlags = ( + VkImageUsageFlags imageUsageFlags = ( VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT ); - if (canBeRenderTarget) + if (usageFlags & REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT) { - usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; } result = (VulkanTexture*) SDL_malloc(sizeof(VulkanTexture)); @@ -4122,6 +4135,7 @@ static REFRESH_Texture* VULKAN_CreateTextureCube( VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_TYPE_2D, + imageUsageFlags, usageFlags, result ); @@ -4164,6 +4178,7 @@ static REFRESH_ColorTarget* VULKAN_CreateColorTarget( VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_TYPE_2D, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + REFRESH_TEXTUREUSAGE_COLOR_TARGET_BIT, colorTarget->multisampleTexture ); colorTarget->multisampleCount = multisampleCount; @@ -4402,6 +4417,37 @@ static void VULKAN_SetTextureData2D( 1, &imageCopy )); + + if (vulkanTexture->usageFlags & REFRESH_TEXTUREUSAGE_VERTEX_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_VERTEX_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + } + else if (vulkanTexture->usageFlags & REFRESH_TEXTUREUSAGE_FRAGMENT_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_FRAGMENT_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + } } static void VULKAN_SetTextureData3D( @@ -4482,6 +4528,37 @@ static void VULKAN_SetTextureData3D( 1, &imageCopy )); + + if (vulkanTexture->usageFlags & REFRESH_TEXTUREUSAGE_VERTEX_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_VERTEX_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + } + else if (vulkanTexture->usageFlags & REFRESH_TEXTUREUSAGE_FRAGMENT_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_FRAGMENT_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + } } static void VULKAN_SetTextureDataCube( @@ -4561,6 +4638,37 @@ static void VULKAN_SetTextureDataCube( 1, &imageCopy )); + + if (vulkanTexture->usageFlags & REFRESH_TEXTUREUSAGE_VERTEX_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_VERTEX_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + } + else if (vulkanTexture->usageFlags & REFRESH_TEXTUREUSAGE_FRAGMENT_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_FRAGMENT_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + } } static void VULKAN_SetTextureDataYUV( @@ -4729,6 +4837,37 @@ static void VULKAN_SetTextureDataYUV( 1, &imageCopy )); + + if (tex->usageFlags & REFRESH_TEXTUREUSAGE_VERTEX_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_VERTEX_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + tex->layerCount, + 0, + tex->levelCount, + 0, + tex->image, + &tex->resourceAccessType + ); + } + else if (tex->usageFlags & REFRESH_TEXTUREUSAGE_FRAGMENT_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_FRAGMENT_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + tex->layerCount, + 0, + tex->levelCount, + 0, + tex->image, + &tex->resourceAccessType + ); + } } static void VULKAN_INTERNAL_SetBufferData( @@ -5312,19 +5451,59 @@ static void VULKAN_BeginRenderPass( VK_SUBPASS_CONTENTS_INLINE )); + renderer->currentFramebuffer = vulkanFramebuffer; + SDL_stack_free(clearValues); } static void VULKAN_EndRenderPass( REFRESH_Renderer *driverData ) { + uint32_t i; VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanTexture *currentTexture; RECORD_CMD(renderer->vkCmdEndRenderPass( renderer->currentCommandBuffer )); + for (i = 0; i < renderer->currentFramebuffer->colorTargetCount; i += 1) + { + currentTexture = renderer->currentFramebuffer->colorTargets[i]->texture; + if (currentTexture->usageFlags & REFRESH_TEXTUREUSAGE_VERTEX_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_VERTEX_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + currentTexture->layerCount, + 0, + currentTexture->levelCount, + 0, + currentTexture->image, + ¤tTexture->resourceAccessType + ); + } + else if (currentTexture->usageFlags & REFRESH_TEXTUREUSAGE_FRAGMENT_SAMPLER_BIT) + { + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + RESOURCE_ACCESS_FRAGMENT_SHADER_READ_SAMPLED_IMAGE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + currentTexture->layerCount, + 0, + currentTexture->levelCount, + 0, + currentTexture->image, + ¤tTexture->resourceAccessType + ); + } + } + renderer->currentGraphicsPipeline = NULL; + renderer->currentFramebuffer = NULL; } static void VULKAN_BindGraphicsPipeline( @@ -5428,34 +5607,6 @@ static void VULKAN_BindIndexBuffer( )); } -static void VULKAN_TextureLayoutTransition( - REFRESH_Renderer *driverData, - REFRESH_TextureLayout layout, - REFRESH_Texture **pTextures, - uint32_t textureCount -) { - uint32_t i; - VulkanTexture* currentTexture; - VulkanRenderer* renderer = (VulkanRenderer*) driverData; - - for (i = 0; i < textureCount; i += 1) - { - currentTexture = (VulkanTexture*) pTextures[i]; - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - RefreshToVK_ImageLayout[layout], - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - currentTexture->layerCount, - 0, - currentTexture->levelCount, - 0, - currentTexture->image, - ¤tTexture->resourceAccessType - ); - } -} - static void VULKAN_QueuePresent( REFRESH_Renderer* driverData, REFRESH_TextureSlice* textureSlice, @@ -7000,6 +7151,10 @@ static REFRESH_Device* VULKAN_CreateDevice( renderer->descriptorPools = NULL; renderer->descriptorPoolCount = 0; + /* State tracking */ + renderer->currentGraphicsPipeline = NULL; + renderer->currentFramebuffer = NULL; + return result; }