mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-11-01 03:18:02 +03:00
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]>
This commit is contained in:
5 files changed
+84
-29
No files matched your search
@@ -49,7 +49,8 @@ genX(hasvk_mfc_emit_static_state)(struct anv_cmd_buffer *cmd_buffer,
|
||||
uint32_t dst_page_offset,
|
||||
uint64_t dst_buffer_range,
|
||||
uint32_t width_in_mbs, uint32_t height_in_mbs,
|
||||
bool is_p, struct anv_address ref_address)
|
||||
bool is_p,
|
||||
const struct anv_video_reference_state *refs)
|
||||
{
|
||||
struct anv_video_session *vid = cmd_buffer->video.vid;
|
||||
|
||||
@@ -149,10 +150,13 @@ genX(hasvk_mfc_emit_static_state)(struct anv_cmd_buffer *cmd_buffer,
|
||||
* them with the valid, mapped recon address. */
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(buf.ReferencePictureAddress); i++)
|
||||
buf.ReferencePictureAddress[i] = recon_address;
|
||||
/* Frame store 0 is the P-frame's reference (previous reconstructed
|
||||
* frame); REF_IDX_STATE L0[0] maps ref index 0 to this frame store. */
|
||||
if (is_p)
|
||||
buf.ReferencePictureAddress[0] = ref_address;
|
||||
/* Frame store i holds DPB slot i, so a slot the picture can reference
|
||||
* goes straight into its own entry; the rest keep the recon address the
|
||||
* PRM asks for. */
|
||||
for (unsigned i = 0; i < ANV_VIDEO_MAX_DPB_SLOTS; i++) {
|
||||
if (refs->slot_valid[i])
|
||||
buf.ReferencePictureAddress[i] = refs->slot_address[i];
|
||||
}
|
||||
}
|
||||
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(MFX_BSP_BUF_BASE_ADDR_STATE), bsp) {
|
||||
@@ -290,17 +294,22 @@ genX(hasvk_mfc_emit_static_state)(struct anv_cmd_buffer *cmd_buffer,
|
||||
dmv.POCList[i] = i / 2;
|
||||
}
|
||||
|
||||
/* Reference index lists. Entries are set to the "non-existing" marker 0x80
|
||||
* (intel_mfc_avc_ref_idx_state). For a P frame, L0[0] points at frame store
|
||||
* 0: entry = (is_long_term<<6)|((top^bottom^1)<<5)|(frame_store_id<<1)|... ;
|
||||
* for a short-term progressive frame at store 0 this is 0x20
|
||||
* (intel_get_ref_idx_state_1). L1 is unused (P has no backward references). */
|
||||
/* Reference index lists. Unused entries carry the "non-existing" marker
|
||||
* 0x80 (intel_mfc_avc_ref_idx_state). A used one is
|
||||
* (is_long_term<<6)|((top^bottom^1)<<5)|(frame_store_id<<1), which for a
|
||||
* short-term progressive frame comes out as 0x20|(frame_store_id<<1)
|
||||
* (intel_get_ref_idx_state_1). L1 stays empty: B frames are out of scope,
|
||||
* so there are no backward references. */
|
||||
for (unsigned list = 0; list < 2; list++) {
|
||||
anv_batch_emit(&cmd_buffer->batch, GENX(MFX_AVC_REF_IDX_STATE), ref_idx) {
|
||||
ref_idx.ReferencePictureListSelect = list;
|
||||
memset(ref_idx.ReferenceListEntry, 0x80, sizeof(ref_idx.ReferenceListEntry));
|
||||
if (is_p && list == 0)
|
||||
ref_idx.ReferenceListEntry[0] = 0x20;
|
||||
if (is_p && list == 0) {
|
||||
unsigned n = MIN2(refs->l0_count,
|
||||
ARRAY_SIZE(ref_idx.ReferenceListEntry));
|
||||
for (unsigned i = 0; i < n; i++)
|
||||
ref_idx.ReferenceListEntry[i] = 0x20 | (refs->l0_slot[i] << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* GFX_VERx10 == 70 */
|
||||
|
||||
Reference in new issue
Block a user