texture usage for auto layout transition

submit_rewrite
cosmonaut 2020-12-28 13:40:26 -08:00
parent 941cce595c
commit a92a03a69a
4 changed files with 222 additions and 106 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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)

View File

@ -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,
&currentTexture->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,
&currentTexture->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,
&currentTexture->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;
}