Fixed pitch and chroma issues with the Vulkan planar YUV texture update functions
Build (All) / Create test plan (push) Has been cancelled
Build (All) / level1 (push) Has been cancelled
Build (All) / level2 (push) Has been cancelled

Fixes https://github.com/libsdl-org/SDL/issues/13734

(cherry picked from commit 466f93aee1)
This commit is contained in:
Sam Lantinga
2025-09-07 10:00:55 -07:00
parent 414ae344af
commit ad2b211f75
+19 -6
View File
@@ -421,7 +421,7 @@ static int VULKAN_VkFormatGetNumPlanes(VkFormat vkFormat)
} }
} }
static VkDeviceSize VULKAN_GetBytesPerPixel(VkFormat vkFormat) static VkDeviceSize VULKAN_GetBytesPerPixel(VkFormat vkFormat, int plane)
{ {
switch (vkFormat) { switch (vkFormat) {
case VK_FORMAT_R8_UNORM: case VK_FORMAT_R8_UNORM:
@@ -436,6 +436,10 @@ static VkDeviceSize VULKAN_GetBytesPerPixel(VkFormat vkFormat)
return 4; return 4;
case VK_FORMAT_R16G16B16A16_SFLOAT: case VK_FORMAT_R16G16B16A16_SFLOAT:
return 8; return 8;
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
return 1;
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
return (plane == 0) ? 1 : 2;
default: default:
return 4; return 4;
} }
@@ -2811,7 +2815,7 @@ static void VULKAN_DestroyTexture(SDL_Renderer *renderer,
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) 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)
{ {
VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(format); VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(format, plane);
VkDeviceSize length = w * pixelSize; VkDeviceSize length = w * pixelSize;
VkDeviceSize uploadBufferSize = length * h; VkDeviceSize uploadBufferSize = length * h;
const Uint8 *src; const Uint8 *src;
@@ -2964,12 +2968,21 @@ static bool VULKAN_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainImage.imageLayout)) { if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainImage.imageLayout)) {
return false; return false;
} }
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 1, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Uplane, Upitch, &textureData->mainImage.imageLayout)) { if (texture->format == SDL_PIXELFORMAT_YV12) {
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 1, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch, &textureData->mainImage.imageLayout)) {
return false; return false;
} }
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 2, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, Vplane, Vpitch, &textureData->mainImage.imageLayout)) { if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 2, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch, &textureData->mainImage.imageLayout)) {
return false; return false;
} }
} else {
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 1, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch, &textureData->mainImage.imageLayout)) {
return false;
}
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 2, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch, &textureData->mainImage.imageLayout)) {
return false;
}
}
return true; return true;
} }
@@ -3010,7 +3023,7 @@ static bool VULKAN_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
return SDL_SetError("texture is already locked"); return SDL_SetError("texture is already locked");
} }
VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(textureData->mainImage.format); VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(textureData->mainImage.format, 0);
VkDeviceSize length = rect->w * pixelSize; VkDeviceSize length = rect->w * pixelSize;
VkDeviceSize stagingBufferSize = length * rect->h; VkDeviceSize stagingBufferSize = length * rect->h;
rc = VULKAN_AllocateBuffer(rendererData, rc = VULKAN_AllocateBuffer(rendererData,
@@ -3999,7 +4012,7 @@ static SDL_Surface* VULKAN_RenderReadPixels(SDL_Renderer *renderer, const SDL_Re
vkFormat = rendererData->surfaceFormat.format; vkFormat = rendererData->surfaceFormat.format;
} }
pixelSize = VULKAN_GetBytesPerPixel(vkFormat); pixelSize = VULKAN_GetBytesPerPixel(vkFormat, 0);
length = rect->w * pixelSize; length = rect->w * pixelSize;
readbackBufferSize = length * rect->h; readbackBufferSize = length * rect->h;
if (VULKAN_AllocateBuffer(rendererData, readbackBufferSize, if (VULKAN_AllocateBuffer(rendererData, readbackBufferSize,