This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 56dbd4cd377bc6ac2a59a9d62a3a93875e2297b3
Author:     Niklas Haas <[email protected]>
AuthorDate: Tue Oct 20 01:17:21 2026 +0200
Commit:     Niklas Haas <[email protected]>
CommitDate: Tue Oct 20 11:43:04 2026 +0000

    swscale/vulkan/ops: implement SWS_OP_PACK and SWS_OP_UNPACK properly
    
    These were hacked into the code as swizzles relying on the _UINT_PACK32 view
    of the image to do the actual (un)packing, which only covered the 2:10:10:10
    formats, and silently produced garbage on drivers lacking storage support
    for those view formats (e.g. ANV).
    
    Implement these operations properly, the way they were intended, by doing
    the actual documented bit-packing operation instead whatever hacky
    assumptions the swizzle was making.
    
    Fixes fate-sws-unscaled-spirv on Intel.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/vulkan/ops.c | 64 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 53 insertions(+), 11 deletions(-)

diff --git a/libswscale/vulkan/ops.c b/libswscale/vulkan/ops.c
index 71769d65d9..87c622c861 100644
--- a/libswscale/vulkan/ops.c
+++ b/libswscale/vulkan/ops.c
@@ -534,6 +534,23 @@ static void define_shader_consts(SwsContext *sws, const 
SwsOpList *ops,
                 }
             }
             break;
+        case SWS_OP_PACK:
+        case SWS_OP_UNPACK: {
+            uint64_t mask[4];
+            int shift[4], tmp[4];
+            ff_sws_pack_op_decode(op, mask, shift);
+            for (int i = 0; i < 4; i++)
+                tmp[i] = spi_OpConstantUInt(spi, u32_type, shift[i]);
+            id->const_ids[id->nb_const_ids++] =
+                spi_OpConstantComposite(spi, id->u32vec4_type,
+                                        tmp[0], tmp[1], tmp[2], tmp[3]);
+            for (int i = 0; i < 4; i++)
+                tmp[i] = spi_OpConstantUInt(spi, u32_type, mask[i]);
+            id->const_ids[id->nb_const_ids++] =
+                spi_OpConstantComposite(spi, id->u32vec4_type,
+                                        tmp[0], tmp[1], tmp[2], tmp[3]);
+            break;
+        }
         case SWS_OP_LSHIFT:
         case SWS_OP_RSHIFT: {
             int tmp = spi_OpConstantUInt(spi, u32_type, op->shift.amount);
@@ -886,10 +903,26 @@ static int read_filtered(SPICtx *spi, SPIRVIDs *id, const 
SwsOpList *ops,
                                     acc_s[0], acc_s[1], acc_s[2], acc_s[3]);
 }
 
+/* Sub-packed formats are accessed as a single raw word per pixel, which is
+ * then (un)packed manually. */
+static VkFormat packed_word_fmt(const SwsOp *op)
+{
+    if (!op || op->rw.mode != SWS_RW_PACKED || op->rw.elems != 1)
+        return VK_FORMAT_UNDEFINED;
+
+    switch (op->type) {
+    case SWS_PIXEL_U8:  return VK_FORMAT_R8_UINT;
+    case SWS_PIXEL_U16: return VK_FORMAT_R16_UINT;
+    case SWS_PIXEL_U32: return VK_FORMAT_R32_UINT;
+    default:            return VK_FORMAT_UNDEFINED;
+    }
+}
+
 static int get_view_fmts(VkFormat view_fmts[AV_NUM_DATA_POINTERS],
                          enum AVPixelFormat fmt, const SwsOp *op)
 {
     const VkFormat *vk_fmts = av_vkfmt_from_pixfmt(fmt);
+    const VkFormat word_fmt = packed_word_fmt(op);
     enum FFVkShaderRepFormat rep = FF_VK_REP_NATIVE;
     if (op)
         rep = op->type == SWS_PIXEL_F32 ? FF_VK_REP_FLOAT : FF_VK_REP_UINT;
@@ -897,7 +930,7 @@ static int get_view_fmts(VkFormat 
view_fmts[AV_NUM_DATA_POINTERS],
         return AVERROR(ENOTSUP);
 
     for (int i = 0; i < av_pix_fmt_count_planes(fmt); i++) {
-        view_fmts[i] = ff_vk_map_fmt_to_rep(vk_fmts[i], rep);
+        view_fmts[i] = word_fmt ? word_fmt : ff_vk_map_fmt_to_rep(vk_fmts[i], 
rep);
         if (view_fmts[i] == VK_FORMAT_UNDEFINED)
             return AVERROR(ENOTSUP);
     }
@@ -1270,18 +1303,27 @@ static int add_ops_spirv(SwsContext *sws, VulkanPriv 
*p, FFVulkanOpsCtx *s,
             nb_const_ids += 5*5 + 1;
             break;
         }
-        case SWS_OP_UNPACK:
-            if (ops->src.format == AV_PIX_FMT_X2BGR10)
-                data = spi_OpVectorShuffle(spi, type_v, data, data, 3, 2, 1, 
0);
-            else
-                data = spi_OpVectorShuffle(spi, type_v, data, data, 3, 0, 1, 
2);
+        case SWS_OP_UNPACK: {
+            int shift = id->const_ids[nb_const_ids++];
+            int mask  = id->const_ids[nb_const_ids++];
+            data = spi_OpVectorShuffle(spi, type_v, data, data, 0, 0, 0, 0);
+            data = spi_OpShiftRightLogical(spi, type_v, data, shift);
+            data = spi_OpBitwiseAnd(spi, type_v, data, mask);
             break;
-        case SWS_OP_PACK:
-            if (ops->dst.format == AV_PIX_FMT_X2BGR10)
-                data = spi_OpVectorShuffle(spi, type_v, data, data, 3, 2, 1, 
0);
-            else
-                data = spi_OpVectorShuffle(spi, type_v, data, data, 1, 2, 3, 
0);
+        }
+        case SWS_OP_PACK: {
+            int shift = id->const_ids[nb_const_ids++];
+            int mask  = id->const_ids[nb_const_ids++];
+            data = spi_OpBitwiseAnd(spi, type_v, data, mask);
+            data = spi_OpShiftLeftLogical(spi, type_v, data, shift);
+            int val = spi_OpCompositeExtract(spi, type_s, data, 0);
+            for (int i = 1; i < 4; i++) {
+                int tmp = spi_OpCompositeExtract(spi, type_s, data, i);
+                val = spi_OpBitwiseOr(spi, type_s, val, tmp);
+            }
+            data = spi_OpCompositeConstruct(spi, type_v, val, val, val, val);
             break;
+        }
         default:
             return AVERROR(ENOTSUP);
         }

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to