This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 1b5041c785f1e735e14ef2db2c98a786ef180954 Author: Lynne <[email protected]> AuthorDate: Wed Sep 9 01:09:50 2026 +0900 Commit: Lynne <[email protected]> CommitDate: Sun Sep 20 17:19:28 2026 +0900 vulkan: keep the iDCT scale factors separable The 8x8 scale table was 64 specialization constants indexed per coefficient. The index is divergent, so nothing folds and every coefficient costs a load from the constant-data segment. The table is an outer product, s[y]*s[x], so pass the eight 1D factors instead: the x factor hoists out of the coefficient loop and the y factor folds once the loop is unrolled. ProRes RAW's gain of 8 becomes a literal in its shader. Reassociation moves a few samples in ten thousand by an LSB or so, well below the existing float iDCT error; PSNR versus software is unchanged. --- libavcodec/vulkan/apv_idct.comp.glsl | 7 +++++-- libavcodec/vulkan/dct.glsl | 16 ++++------------ libavcodec/vulkan/prores_idct.comp.glsl | 7 +++++-- libavcodec/vulkan/prores_raw_idct.comp.glsl | 9 +++++++-- libavcodec/vulkan_apv.c | 7 +++---- libavcodec/vulkan_prores.c | 7 +++---- libavcodec/vulkan_prores_raw.c | 7 +++---- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/libavcodec/vulkan/apv_idct.comp.glsl b/libavcodec/vulkan/apv_idct.comp.glsl index ba37fb1073..c66df279af 100644 --- a/libavcodec/vulkan/apv_idct.comp.glsl +++ b/libavcodec/vulkan/apv_idct.comp.glsl @@ -106,6 +106,9 @@ void main(void) /* blocks fully outside the coded area have nothing stored for them */ const bool oob = pos.x >= cstride || pos.y >= cheight; + /* Loop-invariant column scale */ + const float col_scale = norm * idct_scale[col]; + [[unroll]] for (uint y = 0u; y < 8u; y++) { /* load */ @@ -114,9 +117,9 @@ void main(void) pos.x + int(col))]); /* dequant + norm */ int qs = level_scale * int(q_matrix[comp][col][y]) * (1 << qp_shift); - float v = float(coeff * qs) * norm; + float v = float(coeff * qs) * col_scale; /* scale */ - blocks[block][y * 9u + col] = v * idct_scale[y * 8u + col]; + blocks[block][y * 9u + col] = v * idct_scale[y]; } barrier(); diff --git a/libavcodec/vulkan/dct.glsl b/libavcodec/vulkan/dct.glsl index 76f799b3e1..179c0406e0 100644 --- a/libavcodec/vulkan/dct.glsl +++ b/libavcodec/vulkan/dct.glsl @@ -39,20 +39,12 @@ layout (constant_id = 16) const uint32_t nb_blocks = 1; layout (constant_id = 17) const uint32_t nb_components = 1; +/* Coefficient (y, x) is scaled by sv[y]*sv[x]. Kept separable, as a + * 64-entry table costs a divergent load per coefficient. */ #define V(I) layout(constant_id = (18 + I)) const float sv##I = I; -V( 0) V( 1) V( 2) V( 3) V( 4) V( 5) V( 6) V( 7) V( 8) V( 9) V(10) V(11) V(12) -V(13) V(14) V(15) V(16) V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) V(25) -V(26) V(27) V(28) V(29) V(30) V(31) V(32) V(33) V(34) V(35) V(36) V(37) V(38) -V(39) V(40) V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) V(49) V(50) V(51) -V(52) V(53) V(54) V(55) V(56) V(57) V(58) V(59) V(60) V(61) V(62) V(63) +V( 0) V( 1) V( 2) V( 3) V( 4) V( 5) V( 6) V( 7) -const float idct_scale[64] = { - sv0, sv1, sv2, sv3, sv4, sv5, sv6, sv7, sv8, sv9, sv10, sv11, sv12, - sv13, sv14, sv15, sv16, sv17, sv18, sv19, sv20, sv21, sv22, sv23, sv24, sv25, - sv26, sv27, sv28, sv29, sv30, sv31, sv32, sv33, sv34, sv35, sv36, sv37, sv38, - sv39, sv40, sv41, sv42, sv43, sv44, sv45, sv46, sv47, sv48, sv49, sv50, sv51, - sv52, sv53, sv54, sv55, sv56, sv57, sv58, sv59, sv60, sv61, sv62, sv63 -}; +const float idct_scale[8] = { sv0, sv1, sv2, sv3, sv4, sv5, sv6, sv7 }; /* Padded by 1 row to avoid bank conflicts */ shared float blocks[nb_blocks][nb_components*8*(8 + 1)]; diff --git a/libavcodec/vulkan/prores_idct.comp.glsl b/libavcodec/vulkan/prores_idct.comp.glsl index 8ef22b0384..8c7fb60c79 100644 --- a/libavcodec/vulkan/prores_idct.comp.glsl +++ b/libavcodec/vulkan/prores_idct.comp.glsl @@ -82,11 +82,14 @@ void main(void) uint8_t qidx = quant_idx[(gid.y >> 1) * mb_width + (gid.x >> (4 - chroma_shift))]; int qscale = qidx > 128 ? (qidx - 96) << 2 : qidx, mat = int(gid.z != 0) << 6; + /* Loop-invariant column scale */ + const float col_scale = norm * idct_scale[idx]; + [[unroll]] for (uint i = 0; i < 8; ++i) { uint cidx = (i << 3) + idx; int c = sign_extend(int(get_px(comp, ivec2(gid.x, (gid.y << 3) + i))), 16); - float v = float(c * qscale * int(qmat[mat + cidx])) * norm; - blocks[block][i * 9 + idx] = v * idct_scale[cidx]; + float v = float(c * qscale * int(qmat[mat + cidx])) * col_scale; + blocks[block][i * 9 + idx] = v * idct_scale[i]; } } diff --git a/libavcodec/vulkan/prores_raw_idct.comp.glsl b/libavcodec/vulkan/prores_raw_idct.comp.glsl index dcc8626d48..ebaa43c999 100644 --- a/libavcodec/vulkan/prores_raw_idct.comp.glsl +++ b/libavcodec/vulkan/prores_raw_idct.comp.glsl @@ -88,13 +88,18 @@ void main(void) } barrier(); + const float norm = 8.0; /* DCT normalization const */ + + /* Loop-invariant column scale */ + const float col_scale = float(qscale) * norm * idct_scale[ROW_ID]; + [[unroll]] for (uint y = 0; y < 8; y++) { uint block_off = y*8 + ROW_ID; int v = int(imageLoad(dst, offs + 2*ivec2(BLOCK_ID*8, 0) + scan[block_off])[0]); /* Dequantize (coeff * qmat * qscale), matching the reference decoder */ - float vf = float(sign_extend(v, 16)) * float(qmat_buf[block_off]) * float(qscale); - blocks[BLOCK_ID][COMP_ID*72 + y*9 + ROW_ID] = vf * idct_scale[block_off]; + float vf = float(sign_extend(v, 16)) * float(qmat_buf[block_off]) * col_scale; + blocks[BLOCK_ID][COMP_ID*72 + y*9 + ROW_ID] = vf * idct_scale[y]; } /* Column-wise iDCT */ diff --git a/libavcodec/vulkan_apv.c b/libavcodec/vulkan_apv.c index 1ad5ab0a41..e9c469e6ad 100644 --- a/libavcodec/vulkan_apv.c +++ b/libavcodec/vulkan_apv.c @@ -406,7 +406,7 @@ static int init_idct_shader(AVCodecContext *avctx, FFVulkanContext *s, AVHWFramesContext *dec_frames_ctx; dec_frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; - SPEC_LIST_CREATE(sl, 1 + 64, (1 + 64)*sizeof(uint32_t)) + SPEC_LIST_CREATE(sl, 1 + 8, (1 + 8)*sizeof(uint32_t)) SPEC_LIST_ADD(sl, 16, 32, 8); /* nb_blocks per workgroup */ const double idct_8_scales[8] = { @@ -415,9 +415,8 @@ static int init_idct_shader(AVCodecContext *avctx, FFVulkanContext *s, cos(4.0*M_PI/16.0) / 2.0, cos(5.0*M_PI/16.0) / 2.0, cos(6.0*M_PI/16.0) / 2.0, cos(7.0*M_PI/16.0) / 2.0, }; - for (int i = 0; i < 64; i++) - SPEC_LIST_ADD(sl, 18 + i, 32, - av_float2int(idct_8_scales[i >> 3]*idct_8_scales[i & 7])); + for (int i = 0; i < 8; i++) + SPEC_LIST_ADD(sl, 18 + i, 32, av_float2int(idct_8_scales[i])); ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl, (uint32_t []) { 32, 2, 1 }, 0); diff --git a/libavcodec/vulkan_prores.c b/libavcodec/vulkan_prores.c index ff4185fb79..d8d7808ef8 100644 --- a/libavcodec/vulkan_prores.c +++ b/libavcodec/vulkan_prores.c @@ -419,7 +419,7 @@ static int init_idct_shader(AVCodecContext *avctx, FFVulkanContext *s, AVHWFramesContext *dec_frames_ctx; dec_frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; - SPEC_LIST_CREATE(sl, 2 + 64, (2 + 64)*sizeof(uint32_t)) + SPEC_LIST_CREATE(sl, 2 + 8, (2 + 8)*sizeof(uint32_t)) SPEC_LIST_ADD(sl, 0, 32, interlaced); SPEC_LIST_ADD(sl, 16, 32, 4*2); /* nb_blocks */ @@ -429,9 +429,8 @@ static int init_idct_shader(AVCodecContext *avctx, FFVulkanContext *s, cos(4.0*M_PI/16.0) / 2.0, cos(5.0*M_PI/16.0) / 2.0, cos(6.0*M_PI/16.0) / 2.0, cos(7.0*M_PI/16.0) / 2.0, }; - for (int i = 0; i < 64; i++) - SPEC_LIST_ADD(sl, 18 + i, 32, - av_float2int(idct_8_scales[i >> 3]*idct_8_scales[i & 7])); + for (int i = 0; i < 8; i++) + SPEC_LIST_ADD(sl, 18 + i, 32, av_float2int(idct_8_scales[i])); ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl, diff --git a/libavcodec/vulkan_prores_raw.c b/libavcodec/vulkan_prores_raw.c index b93b21ad1e..45936b68a4 100644 --- a/libavcodec/vulkan_prores_raw.c +++ b/libavcodec/vulkan_prores_raw.c @@ -336,7 +336,7 @@ static int init_idct_shader(AVCodecContext *avctx, FFVulkanContext *s, int version) { int err; - SPEC_LIST_CREATE(sl, 2 + 64, (2 + 64)*sizeof(uint32_t)) + SPEC_LIST_CREATE(sl, 2 + 8, (2 + 8)*sizeof(uint32_t)) int nb_blocks = version == 0 ? 8 : 16; SPEC_LIST_ADD(sl, 16, 32, nb_blocks); @@ -348,9 +348,8 @@ static int init_idct_shader(AVCodecContext *avctx, FFVulkanContext *s, cos(4.0*M_PI/16.0) / 2.0, cos(5.0*M_PI/16.0) / 2.0, cos(6.0*M_PI/16.0) / 2.0, cos(7.0*M_PI/16.0) / 2.0, }; - for (int i = 0; i < 64; i++) - SPEC_LIST_ADD(sl, 18 + i, 32, - av_float2int(8*idct_8_scales[i >> 3]*idct_8_scales[i & 7])); + for (int i = 0; i < 8; i++) + SPEC_LIST_ADD(sl, 18 + i, 32, av_float2int(idct_8_scales[i])); ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl, (uint32_t []) { 8, nb_blocks, 4 }, 0); -- 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]
