Support 16-bit packed texture formats with the Vulkan renderer

This commit is contained in:
Cameron Cawley
2026-01-18 22:21:35 +00:00
committed by Sam Lantinga
parent d4d66e77cc
commit 07be29b625

View File

@@ -134,6 +134,7 @@
VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices) \
VULKAN_INSTANCE_FUNCTION(vkGetDeviceProcAddr) \
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures) \
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties) \
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties) \
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties) \
VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties) \
@@ -144,7 +145,6 @@
VULKAN_INSTANCE_FUNCTION(vkQueueWaitIdle) \
VULKAN_OPTIONAL_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2KHR) \
VULKAN_OPTIONAL_INSTANCE_FUNCTION(vkGetPhysicalDeviceFormatProperties2KHR) \
VULKAN_OPTIONAL_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties2KHR) \
VULKAN_OPTIONAL_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties2KHR) \
VULKAN_OPTIONAL_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2KHR) \
VULKAN_OPTIONAL_DEVICE_FUNCTION(vkCreateSamplerYcbcrConversionKHR) \
@@ -392,22 +392,40 @@ typedef struct
static bool VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, VkImage image, VkFormat format, int plane, int x, int y, int w, int h, const void *pixels, int pitch, VkImageLayout *imageLayout);
// TODO: Sort this list based on what the Vulkan driver prefers?
static const struct
{
SDL_PixelFormat sdl;
VkFormat unorm;
VkFormat srgb;
} vk_format_map[] = {
{ SDL_PIXELFORMAT_BGRA32, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_SRGB }, // SDL_PIXELFORMAT_ARGB8888 on little endian systems
{ SDL_PIXELFORMAT_RGBA32, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SRGB },
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
{ SDL_PIXELFORMAT_ABGR8888, VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_FORMAT_A8B8G8R8_SRGB_PACK32 },
#endif
{ SDL_PIXELFORMAT_ABGR2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
{ SDL_PIXELFORMAT_RGBA64_FLOAT, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R16G16B16A16_SFLOAT },
{ SDL_PIXELFORMAT_RGB565, VK_FORMAT_R5G6B5_UNORM_PACK16, VK_FORMAT_R5G6B5_UNORM_PACK16 },
{ SDL_PIXELFORMAT_BGR565, VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16 },
{ SDL_PIXELFORMAT_RGBA5551, VK_FORMAT_R5G5B5A1_UNORM_PACK16, VK_FORMAT_R5G5B5A1_UNORM_PACK16 },
{ SDL_PIXELFORMAT_BGRA5551, VK_FORMAT_B5G5R5A1_UNORM_PACK16, VK_FORMAT_B5G5R5A1_UNORM_PACK16 },
{ SDL_PIXELFORMAT_ARGB1555, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_A1R5G5B5_UNORM_PACK16 },
{ SDL_PIXELFORMAT_RGBA4444, VK_FORMAT_R4G4B4A4_UNORM_PACK16, VK_FORMAT_R4G4B4A4_UNORM_PACK16 },
{ SDL_PIXELFORMAT_BGRA4444, VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_B4G4R4A4_UNORM_PACK16 },
{ SDL_PIXELFORMAT_ARGB4444, VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT },
{ SDL_PIXELFORMAT_ABGR4444, VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT }
};
static SDL_PixelFormat VULKAN_VkFormatToSDLPixelFormat(VkFormat vkFormat)
{
switch (vkFormat) {
case VK_FORMAT_R8G8B8A8_UNORM:
return SDL_PIXELFORMAT_RGBA32;
case VK_FORMAT_B8G8R8A8_UNORM:
return SDL_PIXELFORMAT_BGRA32;
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
return SDL_PIXELFORMAT_ABGR8888;
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
return SDL_PIXELFORMAT_ABGR2101010;
case VK_FORMAT_R16G16B16A16_SFLOAT:
return SDL_PIXELFORMAT_RGBA64_FLOAT;
default:
return SDL_PIXELFORMAT_UNKNOWN;
for (int i = 0; i < SDL_arraysize(vk_format_map); i++) {
if (vk_format_map[i].unorm == vkFormat ||
vk_format_map[i].srgb == vkFormat) {
return vk_format_map[i].sdl;
}
}
return SDL_PIXELFORMAT_UNKNOWN;
}
static int VULKAN_VkFormatGetNumPlanes(VkFormat vkFormat)
@@ -432,16 +450,6 @@ static VkDeviceSize VULKAN_GetBytesPerPixel(VkFormat vkFormat, int plane)
return 2;
case VK_FORMAT_R16G16_UNORM:
return 4;
case VK_FORMAT_R8G8B8A8_SRGB:
case VK_FORMAT_R8G8B8A8_UNORM:
case VK_FORMAT_B8G8R8A8_SRGB:
case VK_FORMAT_B8G8R8A8_UNORM:
case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
return 4;
case VK_FORMAT_R16G16B16A16_SFLOAT:
return 8;
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
return 1;
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
@@ -449,34 +457,13 @@ static VkDeviceSize VULKAN_GetBytesPerPixel(VkFormat vkFormat, int plane)
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
return (plane == 0) ? 2 : 4;
default:
return 4;
return SDL_BYTESPERPIXEL(VULKAN_VkFormatToSDLPixelFormat(vkFormat));
}
}
static VkFormat SDLPixelFormatToVkTextureFormat(Uint32 format, Uint32 output_colorspace)
static VkFormat SDLPixelFormatToVkTextureFormat(SDL_PixelFormat format, Uint32 output_colorspace)
{
switch (format) {
case SDL_PIXELFORMAT_RGBA64_FLOAT:
return VK_FORMAT_R16G16B16A16_SFLOAT;
case SDL_PIXELFORMAT_ABGR2101010:
return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
case SDL_PIXELFORMAT_RGBA32:
if (output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
return VK_FORMAT_R8G8B8A8_SRGB;
}
return VK_FORMAT_R8G8B8A8_UNORM;
case SDL_PIXELFORMAT_BGRA32:
if (output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
return VK_FORMAT_B8G8R8A8_SRGB;
}
return VK_FORMAT_B8G8R8A8_UNORM;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
case SDL_PIXELFORMAT_ABGR8888:
if (output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
return VK_FORMAT_A8B8G8R8_SRGB_PACK32;
}
return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
#endif
case SDL_PIXELFORMAT_INDEX8:
return VK_FORMAT_R8_UNORM;
case SDL_PIXELFORMAT_YUY2:
@@ -492,6 +479,15 @@ static VkFormat SDLPixelFormatToVkTextureFormat(Uint32 format, Uint32 output_col
case SDL_PIXELFORMAT_P010:
return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
default:
for (int i = 0; i < SDL_arraysize(vk_format_map); i++) {
if (vk_format_map[i].sdl == format) {
if (output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
return vk_format_map[i].srgb;
} else {
return vk_format_map[i].unorm;
}
}
}
return VK_FORMAT_UNDEFINED;
}
}
@@ -4580,14 +4576,6 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD
VULKAN_InvalidateCachedState(renderer);
renderer->name = VULKAN_RenderDriver.name;
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA32); // SDL_PIXELFORMAT_ARGB8888 on little endian systems
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA32);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888);
#endif
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR2101010);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA64_FLOAT);
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 16384);
/* HACK: make sure the SDL_Renderer references the SDL_Window data now, in
@@ -4604,6 +4592,34 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD
return false;
}
for (int i = 0; i < SDL_arraysize(vk_format_map); i++) {
VkImageFormatProperties properties;
if (vkGetPhysicalDeviceImageFormatProperties(rendererData->physicalDevice,
vk_format_map[i].unorm,
VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT,
0,
&properties) != VK_SUCCESS) {
continue;
}
if (vkGetPhysicalDeviceImageFormatProperties(rendererData->physicalDevice,
vk_format_map[i].srgb,
VK_IMAGE_TYPE_2D,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT,
0,
&properties) != VK_SUCCESS) {
continue;
}
SDL_AddSupportedTextureFormat(renderer, vk_format_map[i].sdl);
}
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
#ifdef SDL_HAVE_YUV
if (rendererData->supportsKHRSamplerYCbCrConversion) {
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);