Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a9590acee3 | |||
| 989818c2e6 | |||
| 1446b779a6 | |||
| c2d1e9790e | |||
| e506ef0803 | |||
| 2079fe39c6 | |||
| 55d3618408 | |||
| 746533582e | |||
| 224f4be9e2 | |||
| e3c28495ae | |||
| 8b8e8dc6e8 | |||
| 02d564b43e | |||
| 2074a50554 | |||
| bc5edf656d | |||
| 37b75b5813 | |||
| d8de7754fa | |||
| de9266a6eb | |||
| 3db059ffab | |||
| 2faa849ce2 | |||
| cb3aef3dac | |||
| 31c68d0d0e | |||
| df9e1c9d78 |
+162
-26
@@ -284,6 +284,55 @@ if (DAEDALUS_BUILD_VULKAN)
|
|||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(H264DEBLOCK_H_SPV ${CMAKE_BINARY_DIR}/v3d_h264deblock_h.spv)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${H264DEBLOCK_H_SPV}
|
||||||
|
COMMAND ${GLSLANG_VALIDATOR} -V --target-env vulkan1.3
|
||||||
|
-o ${H264DEBLOCK_H_SPV}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/v3d_h264deblock_h.comp
|
||||||
|
DEPENDS ${CMAKE_SOURCE_DIR}/src/v3d_h264deblock_h.comp
|
||||||
|
COMMENT "glslang: v3d_h264deblock_h.comp -> v3d_h264deblock_h.spv"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
set(H264DEBLOCK_CHROMA_V_SPV ${CMAKE_BINARY_DIR}/v3d_h264deblock_chroma_v.spv)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${H264DEBLOCK_CHROMA_V_SPV}
|
||||||
|
COMMAND ${GLSLANG_VALIDATOR} -V --target-env vulkan1.3
|
||||||
|
-o ${H264DEBLOCK_CHROMA_V_SPV}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/v3d_h264deblock_chroma_v.comp
|
||||||
|
DEPENDS ${CMAKE_SOURCE_DIR}/src/v3d_h264deblock_chroma_v.comp
|
||||||
|
COMMENT "glslang: v3d_h264deblock_chroma_v.comp -> .spv"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
set(H264DEBLOCK_CHROMA_H_SPV ${CMAKE_BINARY_DIR}/v3d_h264deblock_chroma_h.spv)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${H264DEBLOCK_CHROMA_H_SPV}
|
||||||
|
COMMAND ${GLSLANG_VALIDATOR} -V --target-env vulkan1.3
|
||||||
|
-o ${H264DEBLOCK_CHROMA_H_SPV}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/v3d_h264deblock_chroma_h.comp
|
||||||
|
DEPENDS ${CMAKE_SOURCE_DIR}/src/v3d_h264deblock_chroma_h.comp
|
||||||
|
COMMENT "glslang: v3d_h264deblock_chroma_h.comp -> .spv"
|
||||||
|
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)
|
set(H264_IDCT4_SPV ${CMAKE_BINARY_DIR}/v3d_h264_idct4.spv)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${H264_IDCT4_SPV}
|
OUTPUT ${H264_IDCT4_SPV}
|
||||||
@@ -317,7 +366,63 @@ if (DAEDALUS_BUILD_VULKAN)
|
|||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(daedalus_shaders ALL DEPENDS ${NOOP_SPV} ${IDCT8_SPV} ${LPF_SPV} ${MC_SPV} ${LPF8_SPV} ${CDEF_SPV} ${H264DEBLOCK_SPV} ${H264_IDCT4_SPV} ${H264_IDCT8_SPV} ${H264_QPEL_MC20_SPV})
|
set(H264_QPEL_MC02_SPV ${CMAKE_BINARY_DIR}/v3d_h264_qpel_mc02.spv)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${H264_QPEL_MC02_SPV}
|
||||||
|
COMMAND ${GLSLANG_VALIDATOR} -V --target-env vulkan1.3
|
||||||
|
-o ${H264_QPEL_MC02_SPV}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/v3d_h264_qpel_mc02.comp
|
||||||
|
DEPENDS ${CMAKE_SOURCE_DIR}/src/v3d_h264_qpel_mc02.comp
|
||||||
|
COMMENT "glslang: v3d_h264_qpel_mc02.comp -> v3d_h264_qpel_mc02.spv"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
set(H264_QPEL_MC22_SPV ${CMAKE_BINARY_DIR}/v3d_h264_qpel_mc22.spv)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${H264_QPEL_MC22_SPV}
|
||||||
|
COMMAND ${GLSLANG_VALIDATOR} -V --target-env vulkan1.3
|
||||||
|
-o ${H264_QPEL_MC22_SPV}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/v3d_h264_qpel_mc22.comp
|
||||||
|
DEPENDS ${CMAKE_SOURCE_DIR}/src/v3d_h264_qpel_mc22.comp
|
||||||
|
COMMENT "glslang: v3d_h264_qpel_mc22.comp -> v3d_h264_qpel_mc22.spv"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# Quarter-pel single-axis variants (mc10/30/01/03) + diagonal
|
||||||
|
# variants (mc11/12/13/21/23/31/32/33) — each composes 1-2 half-pel
|
||||||
|
# results with optional L2 averaging. Same WG geometry as mc20/mc02.
|
||||||
|
foreach(_mc mc10 mc30 mc01 mc03 mc11 mc12 mc13 mc21 mc23 mc31 mc32 mc33)
|
||||||
|
set(_spv ${CMAKE_BINARY_DIR}/v3d_h264_qpel_${_mc}.spv)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${_spv}
|
||||||
|
COMMAND ${GLSLANG_VALIDATOR} -V --target-env vulkan1.3
|
||||||
|
-o ${_spv}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/v3d_h264_qpel_${_mc}.comp
|
||||||
|
DEPENDS ${CMAKE_SOURCE_DIR}/src/v3d_h264_qpel_${_mc}.comp
|
||||||
|
COMMENT "glslang: v3d_h264_qpel_${_mc}.comp -> .spv"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
set(H264_QPEL_${_mc}_SPV ${_spv})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# avg_ biprediction variants — same shader as put_ + extra L2 with
|
||||||
|
# existing dst. All 15 useful positions.
|
||||||
|
foreach(_mc mc20 mc02 mc22 mc10 mc30 mc01 mc03
|
||||||
|
mc11 mc12 mc13 mc21 mc23 mc31 mc32 mc33)
|
||||||
|
set(_spv ${CMAKE_BINARY_DIR}/v3d_h264_qpel_avg_${_mc}.spv)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${_spv}
|
||||||
|
COMMAND ${GLSLANG_VALIDATOR} -V --target-env vulkan1.3
|
||||||
|
-o ${_spv}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/v3d_h264_qpel_avg_${_mc}.comp
|
||||||
|
DEPENDS ${CMAKE_SOURCE_DIR}/src/v3d_h264_qpel_avg_${_mc}.comp
|
||||||
|
COMMENT "glslang: v3d_h264_qpel_avg_${_mc}.comp -> .spv"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
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} ${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.
|
# v3d_runner — reusable Vulkan plumbing.
|
||||||
add_library(v3d_runner STATIC src/v3d_runner.c)
|
add_library(v3d_runner STATIC src/v3d_runner.c)
|
||||||
@@ -392,6 +497,10 @@ endif()
|
|||||||
add_library(daedalus_core STATIC
|
add_library(daedalus_core STATIC
|
||||||
src/daedalus_core.c
|
src/daedalus_core.c
|
||||||
src/h264_chroma_dc.c
|
src/h264_chroma_dc.c
|
||||||
|
src/h264_intra_pred_4x4.c
|
||||||
|
src/h264_intra_pred_16x16.c
|
||||||
|
src/h264_intra_pred_chroma8x8.c
|
||||||
|
src/h264_intra_pred_8x8_luma.c
|
||||||
src/v3d_runner.c
|
src/v3d_runner.c
|
||||||
${FFASM_SOURCES}
|
${FFASM_SOURCES}
|
||||||
${FFASM_LPF_SOURCES}
|
${FFASM_LPF_SOURCES}
|
||||||
@@ -446,9 +555,45 @@ if (DAEDALUS_BUILD_VULKAN)
|
|||||||
${LPF8_SPV}
|
${LPF8_SPV}
|
||||||
${CDEF_SPV}
|
${CDEF_SPV}
|
||||||
${H264DEBLOCK_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_IDCT4_SPV}
|
||||||
${H264_IDCT8_SPV}
|
${H264_IDCT8_SPV}
|
||||||
${H264_QPEL_MC20_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}
|
||||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/daedalus-fourier/shaders
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/daedalus-fourier/shaders
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
@@ -538,38 +683,29 @@ add_executable(test_api_opportunistic_qpu tests/test_api_opportunistic_qpu.c)
|
|||||||
target_link_libraries(test_api_opportunistic_qpu PRIVATE daedalus_core)
|
target_link_libraries(test_api_opportunistic_qpu PRIVATE daedalus_core)
|
||||||
target_compile_options(test_api_opportunistic_qpu PRIVATE -O2)
|
target_compile_options(test_api_opportunistic_qpu PRIVATE -O2)
|
||||||
|
|
||||||
# H.264 Intra_4x4 luma prediction (9 modes) — reference + tests.
|
# H.264 Intra_4x4 luma prediction (9 modes) — public src primitives.
|
||||||
# Pure CPU + spec-derived; no daedalus_core dependency yet (this is
|
# The bodies now live in src/h264_intra_pred_4x4.c (linked into
|
||||||
# the bit-exact gate for the eventual shader / dispatch wiring).
|
# daedalus_core for use by libavcodec.so substitution-arc consumers).
|
||||||
add_executable(test_intra_pred_4x4
|
# This test exercises the public symbols.
|
||||||
tests/test_intra_pred_4x4.c
|
add_executable(test_intra_pred_4x4 tests/test_intra_pred_4x4.c)
|
||||||
tests/h264_intra_pred_4x4_ref.c
|
target_link_libraries(test_intra_pred_4x4 PRIVATE daedalus_core)
|
||||||
)
|
|
||||||
target_compile_options(test_intra_pred_4x4 PRIVATE -O2)
|
target_compile_options(test_intra_pred_4x4 PRIVATE -O2)
|
||||||
|
|
||||||
# H.264 Intra_16x16 luma prediction (4 modes: V, H, DC, Plane) —
|
# H.264 Intra_16x16 luma prediction (4 modes) — public src primitives,
|
||||||
# reference + tests. Same spec-gate role as the 4x4 sibling.
|
# linked from daedalus_core.
|
||||||
add_executable(test_intra_pred_16x16
|
add_executable(test_intra_pred_16x16 tests/test_intra_pred_16x16.c)
|
||||||
tests/test_intra_pred_16x16.c
|
target_link_libraries(test_intra_pred_16x16 PRIVATE daedalus_core)
|
||||||
tests/h264_intra_pred_16x16_ref.c
|
|
||||||
)
|
|
||||||
target_compile_options(test_intra_pred_16x16 PRIVATE -O2)
|
target_compile_options(test_intra_pred_16x16 PRIVATE -O2)
|
||||||
|
|
||||||
# H.264 Intra_8x8 chroma prediction (4 modes: DC, H, V, Plane) —
|
# H.264 Intra_8x8 chroma prediction (4 modes) — public src primitives.
|
||||||
# reference + tests. DC is per-quadrant (asymmetric); Plane uses
|
add_executable(test_intra_pred_chroma8x8 tests/test_intra_pred_chroma8x8.c)
|
||||||
# slope coefficient 34 instead of luma's 5.
|
target_link_libraries(test_intra_pred_chroma8x8 PRIVATE daedalus_core)
|
||||||
add_executable(test_intra_pred_chroma8x8
|
|
||||||
tests/test_intra_pred_chroma8x8.c
|
|
||||||
tests/h264_intra_pred_chroma8x8_ref.c
|
|
||||||
)
|
|
||||||
target_compile_options(test_intra_pred_chroma8x8 PRIVATE -O2)
|
target_compile_options(test_intra_pred_chroma8x8 PRIVATE -O2)
|
||||||
|
|
||||||
# H.264 Intra_8x8 luma prediction (High profile, 9 modes + 1-2-1
|
# H.264 Intra_8x8 luma prediction (High profile, 9 modes + 1-2-1
|
||||||
# reference-sample pre-filter).
|
# pre-filter) — public src primitives.
|
||||||
add_executable(test_intra_pred_8x8_luma
|
add_executable(test_intra_pred_8x8_luma tests/test_intra_pred_8x8_luma.c)
|
||||||
tests/test_intra_pred_8x8_luma.c
|
target_link_libraries(test_intra_pred_8x8_luma PRIVATE daedalus_core)
|
||||||
tests/h264_intra_pred_8x8_luma_ref.c
|
|
||||||
)
|
|
||||||
target_compile_options(test_intra_pred_8x8_luma PRIVATE -O2)
|
target_compile_options(test_intra_pred_8x8_luma PRIVATE -O2)
|
||||||
|
|
||||||
# H.264 chroma DC 2x2 Hadamard pre-pass primitive. Pure transform,
|
# H.264 chroma DC 2x2 Hadamard pre-pass primitive. Pure transform,
|
||||||
|
|||||||
@@ -559,6 +559,73 @@ DECLARE_QPEL_AVG(avg_mc33)
|
|||||||
* ----------------------------------------------------------------- */
|
* ----------------------------------------------------------------- */
|
||||||
void daedalus_h264_chroma_dc_hadamard_2x2(int16_t c[4]);
|
void daedalus_h264_chroma_dc_hadamard_2x2(int16_t c[4]);
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------
|
||||||
|
* H.264 Intra_4x4 luma prediction (per H.264 §8.3.1.4). 9 modes.
|
||||||
|
*
|
||||||
|
* Pure CPU primitives — each is a small straightforward fill of a
|
||||||
|
* 4x4 output block from neighbour pixels in the same buffer. No
|
||||||
|
* substrate-dispatch wrapper (the work is too small to amortise).
|
||||||
|
*
|
||||||
|
* FFmpeg-style interface: `dst` at row 0 col 0 of the 4x4 output.
|
||||||
|
* Reads top-left at dst[-stride-1], top at dst[-stride..-stride+7]
|
||||||
|
* (top-right for DDL/VL), and left at dst[r*stride - 1] for r=0..3.
|
||||||
|
* Caller must ensure all 13 neighbour bytes are valid (interior-MB
|
||||||
|
* assumption — H.264 availability fallback handled at caller).
|
||||||
|
*
|
||||||
|
* Bit-exact validated against tests/test_intra_pred_4x4.c (10-case
|
||||||
|
* spec-derived test suite including the asymmetric Vertical_Right
|
||||||
|
* 16-cell hand-derived case; see fourier PR #12).
|
||||||
|
* ----------------------------------------------------------------- */
|
||||||
|
void daedalus_h264_pred_4x4_vertical (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_4x4_horizontal(uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_4x4_dc (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_4x4_ddl (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_4x4_ddr (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_4x4_vr (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_4x4_hd (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_4x4_vl (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_4x4_hu (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------
|
||||||
|
* H.264 Intra_16x16 luma prediction (per §8.3.2). 4 modes:
|
||||||
|
* Vertical / Horizontal / DC / Plane. Same FFmpeg-style interface
|
||||||
|
* as the 4x4 family at 16x16 scale. Same neighbour availability
|
||||||
|
* assumption (interior-MB).
|
||||||
|
* ----------------------------------------------------------------- */
|
||||||
|
void daedalus_h264_pred_16x16_vertical (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_16x16_horizontal(uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_16x16_dc (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_16x16_plane (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------
|
||||||
|
* H.264 Intra_8x8 chroma prediction (per §8.3.3, 4:2:0). 4 modes:
|
||||||
|
* DC / Horizontal / Vertical / Plane. Note: DC is per-quadrant
|
||||||
|
* asymmetric; Plane uses slope coefficient 34 (not luma's 5).
|
||||||
|
* ----------------------------------------------------------------- */
|
||||||
|
void daedalus_h264_pred_chroma8x8_dc (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_chroma8x8_horizontal(uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_chroma8x8_vertical (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_chroma8x8_plane (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------
|
||||||
|
* H.264 Intra_8x8 luma prediction (High profile, per §8.3.2.1).
|
||||||
|
* 9 modes with the spec-defined 1-2-1 reference-sample pre-filter
|
||||||
|
* applied internally to the 25 neighbours before the mode arithmetic.
|
||||||
|
*
|
||||||
|
* "_8x8l" naming follows the FFmpeg h264pred_template convention
|
||||||
|
* (pred8x8l_<mode>_c) to keep the substitution wrappers a 1:1 name
|
||||||
|
* map.
|
||||||
|
* ----------------------------------------------------------------- */
|
||||||
|
void daedalus_h264_pred_8x8l_vertical (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_8x8l_horizontal(uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_8x8l_dc (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_8x8l_ddl (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_8x8l_ddr (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_8x8l_vr (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_8x8l_hd (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_8x8l_vl (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
void daedalus_h264_pred_8x8l_hu (uint8_t *dst, ptrdiff_t stride);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------
|
/* -------------------------------------------------------------------
|
||||||
* Recipe query — what does the API recommend for each kernel?
|
* Recipe query — what does the API recommend for each kernel?
|
||||||
* ----------------------------------------------------------------- */
|
* ----------------------------------------------------------------- */
|
||||||
|
|||||||
+843
-94
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,7 @@
|
|||||||
static inline int clip_u8(int v) { return v < 0 ? 0 : v > 255 ? 255 : v; }
|
static inline int clip_u8(int v) { return v < 0 ? 0 : v > 255 ? 255 : v; }
|
||||||
|
|
||||||
/* Mode 0 — Vertical: each col = top[col]. */
|
/* Mode 0 — Vertical: each col = top[col]. */
|
||||||
void daedalus_h264_pred_16x16_vertical_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_16x16_vertical(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
for (int r = 0; r < 16; r++)
|
for (int r = 0; r < 16; r++)
|
||||||
@@ -37,7 +37,7 @@ void daedalus_h264_pred_16x16_vertical_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 1 — Horizontal: each row = left[row]. */
|
/* Mode 1 — Horizontal: each row = left[row]. */
|
||||||
void daedalus_h264_pred_16x16_horizontal_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_16x16_horizontal(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
for (int r = 0; r < 16; r++) {
|
for (int r = 0; r < 16; r++) {
|
||||||
uint8_t l = dst[r * stride - 1];
|
uint8_t l = dst[r * stride - 1];
|
||||||
@@ -46,7 +46,7 @@ void daedalus_h264_pred_16x16_horizontal_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 2 — DC: ((sum_top16 + sum_left16 + 16) >> 5) broadcast. */
|
/* Mode 2 — DC: ((sum_top16 + sum_left16 + 16) >> 5) broadcast. */
|
||||||
void daedalus_h264_pred_16x16_dc_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_16x16_dc(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
int sum = 16; /* rounding for >> 5 over 32 samples */
|
int sum = 16; /* rounding for >> 5 over 32 samples */
|
||||||
@@ -77,7 +77,7 @@ void daedalus_h264_pred_16x16_dc_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
* (it does NOT participate in the H/V sums in the 16x16 case — only
|
* (it does NOT participate in the H/V sums in the 16x16 case — only
|
||||||
* for the chroma 8x8 plane mode).
|
* for the chroma 8x8 plane mode).
|
||||||
*/
|
*/
|
||||||
void daedalus_h264_pred_16x16_plane_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_16x16_plane(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
/* H accumulates differences across the right vs left half of the
|
/* H accumulates differences across the right vs left half of the
|
||||||
@@ -52,7 +52,7 @@ static inline uint8_t avg2(int a, int b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 0 — Vertical: each col = top[col]. */
|
/* Mode 0 — Vertical: each col = top[col]. */
|
||||||
void daedalus_h264_pred_4x4_vertical_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_4x4_vertical(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
for (int r = 0; r < 4; r++) {
|
for (int r = 0; r < 4; r++) {
|
||||||
@@ -61,7 +61,7 @@ void daedalus_h264_pred_4x4_vertical_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 1 — Horizontal: each row = left[row]. */
|
/* Mode 1 — Horizontal: each row = left[row]. */
|
||||||
void daedalus_h264_pred_4x4_horizontal_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_4x4_horizontal(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
for (int r = 0; r < 4; r++) {
|
for (int r = 0; r < 4; r++) {
|
||||||
uint8_t l = dst[r * stride - 1];
|
uint8_t l = dst[r * stride - 1];
|
||||||
@@ -70,7 +70,7 @@ void daedalus_h264_pred_4x4_horizontal_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 2 — DC: mean of top 4 + left 4, broadcast. */
|
/* Mode 2 — DC: mean of top 4 + left 4, broadcast. */
|
||||||
void daedalus_h264_pred_4x4_dc_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_4x4_dc(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
int sum = 4; /* rounding for ((sum + 4) >> 3) */
|
int sum = 4; /* rounding for ((sum + 4) >> 3) */
|
||||||
@@ -82,7 +82,7 @@ void daedalus_h264_pred_4x4_dc_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 3 — Diagonal_Down_Left. Uses top[0..7] (incl. top-right). */
|
/* Mode 3 — Diagonal_Down_Left. Uses top[0..7] (incl. top-right). */
|
||||||
void daedalus_h264_pred_4x4_ddl_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_4x4_ddl(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
int t0 = top[0], t1 = top[1], t2 = top[2], t3 = top[3];
|
int t0 = top[0], t1 = top[1], t2 = top[2], t3 = top[3];
|
||||||
@@ -102,7 +102,7 @@ void daedalus_h264_pred_4x4_ddl_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 4 — Diagonal_Down_Right. Uses top-left + top[0..3] + left[0..3]. */
|
/* Mode 4 — Diagonal_Down_Right. Uses top-left + top[0..3] + left[0..3]. */
|
||||||
void daedalus_h264_pred_4x4_ddr_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_4x4_ddr(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
int tl = dst[-stride - 1];
|
int tl = dst[-stride - 1];
|
||||||
int t0 = dst[-stride + 0], t1 = dst[-stride + 1];
|
int t0 = dst[-stride + 0], t1 = dst[-stride + 1];
|
||||||
@@ -123,7 +123,7 @@ void daedalus_h264_pred_4x4_ddr_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 5 — Vertical_Right. */
|
/* Mode 5 — Vertical_Right. */
|
||||||
void daedalus_h264_pred_4x4_vr_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_4x4_vr(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
int tl = dst[-stride - 1];
|
int tl = dst[-stride - 1];
|
||||||
int t0 = dst[-stride + 0], t1 = dst[-stride + 1];
|
int t0 = dst[-stride + 0], t1 = dst[-stride + 1];
|
||||||
@@ -153,7 +153,7 @@ void daedalus_h264_pred_4x4_vr_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 6 — Horizontal_Down. */
|
/* Mode 6 — Horizontal_Down. */
|
||||||
void daedalus_h264_pred_4x4_hd_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_4x4_hd(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
int tl = dst[-stride - 1];
|
int tl = dst[-stride - 1];
|
||||||
int t0 = dst[-stride + 0], t1 = dst[-stride + 1], t2 = dst[-stride + 2];
|
int t0 = dst[-stride + 0], t1 = dst[-stride + 1], t2 = dst[-stride + 2];
|
||||||
@@ -182,7 +182,7 @@ void daedalus_h264_pred_4x4_hd_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 7 — Vertical_Left. Uses top[0..7]. */
|
/* Mode 7 — Vertical_Left. Uses top[0..7]. */
|
||||||
void daedalus_h264_pred_4x4_vl_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_4x4_vl(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
int t0=top[0], t1=top[1], t2=top[2], t3=top[3];
|
int t0=top[0], t1=top[1], t2=top[2], t3=top[3];
|
||||||
@@ -211,7 +211,7 @@ void daedalus_h264_pred_4x4_vl_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 8 — Horizontal_Up. Uses left[0..3] only. */
|
/* Mode 8 — Horizontal_Up. Uses left[0..3] only. */
|
||||||
void daedalus_h264_pred_4x4_hu_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_4x4_hu(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
int l0 = dst[ 0*stride - 1], l1 = dst[ 1*stride - 1];
|
int l0 = dst[ 0*stride - 1], l1 = dst[ 1*stride - 1];
|
||||||
int l2 = dst[ 2*stride - 1], l3 = dst[ 3*stride - 1];
|
int l2 = dst[ 2*stride - 1], l3 = dst[ 3*stride - 1];
|
||||||
@@ -90,7 +90,7 @@ static void filter_refs(const uint8_t *dst, ptrdiff_t stride,
|
|||||||
#define FTL filt[0] /* filtered top-left */
|
#define FTL filt[0] /* filtered top-left */
|
||||||
|
|
||||||
/* Mode 0 Vertical (§8.3.2.1.2): pred[r,c] = filt_top[c]. */
|
/* Mode 0 Vertical (§8.3.2.1.2): pred[r,c] = filt_top[c]. */
|
||||||
void daedalus_h264_pred_8x8l_vertical_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_8x8l_vertical(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
uint8_t filt[25];
|
uint8_t filt[25];
|
||||||
filter_refs(dst, stride, filt);
|
filter_refs(dst, stride, filt);
|
||||||
@@ -99,7 +99,7 @@ void daedalus_h264_pred_8x8l_vertical_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 1 Horizontal (§8.3.2.1.3): pred[r,c] = filt_left[r]. */
|
/* Mode 1 Horizontal (§8.3.2.1.3): pred[r,c] = filt_left[r]. */
|
||||||
void daedalus_h264_pred_8x8l_horizontal_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_8x8l_horizontal(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
uint8_t filt[25];
|
uint8_t filt[25];
|
||||||
filter_refs(dst, stride, filt);
|
filter_refs(dst, stride, filt);
|
||||||
@@ -110,7 +110,7 @@ void daedalus_h264_pred_8x8l_horizontal_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
/* Mode 2 DC (§8.3.2.1.4): ((sum_filt_top[0..7] + sum_filt_left[0..7]
|
/* Mode 2 DC (§8.3.2.1.4): ((sum_filt_top[0..7] + sum_filt_left[0..7]
|
||||||
* + 8) >> 4) broadcast. Note the +8 (not +4 like 4x4): there are
|
* + 8) >> 4) broadcast. Note the +8 (not +4 like 4x4): there are
|
||||||
* 16 samples summed total, so >> 4 with half-step rounding +8. */
|
* 16 samples summed total, so >> 4 with half-step rounding +8. */
|
||||||
void daedalus_h264_pred_8x8l_dc_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_8x8l_dc(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
uint8_t filt[25];
|
uint8_t filt[25];
|
||||||
filter_refs(dst, stride, filt);
|
filter_refs(dst, stride, filt);
|
||||||
@@ -143,7 +143,7 @@ void daedalus_h264_pred_8x8l_dc_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
#define LT FTL
|
#define LT FTL
|
||||||
|
|
||||||
/* Mode 3 DDL (Diagonal_Down_Left) — uses TOP + TOP_RIGHT, no LEFT. */
|
/* Mode 3 DDL (Diagonal_Down_Left) — uses TOP + TOP_RIGHT, no LEFT. */
|
||||||
void daedalus_h264_pred_8x8l_ddl_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_8x8l_ddl(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
uint8_t filt[25];
|
uint8_t filt[25];
|
||||||
filter_refs(dst, stride, filt);
|
filter_refs(dst, stride, filt);
|
||||||
@@ -165,7 +165,7 @@ void daedalus_h264_pred_8x8l_ddl_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 4 DDR (Diagonal_Down_Right). */
|
/* Mode 4 DDR (Diagonal_Down_Right). */
|
||||||
void daedalus_h264_pred_8x8l_ddr_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_8x8l_ddr(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
uint8_t filt[25];
|
uint8_t filt[25];
|
||||||
filter_refs(dst, stride, filt);
|
filter_refs(dst, stride, filt);
|
||||||
@@ -187,7 +187,7 @@ void daedalus_h264_pred_8x8l_ddr_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 5 VR (Vertical_Right). */
|
/* Mode 5 VR (Vertical_Right). */
|
||||||
void daedalus_h264_pred_8x8l_vr_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_8x8l_vr(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
uint8_t filt[25];
|
uint8_t filt[25];
|
||||||
filter_refs(dst, stride, filt);
|
filter_refs(dst, stride, filt);
|
||||||
@@ -216,7 +216,7 @@ void daedalus_h264_pred_8x8l_vr_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 6 HD (Horizontal_Down). */
|
/* Mode 6 HD (Horizontal_Down). */
|
||||||
void daedalus_h264_pred_8x8l_hd_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_8x8l_hd(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
uint8_t filt[25];
|
uint8_t filt[25];
|
||||||
filter_refs(dst, stride, filt);
|
filter_refs(dst, stride, filt);
|
||||||
@@ -245,7 +245,7 @@ void daedalus_h264_pred_8x8l_hd_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 7 VL (Vertical_Left) — uses TOP + TOP_RIGHT only. */
|
/* Mode 7 VL (Vertical_Left) — uses TOP + TOP_RIGHT only. */
|
||||||
void daedalus_h264_pred_8x8l_vl_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_8x8l_vl(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
uint8_t filt[25];
|
uint8_t filt[25];
|
||||||
filter_refs(dst, stride, filt);
|
filter_refs(dst, stride, filt);
|
||||||
@@ -274,7 +274,7 @@ void daedalus_h264_pred_8x8l_vl_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 8 HU (Horizontal_Up) — uses LEFT only. */
|
/* Mode 8 HU (Horizontal_Up) — uses LEFT only. */
|
||||||
void daedalus_h264_pred_8x8l_hu_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_8x8l_hu(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
uint8_t filt[25];
|
uint8_t filt[25];
|
||||||
filter_refs(dst, stride, filt);
|
filter_refs(dst, stride, filt);
|
||||||
@@ -43,7 +43,7 @@ static inline int clip_u8(int v) { return v < 0 ? 0 : v > 255 ? 255 : v; }
|
|||||||
* quadrant ignores the top-left-half because that half is "vertically
|
* quadrant ignores the top-left-half because that half is "vertically
|
||||||
* above" the top-left quadrant; the spec uses top[4..7] only.
|
* above" the top-left quadrant; the spec uses top[4..7] only.
|
||||||
*/
|
*/
|
||||||
void daedalus_h264_pred_chroma8x8_dc_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_chroma8x8_dc(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
int top_lo = 0, top_hi = 0, left_lo = 0, left_hi = 0;
|
int top_lo = 0, top_hi = 0, left_lo = 0, left_hi = 0;
|
||||||
@@ -68,7 +68,7 @@ void daedalus_h264_pred_chroma8x8_dc_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 1 — Horizontal: each row = left[row]. */
|
/* Mode 1 — Horizontal: each row = left[row]. */
|
||||||
void daedalus_h264_pred_chroma8x8_horizontal_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_chroma8x8_horizontal(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
for (int r = 0; r < 8; r++) {
|
for (int r = 0; r < 8; r++) {
|
||||||
uint8_t l = dst[r * stride - 1];
|
uint8_t l = dst[r * stride - 1];
|
||||||
@@ -77,7 +77,7 @@ void daedalus_h264_pred_chroma8x8_horizontal_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mode 2 — Vertical: each col = top[col]. */
|
/* Mode 2 — Vertical: each col = top[col]. */
|
||||||
void daedalus_h264_pred_chroma8x8_vertical_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_chroma8x8_vertical(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
for (int r = 0; r < 8; r++)
|
for (int r = 0; r < 8; r++)
|
||||||
@@ -97,7 +97,7 @@ void daedalus_h264_pred_chroma8x8_vertical_ref(uint8_t *dst, ptrdiff_t stride)
|
|||||||
* - Centre is (x-3, y-3) (not x-7, y-7).
|
* - Centre is (x-3, y-3) (not x-7, y-7).
|
||||||
* - Spans 4 differences per sum (not 8).
|
* - Spans 4 differences per sum (not 8).
|
||||||
*/
|
*/
|
||||||
void daedalus_h264_pred_chroma8x8_plane_ref(uint8_t *dst, ptrdiff_t stride)
|
void daedalus_h264_pred_chroma8x8_plane(uint8_t *dst, ptrdiff_t stride)
|
||||||
{
|
{
|
||||||
const uint8_t *top = dst - stride;
|
const uint8_t *top = dst - stride;
|
||||||
int H = 0, V = 0;
|
int H = 0, V = 0;
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc01 (biprediction) (8x8, ¼-pel vertical),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 "d" position:
|
||||||
|
//
|
||||||
|
// dst[r,c] = ((clip255(mc02(s)[r,c]) + s[r,c] + 1) >> 1)
|
||||||
|
//
|
||||||
|
// Sibling of v3d_h264_qpel_mc02.comp with L2 step against src[r, c].
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc01_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int vp = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
int avg = (vp + s_0 + 1) >> 1; // L2 with src[r, c]
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc02 (biprediction) (8x8, vertical half-pel), V3D 7.1.
|
||||||
|
//
|
||||||
|
// Sibling of cycle 9's v3d_h264_qpel_mc20.comp. Same 6-tap filter,
|
||||||
|
// transposed to vertical direction:
|
||||||
|
//
|
||||||
|
// dst[r,c] = clip255(
|
||||||
|
// ( s[r-2,c]
|
||||||
|
// - 5 * s[r-1,c]
|
||||||
|
// + 20 * s[r, c]
|
||||||
|
// + 20 * s[r+1,c]
|
||||||
|
// - 5 * s[r+2,c]
|
||||||
|
// + s[r+3,c]
|
||||||
|
// + 16
|
||||||
|
// ) >> 5)
|
||||||
|
//
|
||||||
|
// src+src_off points at row 0 col 0 of the OUTPUT block; the filter
|
||||||
|
// reads rows -2..+3 (2 rows of top context, 3 rows of bottom).
|
||||||
|
//
|
||||||
|
// Same WG layout as mc20: 64 lanes / 1 block-per-WG / 1 lane-per-pixel.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc02_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PC {
|
||||||
|
uint n_blocks;
|
||||||
|
uint stride_u8;
|
||||||
|
uint _pad0, _pad1;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3;
|
||||||
|
uint c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
// Read the 6 rows of vertical context at col (c) of THIS output row.
|
||||||
|
// src_off+r*stride+c is at the OUTPUT pixel position; the kernel
|
||||||
|
// samples r-2..r+3 along the column. Unsigned-safe because the
|
||||||
|
// public API contract guarantees src_off >= 2*stride.
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int p = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + p + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc03 (biprediction) (8x8, ¾-pel vertical),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 "n" position:
|
||||||
|
//
|
||||||
|
// dst[r,c] = ((clip255(mc02(s)[r,c]) + s[r+1, c] + 1) >> 1)
|
||||||
|
//
|
||||||
|
// Same as mc01 but L2-averages with src[r+1, c] instead of src[r, c].
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc03_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int vp = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
int avg = (vp + s_p1 + 1) >> 1; // L2 with src[r+1, c]
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc10 (biprediction) (8x8, ¼-pel horizontal),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 "a" position:
|
||||||
|
//
|
||||||
|
// dst[r,c] = ((clip255(mc20(s)[r,c]) + s[r,c] + 1) >> 1)
|
||||||
|
//
|
||||||
|
// = horizontal half-pel filter, clipped to u8, then L2 rounded-averaged
|
||||||
|
// with the integer source pixel at the SAME position. Sibling of
|
||||||
|
// v3d_h264_qpel_mc20.comp with the L2 step added at the tail.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc10_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int hp = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
// L2 average with the integer source at the SAME (r, c) position.
|
||||||
|
int avg = (hp + s_0 + 1) >> 1;
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc11 (biprediction) (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc11[r,c] = avg(mc20(r, c),
|
||||||
|
// mc02(r, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc11_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_h(src_off, stride, r, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc12 (biprediction) (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc12[r,c] = avg(mc22(r, c),
|
||||||
|
// mc02(r, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc12_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_hv(src_off, stride, r, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc13 (biprediction) (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc13[r,c] = avg(mc20(r+1, c),
|
||||||
|
// mc02(r, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc13_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_h(src_off, stride, r+1u, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc20 (biprediction) (8x8, horizontal half-pel), V3D 7.1.
|
||||||
|
//
|
||||||
|
// H.264 spec §8.4.2.2.1 horizontal 6-tap luma interpolation:
|
||||||
|
//
|
||||||
|
// dst[r,c] = clip255(
|
||||||
|
// ( s[r,c-2]
|
||||||
|
// - 5 * s[r,c-1]
|
||||||
|
// + 20 * s[r,c]
|
||||||
|
// + 20 * s[r,c+1]
|
||||||
|
// - 5 * s[r,c+2]
|
||||||
|
// + s[r,c+3]
|
||||||
|
// + 16
|
||||||
|
// ) >> 5)
|
||||||
|
//
|
||||||
|
// Single-stride: dst and src share `stride` (H264QpelContext
|
||||||
|
// convention). src+src_off already points at the leftmost output
|
||||||
|
// column (col 0); the filter reads cols -2..+3. Caller guarantees
|
||||||
|
// edge-padding context per the public API docstring.
|
||||||
|
//
|
||||||
|
// Workgroup layout: 64 invocations = 1 lane per output pixel.
|
||||||
|
// 1 block per WG; n_blocks WGs total. This is the simplest layout
|
||||||
|
// that avoids any inter-lane communication — each lane independently
|
||||||
|
// reads its 6 src samples and writes its 1 dst sample. V3D's L2
|
||||||
|
// cache handles the redundant reads from adjacent lanes.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc20_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0) readonly buffer Src {
|
||||||
|
uint8_t src[];
|
||||||
|
} u_src;
|
||||||
|
|
||||||
|
layout(binding = 1) buffer Dst {
|
||||||
|
uint8_t dst[];
|
||||||
|
} u_dst;
|
||||||
|
|
||||||
|
layout(binding = 2) readonly buffer Meta {
|
||||||
|
uvec4 meta[]; // .x = dst_off, .y = src_off
|
||||||
|
} u_meta;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PC {
|
||||||
|
uint n_blocks;
|
||||||
|
uint stride_u8;
|
||||||
|
uint _pad0, _pad1;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// 1 block per WG, 64 lanes covering the 8x8 output block.
|
||||||
|
uint wg_id = gl_WorkGroupID.x;
|
||||||
|
uint block_idx = wg_id;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3; // 0..7 (row)
|
||||||
|
uint c = lane & 7u; // 0..7 (column)
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
// src points at output col 0 of the block; filter reads cols -2..+3
|
||||||
|
// of the current row. Negative col arithmetic is unsigned-safe
|
||||||
|
// because src_off >= 2 (caller-guaranteed left context).
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base + 0u]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int p = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + p + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc21 (biprediction) (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc21[r,c] = avg(mc22(r, c),
|
||||||
|
// mc20(r, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc21_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_hv(src_off, stride, r, c);
|
||||||
|
int b = hpel_h(src_off, stride, r, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc22 (biprediction) (8x8, 2D half-pel "j" position).
|
||||||
|
// V3D 7.1.
|
||||||
|
//
|
||||||
|
// Cascaded H+V 6-tap per H.264 §8.4.2.2.1 / FFmpeg ff_put_h264_qpel8_mc22_neon:
|
||||||
|
//
|
||||||
|
// tmp[r,c] = src[r,c-2] - 5*src[r,c-1] + 20*src[r,c] + 20*src[r,c+1]
|
||||||
|
// - 5*src[r,c+2] + src[r,c+3] (int16)
|
||||||
|
//
|
||||||
|
// dst[r,c] = clip255((tmp[r-2,c] - 5*tmp[r-1,c] + 20*tmp[r,c]
|
||||||
|
// + 20*tmp[r+1,c] - 5*tmp[r+2,c] + tmp[r+3,c]
|
||||||
|
// + 512) >> 10)
|
||||||
|
//
|
||||||
|
// The +512 >> 10 final scale compensates for both 6-tap scalings.
|
||||||
|
// CANNOT just cascade mc20→mc02 because intermediate must be int16
|
||||||
|
// (no per-stage clip), so this is a dedicated kernel.
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes its own (r, c) output by
|
||||||
|
// running the FULL cascade — 6 horizontal lowpass int16 values for
|
||||||
|
// rows r-2..r+3, then a vertical lowpass on those. ~50 ALU ops per
|
||||||
|
// lane. No shared memory / barriers needed; V3D L2 absorbs the
|
||||||
|
// redundant src reads across lanes.
|
||||||
|
//
|
||||||
|
// WG layout: 64 lanes / 1 block-per-WG / 1 lane-per-output-pixel
|
||||||
|
// (same as mc20 / mc02).
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc22_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PC {
|
||||||
|
uint n_blocks;
|
||||||
|
uint stride_u8;
|
||||||
|
uint _pad0, _pad1;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
// Horizontal 6-tap filter at (row_off, c) — reads src at cols c-2..c+3
|
||||||
|
// of the row identified by row_off, returns int16 intermediate (NOT
|
||||||
|
// scaled — the v-pass does the +512 >> 10 for both stages).
|
||||||
|
int hpel_h(uint row_off, uint c)
|
||||||
|
{
|
||||||
|
int s_m2 = int(u_src.src[row_off + c - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_off + c - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_off + c ]);
|
||||||
|
int s_p1 = int(u_src.src[row_off + c + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_off + c + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_off + c + 3u]);
|
||||||
|
return s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3;
|
||||||
|
uint c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
// Compute 6 horizontal lowpass values at rows r-2..r+3 (relative
|
||||||
|
// to the output row r) of column c. src_off+r*stride+c is the
|
||||||
|
// output pixel position; we sample rows r-2..r+3.
|
||||||
|
// Unsigned-safe because src_off >= 2*stride per the caller contract.
|
||||||
|
int t0 = hpel_h(src_off + (r - 2u) * stride, c);
|
||||||
|
int t1 = hpel_h(src_off + (r - 1u) * stride, c);
|
||||||
|
int t2 = hpel_h(src_off + r * stride, c);
|
||||||
|
int t3 = hpel_h(src_off + (r + 1u) * stride, c);
|
||||||
|
int t4 = hpel_h(src_off + (r + 2u) * stride, c);
|
||||||
|
int t5 = hpel_h(src_off + (r + 3u) * stride, c);
|
||||||
|
|
||||||
|
int v = t0 - 5 * t1 + 20 * t2 + 20 * t3 - 5 * t4 + t5 + 512;
|
||||||
|
int p = clamp(v >> 10, 0, 255);
|
||||||
|
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + p + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc23 (biprediction) (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc23[r,c] = avg(mc22(r, c),
|
||||||
|
// mc20(r+1, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc23_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_hv(src_off, stride, r, c);
|
||||||
|
int b = hpel_h(src_off, stride, r+1u, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc30 (biprediction) (8x8, ¾-pel horizontal),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 "c" position:
|
||||||
|
//
|
||||||
|
// dst[r,c] = ((clip255(mc20(s)[r,c]) + s[r,c+1] + 1) >> 1)
|
||||||
|
//
|
||||||
|
// Same as mc10 but L2-averages with src[r, c+1] instead of src[r, c].
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc30_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int hp = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
int avg = (hp + s_p1 + 1) >> 1; // L2 with src[r, c+1]
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc31 (biprediction) (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc31[r,c] = avg(mc20(r, c),
|
||||||
|
// mc02(r, c+1))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc31_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_h(src_off, stride, r, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c+1u);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc32 (biprediction) (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc32[r,c] = avg(mc22(r, c),
|
||||||
|
// mc02(r, c+1))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc32_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_hv(src_off, stride, r, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c+1u);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel avg_mc33 (biprediction) (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc33[r,c] = avg(mc20(r+1, c),
|
||||||
|
// mc02(r, c+1))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// avg_ variant for B-slice biprediction per H.264 §8.4.2.3.1:
|
||||||
|
// dst[r,c] = avg(dst[r,c], mc33_value)
|
||||||
|
// Caller pre-loads dst with the list0 prediction; this shader
|
||||||
|
// folds in the list1 contribution.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_h(src_off, stride, r+1u, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c+1u);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
uint final_off = dst_off + r * stride + c;
|
||||||
|
int prev = int(u_dst.dst[final_off]);
|
||||||
|
u_dst.dst[final_off] = uint8_t((prev + avg + 1) >> 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc01 (8x8, ¼-pel vertical),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 "d" position:
|
||||||
|
//
|
||||||
|
// dst[r,c] = ((clip255(mc02(s)[r,c]) + s[r,c] + 1) >> 1)
|
||||||
|
//
|
||||||
|
// Sibling of v3d_h264_qpel_mc02.comp with L2 step against src[r, c].
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int vp = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
int avg = (vp + s_0 + 1) >> 1; // L2 with src[r, c]
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc02 (8x8, vertical half-pel), V3D 7.1.
|
||||||
|
//
|
||||||
|
// v2: cooperative-load shared-memory tile.
|
||||||
|
//
|
||||||
|
// dst[r,c] = clip255(
|
||||||
|
// ( s[r-2,c]
|
||||||
|
// - 5 * s[r-1,c]
|
||||||
|
// + 20 * s[r, c]
|
||||||
|
// + 20 * s[r+1,c]
|
||||||
|
// - 5 * s[r+2,c]
|
||||||
|
// + s[r+3,c]
|
||||||
|
// + 16
|
||||||
|
// ) >> 5)
|
||||||
|
//
|
||||||
|
// src+src_off points at row 0 col 0 of the OUTPUT block; the filter
|
||||||
|
// reads rows -2..+3 (2 rows of top context, 3 rows of bottom), total
|
||||||
|
// 13 distinct source rows × 8 cols = 104 bytes per 8x8 output.
|
||||||
|
//
|
||||||
|
// v1 had each of the 64 lanes do 6 SSBO loads → 384 loads/WG to cover
|
||||||
|
// 104 unique bytes (3.7x redundant), and each lane's loads were stride-
|
||||||
|
// spaced (one cache line per byte under V3D's TMU). PR #36 bench
|
||||||
|
// showed mc02 was the only qpel position where CPU NEON still beat
|
||||||
|
// QPU (16.96 ns/op CPU vs 20.54 ns/op QPU; 1.21x CPU favoring).
|
||||||
|
//
|
||||||
|
// v2 splits the work into a coalesced load phase + a shared-memory
|
||||||
|
// compute phase:
|
||||||
|
//
|
||||||
|
// Phase 1: each of the 64 lanes cooperatively loads the 104-byte
|
||||||
|
// source tile into shared memory. Lanes 0..63 load bytes at indices
|
||||||
|
// 0..63 (covers source rows 0..7 of the 13-row tile); lanes 0..39
|
||||||
|
// second-load bytes 64..103 (rows 8..12). Reads within a row are
|
||||||
|
// contiguous so the SIMD groups coalesce; total SSBO loads = 104,
|
||||||
|
// matching the unique-byte count.
|
||||||
|
//
|
||||||
|
// Phase 2: all 64 lanes compute one output pixel each, reading 6
|
||||||
|
// bytes from shared. Shared-memory access on V3D is local-store
|
||||||
|
// backed (no TMU round-trip).
|
||||||
|
//
|
||||||
|
// Same WG layout as v1: 64 lanes / 1 block-per-WG / 1 lane-per-pixel.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PC {
|
||||||
|
uint n_blocks;
|
||||||
|
uint stride_u8;
|
||||||
|
uint _pad0, _pad1;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
// 13 source rows × 8 cols. int storage (4 bytes each) — wasteful vs
|
||||||
|
// uint8_t but avoids 8-bit-shared interop concerns on glslang+v3dv;
|
||||||
|
// 416 bytes shared/WG is well within any reasonable local-store budget.
|
||||||
|
shared int s_tile[13 * 8];
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
// Source-tile base: src_off points at output-row-0 col-0, the tile
|
||||||
|
// starts 2 rows above. Unsigned-safe because the public API
|
||||||
|
// contract guarantees src_off >= 2*stride.
|
||||||
|
uint tile_base = src_off - 2u * stride;
|
||||||
|
|
||||||
|
// Phase 1: cooperative load — 64 lanes load 104 bytes.
|
||||||
|
{
|
||||||
|
uint sr = lane >> 3; // 0..7
|
||||||
|
uint sc = lane & 7u;
|
||||||
|
s_tile[lane] = int(u_src.src[tile_base + sr * stride + sc]);
|
||||||
|
}
|
||||||
|
if (lane < 40u) {
|
||||||
|
uint idx = lane + 64u; // 64..103
|
||||||
|
uint sr = idx >> 3; // 8..12
|
||||||
|
uint sc = idx & 7u;
|
||||||
|
s_tile[idx] = int(u_src.src[tile_base + sr * stride + sc]);
|
||||||
|
}
|
||||||
|
|
||||||
|
barrier();
|
||||||
|
|
||||||
|
// Phase 2: each lane computes one output pixel from the shared tile.
|
||||||
|
uint r = lane >> 3;
|
||||||
|
uint c = lane & 7u;
|
||||||
|
|
||||||
|
int s_m2 = s_tile[(r + 0u) * 8u + c];
|
||||||
|
int s_m1 = s_tile[(r + 1u) * 8u + c];
|
||||||
|
int s_0 = s_tile[(r + 2u) * 8u + c];
|
||||||
|
int s_p1 = s_tile[(r + 3u) * 8u + c];
|
||||||
|
int s_p2 = s_tile[(r + 4u) * 8u + c];
|
||||||
|
int s_p3 = s_tile[(r + 5u) * 8u + c];
|
||||||
|
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int p = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(p);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc03 (8x8, ¾-pel vertical),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 "n" position:
|
||||||
|
//
|
||||||
|
// dst[r,c] = ((clip255(mc02(s)[r,c]) + s[r+1, c] + 1) >> 1)
|
||||||
|
//
|
||||||
|
// Same as mc01 but L2-averages with src[r+1, c] instead of src[r, c].
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int vp = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
int avg = (vp + s_p1 + 1) >> 1; // L2 with src[r+1, c]
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc10 (8x8, ¼-pel horizontal),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 "a" position:
|
||||||
|
//
|
||||||
|
// dst[r,c] = ((clip255(mc20(s)[r,c]) + s[r,c] + 1) >> 1)
|
||||||
|
//
|
||||||
|
// = horizontal half-pel filter, clipped to u8, then L2 rounded-averaged
|
||||||
|
// with the integer source pixel at the SAME position. Sibling of
|
||||||
|
// v3d_h264_qpel_mc20.comp with the L2 step added at the tail.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int hp = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
// L2 average with the integer source at the SAME (r, c) position.
|
||||||
|
int avg = (hp + s_0 + 1) >> 1;
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc11 (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc11[r,c] = avg(mc20(r, c),
|
||||||
|
// mc02(r, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_h(src_off, stride, r, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc12 (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc12[r,c] = avg(mc22(r, c),
|
||||||
|
// mc02(r, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_hv(src_off, stride, r, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc13 (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc13[r,c] = avg(mc20(r+1, c),
|
||||||
|
// mc02(r, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_h(src_off, stride, r+1u, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc21 (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc21[r,c] = avg(mc22(r, c),
|
||||||
|
// mc20(r, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_hv(src_off, stride, r, c);
|
||||||
|
int b = hpel_h(src_off, stride, r, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc22 (8x8, 2D half-pel "j" position).
|
||||||
|
// V3D 7.1.
|
||||||
|
//
|
||||||
|
// Cascaded H+V 6-tap per H.264 §8.4.2.2.1 / FFmpeg ff_put_h264_qpel8_mc22_neon:
|
||||||
|
//
|
||||||
|
// tmp[r,c] = src[r,c-2] - 5*src[r,c-1] + 20*src[r,c] + 20*src[r,c+1]
|
||||||
|
// - 5*src[r,c+2] + src[r,c+3] (int16)
|
||||||
|
//
|
||||||
|
// dst[r,c] = clip255((tmp[r-2,c] - 5*tmp[r-1,c] + 20*tmp[r,c]
|
||||||
|
// + 20*tmp[r+1,c] - 5*tmp[r+2,c] + tmp[r+3,c]
|
||||||
|
// + 512) >> 10)
|
||||||
|
//
|
||||||
|
// The +512 >> 10 final scale compensates for both 6-tap scalings.
|
||||||
|
// CANNOT just cascade mc20→mc02 because intermediate must be int16
|
||||||
|
// (no per-stage clip), so this is a dedicated kernel.
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes its own (r, c) output by
|
||||||
|
// running the FULL cascade — 6 horizontal lowpass int16 values for
|
||||||
|
// rows r-2..r+3, then a vertical lowpass on those. ~50 ALU ops per
|
||||||
|
// lane. No shared memory / barriers needed; V3D L2 absorbs the
|
||||||
|
// redundant src reads across lanes.
|
||||||
|
//
|
||||||
|
// WG layout: 64 lanes / 1 block-per-WG / 1 lane-per-output-pixel
|
||||||
|
// (same as mc20 / mc02).
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PC {
|
||||||
|
uint n_blocks;
|
||||||
|
uint stride_u8;
|
||||||
|
uint _pad0, _pad1;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
// Horizontal 6-tap filter at (row_off, c) — reads src at cols c-2..c+3
|
||||||
|
// of the row identified by row_off, returns int16 intermediate (NOT
|
||||||
|
// scaled — the v-pass does the +512 >> 10 for both stages).
|
||||||
|
int hpel_h(uint row_off, uint c)
|
||||||
|
{
|
||||||
|
int s_m2 = int(u_src.src[row_off + c - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_off + c - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_off + c ]);
|
||||||
|
int s_p1 = int(u_src.src[row_off + c + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_off + c + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_off + c + 3u]);
|
||||||
|
return s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3;
|
||||||
|
uint c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
// Compute 6 horizontal lowpass values at rows r-2..r+3 (relative
|
||||||
|
// to the output row r) of column c. src_off+r*stride+c is the
|
||||||
|
// output pixel position; we sample rows r-2..r+3.
|
||||||
|
// Unsigned-safe because src_off >= 2*stride per the caller contract.
|
||||||
|
int t0 = hpel_h(src_off + (r - 2u) * stride, c);
|
||||||
|
int t1 = hpel_h(src_off + (r - 1u) * stride, c);
|
||||||
|
int t2 = hpel_h(src_off + r * stride, c);
|
||||||
|
int t3 = hpel_h(src_off + (r + 1u) * stride, c);
|
||||||
|
int t4 = hpel_h(src_off + (r + 2u) * stride, c);
|
||||||
|
int t5 = hpel_h(src_off + (r + 3u) * stride, c);
|
||||||
|
|
||||||
|
int v = t0 - 5 * t1 + 20 * t2 + 20 * t3 - 5 * t4 + t5 + 512;
|
||||||
|
int p = clamp(v >> 10, 0, 255);
|
||||||
|
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(p);
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc23 (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc23[r,c] = avg(mc22(r, c),
|
||||||
|
// mc20(r+1, c))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_hv(src_off, stride, r, c);
|
||||||
|
int b = hpel_h(src_off, stride, r+1u, c);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc30 (8x8, ¾-pel horizontal),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 "c" position:
|
||||||
|
//
|
||||||
|
// dst[r,c] = ((clip255(mc20(s)[r,c]) + s[r,c+1] + 1) >> 1)
|
||||||
|
//
|
||||||
|
// Same as mc10 but L2-averages with src[r, c+1] instead of src[r, c].
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5 * s_m1 + 20 * s_0 + 20 * s_p1 - 5 * s_p2 + s_p3 + 16;
|
||||||
|
int hp = clamp(v >> 5, 0, 255);
|
||||||
|
|
||||||
|
int avg = (hp + s_p1 + 1) >> 1; // L2 with src[r, c+1]
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc31 (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc31[r,c] = avg(mc20(r, c),
|
||||||
|
// mc02(r, c+1))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_h(src_off, stride, r, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c+1u);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc32 (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc32[r,c] = avg(mc22(r, c),
|
||||||
|
// mc02(r, c+1))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_hv(src_off, stride, r, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c+1u);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
// daedalus-fourier — H.264 luma qpel mc33 (8x8, diagonal quarter-pel),
|
||||||
|
// V3D 7.1. Per H.264 §8.4.2.2.1 (table 8-4) — composes two half-pel
|
||||||
|
// anchors via L2 rounded-average:
|
||||||
|
//
|
||||||
|
// mc33[r,c] = avg(mc20(r+1, c),
|
||||||
|
// mc02(r, c+1))
|
||||||
|
//
|
||||||
|
// Per-lane structure: each lane computes BOTH anchor outputs at its
|
||||||
|
// own (r, c) target offset, then L2 averages. No shared memory.
|
||||||
|
// Same WG geometry as the other qpel shaders.
|
||||||
|
//
|
||||||
|
// 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 = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
layout(binding = 0) readonly buffer Src { uint8_t src[]; } u_src;
|
||||||
|
layout(binding = 1) buffer Dst { uint8_t dst[]; } u_dst;
|
||||||
|
layout(binding = 2) readonly buffer Meta { uvec4 meta[]; } u_meta;
|
||||||
|
layout(push_constant) uniform PC { uint n_blocks, stride_u8, _p0, _p1; } pc;
|
||||||
|
|
||||||
|
int hpel_h(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint row_base = src_off + r * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_v(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
uint col_base = src_off + c;
|
||||||
|
int s_m2 = int(u_src.src[col_base + (r - 2u) * stride]);
|
||||||
|
int s_m1 = int(u_src.src[col_base + (r - 1u) * stride]);
|
||||||
|
int s_0 = int(u_src.src[col_base + r * stride]);
|
||||||
|
int s_p1 = int(u_src.src[col_base + (r + 1u) * stride]);
|
||||||
|
int s_p2 = int(u_src.src[col_base + (r + 2u) * stride]);
|
||||||
|
int s_p3 = int(u_src.src[col_base + (r + 3u) * stride]);
|
||||||
|
int v = s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3 + 16;
|
||||||
|
return clamp(v >> 5, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv_row(uint src_off, uint stride, uint rr, uint c) {
|
||||||
|
// Single row's int16 horizontal lowpass (NOT clipped — used as
|
||||||
|
// intermediate for the vertical pass of hpel_hv).
|
||||||
|
uint row_base = src_off + rr * stride + c;
|
||||||
|
int s_m2 = int(u_src.src[row_base - 2u]);
|
||||||
|
int s_m1 = int(u_src.src[row_base - 1u]);
|
||||||
|
int s_0 = int(u_src.src[row_base ]);
|
||||||
|
int s_p1 = int(u_src.src[row_base + 1u]);
|
||||||
|
int s_p2 = int(u_src.src[row_base + 2u]);
|
||||||
|
int s_p3 = int(u_src.src[row_base + 3u]);
|
||||||
|
return s_m2 - 5*s_m1 + 20*s_0 + 20*s_p1 - 5*s_p2 + s_p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hpel_hv(uint src_off, uint stride, uint r, uint c) {
|
||||||
|
int t0 = hpel_hv_row(src_off, stride, r - 2u, c);
|
||||||
|
int t1 = hpel_hv_row(src_off, stride, r - 1u, c);
|
||||||
|
int t2 = hpel_hv_row(src_off, stride, r, c);
|
||||||
|
int t3 = hpel_hv_row(src_off, stride, r + 1u, c);
|
||||||
|
int t4 = hpel_hv_row(src_off, stride, r + 2u, c);
|
||||||
|
int t5 = hpel_hv_row(src_off, stride, r + 3u, c);
|
||||||
|
int v = t0 - 5*t1 + 20*t2 + 20*t3 - 5*t4 + t5 + 512;
|
||||||
|
return clamp(v >> 10, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint block_idx = gl_WorkGroupID.x;
|
||||||
|
if (block_idx >= pc.n_blocks) return;
|
||||||
|
|
||||||
|
uint lane = gl_LocalInvocationID.x;
|
||||||
|
uint r = lane >> 3, c = lane & 7u;
|
||||||
|
|
||||||
|
uint dst_off = u_meta.meta[block_idx].x;
|
||||||
|
uint src_off = u_meta.meta[block_idx].y;
|
||||||
|
uint stride = pc.stride_u8;
|
||||||
|
|
||||||
|
int a = hpel_h(src_off, stride, r+1u, c);
|
||||||
|
int b = hpel_v(src_off, stride, r, c+1u);
|
||||||
|
int avg = (a + b + 1) >> 1;
|
||||||
|
u_dst.dst[dst_off + r * stride + c] = uint8_t(avg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// daedalus-fourier — H.264 chroma 4:2:0 H loop filter (horizontal
|
||||||
|
// filter across a vertical edge), non-intra bS<4 variant.
|
||||||
|
//
|
||||||
|
// Sibling of v3d_h264deblock_chroma_v.comp; same kernel transposed
|
||||||
|
// to read pix[-2..+1] (cols) instead of pix[-2*stride..+1*stride]
|
||||||
|
// (rows). Same 8-cell × 4-segment geometry, same WG layout (lanes
|
||||||
|
// 8..15 of each edge early-return — only 8 active per edge).
|
||||||
|
//
|
||||||
|
// 4:2:0-only: 4:2:2 chroma_h has a 16-row edge that this shader
|
||||||
|
// doesn't address. daedalus_dispatch_h264_deblock_chroma_h is
|
||||||
|
// 4:2:0-only by design; caller (libavcodec init) gates accordingly.
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
uint dst_stride_u8;
|
||||||
|
uint _pad0;
|
||||||
|
uint _pad1;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint lane_in_wg = gl_GlobalInvocationID.x & 255u;
|
||||||
|
uint edge_in_wg = lane_in_wg >> 4; // 0..15
|
||||||
|
uint row_in_edge = lane_in_wg & 15u; // 0..15 — only 0..7 active
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
uint seg = row_in_edge >> 1;
|
||||||
|
uint tc0_byte = (m.z >> (seg * 8u)) & 0xffu;
|
||||||
|
int tc0_s = int(tc0_byte);
|
||||||
|
if (tc0_s >= 128) tc0_s -= 256;
|
||||||
|
|
||||||
|
if (alpha == 0 || beta == 0) return;
|
||||||
|
if (tc0_s < 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;
|
||||||
|
|
||||||
|
int tc = tc0_s + 1;
|
||||||
|
int delta = clamp(((q0 - p0) * 4 + (p1 - q1) + 4) >> 3, -tc, tc);
|
||||||
|
|
||||||
|
u_dst.dst[dst_off - 1u] = uint8_t(clamp(p0 + delta, 0, 255));
|
||||||
|
u_dst.dst[dst_off ] = uint8_t(clamp(q0 - delta, 0, 255));
|
||||||
|
}
|
||||||
@@ -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,76 @@
|
|||||||
|
// daedalus-fourier — H.264 chroma 4:2:0 V loop filter (vertical
|
||||||
|
// filter across a horizontal edge), non-intra bS<4 variant.
|
||||||
|
//
|
||||||
|
// Per H.264 §8.7.2.4: chroma kernel is simpler than luma's bS<4 —
|
||||||
|
// only p0 / q0 are updated (chroma never modifies p1, p2, q1, q2),
|
||||||
|
// tC = tc0_seg + 1 (no luma-style ap/aq side bonus), and the edge
|
||||||
|
// spans 8 cells (4 segments × 2 cells/seg).
|
||||||
|
//
|
||||||
|
// V3D 7.1 via Mesa v3dv compute. WG geometry kept identical to the
|
||||||
|
// luma shader (16 edges × 16 lanes/WG) for uniform dispatch math
|
||||||
|
// across the deblock family; lanes 8..15 of each edge early-return.
|
||||||
|
//
|
||||||
|
// 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[]; // per edge: (dst_off, alpha|beta<<8, packed_tc0, _pad)
|
||||||
|
} u_meta;
|
||||||
|
|
||||||
|
layout(binding = 1) buffer Dst {
|
||||||
|
uint8_t dst[];
|
||||||
|
} u_dst;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PC {
|
||||||
|
uint n_edges;
|
||||||
|
uint dst_stride_u8;
|
||||||
|
uint _pad0;
|
||||||
|
uint _pad1;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint lane_in_wg = gl_GlobalInvocationID.x & 255u;
|
||||||
|
uint edge_in_wg = lane_in_wg >> 4; // 0..15
|
||||||
|
uint col_in_edge = lane_in_wg & 15u; // 0..15 — only 0..7 active
|
||||||
|
|
||||||
|
uint edge_idx = gl_WorkGroupID.x * 16u + edge_in_wg;
|
||||||
|
if (edge_idx >= pc.n_edges) return;
|
||||||
|
if (col_in_edge >= 8u) return; // 8 cells per chroma edge
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 8 cells / 4 segments = 2 cells per segment.
|
||||||
|
uint seg = col_in_edge >> 1;
|
||||||
|
uint tc0_byte = (m.z >> (seg * 8u)) & 0xffu;
|
||||||
|
int tc0_s = int(tc0_byte);
|
||||||
|
if (tc0_s >= 128) tc0_s -= 256;
|
||||||
|
|
||||||
|
if (alpha == 0 || beta == 0) return;
|
||||||
|
if (tc0_s < 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;
|
||||||
|
|
||||||
|
int tc = tc0_s + 1;
|
||||||
|
int delta = clamp(((q0 - p0) * 4 + (p1 - q1) + 4) >> 3, -tc, tc);
|
||||||
|
|
||||||
|
u_dst.dst[dst_off - 1u * stride] = uint8_t(clamp(p0 + delta, 0, 255));
|
||||||
|
u_dst.dst[dst_off ] = uint8_t(clamp(q0 - delta, 0, 255));
|
||||||
|
// p1, q1 untouched — chroma kernel only updates p0/q0.
|
||||||
|
}
|
||||||
@@ -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,111 @@
|
|||||||
|
// daedalus-fourier — H.264 luma "h_loop_filter" (horizontal filtering
|
||||||
|
// across a vertical edge), non-intra bS<4 variant. Sibling of cycle 8's
|
||||||
|
// v3d_h264deblock.comp; same algorithm with row/col access transposed.
|
||||||
|
//
|
||||||
|
// V3D 7.1 via Mesa v3dv compute. Same WG geometry as the V shader:
|
||||||
|
// - 256 invocations / WG, 16 edges/WG (16 lanes/edge = 1 sg/edge)
|
||||||
|
// - uint8_t dst SSBO via storageBuffer8BitAccess
|
||||||
|
// - No barrier (each lane independent)
|
||||||
|
// - lane_in_edge = ROW index (0..15) along the vertical edge
|
||||||
|
// - meta.dst_off points to (row 0, col 0) of the RIGHT block;
|
||||||
|
// the kernel reads cols [-4..+3] of each row and writes [-2..+1].
|
||||||
|
//
|
||||||
|
// Filter contract (per H.264 §8.7.2.4):
|
||||||
|
// 1. (m.x % pc.dst_stride_u8) ≥ 4 (kernel reads p3 at pix[-4])
|
||||||
|
// 2. pc.dst_stride_u8 = byte stride between rows
|
||||||
|
// 3. tc0_s pre-stored as signed int8 in m.z packed 4 bytes (one per
|
||||||
|
// 4-row segment along the 16-row edge)
|
||||||
|
//
|
||||||
|
// License: BSD-2-Clause. Algorithm transcribed from
|
||||||
|
// tests/h264_h_loop_filter_luma_ref.c which mirrors FFmpeg
|
||||||
|
// ff_h264_h_loop_filter_luma_neon (LGPL-2.1+).
|
||||||
|
|
||||||
|
#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[]; // per edge: (dst_off, alpha|beta<<8, packed_tc0, _pad)
|
||||||
|
} u_meta;
|
||||||
|
|
||||||
|
layout(binding = 1) buffer Dst {
|
||||||
|
uint8_t dst[];
|
||||||
|
} u_dst;
|
||||||
|
|
||||||
|
layout(push_constant) uniform PC {
|
||||||
|
uint n_edges;
|
||||||
|
uint dst_stride_u8;
|
||||||
|
uint _pad0;
|
||||||
|
uint _pad1;
|
||||||
|
} pc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint gid = gl_GlobalInvocationID.x;
|
||||||
|
uint wg_id = gl_WorkGroupID.x;
|
||||||
|
uint lane_in_wg = gid & 255u;
|
||||||
|
uint edge_in_wg = lane_in_wg >> 4; // 0..15 (16 edges/WG)
|
||||||
|
uint row_in_edge = lane_in_wg & 15u; // 0..15 — ROW along the V edge
|
||||||
|
|
||||||
|
uint edge_idx = wg_id * 16u + edge_in_wg;
|
||||||
|
if (edge_idx >= pc.n_edges) return;
|
||||||
|
|
||||||
|
uvec4 m = u_meta.meta[edge_idx];
|
||||||
|
uint stride = pc.dst_stride_u8;
|
||||||
|
// dst_off addresses row 0 col 0 of the right block; advance by row * stride
|
||||||
|
// to land at this lane's row. The kernel reads pix[-4..+3] AT THIS ROW.
|
||||||
|
uint dst_off = m.x + row_in_edge * stride;
|
||||||
|
int alpha = int(m.y & 0xffu);
|
||||||
|
int beta = int((m.y >> 8) & 0xffu);
|
||||||
|
|
||||||
|
// tc0 segment = 0..3 indexed by (row_in_edge / 4).
|
||||||
|
uint seg = row_in_edge >> 2;
|
||||||
|
uint tc0_byte = (m.z >> (seg * 8u)) & 0xffu;
|
||||||
|
int tc0_s = int(tc0_byte);
|
||||||
|
if (tc0_s >= 128) tc0_s -= 256;
|
||||||
|
|
||||||
|
if (alpha == 0 || beta == 0) return;
|
||||||
|
if (tc0_s < 0) return; // segment skip
|
||||||
|
|
||||||
|
// Horizontal access pattern — read cols at offsets [-3..+2] of this row.
|
||||||
|
// p3 (col -4) unused in bS<4; same DCE comment as the V shader.
|
||||||
|
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]);
|
||||||
|
|
||||||
|
// Edge preconditions (same as V).
|
||||||
|
if (abs(p0 - q0) >= alpha) return;
|
||||||
|
if (abs(p1 - p0) >= beta) return;
|
||||||
|
if (abs(q1 - q0) >= beta) return;
|
||||||
|
|
||||||
|
int ap = abs(p2 - p0);
|
||||||
|
int aq = abs(q2 - q0);
|
||||||
|
bool ap_lt = ap < beta;
|
||||||
|
bool aq_lt = aq < beta;
|
||||||
|
int tc = tc0_s + int(ap_lt) + int(aq_lt);
|
||||||
|
|
||||||
|
int delta = clamp(((q0 - p0) * 4 + (p1 - q1) + 4) >> 3, -tc, tc);
|
||||||
|
int p0p = clamp(p0 + delta, 0, 255);
|
||||||
|
int q0p = clamp(q0 - delta, 0, 255);
|
||||||
|
|
||||||
|
int p1p = p1;
|
||||||
|
if (ap_lt) {
|
||||||
|
int d_p1 = clamp((p2 + ((p0 + q0 + 1) >> 1) - 2*p1) >> 1, -tc0_s, tc0_s);
|
||||||
|
p1p = clamp(p1 + d_p1, 0, 255);
|
||||||
|
}
|
||||||
|
int q1p = q1;
|
||||||
|
if (aq_lt) {
|
||||||
|
int d_q1 = clamp((q2 + ((p0 + q0 + 1) >> 1) - 2*q1) >> 1, -tc0_s, tc0_s);
|
||||||
|
q1p = clamp(q1 + d_q1, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
u_dst.dst[dst_off - 2u] = uint8_t(p1p);
|
||||||
|
u_dst.dst[dst_off - 1u] = uint8_t(p0p);
|
||||||
|
u_dst.dst[dst_off ] = uint8_t(q0p);
|
||||||
|
u_dst.dst[dst_off + 1u] = uint8_t(q1p);
|
||||||
|
}
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
+122
-73
@@ -2,25 +2,22 @@
|
|||||||
/* CLOCK_MONOTONIC under -std=c11 -CMAKE_C_EXTENSIONS=OFF. */
|
/* CLOCK_MONOTONIC under -std=c11 -CMAKE_C_EXTENSIONS=OFF. */
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
/*
|
/*
|
||||||
* bench_h264_primitives — NEON-path latency baseline for the H.264
|
* bench_h264_primitives — latency baseline for the H.264 primitive
|
||||||
* primitive library landed across PRs #9–#23.
|
* library landed across PRs #9–#35.
|
||||||
*
|
*
|
||||||
* Each kernel is exercised at a representative per-frame N for 1080p
|
* Each kernel is exercised at a representative per-frame N for 1080p
|
||||||
* (8160 MBs); the per-kernel total + ns/op + ms/frame are reported.
|
* (8160 MBs); the per-kernel total + ns/op + ms/frame are reported,
|
||||||
* Lets us answer "what's the total NEON-only budget for the H.264
|
* once per substrate (CPU NEON, QPU V3D7 compute). The QPU column
|
||||||
* decode at 1080p" — useful for sizing intercept-patch decisions
|
* appears only when the host has a usable Vulkan device. When both
|
||||||
* (which kernels NEED QPU shaders vs which are budget-fine on NEON).
|
* columns exist a CPU/QPU ratio is printed; that's the per-kernel
|
||||||
|
* data the QPU-substrate decree (2026-05-23) deliberately overrides
|
||||||
|
* but which is still useful to track over time as dispatch overhead
|
||||||
|
* shrinks (buffer pool, persistent cmdbuf, dmabuf import — tasks 160-162).
|
||||||
*
|
*
|
||||||
* NOT a ctest — produces wall-time numbers, doesn't pass/fail.
|
* NOT a ctest — produces wall-time numbers, doesn't pass/fail.
|
||||||
*
|
*
|
||||||
* Invoke: ./build/bench_h264_primitives [iters]
|
* Invoke: ./build/bench_h264_primitives [iters [warmup]]
|
||||||
* (default iters = 50, post-warmup = 5)
|
* (default iters = 50, warmup = 5)
|
||||||
*
|
|
||||||
* NB: results are inherently approximate — single-core, includes
|
|
||||||
* loop overhead + memory access patterns that may not match what
|
|
||||||
* a real decode would hit (we touch a small set of pages repeatedly).
|
|
||||||
* The numbers are useful for relative comparison and order-of-
|
|
||||||
* magnitude sizing, not absolute perf claims.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "daedalus.h"
|
#include "daedalus.h"
|
||||||
@@ -46,11 +43,6 @@ static double now_ms(void) {
|
|||||||
|
|
||||||
/* Per-1080p-frame counts (8160 MBs at 1920x1088). */
|
/* Per-1080p-frame counts (8160 MBs at 1920x1088). */
|
||||||
#define MBS_1080P 8160
|
#define MBS_1080P 8160
|
||||||
#define LUMA_4x4_PER_MB 16 /* if transform_8x8=0 */
|
|
||||||
#define LUMA_8x8_PER_MB 4 /* if transform_8x8=1 */
|
|
||||||
#define CHROMA_4x4_PER_MB 8 /* 4 Cb + 4 Cr */
|
|
||||||
#define DEBLOCK_LUMA_EDGES_PER_MB 4 /* 4 horiz + 4 vert internal+MB-edge — ~4 each */
|
|
||||||
#define DEBLOCK_CHROMA_EDGES_PER_MB 2 /* 2 each direction */
|
|
||||||
|
|
||||||
/* Standard benchmark loop. fn() is called n times per iteration. */
|
/* Standard benchmark loop. fn() is called n times per iteration. */
|
||||||
typedef void (*bench_fn)(void);
|
typedef void (*bench_fn)(void);
|
||||||
@@ -64,16 +56,18 @@ static double bench_ns(const char *name, int iters, int warmup,
|
|||||||
double t1 = now_ms();
|
double t1 = now_ms();
|
||||||
double total_ms = (t1 - t0);
|
double total_ms = (t1 - t0);
|
||||||
double ns_per_op = (total_ms * 1e6) / ((double) iters * ops_per_iter);
|
double ns_per_op = (total_ms * 1e6) / ((double) iters * ops_per_iter);
|
||||||
printf(" %-32s %8.2f ns/op (%d iters x %d ops)\n",
|
printf(" %-32s %10.2f ns/op (%d iters x %d ops)\n",
|
||||||
name, ns_per_op, iters, ops_per_iter);
|
name, ns_per_op, iters, ops_per_iter);
|
||||||
return ns_per_op;
|
return ns_per_op;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- Per-kernel scaffolding. Each section sets up the buffers +
|
/* ---- Per-kernel scaffolding. Each section sets up the buffers +
|
||||||
* meta, then defines a static fn() that calls the corresponding
|
* meta, then defines a static fn() that calls the corresponding
|
||||||
* dispatch with a representative N. */
|
* dispatch with a representative N. The substrate is read from the
|
||||||
|
* global g_sub so the same fn() can be re-driven with CPU then QPU. */
|
||||||
|
|
||||||
static daedalus_ctx *ctx;
|
static daedalus_ctx *ctx;
|
||||||
|
static daedalus_substrate g_sub = DAEDALUS_SUBSTRATE_CPU;
|
||||||
|
|
||||||
/* --- IDCT 4x4 luma: N = 16 blocks per MB. Bench with 1024 blocks
|
/* --- IDCT 4x4 luma: N = 16 blocks per MB. Bench with 1024 blocks
|
||||||
* per call (64 MBs worth). Per-MB the dispatch overhead is the
|
* per call (64 MBs worth). Per-MB the dispatch overhead is the
|
||||||
@@ -83,7 +77,7 @@ static daedalus_h264_block_meta idct4_meta[1024];
|
|||||||
static uint8_t idct_dst[64 * 4 * 16 * 16]; /* 64 MB-rows × ... */
|
static uint8_t idct_dst[64 * 4 * 16 * 16]; /* 64 MB-rows × ... */
|
||||||
|
|
||||||
static void bench_idct4(void) {
|
static void bench_idct4(void) {
|
||||||
daedalus_dispatch_h264_idct4(ctx, DAEDALUS_SUBSTRATE_CPU,
|
daedalus_dispatch_h264_idct4(ctx, g_sub,
|
||||||
idct_dst, 64*16, idct4_coeffs, 1024, idct4_meta);
|
idct_dst, 64*16, idct4_coeffs, 1024, idct4_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +86,7 @@ static int16_t idct8_coeffs[256 * 64];
|
|||||||
static daedalus_h264_block_meta idct8_meta[256];
|
static daedalus_h264_block_meta idct8_meta[256];
|
||||||
|
|
||||||
static void bench_idct8(void) {
|
static void bench_idct8(void) {
|
||||||
daedalus_dispatch_h264_idct8(ctx, DAEDALUS_SUBSTRATE_CPU,
|
daedalus_dispatch_h264_idct8(ctx, g_sub,
|
||||||
idct_dst, 64*16, idct8_coeffs, 256, idct8_meta);
|
idct_dst, 64*16, idct8_coeffs, 256, idct8_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,12 +95,12 @@ static daedalus_h264_deblock_meta deblock_meta[256];
|
|||||||
static uint8_t deblock_dst[256 * 16 * 16];
|
static uint8_t deblock_dst[256 * 16 * 16];
|
||||||
|
|
||||||
static void bench_deblock_v(void) {
|
static void bench_deblock_v(void) {
|
||||||
daedalus_dispatch_h264_deblock_luma_v(ctx, DAEDALUS_SUBSTRATE_CPU,
|
daedalus_dispatch_h264_deblock_luma_v(ctx, g_sub,
|
||||||
deblock_dst, 16, 256, deblock_meta);
|
deblock_dst, 16, 256, deblock_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bench_deblock_h(void) {
|
static void bench_deblock_h(void) {
|
||||||
daedalus_dispatch_h264_deblock_luma_h(ctx, DAEDALUS_SUBSTRATE_CPU,
|
daedalus_dispatch_h264_deblock_luma_h(ctx, g_sub,
|
||||||
deblock_dst, 16, 256, deblock_meta);
|
deblock_dst, 16, 256, deblock_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,18 +110,43 @@ static uint8_t qpel_dst[256 * 16 * 16];
|
|||||||
static daedalus_h264_qpel_meta qpel_meta[256];
|
static daedalus_h264_qpel_meta qpel_meta[256];
|
||||||
|
|
||||||
static void bench_qpel_mc20(void) {
|
static void bench_qpel_mc20(void) {
|
||||||
daedalus_dispatch_h264_qpel_mc20(ctx, DAEDALUS_SUBSTRATE_CPU,
|
daedalus_dispatch_h264_qpel_mc20(ctx, g_sub,
|
||||||
qpel_dst, qpel_src, 16, 256, qpel_meta);
|
qpel_dst, qpel_src, 16, 256, qpel_meta);
|
||||||
}
|
}
|
||||||
static void bench_qpel_mc02(void) {
|
static void bench_qpel_mc02(void) {
|
||||||
daedalus_dispatch_h264_qpel_mc02(ctx, DAEDALUS_SUBSTRATE_CPU,
|
daedalus_dispatch_h264_qpel_mc02(ctx, g_sub,
|
||||||
qpel_dst, qpel_src, 16, 256, qpel_meta);
|
qpel_dst, qpel_src, 16, 256, qpel_meta);
|
||||||
}
|
}
|
||||||
static void bench_qpel_mc22(void) {
|
static void bench_qpel_mc22(void) {
|
||||||
daedalus_dispatch_h264_qpel_mc22(ctx, DAEDALUS_SUBSTRATE_CPU,
|
daedalus_dispatch_h264_qpel_mc22(ctx, g_sub,
|
||||||
qpel_dst, qpel_src, 16, 256, qpel_meta);
|
qpel_dst, qpel_src, 16, 256, qpel_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- One row of bench output:
|
||||||
|
* - kernel name + N
|
||||||
|
* - CPU ns/op
|
||||||
|
* - QPU ns/op (or "n/a" if Vulkan absent)
|
||||||
|
* - CPU/QPU ratio (>1 means QPU wins; <1 means CPU wins) */
|
||||||
|
struct row {
|
||||||
|
const char *name;
|
||||||
|
int n_per_call;
|
||||||
|
bench_fn fn;
|
||||||
|
double cpu_ns;
|
||||||
|
double qpu_ns; /* -1 if not measured */
|
||||||
|
int frame_n; /* count per 1080p frame */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct row rows[] = {
|
||||||
|
{"IDCT 4x4 luma", 1024, bench_idct4, 0, -1, MBS_1080P * 16},
|
||||||
|
{"IDCT 8x8 luma", 256, bench_idct8, 0, -1, MBS_1080P * 4},
|
||||||
|
{"Deblock luma_v", 256, bench_deblock_v, 0, -1, MBS_1080P * 4},
|
||||||
|
{"Deblock luma_h", 256, bench_deblock_h, 0, -1, MBS_1080P * 4},
|
||||||
|
{"qpel mc20 (8x8)", 256, bench_qpel_mc20, 0, -1, MBS_1080P * 4},
|
||||||
|
{"qpel mc02 (8x8)", 256, bench_qpel_mc02, 0, -1, MBS_1080P * 4},
|
||||||
|
{"qpel mc22 (8x8)", 256, bench_qpel_mc22, 0, -1, MBS_1080P * 4},
|
||||||
|
};
|
||||||
|
#define N_ROWS ((int)(sizeof(rows)/sizeof(rows[0])))
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int iters = argc > 1 ? atoi(argv[1]) : 50;
|
int iters = argc > 1 ? atoi(argv[1]) : 50;
|
||||||
@@ -138,6 +157,7 @@ int main(int argc, char **argv)
|
|||||||
fprintf(stderr, "ctx create failed (Vulkan?)\n");
|
fprintf(stderr, "ctx create failed (Vulkan?)\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
int has_qpu = daedalus_ctx_has_qpu(ctx);
|
||||||
|
|
||||||
/* Pre-fill all input buffers with random data so the NEON inner
|
/* Pre-fill all input buffers with random data so the NEON inner
|
||||||
* loops see realistic memory access patterns. */
|
* loops see realistic memory access patterns. */
|
||||||
@@ -147,8 +167,7 @@ int main(int argc, char **argv)
|
|||||||
idct8_coeffs[i] = (int16_t)((int)(xs64() % 1024) - 512);
|
idct8_coeffs[i] = (int16_t)((int)(xs64() % 1024) - 512);
|
||||||
for (size_t i = 0; i < sizeof(qpel_src); i++) qpel_src[i] = (uint8_t)(xs64() & 0xff);
|
for (size_t i = 0; i < sizeof(qpel_src); i++) qpel_src[i] = (uint8_t)(xs64() & 0xff);
|
||||||
|
|
||||||
/* IDCT meta: each block at offset i*16 (row layout matters less
|
/* IDCT meta. */
|
||||||
* here since we're just measuring per-block latency). */
|
|
||||||
for (size_t i = 0; i < 1024; i++)
|
for (size_t i = 0; i < 1024; i++)
|
||||||
idct4_meta[i].dst_off = (uint32_t)((i / 16) * 64 + (i % 16) * 4);
|
idct4_meta[i].dst_off = (uint32_t)((i / 16) * 64 + (i % 16) * 4);
|
||||||
for (size_t i = 0; i < 256; i++)
|
for (size_t i = 0; i < 256; i++)
|
||||||
@@ -162,58 +181,88 @@ int main(int argc, char **argv)
|
|||||||
for (int s = 0; s < 4; s++) deblock_meta[i].tc0[s] = (int8_t)(s + 1);
|
for (int s = 0; s < 4; s++) deblock_meta[i].tc0[s] = (int8_t)(s + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* qpel meta: src and dst at row 3 col 3 of each 16x16 tile. */
|
/* qpel meta. */
|
||||||
for (size_t i = 0; i < 256; i++) {
|
for (size_t i = 0; i < 256; i++) {
|
||||||
qpel_meta[i].src_off = (uint32_t)(i * 256 + 3 * 16 + 3);
|
qpel_meta[i].src_off = (uint32_t)(i * 256 + 3 * 16 + 3);
|
||||||
qpel_meta[i].dst_off = (uint32_t)(i * 256 + 3 * 16 + 3);
|
qpel_meta[i].dst_off = (uint32_t)(i * 256 + 3 * 16 + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("bench_h264_primitives: %d iters (%d warmup), substrate=CPU NEON\n",
|
printf("bench_h264_primitives: %d iters (%d warmup)\n", iters, warmup);
|
||||||
iters, warmup);
|
printf(" ctx has_qpu=%d (CPU pass always runs; QPU pass skipped without Vulkan)\n\n", has_qpu);
|
||||||
printf("Per-call N is set per kernel; ns/op is per BLOCK or EDGE.\n\n");
|
|
||||||
|
|
||||||
double idct4_ns = bench_ns("IDCT 4x4 luma", iters, warmup, 1024, bench_idct4);
|
/* Pass 1: CPU NEON. */
|
||||||
double idct8_ns = bench_ns("IDCT 8x8 luma", iters, warmup, 256, bench_idct8);
|
g_sub = DAEDALUS_SUBSTRATE_CPU;
|
||||||
double debl_v_ns = bench_ns("Deblock luma_v", iters, warmup, 256, bench_deblock_v);
|
printf("== CPU NEON ==\n");
|
||||||
double debl_h_ns = bench_ns("Deblock luma_h", iters, warmup, 256, bench_deblock_h);
|
for (int i = 0; i < N_ROWS; i++)
|
||||||
double qmc20_ns = bench_ns("qpel mc20 (8x8)", iters, warmup, 256, bench_qpel_mc20);
|
rows[i].cpu_ns = bench_ns(rows[i].name, iters, warmup, rows[i].n_per_call, rows[i].fn);
|
||||||
double qmc02_ns = bench_ns("qpel mc02 (8x8)", iters, warmup, 256, bench_qpel_mc02);
|
|
||||||
double qmc22_ns = bench_ns("qpel mc22 (8x8)", iters, warmup, 256, bench_qpel_mc22);
|
|
||||||
|
|
||||||
/* Per-frame budget summary at 1080p (8160 MBs). Worst-case
|
/* Pass 2: QPU compute (if available). */
|
||||||
* assumptions:
|
if (has_qpu) {
|
||||||
* - All MBs are transform_4x4 (16 4x4 IDCTs each) — so 130,560
|
g_sub = DAEDALUS_SUBSTRATE_QPU;
|
||||||
* IDCT 4x4 blocks per frame. If High profile transform_8x8,
|
printf("\n== QPU V3D7 compute ==\n");
|
||||||
* it'd be 32,640 IDCT 8x8 blocks instead.
|
for (int i = 0; i < N_ROWS; i++)
|
||||||
* - All MBs are intra (no MC — qpel zero) OR all inter (no
|
rows[i].qpu_ns = bench_ns(rows[i].name, iters, warmup, rows[i].n_per_call, rows[i].fn);
|
||||||
* intra prediction). We report MC at "all inter, all qpel
|
}
|
||||||
* mc22" worst case.
|
|
||||||
* - Deblock: ~4 luma_v + 4 luma_h edges per MB; assume all 8
|
/* Summary table — both substrates side by side. */
|
||||||
* edges trigger filtering. */
|
printf("\n== Per-kernel comparison ==\n");
|
||||||
printf("\nProjected 1080p frame budgets (worst-case, CPU NEON only):\n");
|
printf(" %-24s %12s %12s %8s %7s\n",
|
||||||
printf(" IDCT 4x4 (all-4x4 MBs): %7.2f ms (%d blocks)\n",
|
"kernel", "CPU ns/op", "QPU ns/op", "winner", "ms/frame");
|
||||||
idct4_ns * MBS_1080P * 16 / 1e6, MBS_1080P * 16);
|
for (int i = 0; i < N_ROWS; i++) {
|
||||||
printf(" IDCT 8x8 (all-8x8 MBs): %7.2f ms (%d blocks)\n",
|
double cpu_ms = rows[i].cpu_ns * rows[i].frame_n / 1e6;
|
||||||
idct8_ns * MBS_1080P * 4 / 1e6, MBS_1080P * 4);
|
double qpu_ms = rows[i].qpu_ns > 0 ? rows[i].qpu_ns * rows[i].frame_n / 1e6 : -1;
|
||||||
printf(" Deblock luma_v (all MBs): %7.2f ms (%d edges)\n",
|
const char *winner;
|
||||||
debl_v_ns * MBS_1080P * 4 / 1e6, MBS_1080P * 4);
|
char ratio[16];
|
||||||
printf(" Deblock luma_h (all MBs): %7.2f ms (%d edges)\n",
|
if (rows[i].qpu_ns <= 0) {
|
||||||
debl_h_ns * MBS_1080P * 4 / 1e6, MBS_1080P * 4);
|
winner = "CPU"; /* QPU n/a */
|
||||||
printf(" qpel mc22 (all 8x8 blocks): %7.2f ms (%d blocks)\n",
|
snprintf(ratio, sizeof(ratio), "n/a");
|
||||||
qmc22_ns * MBS_1080P * 4 / 1e6, MBS_1080P * 4);
|
} else if (rows[i].cpu_ns < rows[i].qpu_ns) {
|
||||||
|
winner = "CPU";
|
||||||
|
snprintf(ratio, sizeof(ratio), "%.2fx", rows[i].qpu_ns / rows[i].cpu_ns);
|
||||||
|
} else {
|
||||||
|
winner = "QPU";
|
||||||
|
snprintf(ratio, sizeof(ratio), "%.2fx", rows[i].cpu_ns / rows[i].qpu_ns);
|
||||||
|
}
|
||||||
|
char qpu_field[16];
|
||||||
|
if (rows[i].qpu_ns > 0) snprintf(qpu_field, sizeof(qpu_field), "%.2f", rows[i].qpu_ns);
|
||||||
|
else snprintf(qpu_field, sizeof(qpu_field), "n/a");
|
||||||
|
char ms_field[24];
|
||||||
|
if (qpu_ms > 0)
|
||||||
|
snprintf(ms_field, sizeof(ms_field), "%.2f/%.2f", cpu_ms, qpu_ms);
|
||||||
|
else
|
||||||
|
snprintf(ms_field, sizeof(ms_field), "%.2f/n/a", cpu_ms);
|
||||||
|
printf(" %-24s %12.2f %12s %3s %s %s\n",
|
||||||
|
rows[i].name, rows[i].cpu_ns, qpu_field, winner, ratio, ms_field);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Per-frame budget summary at 1080p (8160 MBs). */
|
||||||
|
double cpu_idct4 = rows[0].cpu_ns * MBS_1080P * 16 / 1e6;
|
||||||
|
double cpu_debl = (rows[2].cpu_ns + rows[3].cpu_ns) * MBS_1080P * 4 / 1e6;
|
||||||
|
double cpu_mc = rows[6].cpu_ns * MBS_1080P * 4 / 1e6; /* mc22 worst-case */
|
||||||
|
double cpu_sum = cpu_idct4 + cpu_debl + cpu_mc;
|
||||||
|
|
||||||
|
printf("\n== Projected 1080p worst-case (CPU NEON only) ==\n");
|
||||||
|
printf(" IDCT 4x4 + deblock luma + qpel mc22: %.2f ms (30fps deadline 33.33)\n", cpu_sum);
|
||||||
|
printf(" Margin: %+.2f ms\n", 33.33 - cpu_sum);
|
||||||
|
|
||||||
|
if (has_qpu) {
|
||||||
|
double qpu_idct4 = rows[0].qpu_ns * MBS_1080P * 16 / 1e6;
|
||||||
|
double qpu_debl = (rows[2].qpu_ns + rows[3].qpu_ns) * MBS_1080P * 4 / 1e6;
|
||||||
|
double qpu_mc = rows[6].qpu_ns * MBS_1080P * 4 / 1e6;
|
||||||
|
double qpu_sum = qpu_idct4 + qpu_debl + qpu_mc;
|
||||||
|
printf("\n== Projected 1080p worst-case (QPU V3D7 compute only) ==\n");
|
||||||
|
printf(" IDCT 4x4 + deblock luma + qpel mc22: %.2f ms (30fps deadline 33.33)\n", qpu_sum);
|
||||||
|
printf(" Margin: %+.2f ms\n", 33.33 - qpu_sum);
|
||||||
|
printf("\n CPU vs QPU sum ratio: %.2fx (>1 means QPU wins)\n",
|
||||||
|
qpu_sum > 0 ? cpu_sum / qpu_sum : 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
double sum_idct_4x4 = idct4_ns * MBS_1080P * 16 / 1e6;
|
|
||||||
double sum_deblock = (debl_v_ns + debl_h_ns) * MBS_1080P * 4 / 1e6;
|
|
||||||
double sum_mc = qmc22_ns * MBS_1080P * 4 / 1e6; /* worst-case all-mc22 */
|
|
||||||
printf("\n Sum (IDCT 4x4 + deblock luma + MC all-mc22): %7.2f ms\n",
|
|
||||||
sum_idct_4x4 + sum_deblock + sum_mc);
|
|
||||||
printf(" 30 fps deadline: 33.33 ms\n");
|
|
||||||
printf(" Margin: %+.2f ms\n",
|
|
||||||
33.33 - (sum_idct_4x4 + sum_deblock + sum_mc));
|
|
||||||
printf("\n(NOT included: chroma deblock, chroma IDCT, intra prediction,\n");
|
printf("\n(NOT included: chroma deblock, chroma IDCT, intra prediction,\n");
|
||||||
printf(" CABAC/CAVLC entropy. These bench numbers are a budget LOWER\n");
|
printf(" CABAC/CAVLC entropy. These bench numbers are a budget LOWER\n");
|
||||||
printf(" bound; the real decode stack adds 20-40%% on top.)\n");
|
printf(" bound; the real decode stack adds 20-40%% on top.\n");
|
||||||
(void) qmc20_ns; (void) qmc02_ns;
|
printf(" Per-kernel substrate decisions belong in daedalus_core.c recipe\n");
|
||||||
|
printf(" table; the QPU substrate decree (2026-05-23) keeps everything\n");
|
||||||
|
printf(" on QPU regardless of these numbers as a policy choice.)\n");
|
||||||
|
|
||||||
daedalus_ctx_destroy(ctx);
|
daedalus_ctx_destroy(ctx);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -683,13 +683,13 @@ int main(void)
|
|||||||
printf(" H264_QPEL_MC20 recipe substrate: %d\n",
|
printf(" H264_QPEL_MC20 recipe substrate: %d\n",
|
||||||
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_QPEL_MC20));
|
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_QPEL_MC20));
|
||||||
|
|
||||||
printf(" H264_DEBLOCK_LH recipe substrate: %d (CPU, no QPU H shader yet)\n",
|
printf(" H264_DEBLOCK_LH recipe substrate: %d\n",
|
||||||
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_DEBLOCK_LH));
|
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_DEBLOCK_LH));
|
||||||
printf(" H264_DEBLOCK_CV recipe substrate: %d (CPU)\n",
|
printf(" H264_DEBLOCK_CV recipe substrate: %d\n",
|
||||||
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_DEBLOCK_CV));
|
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_DEBLOCK_CV));
|
||||||
printf(" H264_DEBLOCK_CH recipe substrate: %d (CPU)\n",
|
printf(" H264_DEBLOCK_CH recipe substrate: %d\n",
|
||||||
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_DEBLOCK_CH));
|
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_DEBLOCK_CH));
|
||||||
printf(" H264_DEBLOCK_*_INTRA recipe substrate: %d (CPU, bS=4 set)\n",
|
printf(" H264_DEBLOCK_*_INTRA recipe substrate: %d (bS=4 family, all on QPU)\n",
|
||||||
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_DEBLOCK_LV_INTRA));
|
(int) daedalus_recipe_substrate_for(DAEDALUS_KERNEL_H264_DEBLOCK_LV_INTRA));
|
||||||
|
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
extern void daedalus_h264_pred_16x16_vertical_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_16x16_vertical(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_16x16_horizontal_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_16x16_horizontal(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_16x16_dc_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_16x16_dc(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_16x16_plane_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_16x16_plane(uint8_t *dst, ptrdiff_t stride);
|
||||||
|
|
||||||
#define STRIDE 17
|
#define STRIDE 17
|
||||||
#define ROWS 17
|
#define ROWS 17
|
||||||
@@ -84,7 +84,7 @@ int main(void)
|
|||||||
int t[16], l[16];
|
int t[16], l[16];
|
||||||
for (int i = 0; i < 16; i++) { t[i] = 10 + i; l[i] = 0; }
|
for (int i = 0; i < 16; i++) { t[i] = 10 + i; l[i] = 0; }
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_16x16_vertical_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_16x16_vertical(&buf[1][1], STRIDE);
|
||||||
struct vertical_ctx vc = { t };
|
struct vertical_ctx vc = { t };
|
||||||
fail |= check(buf, "Vertical (mode 0)", expect_vertical, &vc);
|
fail |= check(buf, "Vertical (mode 0)", expect_vertical, &vc);
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ int main(void)
|
|||||||
int t[16] = {0}, l[16];
|
int t[16] = {0}, l[16];
|
||||||
for (int i = 0; i < 16; i++) l[i] = 50 + i;
|
for (int i = 0; i < 16; i++) l[i] = 50 + i;
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_16x16_horizontal_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_16x16_horizontal(&buf[1][1], STRIDE);
|
||||||
struct horizontal_ctx hc = { l };
|
struct horizontal_ctx hc = { l };
|
||||||
fail |= check(buf, "Horizontal (mode 1)", expect_horizontal, &hc);
|
fail |= check(buf, "Horizontal (mode 1)", expect_horizontal, &hc);
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ int main(void)
|
|||||||
int t[16], l[16];
|
int t[16], l[16];
|
||||||
for (int i = 0; i < 16; i++) { t[i] = 2; l[i] = 6; }
|
for (int i = 0; i < 16; i++) { t[i] = 2; l[i] = 6; }
|
||||||
set_ctx(buf, 99, t, l);
|
set_ctx(buf, 99, t, l);
|
||||||
daedalus_h264_pred_16x16_dc_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_16x16_dc(&buf[1][1], STRIDE);
|
||||||
uint8_t exp_val = 4;
|
uint8_t exp_val = 4;
|
||||||
fail |= check(buf, "DC (mode 2)", expect_uniform, &exp_val);
|
fail |= check(buf, "DC (mode 2)", expect_uniform, &exp_val);
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ int main(void)
|
|||||||
int t[16], l[16];
|
int t[16], l[16];
|
||||||
for (int i = 0; i < 16; i++) { t[i] = 100; l[i] = 100; }
|
for (int i = 0; i < 16; i++) { t[i] = 100; l[i] = 100; }
|
||||||
set_ctx(buf, 100, t, l); /* uniform tl too — H/V sums actually zero */
|
set_ctx(buf, 100, t, l); /* uniform tl too — H/V sums actually zero */
|
||||||
daedalus_h264_pred_16x16_plane_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_16x16_plane(&buf[1][1], STRIDE);
|
||||||
uint8_t exp_val = 100;
|
uint8_t exp_val = 100;
|
||||||
fail |= check(buf, "Plane (mode 3, uniform)", expect_uniform, &exp_val);
|
fail |= check(buf, "Plane (mode 3, uniform)", expect_uniform, &exp_val);
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ int main(void)
|
|||||||
int t[16], l[16];
|
int t[16], l[16];
|
||||||
for (int i = 0; i < 16; i++) { t[i] = i; l[i] = i; }
|
for (int i = 0; i < 16; i++) { t[i] = i; l[i] = i; }
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_16x16_plane_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_16x16_plane(&buf[1][1], STRIDE);
|
||||||
uint8_t tl_actual = buf[1 + 0][1 + 0];
|
uint8_t tl_actual = buf[1 + 0][1 + 0];
|
||||||
uint8_t br_actual = buf[1 + 15][1 + 15];
|
uint8_t br_actual = buf[1 + 15][1 + 15];
|
||||||
int spot_fail = 0;
|
int spot_fail = 0;
|
||||||
|
|||||||
+19
-19
@@ -22,15 +22,15 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
extern void daedalus_h264_pred_4x4_vertical_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_4x4_vertical(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_4x4_horizontal_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_4x4_horizontal(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_4x4_dc_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_4x4_dc(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_4x4_ddl_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_4x4_ddl(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_4x4_ddr_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_4x4_ddr(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_4x4_vr_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_4x4_vr(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_4x4_hd_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_4x4_hd(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_4x4_vl_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_4x4_vl(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_4x4_hu_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_4x4_hu(uint8_t *dst, ptrdiff_t stride);
|
||||||
|
|
||||||
#define STRIDE 9
|
#define STRIDE 9
|
||||||
typedef void (*pred_fn)(uint8_t *dst, ptrdiff_t stride);
|
typedef void (*pred_fn)(uint8_t *dst, ptrdiff_t stride);
|
||||||
@@ -82,7 +82,7 @@ int main(void)
|
|||||||
int t[8] = { 10, 20, 30, 40, 0, 0, 0, 0 };
|
int t[8] = { 10, 20, 30, 40, 0, 0, 0, 0 };
|
||||||
int l[4] = { 0, 0, 0, 0 };
|
int l[4] = { 0, 0, 0, 0 };
|
||||||
set_ctx(buf, tl, t, l);
|
set_ctx(buf, tl, t, l);
|
||||||
daedalus_h264_pred_4x4_vertical_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_vertical(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{10,20,30,40}, {10,20,30,40}, {10,20,30,40}, {10,20,30,40}
|
{10,20,30,40}, {10,20,30,40}, {10,20,30,40}, {10,20,30,40}
|
||||||
};
|
};
|
||||||
@@ -95,7 +95,7 @@ int main(void)
|
|||||||
int t[8] = { 0,0,0,0, 0,0,0,0 };
|
int t[8] = { 0,0,0,0, 0,0,0,0 };
|
||||||
int l[4] = { 50, 60, 70, 80 };
|
int l[4] = { 50, 60, 70, 80 };
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_4x4_horizontal_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_horizontal(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{50,50,50,50}, {60,60,60,60}, {70,70,70,70}, {80,80,80,80}
|
{50,50,50,50}, {60,60,60,60}, {70,70,70,70}, {80,80,80,80}
|
||||||
};
|
};
|
||||||
@@ -110,7 +110,7 @@ int main(void)
|
|||||||
int t[8] = { 1,1,1,1, 0,0,0,0 };
|
int t[8] = { 1,1,1,1, 0,0,0,0 };
|
||||||
int l[4] = { 3,3,3,3 };
|
int l[4] = { 3,3,3,3 };
|
||||||
set_ctx(buf, 99, t, l); /* tl unused for DC */
|
set_ctx(buf, 99, t, l); /* tl unused for DC */
|
||||||
daedalus_h264_pred_4x4_dc_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_dc(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{2,2,2,2}, {2,2,2,2}, {2,2,2,2}, {2,2,2,2}
|
{2,2,2,2}, {2,2,2,2}, {2,2,2,2}, {2,2,2,2}
|
||||||
};
|
};
|
||||||
@@ -125,7 +125,7 @@ int main(void)
|
|||||||
int t[8] = { 100,100,100,100, 100,100,100,100 };
|
int t[8] = { 100,100,100,100, 100,100,100,100 };
|
||||||
int l[4] = { 0,0,0,0 };
|
int l[4] = { 0,0,0,0 };
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_4x4_ddl_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_ddl(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{100,100,100,100}, {100,100,100,100},
|
{100,100,100,100}, {100,100,100,100},
|
||||||
{100,100,100,100}, {100,100,100,100}
|
{100,100,100,100}, {100,100,100,100}
|
||||||
@@ -140,7 +140,7 @@ int main(void)
|
|||||||
int t[8] = { 200,200,200,200, 0,0,0,0 };
|
int t[8] = { 200,200,200,200, 0,0,0,0 };
|
||||||
int l[4] = { 200,200,200,200 };
|
int l[4] = { 200,200,200,200 };
|
||||||
set_ctx(buf, 200, t, l);
|
set_ctx(buf, 200, t, l);
|
||||||
daedalus_h264_pred_4x4_ddr_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_ddr(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{200,200,200,200}, {200,200,200,200},
|
{200,200,200,200}, {200,200,200,200},
|
||||||
{200,200,200,200}, {200,200,200,200}
|
{200,200,200,200}, {200,200,200,200}
|
||||||
@@ -155,7 +155,7 @@ int main(void)
|
|||||||
int t[8] = { 80,80,80,80, 0,0,0,0 };
|
int t[8] = { 80,80,80,80, 0,0,0,0 };
|
||||||
int l[4] = { 80,80,80,80 };
|
int l[4] = { 80,80,80,80 };
|
||||||
set_ctx(buf, 80, t, l);
|
set_ctx(buf, 80, t, l);
|
||||||
daedalus_h264_pred_4x4_vr_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_vr(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{80,80,80,80}, {80,80,80,80}, {80,80,80,80}, {80,80,80,80}
|
{80,80,80,80}, {80,80,80,80}, {80,80,80,80}, {80,80,80,80}
|
||||||
};
|
};
|
||||||
@@ -168,7 +168,7 @@ int main(void)
|
|||||||
int t[8] = { 120,120,120,120, 0,0,0,0 };
|
int t[8] = { 120,120,120,120, 0,0,0,0 };
|
||||||
int l[4] = { 120,120,120,120 };
|
int l[4] = { 120,120,120,120 };
|
||||||
set_ctx(buf, 120, t, l);
|
set_ctx(buf, 120, t, l);
|
||||||
daedalus_h264_pred_4x4_hd_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_hd(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{120,120,120,120}, {120,120,120,120},
|
{120,120,120,120}, {120,120,120,120},
|
||||||
{120,120,120,120}, {120,120,120,120}
|
{120,120,120,120}, {120,120,120,120}
|
||||||
@@ -182,7 +182,7 @@ int main(void)
|
|||||||
int t[8] = { 64,64,64,64, 64,64,64,64 };
|
int t[8] = { 64,64,64,64, 64,64,64,64 };
|
||||||
int l[4] = { 0,0,0,0 };
|
int l[4] = { 0,0,0,0 };
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_4x4_vl_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_vl(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{64,64,64,64}, {64,64,64,64}, {64,64,64,64}, {64,64,64,64}
|
{64,64,64,64}, {64,64,64,64}, {64,64,64,64}, {64,64,64,64}
|
||||||
};
|
};
|
||||||
@@ -195,7 +195,7 @@ int main(void)
|
|||||||
int t[8] = { 0,0,0,0, 0,0,0,0 };
|
int t[8] = { 0,0,0,0, 0,0,0,0 };
|
||||||
int l[4] = { 200,200,200,200 };
|
int l[4] = { 200,200,200,200 };
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_4x4_hu_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_hu(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{200,200,200,200}, {200,200,200,200},
|
{200,200,200,200}, {200,200,200,200},
|
||||||
{200,200,200,200}, {200,200,200,200}
|
{200,200,200,200}, {200,200,200,200}
|
||||||
@@ -230,7 +230,7 @@ int main(void)
|
|||||||
int t[8] = { 10,20,30,40, 0,0,0,0 };
|
int t[8] = { 10,20,30,40, 0,0,0,0 };
|
||||||
int l[4] = { 50,60,70,0 };
|
int l[4] = { 50,60,70,0 };
|
||||||
set_ctx(buf, 5, t, l);
|
set_ctx(buf, 5, t, l);
|
||||||
daedalus_h264_pred_4x4_vr_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_4x4_vr(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[4][4] = {
|
uint8_t exp[4][4] = {
|
||||||
{ 8,15,25,35},
|
{ 8,15,25,35},
|
||||||
{18,11,20,30},
|
{18,11,20,30},
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
extern void daedalus_h264_pred_8x8l_vertical_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_8x8l_vertical(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_8x8l_horizontal_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_8x8l_horizontal(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_8x8l_dc_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_8x8l_dc(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_8x8l_ddl_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_8x8l_ddl(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_8x8l_ddr_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_8x8l_ddr(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_8x8l_vr_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_8x8l_vr(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_8x8l_hd_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_8x8l_hd(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_8x8l_vl_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_8x8l_vl(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_8x8l_hu_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_8x8l_hu(uint8_t *dst, ptrdiff_t stride);
|
||||||
|
|
||||||
#define STRIDE 17
|
#define STRIDE 17
|
||||||
#define ROWS 9
|
#define ROWS 9
|
||||||
@@ -61,7 +61,7 @@ int main(void)
|
|||||||
for (int i = 0; i < 16; i++) t[i] = 50;
|
for (int i = 0; i < 16; i++) t[i] = 50;
|
||||||
for (int j = 0; j < 8; j++) l[j] = 0;
|
for (int j = 0; j < 8; j++) l[j] = 0;
|
||||||
set_ctx(buf, 50, t, l);
|
set_ctx(buf, 50, t, l);
|
||||||
daedalus_h264_pred_8x8l_vertical_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_8x8l_vertical(&buf[1][1], STRIDE);
|
||||||
fail |= check_uniform(buf, "Vertical (mode 0, uniform top)", 50);
|
fail |= check_uniform(buf, "Vertical (mode 0, uniform top)", 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ int main(void)
|
|||||||
int t[16] = {0}, l[8];
|
int t[16] = {0}, l[8];
|
||||||
for (int j = 0; j < 8; j++) l[j] = 70;
|
for (int j = 0; j < 8; j++) l[j] = 70;
|
||||||
set_ctx(buf, 70, t, l);
|
set_ctx(buf, 70, t, l);
|
||||||
daedalus_h264_pred_8x8l_horizontal_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_8x8l_horizontal(&buf[1][1], STRIDE);
|
||||||
fail |= check_uniform(buf, "Horizontal (mode 1, uniform left)", 70);
|
fail |= check_uniform(buf, "Horizontal (mode 1, uniform left)", 70);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ int main(void)
|
|||||||
for (int i = 0; i < 16; i++) t[i] = 33;
|
for (int i = 0; i < 16; i++) t[i] = 33;
|
||||||
for (int j = 0; j < 8; j++) l[j] = 33;
|
for (int j = 0; j < 8; j++) l[j] = 33;
|
||||||
set_ctx(buf, 33, t, l);
|
set_ctx(buf, 33, t, l);
|
||||||
daedalus_h264_pred_8x8l_dc_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_8x8l_dc(&buf[1][1], STRIDE);
|
||||||
fail |= check_uniform(buf, "DC (mode 2, uniform)", 33);
|
fail |= check_uniform(buf, "DC (mode 2, uniform)", 33);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ int main(void)
|
|||||||
int t[16], l[8] = {0};
|
int t[16], l[8] = {0};
|
||||||
for (int i = 0; i < 16; i++) t[i] = i;
|
for (int i = 0; i < 16; i++) t[i] = i;
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_8x8l_vertical_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_8x8l_vertical(&buf[1][1], STRIDE);
|
||||||
int diff = 0;
|
int diff = 0;
|
||||||
for (int r = 0; r < 8; r++)
|
for (int r = 0; r < 8; r++)
|
||||||
for (int c = 0; c < 8; c++)
|
for (int c = 0; c < 8; c++)
|
||||||
@@ -129,7 +129,7 @@ int main(void)
|
|||||||
int t[16] = {0}, l[8];
|
int t[16] = {0}, l[8];
|
||||||
for (int j = 0; j < 8; j++) l[j] = j;
|
for (int j = 0; j < 8; j++) l[j] = j;
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_8x8l_horizontal_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_8x8l_horizontal(&buf[1][1], STRIDE);
|
||||||
int diff = 0;
|
int diff = 0;
|
||||||
for (int r = 0; r < 8; r++)
|
for (int r = 0; r < 8; r++)
|
||||||
for (int c = 0; c < 8; c++)
|
for (int c = 0; c < 8; c++)
|
||||||
@@ -146,12 +146,12 @@ int main(void)
|
|||||||
{
|
{
|
||||||
typedef void (*pred_fn_t)(uint8_t *dst, ptrdiff_t stride);
|
typedef void (*pred_fn_t)(uint8_t *dst, ptrdiff_t stride);
|
||||||
struct { const char *name; pred_fn_t fn; } modes[] = {
|
struct { const char *name; pred_fn_t fn; } modes[] = {
|
||||||
{ "DDL (mode 3, uniform)", daedalus_h264_pred_8x8l_ddl_ref },
|
{ "DDL (mode 3, uniform)", daedalus_h264_pred_8x8l_ddl },
|
||||||
{ "DDR (mode 4, uniform)", daedalus_h264_pred_8x8l_ddr_ref },
|
{ "DDR (mode 4, uniform)", daedalus_h264_pred_8x8l_ddr },
|
||||||
{ "VR (mode 5, uniform)", daedalus_h264_pred_8x8l_vr_ref },
|
{ "VR (mode 5, uniform)", daedalus_h264_pred_8x8l_vr },
|
||||||
{ "HD (mode 6, uniform)", daedalus_h264_pred_8x8l_hd_ref },
|
{ "HD (mode 6, uniform)", daedalus_h264_pred_8x8l_hd },
|
||||||
{ "VL (mode 7, uniform)", daedalus_h264_pred_8x8l_vl_ref },
|
{ "VL (mode 7, uniform)", daedalus_h264_pred_8x8l_vl },
|
||||||
{ "HU (mode 8, uniform)", daedalus_h264_pred_8x8l_hu_ref },
|
{ "HU (mode 8, uniform)", daedalus_h264_pred_8x8l_hu },
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
|
for (size_t i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
|
||||||
uint8_t buf[ROWS][STRIDE];
|
uint8_t buf[ROWS][STRIDE];
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
extern void daedalus_h264_pred_chroma8x8_dc_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_chroma8x8_dc(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_chroma8x8_horizontal_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_chroma8x8_horizontal(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_chroma8x8_vertical_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_chroma8x8_vertical(uint8_t *dst, ptrdiff_t stride);
|
||||||
extern void daedalus_h264_pred_chroma8x8_plane_ref(uint8_t *dst, ptrdiff_t stride);
|
extern void daedalus_h264_pred_chroma8x8_plane(uint8_t *dst, ptrdiff_t stride);
|
||||||
|
|
||||||
#define STRIDE 9
|
#define STRIDE 9
|
||||||
#define ROWS 9
|
#define ROWS 9
|
||||||
@@ -69,7 +69,7 @@ int main(void)
|
|||||||
uint8_t buf[ROWS][STRIDE];
|
uint8_t buf[ROWS][STRIDE];
|
||||||
int t[8] = {0}, l[8] = {10, 20, 30, 40, 50, 60, 70, 80};
|
int t[8] = {0}, l[8] = {10, 20, 30, 40, 50, 60, 70, 80};
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_chroma8x8_horizontal_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_chroma8x8_horizontal(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[8][8];
|
uint8_t exp[8][8];
|
||||||
for (int r = 0; r < 8; r++) for (int c = 0; c < 8; c++) exp[r][c] = (uint8_t) l[r];
|
for (int r = 0; r < 8; r++) for (int c = 0; c < 8; c++) exp[r][c] = (uint8_t) l[r];
|
||||||
fail |= check_per_cell(buf, "Horizontal (mode 1)", exp);
|
fail |= check_per_cell(buf, "Horizontal (mode 1)", exp);
|
||||||
@@ -80,7 +80,7 @@ int main(void)
|
|||||||
uint8_t buf[ROWS][STRIDE];
|
uint8_t buf[ROWS][STRIDE];
|
||||||
int t[8] = {15, 25, 35, 45, 55, 65, 75, 85}, l[8] = {0};
|
int t[8] = {15, 25, 35, 45, 55, 65, 75, 85}, l[8] = {0};
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_chroma8x8_vertical_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_chroma8x8_vertical(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[8][8];
|
uint8_t exp[8][8];
|
||||||
for (int r = 0; r < 8; r++) for (int c = 0; c < 8; c++) exp[r][c] = (uint8_t) t[c];
|
for (int r = 0; r < 8; r++) for (int c = 0; c < 8; c++) exp[r][c] = (uint8_t) t[c];
|
||||||
fail |= check_per_cell(buf, "Vertical (mode 2)", exp);
|
fail |= check_per_cell(buf, "Vertical (mode 2)", exp);
|
||||||
@@ -104,7 +104,7 @@ int main(void)
|
|||||||
int t[8] = { 8, 8, 8, 8, 16, 16, 16, 16 };
|
int t[8] = { 8, 8, 8, 8, 16, 16, 16, 16 };
|
||||||
int l[8] = { 24, 24, 24, 24, 40, 40, 40, 40 };
|
int l[8] = { 24, 24, 24, 24, 40, 40, 40, 40 };
|
||||||
set_ctx(buf, 99, t, l);
|
set_ctx(buf, 99, t, l);
|
||||||
daedalus_h264_pred_chroma8x8_dc_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_chroma8x8_dc(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[8][8] = {
|
uint8_t exp[8][8] = {
|
||||||
{16,16,16,16, 16,16,16,16},
|
{16,16,16,16, 16,16,16,16},
|
||||||
{16,16,16,16, 16,16,16,16},
|
{16,16,16,16, 16,16,16,16},
|
||||||
@@ -125,7 +125,7 @@ int main(void)
|
|||||||
int t[8], l[8];
|
int t[8], l[8];
|
||||||
for (int i = 0; i < 8; i++) { t[i] = 100; l[i] = 100; }
|
for (int i = 0; i < 8; i++) { t[i] = 100; l[i] = 100; }
|
||||||
set_ctx(buf, 100, t, l);
|
set_ctx(buf, 100, t, l);
|
||||||
daedalus_h264_pred_chroma8x8_plane_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_chroma8x8_plane(&buf[1][1], STRIDE);
|
||||||
uint8_t exp[8][8];
|
uint8_t exp[8][8];
|
||||||
for (int r = 0; r < 8; r++) for (int c = 0; c < 8; c++) exp[r][c] = 100;
|
for (int r = 0; r < 8; r++) for (int c = 0; c < 8; c++) exp[r][c] = 100;
|
||||||
fail |= check_per_cell(buf, "Plane uniform (mode 3)", exp);
|
fail |= check_per_cell(buf, "Plane uniform (mode 3)", exp);
|
||||||
@@ -153,7 +153,7 @@ int main(void)
|
|||||||
int t[8], l[8];
|
int t[8], l[8];
|
||||||
for (int i = 0; i < 8; i++) { t[i] = i; l[i] = i; }
|
for (int i = 0; i < 8; i++) { t[i] = i; l[i] = i; }
|
||||||
set_ctx(buf, 0, t, l);
|
set_ctx(buf, 0, t, l);
|
||||||
daedalus_h264_pred_chroma8x8_plane_ref(&buf[1][1], STRIDE);
|
daedalus_h264_pred_chroma8x8_plane(&buf[1][1], STRIDE);
|
||||||
uint8_t tl_actual = buf[1 + 0][1 + 0];
|
uint8_t tl_actual = buf[1 + 0][1 + 0];
|
||||||
uint8_t br_actual = buf[1 + 7][1 + 7];
|
uint8_t br_actual = buf[1 + 7][1 + 7];
|
||||||
int spot_fail = 0;
|
int spot_fail = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user