Commit Graph
21 Commits
Author SHA1 Message Date
elwrclandClaude Opus 5 f68161c313 hasvk: Add open-loop CBR and VBR rate control for gen7.
Only constant QP was offered.  Add the two bitrate modes, with the quantizer
derived once per picture from the requested bitrate and frame rate.

There is no closed loop and there cannot be one here: a picture's size is
known only after the GPU encodes it, and vkCmdEncodeVideoKHR merely records
commands.  The VA-API encoder for this hardware runs its bit rate control
after each frame completes, which that API's synchronisation allows and this
one does not, and gen7 has no macroblock-level rate control the hardware
drives on its own -- the VA-API driver leaves those MFX_AVC_IMG_STATE fields
zero on this generation.  Vulkan defines rate control as best effort, and
this is the effort.

The quantizer comes from a measured curve rather than a guess: sweeping QP 14
to 50 over a 176x144 clip gives 361 bits per macroblock at QP 26 for an I
picture and 166 for a P one, halving every 12.5 steps of the quantizer for I
and every 10.3 for P.  Measured against the target across a 15x range of
bitrates, I pictures land between 0.82x and 1.30x, P pictures between 0.59x
and 1.56x -- the spread on P is content dependent and nothing open loop can
narrow it.  A target below about 90 bits per macroblock cannot be met at all,
since that is where the curve flattens.

dEQP-VK.video.encode.h264 goes from 84 to 92 of 120 with no failures.  The
remaining 28 are quantization maps, which gen7 has no hardware path for, and
B frames.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 08:21:15 +03:00
elwrclandClaude Opus 5 9cb5c4385b hasvk: Track DPB slots instead of assuming a single reference.
The encoder ignored VkVideoReferenceSlotInfoKHR entirely: it took
pReferenceSlots[0] as the one reference, wrote its address into frame store 0
and hardcoded the L0 list to that store.  Two DPB slots were all it could
honestly advertise, which is fewer than a GOP of any length needs.

Record each slot the operation names under its own index, since a slot maps
onto the frame store of the same index and MFX_PIPE_BUF_ADDR_STATE holds 16
of those, and build the L0 entries from StdVideoEncodeH264ReferenceListsInfo,
whose RefPicList0 already carries slot indices.  Clients that pass reference
slots without a list keep the old behaviour.

maxDpbSlots therefore goes to 16.  maxActiveReferencePictures stays at 1:
every macroblock is still coded against reference index 0, so a picture may
be kept in the DPB but only the one it names first is predicted from.

dEQP-VK.video.encode.h264.intra_refresh_* goes from 12 Pass and 32 stopped at
the maxDpbSlots >= GOP frame count precondition to 36 Pass, the remaining 8
being per-picture-partition mode, which is not offered.  The family as a whole
is 76 of 120 with no failures.  ffmpeg's h264_vulkan encoder no longer trips
its slot_index assertion and produces a full GOP.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 07:55:40 +03:00
elwrclandClaude Opus 5 0716678e70 hasvk: Add VK_KHR_video_encode_intra_refresh for gen7.
Each macroblock's intra/inter decision is already made on its own when the
PAK objects are emitted, so refreshing a region is a matter of coding the
macroblocks it covers the way an I slice codes them.  Regions divide the
picture evenly along rows, columns or raster order, which leaves the block,
block-row and block-column modes supported and gives empty regions for free
when the cycle is longer than the split axis.

Two things needed care.  PAK keeps the I slice numbering for MbType5Bits
inside a P slice, where H.264 itself offsets intra mb_types by 5; handing it
the offset value hangs the MFC.  And under constrained intra prediction a
neighbour only counts as available if it is in the refresh region too,
because prediction may not cross into an inter macroblock.

Nothing constrains motion away from not-yet-refreshed regions, which is
sound only because there is no motion estimation: every vector is zero, so a
macroblock reads its own co-located block and never leaves its region.
Motion estimation will have to honour VkVideoReferenceIntraRefreshInfoKHR's
dirty region count.

Per-picture-partition mode is not offered.  It wants the refreshed slice
coded as an I slice, header included, rather than as intra macroblocks
inside a P slice.

dEQP-VK.video.encode.h264.intra_refresh_* goes from 44 NotSupported to 12
Pass; all three modes pass in the variants that can run.  The other 32 stop
at a CTS precondition, maxDpbSlots >= GOP frame count, which the driver's
two slots do not meet.  Raising that needs real DPB slot tracking and is
what gates B frames and ffmpeg's encoder too.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 07:35:13 +03:00
elwrclandClaude Opus 5 636d2c2f70 hasvk: Add host_image_copy, H.264 encode and a batch of gen7 fixes.
Squashed work that had been sitting in the working tree. Grouped by area:

Extensions
  VK_EXT_host_image_copy, with a MEMCPY_BIT path that reads and writes the
  image's own tiled layout, VkSubresourceHostMemcpySizeEXT filled in, and
  VkHostImageCopyDevicePerformanceQueryEXT answered.  Depth/stencil and
  non-power-of-two bpb stay NotSupported.
  VK_EXT_pipeline_robustness, VK_KHR_shader_float_controls2,
  VK_KHR_shader_subgroup_rotate, VK_EXT_vertex_input_dynamic_state,
  VK_EXT_conditional_rendering (an MI_PREDICATE path for gen7, which has no
  GPRs), custom_border_color, border_color_swizzle, map_memory2,
  load_store_op_none, depth_clamp_zero_one,
  dynamic_rendering_unused_attachments, index_type_uint8,
  line_rasterization, vertex_attribute_divisor, mutable_descriptor_type.

