Merge pull request 'h264: V3D shaders for the 4 bS=4 intra deblock variants — deblock QPU complete' (#35) from noether/v3d-shader-h264-deblock-intra into main
Reviewed-on: #35
This commit was merged in pull request #35.
This commit is contained in:
+21
-1
@@ -317,6 +317,22 @@ if (DAEDALUS_BUILD_VULKAN)
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Intra (bS=4) deblock shaders — strong/weak filter selector per
|
||||
# H.264 §8.3.2.3. 4 variants (luma_v/h + chroma_v/h).
|
||||
foreach(_kind luma_v_intra luma_h_intra chroma_v_intra chroma_h_intra)
|
||||
set(_spv ${CMAKE_BINARY_DIR}/v3d_h264deblock_${_kind}.spv)
|
||||
add_custom_command(
|
||||
OUTPUT ${_spv}
|
||||
COMMAND ${GLSLANG_VALIDATOR} -V --target-env vulkan1.3
|
||||
-o ${_spv}
|
||||
${CMAKE_SOURCE_DIR}/src/v3d_h264deblock_${_kind}.comp
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/src/v3d_h264deblock_${_kind}.comp
|
||||
COMMENT "glslang: v3d_h264deblock_${_kind}.comp -> .spv"
|
||||
VERBATIM
|
||||
)
|
||||
set(H264DEBLOCK_${_kind}_SPV ${_spv})
|
||||
endforeach()
|
||||
|
||||
set(H264_IDCT4_SPV ${CMAKE_BINARY_DIR}/v3d_h264_idct4.spv)
|
||||
add_custom_command(
|
||||
OUTPUT ${H264_IDCT4_SPV}
|
||||
@@ -406,7 +422,7 @@ if (DAEDALUS_BUILD_VULKAN)
|
||||
set(H264_QPEL_avg_${_mc}_SPV ${_spv})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(daedalus_shaders ALL DEPENDS ${NOOP_SPV} ${IDCT8_SPV} ${LPF_SPV} ${MC_SPV} ${LPF8_SPV} ${CDEF_SPV} ${H264DEBLOCK_SPV} ${H264DEBLOCK_H_SPV} ${H264DEBLOCK_CHROMA_V_SPV} ${H264DEBLOCK_CHROMA_H_SPV} ${H264_IDCT4_SPV} ${H264_IDCT8_SPV} ${H264_QPEL_MC20_SPV} ${H264_QPEL_MC02_SPV} ${H264_QPEL_MC22_SPV} ${H264_QPEL_mc10_SPV} ${H264_QPEL_mc30_SPV} ${H264_QPEL_mc01_SPV} ${H264_QPEL_mc03_SPV} ${H264_QPEL_mc11_SPV} ${H264_QPEL_mc12_SPV} ${H264_QPEL_mc13_SPV} ${H264_QPEL_mc21_SPV} ${H264_QPEL_mc23_SPV} ${H264_QPEL_mc31_SPV} ${H264_QPEL_mc32_SPV} ${H264_QPEL_mc33_SPV} ${H264_QPEL_avg_mc20_SPV} ${H264_QPEL_avg_mc02_SPV} ${H264_QPEL_avg_mc22_SPV} ${H264_QPEL_avg_mc10_SPV} ${H264_QPEL_avg_mc30_SPV} ${H264_QPEL_avg_mc01_SPV} ${H264_QPEL_avg_mc03_SPV} ${H264_QPEL_avg_mc11_SPV} ${H264_QPEL_avg_mc12_SPV} ${H264_QPEL_avg_mc13_SPV} ${H264_QPEL_avg_mc21_SPV} ${H264_QPEL_avg_mc23_SPV} ${H264_QPEL_avg_mc31_SPV} ${H264_QPEL_avg_mc32_SPV} ${H264_QPEL_avg_mc33_SPV})
|
||||
add_custom_target(daedalus_shaders ALL DEPENDS ${NOOP_SPV} ${IDCT8_SPV} ${LPF_SPV} ${MC_SPV} ${LPF8_SPV} ${CDEF_SPV} ${H264DEBLOCK_SPV} ${H264DEBLOCK_H_SPV} ${H264DEBLOCK_CHROMA_V_SPV} ${H264DEBLOCK_CHROMA_H_SPV} ${H264DEBLOCK_luma_v_intra_SPV} ${H264DEBLOCK_luma_h_intra_SPV} ${H264DEBLOCK_chroma_v_intra_SPV} ${H264DEBLOCK_chroma_h_intra_SPV} ${H264_IDCT4_SPV} ${H264_IDCT8_SPV} ${H264_QPEL_MC20_SPV} ${H264_QPEL_MC02_SPV} ${H264_QPEL_MC22_SPV} ${H264_QPEL_mc10_SPV} ${H264_QPEL_mc30_SPV} ${H264_QPEL_mc01_SPV} ${H264_QPEL_mc03_SPV} ${H264_QPEL_mc11_SPV} ${H264_QPEL_mc12_SPV} ${H264_QPEL_mc13_SPV} ${H264_QPEL_mc21_SPV} ${H264_QPEL_mc23_SPV} ${H264_QPEL_mc31_SPV} ${H264_QPEL_mc32_SPV} ${H264_QPEL_mc33_SPV} ${H264_QPEL_avg_mc20_SPV} ${H264_QPEL_avg_mc02_SPV} ${H264_QPEL_avg_mc22_SPV} ${H264_QPEL_avg_mc10_SPV} ${H264_QPEL_avg_mc30_SPV} ${H264_QPEL_avg_mc01_SPV} ${H264_QPEL_avg_mc03_SPV} ${H264_QPEL_avg_mc11_SPV} ${H264_QPEL_avg_mc12_SPV} ${H264_QPEL_avg_mc13_SPV} ${H264_QPEL_avg_mc21_SPV} ${H264_QPEL_avg_mc23_SPV} ${H264_QPEL_avg_mc31_SPV} ${H264_QPEL_avg_mc32_SPV} ${H264_QPEL_avg_mc33_SPV})
|
||||
|
||||
# v3d_runner — reusable Vulkan plumbing.
|
||||
add_library(v3d_runner STATIC src/v3d_runner.c)
|
||||
@@ -542,6 +558,10 @@ if (DAEDALUS_BUILD_VULKAN)
|
||||
${H264DEBLOCK_H_SPV}
|
||||
${H264DEBLOCK_CHROMA_V_SPV}
|
||||
${H264DEBLOCK_CHROMA_H_SPV}
|
||||
${H264DEBLOCK_luma_v_intra_SPV}
|
||||
${H264DEBLOCK_luma_h_intra_SPV}
|
||||
${H264DEBLOCK_chroma_v_intra_SPV}
|
||||
${H264DEBLOCK_chroma_h_intra_SPV}
|
||||
${H264_IDCT4_SPV}
|
||||
${H264_IDCT8_SPV}
|
||||
${H264_QPEL_MC20_SPV}
|
||||
|
||||
+130
-11
@@ -46,6 +46,11 @@ struct daedalus_ctx {
|
||||
v3d_pipeline h264deblock_chroma_v_pipe;
|
||||
int h264deblock_chroma_h_pipe_ready;
|
||||
v3d_pipeline h264deblock_chroma_h_pipe;
|
||||
/* bS=4 intra deblock pipelines (strong/weak filter selector). */
|
||||
int h264deblock_luma_v_intra_pipe_ready; v3d_pipeline h264deblock_luma_v_intra_pipe;
|
||||
int h264deblock_luma_h_intra_pipe_ready; v3d_pipeline h264deblock_luma_h_intra_pipe;
|
||||
int h264deblock_chroma_v_intra_pipe_ready; v3d_pipeline h264deblock_chroma_v_intra_pipe;
|
||||
int h264deblock_chroma_h_intra_pipe_ready; v3d_pipeline h264deblock_chroma_h_intra_pipe;
|
||||
int h264_idct4_pipe_ready;
|
||||
v3d_pipeline h264_idct4_pipe;
|
||||
int h264_idct8_pipe_ready;
|
||||
@@ -145,6 +150,10 @@ void daedalus_ctx_destroy(daedalus_ctx *ctx)
|
||||
if (ctx->h264deblock_h_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264deblock_h_pipe);
|
||||
if (ctx->h264deblock_chroma_v_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264deblock_chroma_v_pipe);
|
||||
if (ctx->h264deblock_chroma_h_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264deblock_chroma_h_pipe);
|
||||
if (ctx->h264deblock_luma_v_intra_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264deblock_luma_v_intra_pipe);
|
||||
if (ctx->h264deblock_luma_h_intra_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264deblock_luma_h_intra_pipe);
|
||||
if (ctx->h264deblock_chroma_v_intra_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264deblock_chroma_v_intra_pipe);
|
||||
if (ctx->h264deblock_chroma_h_intra_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264deblock_chroma_h_intra_pipe);
|
||||
if (ctx->h264_idct4_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264_idct4_pipe);
|
||||
if (ctx->h264_idct8_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264_idct8_pipe);
|
||||
if (ctx->h264_qpel_mc20_pipe_ready) v3d_runner_destroy_pipeline(ctx->runner, &ctx->h264_qpel_mc20_pipe);
|
||||
@@ -207,10 +216,10 @@ daedalus_substrate daedalus_recipe_substrate_for(daedalus_kernel k)
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_LH: return DAEDALUS_SUBSTRATE_QPU; /* v3d_h264deblock_h.spv */
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_CV: return DAEDALUS_SUBSTRATE_QPU; /* v3d_h264deblock_chroma_v.spv */
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_CH: return DAEDALUS_SUBSTRATE_QPU; /* v3d_h264deblock_chroma_h.spv */
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_LV_INTRA: return DAEDALUS_SUBSTRATE_CPU; /* bS=4 luma QPU pending */
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_LH_INTRA: return DAEDALUS_SUBSTRATE_CPU;
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_CV_INTRA: return DAEDALUS_SUBSTRATE_CPU; /* bS=4 chroma QPU pending */
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_CH_INTRA: return DAEDALUS_SUBSTRATE_CPU;
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_LV_INTRA: return DAEDALUS_SUBSTRATE_QPU; /* v3d_h264deblock_luma_v_intra.spv */
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_LH_INTRA: return DAEDALUS_SUBSTRATE_QPU;
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_CV_INTRA: return DAEDALUS_SUBSTRATE_QPU; /* v3d_h264deblock_chroma_v_intra.spv */
|
||||
case DAEDALUS_KERNEL_H264_DEBLOCK_CH_INTRA: return DAEDALUS_SUBSTRATE_QPU;
|
||||
case DAEDALUS_KERNEL_H264_QPEL_MC20: return DAEDALUS_SUBSTRATE_QPU; /* v3d_h264_qpel_mc20.spv */
|
||||
case DAEDALUS_KERNEL_H264_QPEL_MC02: return DAEDALUS_SUBSTRATE_QPU; /* v3d_h264_qpel_mc02.spv */
|
||||
case DAEDALUS_KERNEL_H264_QPEL_MC22: return DAEDALUS_SUBSTRATE_QPU; /* v3d_h264_qpel_mc22.spv */
|
||||
@@ -1240,6 +1249,107 @@ static int dispatch_h264_deblock_chroma_h_qpu(daedalus_ctx *ctx,
|
||||
"v3d_h264deblock_chroma_h.spv", dst, dst_stride, n_edges, meta, 1);
|
||||
}
|
||||
|
||||
/* -------------------- H.264 luma/chroma intra (bS=4) QPU dispatches.
|
||||
* Same WG geometry as the non-intra shaders, same meta layout (tc0[]
|
||||
* unused — the strong/weak selector replaces it). Bounds match the
|
||||
* non-intra variants exactly:
|
||||
* luma_v: dst_off + 3*stride + 16 (reads p3 at -4*stride, writes p2 at -3*stride)
|
||||
* luma_h: dst_off + 15*stride + 4 (lane → row, reads pix[-4..+3])
|
||||
* chroma_v: 1*stride + 8 (only p1..q1 = ±2*stride)
|
||||
* chroma_h: 7*stride + 2 (lane → row, reads pix[-2..+1])
|
||||
*/
|
||||
static int dispatch_h264_deblock_luma_intra_qpu(daedalus_ctx *ctx,
|
||||
v3d_pipeline *pipe, int *pipe_ready, const char *spv,
|
||||
uint8_t *dst, size_t dst_stride, size_t n_edges,
|
||||
const daedalus_h264_deblock_meta *meta, int orient_h)
|
||||
{
|
||||
if (!*pipe_ready) {
|
||||
if (v3d_runner_create_pipeline(ctx->runner, spv,
|
||||
2, sizeof(h264deblock_pc), pipe) != 0)
|
||||
return -1;
|
||||
*pipe_ready = 1;
|
||||
}
|
||||
size_t meta_bytes = n_edges * 4 * sizeof(uint32_t);
|
||||
size_t dst_max = 0;
|
||||
for (size_t i = 0; i < n_edges; i++) {
|
||||
size_t e = orient_h ? meta[i].dst_off + 15 * dst_stride + 4
|
||||
: meta[i].dst_off + 3 * dst_stride + 16;
|
||||
if (e > dst_max) dst_max = e;
|
||||
}
|
||||
v3d_buffer bm = {0}, bd = {0};
|
||||
if (v3d_runner_acquire_buffer(ctx->runner, meta_bytes, &bm)) return -1;
|
||||
if (v3d_runner_acquire_buffer(ctx->runner, dst_max, &bd)) { v3d_runner_release_buffer(ctx->runner, &bm); return -1; }
|
||||
memcpy(bd.mapped, dst, dst_max);
|
||||
uint32_t *m = bm.mapped;
|
||||
for (size_t i = 0; i < n_edges; i++) {
|
||||
m[4*i+0] = meta[i].dst_off;
|
||||
m[4*i+1] = ((uint32_t) meta[i].alpha) | (((uint32_t) meta[i].beta) << 8);
|
||||
m[4*i+2] = 0; /* tc0 unused for intra */
|
||||
m[4*i+3] = 0;
|
||||
}
|
||||
v3d_buffer binds[2] = { bm, bd };
|
||||
if (v3d_runner_bind_buffers(ctx->runner, pipe, binds, 2)) goto fail;
|
||||
uint32_t wg_count = (uint32_t)((n_edges + 15) / 16);
|
||||
h264deblock_pc pc = { .n_edges = (uint32_t) n_edges,
|
||||
.dst_stride_u8 = (uint32_t) dst_stride };
|
||||
if (v3d_runner_pipeline_cmdbuf_reset(ctx->runner, pipe)) goto fail;
|
||||
VkCommandBuffer cb = pipe->cb;
|
||||
VkCommandBufferBeginInfo cbbi = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
vkBeginCommandBuffer(cb, &cbbi);
|
||||
vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_COMPUTE, pipe->pipeline);
|
||||
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
pipe->layout, 0, 1, &pipe->desc_set, 0, NULL);
|
||||
vkCmdPushConstants(cb, pipe->layout, VK_SHADER_STAGE_COMPUTE_BIT,
|
||||
0, sizeof(pc), &pc);
|
||||
vkCmdDispatch(cb, wg_count, 1, 1);
|
||||
vkEndCommandBuffer(cb);
|
||||
if (v3d_runner_submit_wait(ctx->runner, cb)) goto fail;
|
||||
memcpy(dst, bd.mapped, dst_max);
|
||||
v3d_runner_release_buffer(ctx->runner, &bd);
|
||||
v3d_runner_release_buffer(ctx->runner, &bm);
|
||||
return 0;
|
||||
fail:
|
||||
v3d_runner_release_buffer(ctx->runner, &bd);
|
||||
v3d_runner_release_buffer(ctx->runner, &bm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dispatch_h264_deblock_luma_v_intra_qpu(daedalus_ctx *ctx,
|
||||
uint8_t *dst, size_t dst_stride,
|
||||
size_t n_edges, const daedalus_h264_deblock_meta *meta)
|
||||
{
|
||||
return dispatch_h264_deblock_luma_intra_qpu(ctx,
|
||||
&ctx->h264deblock_luma_v_intra_pipe, &ctx->h264deblock_luma_v_intra_pipe_ready,
|
||||
"v3d_h264deblock_luma_v_intra.spv", dst, dst_stride, n_edges, meta, 0);
|
||||
}
|
||||
|
||||
static int dispatch_h264_deblock_luma_h_intra_qpu(daedalus_ctx *ctx,
|
||||
uint8_t *dst, size_t dst_stride,
|
||||
size_t n_edges, const daedalus_h264_deblock_meta *meta)
|
||||
{
|
||||
return dispatch_h264_deblock_luma_intra_qpu(ctx,
|
||||
&ctx->h264deblock_luma_h_intra_pipe, &ctx->h264deblock_luma_h_intra_pipe_ready,
|
||||
"v3d_h264deblock_luma_h_intra.spv", dst, dst_stride, n_edges, meta, 1);
|
||||
}
|
||||
|
||||
static int dispatch_h264_deblock_chroma_v_intra_qpu(daedalus_ctx *ctx,
|
||||
uint8_t *dst, size_t dst_stride,
|
||||
size_t n_edges, const daedalus_h264_deblock_meta *meta)
|
||||
{
|
||||
return dispatch_h264_deblock_chroma_qpu(ctx,
|
||||
&ctx->h264deblock_chroma_v_intra_pipe, &ctx->h264deblock_chroma_v_intra_pipe_ready,
|
||||
"v3d_h264deblock_chroma_v_intra.spv", dst, dst_stride, n_edges, meta, 0);
|
||||
}
|
||||
|
||||
static int dispatch_h264_deblock_chroma_h_intra_qpu(daedalus_ctx *ctx,
|
||||
uint8_t *dst, size_t dst_stride,
|
||||
size_t n_edges, const daedalus_h264_deblock_meta *meta)
|
||||
{
|
||||
return dispatch_h264_deblock_chroma_qpu(ctx,
|
||||
&ctx->h264deblock_chroma_h_intra_pipe, &ctx->h264deblock_chroma_h_intra_pipe_ready,
|
||||
"v3d_h264deblock_chroma_h_intra.spv", dst, dst_stride, n_edges, meta, 1);
|
||||
}
|
||||
|
||||
/* -------------------- H.264 IDCT 4x4 QPU dispatch (cycle 6) ----- */
|
||||
|
||||
typedef struct {
|
||||
@@ -2063,7 +2173,7 @@ int daedalus_dispatch_h264_deblock_chroma_h(daedalus_ctx *ctx, daedalus_substrat
|
||||
return dispatch_h264_deblock_chroma_h_qpu(ctx, dst, dst_stride, n_edges, meta);
|
||||
}
|
||||
|
||||
#define DEFINE_INTRA_DISPATCH(name, kernel, cpu_fn) \
|
||||
#define DEFINE_INTRA_DISPATCH(name, kernel, cpu_fn, qpu_fn) \
|
||||
int daedalus_dispatch_h264_deblock_ ## name (daedalus_ctx *ctx, \
|
||||
daedalus_substrate sub, uint8_t *dst, size_t dst_stride, \
|
||||
size_t n_edges, const daedalus_h264_deblock_meta *meta) \
|
||||
@@ -2073,14 +2183,23 @@ int daedalus_dispatch_h264_deblock_ ## name (daedalus_ctx *ctx, \
|
||||
eff = daedalus_recipe_substrate_for(kernel); \
|
||||
if (eff == DAEDALUS_SUBSTRATE_QPU && !daedalus_ctx_has_qpu(ctx)) \
|
||||
eff = DAEDALUS_SUBSTRATE_CPU; \
|
||||
if (eff == DAEDALUS_SUBSTRATE_QPU) return -1; \
|
||||
return cpu_fn(ctx, dst, dst_stride, n_edges, meta); \
|
||||
if (eff == DAEDALUS_SUBSTRATE_CPU) \
|
||||
return cpu_fn(ctx, dst, dst_stride, n_edges, meta); \
|
||||
return qpu_fn(ctx, dst, dst_stride, n_edges, meta); \
|
||||
}
|
||||
|
||||
DEFINE_INTRA_DISPATCH(luma_v_intra, DAEDALUS_KERNEL_H264_DEBLOCK_LV_INTRA, dispatch_h264_deblock_luma_v_intra_cpu)
|
||||
DEFINE_INTRA_DISPATCH(luma_h_intra, DAEDALUS_KERNEL_H264_DEBLOCK_LH_INTRA, dispatch_h264_deblock_luma_h_intra_cpu)
|
||||
DEFINE_INTRA_DISPATCH(chroma_v_intra, DAEDALUS_KERNEL_H264_DEBLOCK_CV_INTRA, dispatch_h264_deblock_chroma_v_intra_cpu)
|
||||
DEFINE_INTRA_DISPATCH(chroma_h_intra, DAEDALUS_KERNEL_H264_DEBLOCK_CH_INTRA, dispatch_h264_deblock_chroma_h_intra_cpu)
|
||||
DEFINE_INTRA_DISPATCH(luma_v_intra, DAEDALUS_KERNEL_H264_DEBLOCK_LV_INTRA,
|
||||
dispatch_h264_deblock_luma_v_intra_cpu,
|
||||
dispatch_h264_deblock_luma_v_intra_qpu)
|
||||
DEFINE_INTRA_DISPATCH(luma_h_intra, DAEDALUS_KERNEL_H264_DEBLOCK_LH_INTRA,
|
||||
dispatch_h264_deblock_luma_h_intra_cpu,
|
||||
dispatch_h264_deblock_luma_h_intra_qpu)
|
||||
DEFINE_INTRA_DISPATCH(chroma_v_intra, DAEDALUS_KERNEL_H264_DEBLOCK_CV_INTRA,
|
||||
dispatch_h264_deblock_chroma_v_intra_cpu,
|
||||
dispatch_h264_deblock_chroma_v_intra_qpu)
|
||||
DEFINE_INTRA_DISPATCH(chroma_h_intra, DAEDALUS_KERNEL_H264_DEBLOCK_CH_INTRA,
|
||||
dispatch_h264_deblock_chroma_h_intra_cpu,
|
||||
dispatch_h264_deblock_chroma_h_intra_qpu)
|
||||
|
||||
#undef DEFINE_INTRA_DISPATCH
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// daedalus-fourier — H.264 chroma 4:2:0 intra (bS=4) H deblock —
|
||||
// V3D 7.1. Transpose of v3d_h264deblock_chroma_v_intra.comp.
|
||||
//
|
||||
// License: BSD-2-Clause.
|
||||
|
||||
#version 450
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types : require
|
||||
|
||||
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||
layout(binding = 0) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||
layout(push_constant) uniform PC {
|
||||
uint n_edges, dst_stride_u8, _p0, _p1;
|
||||
} pc;
|
||||
|
||||
void main()
|
||||
{
|
||||
uint lane_in_wg = gl_GlobalInvocationID.x & 255u;
|
||||
uint edge_in_wg = lane_in_wg >> 4;
|
||||
uint row_in_edge = lane_in_wg & 15u;
|
||||
uint edge_idx = gl_WorkGroupID.x * 16u + edge_in_wg;
|
||||
if (edge_idx >= pc.n_edges) return;
|
||||
if (row_in_edge >= 8u) return;
|
||||
|
||||
uvec4 m = u_meta.meta[edge_idx];
|
||||
uint stride = pc.dst_stride_u8;
|
||||
uint dst_off = m.x + row_in_edge * stride;
|
||||
int alpha = int(m.y & 0xffu);
|
||||
int beta = int((m.y >> 8) & 0xffu);
|
||||
if ((alpha | beta) == 0) return;
|
||||
|
||||
int p1 = int(u_dst.dst[dst_off - 2u]);
|
||||
int p0 = int(u_dst.dst[dst_off - 1u]);
|
||||
int q0 = int(u_dst.dst[dst_off ]);
|
||||
int q1 = int(u_dst.dst[dst_off + 1u]);
|
||||
|
||||
if (abs(p0 - q0) >= alpha) return;
|
||||
if (abs(p1 - p0) >= beta) return;
|
||||
if (abs(q1 - q0) >= beta) return;
|
||||
|
||||
u_dst.dst[dst_off - 1u] = uint8_t(clamp((2*p1 + p0 + q1 + 2) >> 2, 0, 255));
|
||||
u_dst.dst[dst_off ] = uint8_t(clamp((2*q1 + q0 + p1 + 2) >> 2, 0, 255));
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// daedalus-fourier — H.264 chroma 4:2:0 intra (bS=4) V deblock —
|
||||
// V3D 7.1. Per H.264 §8.3.2.3 chroma intra path: simpler than luma
|
||||
// — always weak filter, only p0/q0 updated, 8 cells per edge.
|
||||
//
|
||||
// p0' = (2*p1 + p0 + q1 + 2) >> 2
|
||||
// q0' = (2*q1 + q0 + p1 + 2) >> 2
|
||||
//
|
||||
// Same 16-edges × 16-lanes/edge WG shape as luma; lanes 8..15 of each
|
||||
// edge early-return (chroma edges are only 8 cells wide).
|
||||
//
|
||||
// 4:2:0-only — caller-side gating handles 4:2:2 (chroma_format_idc>1)
|
||||
// at the libavcodec init layer.
|
||||
//
|
||||
// License: BSD-2-Clause.
|
||||
|
||||
#version 450
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types : require
|
||||
|
||||
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||
layout(binding = 0) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||
layout(push_constant) uniform PC {
|
||||
uint n_edges, dst_stride_u8, _p0, _p1;
|
||||
} pc;
|
||||
|
||||
void main()
|
||||
{
|
||||
uint lane_in_wg = gl_GlobalInvocationID.x & 255u;
|
||||
uint edge_in_wg = lane_in_wg >> 4;
|
||||
uint col_in_edge = lane_in_wg & 15u;
|
||||
uint edge_idx = gl_WorkGroupID.x * 16u + edge_in_wg;
|
||||
if (edge_idx >= pc.n_edges) return;
|
||||
if (col_in_edge >= 8u) return;
|
||||
|
||||
uvec4 m = u_meta.meta[edge_idx];
|
||||
uint dst_off = m.x + col_in_edge;
|
||||
uint stride = pc.dst_stride_u8;
|
||||
int alpha = int(m.y & 0xffu);
|
||||
int beta = int((m.y >> 8) & 0xffu);
|
||||
if ((alpha | beta) == 0) return;
|
||||
|
||||
int p1 = int(u_dst.dst[dst_off - 2u * stride]);
|
||||
int p0 = int(u_dst.dst[dst_off - 1u * stride]);
|
||||
int q0 = int(u_dst.dst[dst_off]);
|
||||
int q1 = int(u_dst.dst[dst_off + 1u * stride]);
|
||||
|
||||
if (abs(p0 - q0) >= alpha) return;
|
||||
if (abs(p1 - p0) >= beta) return;
|
||||
if (abs(q1 - q0) >= beta) return;
|
||||
|
||||
u_dst.dst[dst_off - 1u * stride] = uint8_t(clamp((2*p1 + p0 + q1 + 2) >> 2, 0, 255));
|
||||
u_dst.dst[dst_off ] = uint8_t(clamp((2*q1 + q0 + p1 + 2) >> 2, 0, 255));
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// daedalus-fourier — H.264 luma intra (bS=4) H deblock — V3D 7.1.
|
||||
//
|
||||
// Sibling of v3d_h264deblock_luma_v_intra.comp transposed to the
|
||||
// horizontal axis: lane → row, reads pix[-4..+3] (cols) instead of
|
||||
// pix[-4*stride..+3*stride] (rows). Same strong/weak filter
|
||||
// selector + same write-back algebra.
|
||||
//
|
||||
// dst_off contract: (m.x % stride) ≥ 4 (kernel reads p3 at pix[-4]).
|
||||
//
|
||||
// License: BSD-2-Clause.
|
||||
|
||||
#version 450
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types : require
|
||||
|
||||
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||
layout(binding = 0) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||
layout(push_constant) uniform PC {
|
||||
uint n_edges, dst_stride_u8, _p0, _p1;
|
||||
} pc;
|
||||
|
||||
void main()
|
||||
{
|
||||
uint lane_in_wg = gl_GlobalInvocationID.x & 255u;
|
||||
uint edge_in_wg = lane_in_wg >> 4;
|
||||
uint row_in_edge = lane_in_wg & 15u;
|
||||
uint edge_idx = gl_WorkGroupID.x * 16u + edge_in_wg;
|
||||
if (edge_idx >= pc.n_edges) return;
|
||||
|
||||
uvec4 m = u_meta.meta[edge_idx];
|
||||
uint stride = pc.dst_stride_u8;
|
||||
uint dst_off = m.x + row_in_edge * stride;
|
||||
int alpha = int(m.y & 0xffu);
|
||||
int beta = int((m.y >> 8) & 0xffu);
|
||||
if ((alpha | beta) == 0) return;
|
||||
|
||||
int p3 = int(u_dst.dst[dst_off - 4u]);
|
||||
int p2 = int(u_dst.dst[dst_off - 3u]);
|
||||
int p1 = int(u_dst.dst[dst_off - 2u]);
|
||||
int p0 = int(u_dst.dst[dst_off - 1u]);
|
||||
int q0 = int(u_dst.dst[dst_off ]);
|
||||
int q1 = int(u_dst.dst[dst_off + 1u]);
|
||||
int q2 = int(u_dst.dst[dst_off + 2u]);
|
||||
int q3 = int(u_dst.dst[dst_off + 3u]);
|
||||
|
||||
if (abs(p0 - q0) >= alpha) return;
|
||||
if (abs(p1 - p0) >= beta) return;
|
||||
if (abs(q1 - q0) >= beta) return;
|
||||
|
||||
bool strong_common = abs(p0 - q0) < (alpha >> 2) + 2;
|
||||
bool strong_p = strong_common && abs(p2 - p0) < beta;
|
||||
bool strong_q = strong_common && abs(q2 - q0) < beta;
|
||||
|
||||
if (strong_p) {
|
||||
u_dst.dst[dst_off - 1u] = uint8_t(clamp((p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4) >> 3, 0, 255));
|
||||
u_dst.dst[dst_off - 2u] = uint8_t(clamp((p2 + p1 + p0 + q0 + 2) >> 2, 0, 255));
|
||||
u_dst.dst[dst_off - 3u] = uint8_t(clamp((2*p3 + 3*p2 + p1 + p0 + q0 + 4) >> 3, 0, 255));
|
||||
} else {
|
||||
u_dst.dst[dst_off - 1u] = uint8_t(clamp((2*p1 + p0 + q1 + 2) >> 2, 0, 255));
|
||||
}
|
||||
|
||||
if (strong_q) {
|
||||
u_dst.dst[dst_off ] = uint8_t(clamp((q2 + 2*q1 + 2*q0 + 2*p0 + p1 + 4) >> 3, 0, 255));
|
||||
u_dst.dst[dst_off + 1u] = uint8_t(clamp((q2 + q1 + q0 + p0 + 2) >> 2, 0, 255));
|
||||
u_dst.dst[dst_off + 2u] = uint8_t(clamp((2*q3 + 3*q2 + q1 + q0 + p0 + 4) >> 3, 0, 255));
|
||||
} else {
|
||||
u_dst.dst[dst_off ] = uint8_t(clamp((2*q1 + q0 + p1 + 2) >> 2, 0, 255));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// daedalus-fourier — H.264 luma intra (bS=4) V deblock — V3D 7.1.
|
||||
//
|
||||
// Per H.264 §8.3.2.3: at I-MB edges and certain inter-MB edges that
|
||||
// force boundary strength to 4, the deblock kernel is structurally
|
||||
// different from bS<4 — it has a per-side strong/weak filter
|
||||
// selector that decides whether to update 3 cells (strong) or 1
|
||||
// (weak), reads p3/q3, and ignores tc0.
|
||||
//
|
||||
// strong_common = |p0-q0| < (α>>2) + 2
|
||||
// strong_p = strong_common AND |p2-p0| < β
|
||||
// strong_q = strong_common AND |q2-q0| < β
|
||||
//
|
||||
// Strong-p updates p0/p1/p2 with specific 5-/4-/3-tap blends.
|
||||
// Weak-p updates p0 only with (2*p1 + p0 + q1 + 2) >> 2.
|
||||
// Mirror for q-side.
|
||||
//
|
||||
// WG geometry identical to v3d_h264deblock.comp (16 edges × 16 lanes/WG).
|
||||
// dst_off contract: m.x ≥ 4*stride (kernel reads p3 at -4*stride).
|
||||
//
|
||||
// License: BSD-2-Clause. Algorithm transcribed from
|
||||
// tests/h264_intra_loop_filter_ref.c (PR #11).
|
||||
|
||||
#version 450
|
||||
#extension GL_EXT_shader_8bit_storage : require
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types : require
|
||||
|
||||
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||
layout(binding = 0) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||
layout(push_constant) uniform PC {
|
||||
uint n_edges, dst_stride_u8, _p0, _p1;
|
||||
} pc;
|
||||
|
||||
void main()
|
||||
{
|
||||
uint lane_in_wg = gl_GlobalInvocationID.x & 255u;
|
||||
uint edge_in_wg = lane_in_wg >> 4;
|
||||
uint col_in_edge = lane_in_wg & 15u;
|
||||
uint edge_idx = gl_WorkGroupID.x * 16u + edge_in_wg;
|
||||
if (edge_idx >= pc.n_edges) return;
|
||||
|
||||
uvec4 m = u_meta.meta[edge_idx];
|
||||
uint dst_off = m.x + col_in_edge;
|
||||
uint stride = pc.dst_stride_u8;
|
||||
int alpha = int(m.y & 0xffu);
|
||||
int beta = int((m.y >> 8) & 0xffu);
|
||||
if ((alpha | beta) == 0) return;
|
||||
|
||||
int p3 = int(u_dst.dst[dst_off - 4u * stride]);
|
||||
int p2 = int(u_dst.dst[dst_off - 3u * stride]);
|
||||
int p1 = int(u_dst.dst[dst_off - 2u * stride]);
|
||||
int p0 = int(u_dst.dst[dst_off - 1u * stride]);
|
||||
int q0 = int(u_dst.dst[dst_off]);
|
||||
int q1 = int(u_dst.dst[dst_off + 1u * stride]);
|
||||
int q2 = int(u_dst.dst[dst_off + 2u * stride]);
|
||||
int q3 = int(u_dst.dst[dst_off + 3u * stride]);
|
||||
|
||||
if (abs(p0 - q0) >= alpha) return;
|
||||
if (abs(p1 - p0) >= beta) return;
|
||||
if (abs(q1 - q0) >= beta) return;
|
||||
|
||||
bool strong_common = abs(p0 - q0) < (alpha >> 2) + 2;
|
||||
bool strong_p = strong_common && abs(p2 - p0) < beta;
|
||||
bool strong_q = strong_common && abs(q2 - q0) < beta;
|
||||
|
||||
if (strong_p) {
|
||||
u_dst.dst[dst_off - 1u * stride] = uint8_t(clamp((p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4) >> 3, 0, 255));
|
||||
u_dst.dst[dst_off - 2u * stride] = uint8_t(clamp((p2 + p1 + p0 + q0 + 2) >> 2, 0, 255));
|
||||
u_dst.dst[dst_off - 3u * stride] = uint8_t(clamp((2*p3 + 3*p2 + p1 + p0 + q0 + 4) >> 3, 0, 255));
|
||||
} else {
|
||||
u_dst.dst[dst_off - 1u * stride] = uint8_t(clamp((2*p1 + p0 + q1 + 2) >> 2, 0, 255));
|
||||
}
|
||||
|
||||
if (strong_q) {
|
||||
u_dst.dst[dst_off ] = uint8_t(clamp((q2 + 2*q1 + 2*q0 + 2*p0 + p1 + 4) >> 3, 0, 255));
|
||||
u_dst.dst[dst_off + 1u * stride] = uint8_t(clamp((q2 + q1 + q0 + p0 + 2) >> 2, 0, 255));
|
||||
u_dst.dst[dst_off + 2u * stride] = uint8_t(clamp((2*q3 + 3*q2 + q1 + q0 + p0 + 4) >> 3, 0, 255));
|
||||
} else {
|
||||
u_dst.dst[dst_off ] = uint8_t(clamp((2*q1 + q0 + p1 + 2) >> 2, 0, 255));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user