diff --git a/src/render/vulkan/SDL_render_vulkan.c b/src/render/vulkan/SDL_render_vulkan.c index ec2dd4a16c..c20eecd8e6 100644 --- a/src/render/vulkan/SDL_render_vulkan.c +++ b/src/render/vulkan/SDL_render_vulkan.c @@ -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);