H.264 encode
  MFC command emission and a bitstream writer, driving intra-only encode
  through the video queue.  Video profile reporting was also corrected from
  270 combinations down to the 11 that actually exist.

Correctness
  gfx7 routes typed surface writes through the render cache, so
  VK_ACCESS_SHADER_WRITE barriers have to flush it -- without that, nothing a
  fragment shader stored was visible.
  nir_opt_algebraic's fadd->flrp fusion rules dropped signed zero; '~' only
  excludes nir_fp_exact, not preserve_signed_zero, so reflect() with a -0
  input came out wrong.  Guarded with (nsz).
  Stop advertising STORAGE_READ_WITHOUT_FORMAT: shaderStorageImageReadWithout-
  Format is false here, and since Vulkan 1.3 the per-format bit is what grants
  permission, so reporting it while rejecting the pipeline is a contradiction.
  gfx7's typed data port ignores SURFTYPE_NULL -- the null surface still has
  one addressable texel, which read and wrote graphics address zero.  Bounds
  check typed image access against the image param when nullDescriptor is
  enabled, the same trick lower_image_atomic_instr already used on IVB.
  Formats that require a sampler Y'CbCr conversion no longer report
  BLIT_SRC/BLIT_DST/STORAGE_IMAGE.  Video decode does not need them.
  Check the surface state allocations in emit_binding_table() and in the push
  descriptor path instead of writing through a NULL map in release builds.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-09 00:32:40 +03:00
dancingmirrors cd91e8f22f hasvk: Remove now unreachable layered clamping. 2026-07-21 22:25:28 +03:00
dancingmirrors 409568b8d4 hasvk: We can use ARYSPC_LOD0 for layered DPB. 2026-07-21 22:25:28 +03:00
dancingmirrors 49447ce96e hasvk: Expose HASVK_DEBUG=video-debug and clean it up. 2026-07-21 22:25:28 +03:00
dancingmirrors 564cead081 hasvk: Without a QPitch override gen7 can't reliably handle layered DPB.
Just accept corruption and avoid intermittent hangs when not tile aligned.
Breaks: dEQP-VK.video.decode.h264.interleaved_layered_dpb_video_layout

Assisted-by: Claude
2026-07-21 22:25:27 +03:00
dancingmirrors 4204b5ff5b hasvk: Initial layered DPB support and plenty of debug output.
Assisted-by: Claude
2026-07-21 22:25:27 +03:00
dancingmirrors bd3d4fc732 hasvk: Gate video decode behind HASVK_DEBUG=video-decode.
Assisted-by: Claude
2026-07-21 22:25:24 +03:00
dancingmirrors 3d258cbaf7 hasvk: Gate video decode behind VIDEO_CODEC_H264DEC so we don't advertise it without the codec.
Assisted-by: Claude
2026-07-21 22:25:24 +03:00
dancingmirrors a2727d71b6 hasvk: Neutralize the unwritten chroma with monochrome video.
Otherwise we sample garbage with, say, yuvj420p.

Assisted-by: Claude
2026-07-21 22:25:23 +03:00
dancingmirrors 0f70099a69 hasvk: Reject result status queries on the video decode queue.
Inline queries enabled by video_maintenance1 would just lock up my
machine and I'm not sure a proper workaround exists.

A few nits while here.

Assisted-by: Claude
2026-07-21 22:25:23 +03:00
dancingmirrors 23b29b1f92 hasvk: Rework H.264 decode into long mode.
This is why the previously added slice header parser exists.

Assisted-by: Claude
2026-07-21 22:08:59 +03:00
dancingmirrors 5c6ad1fb4c hasvk: Validate profiles and harden the video session objects.
Assisted-by: Claude
2026-07-21 22:08:59 +03:00
Dave Airlie 1db147a9ce hasvk: add initial video decode support for h264.
This just adds the files with the programming info, it doesn't
enable the extensions etc

[dancingmirrors: A few forward port fixes.]
2026-07-21 15:23:49 +03:00
Dave Airlie 4d12fc3ec6 hasvk/image: allocate some memory for mv storage after video images.
these images need motion vector storage allocated with them
2026-07-21 15:18:38 +03:00
Kenneth Graunke 203bf6b58d hasvk: Make a batch decoder for each queue family
The decoder context needs to know what engine it's associated with.
Nowadays, we have render, compute, blitter, even video engines being
used from the same driver.  Rather than trying to have a single decoder
and thwacking the engine field back and forth between calls, we make
one per queue family, and stash a pointer in anv_queue for easy access.

(Ported from anv: 79caf8a44b682f731c0fd3b941f38cc1869efe2d)

[dancingmirrors: Adapted for elk.]
2026-07-21 14:54:59 +03:00
Nanley Chery 3126a5ef30 hasvk: Delete enum anv_depth_reg_mode
This is only used on gfx12+.

Reviewed-by: Lionel Landwerlin <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/42394>
2026-07-21 14:29:22 +03:00
elwrcl 7e82b85d19 wip: crocus/rusticl/elk/hasvk local changes before h264 cherry-pick 2026-07-21 14:26:36 +03:00
elwrcl 818cab85dc init 2026-06-06 13:25:15 +03:00