mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-10-31 19:08:03 +03:00
Reapply "hasvk: Encode B pictures on gen7."
This reverts commit 26405fe38c.
This commit is contained in:
5 files changed
+76
-24
No files matched your search
@@ -3663,6 +3663,17 @@ anv_image_dpb_address(const struct anv_image_view *iv,
|
|||||||
&x_offset_sa,
|
&x_offset_sa,
|
||||||
&y_offset_sa);
|
&y_offset_sa);
|
||||||
|
|
||||||
|
/* isl hands back a tile-aligned byte offset plus whatever is left over
|
||||||
|
* inside that tile. MFX takes a plain address for the picture, so the
|
||||||
|
* remainder has to be folded in: dropping it puts every layer whose start
|
||||||
|
* is not tile-aligned at the wrong place -- for a 176x144 NV12 array that
|
||||||
|
* is 16 rows off on every odd layer, which corrupts the reference each
|
||||||
|
* picture builds on. */
|
||||||
|
const struct isl_surf *_surf = &iv->image->planes[0].primary_surface.isl;
|
||||||
|
offset_B += (uint64_t)y_offset_sa * _surf->row_pitch_B;
|
||||||
|
offset_B += (uint64_t)x_offset_sa *
|
||||||
|
(isl_format_get_layout(_surf->format)->bpb / 8);
|
||||||
|
|
||||||
return anv_address_add(addr, offset_B);
|
return anv_address_add(addr, offset_B);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3876,6 +3887,8 @@ struct anv_video_reference_state {
|
|||||||
bool slot_valid[ANV_VIDEO_MAX_DPB_SLOTS];
|
bool slot_valid[ANV_VIDEO_MAX_DPB_SLOTS];
|
||||||
uint8_t l0_slot[ANV_VIDEO_MAX_DPB_SLOTS];
|
uint8_t l0_slot[ANV_VIDEO_MAX_DPB_SLOTS];
|
||||||
uint8_t l0_count;
|
uint8_t l0_count;
|
||||||
|
uint8_t l1_slot[ANV_VIDEO_MAX_DPB_SLOTS];
|
||||||
|
uint8_t l1_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* One picture's slice of an intra refresh cycle: the macroblocks of region
|
/* One picture's slice of an intra refresh cycle: the macroblocks of region
|
||||||
|
|||||||
@@ -93,6 +93,16 @@ anv_CreateVideoSessionParametersKHR(VkDevice _device,
|
|||||||
if (!params)
|
if (!params)
|
||||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||||
|
|
||||||
|
/* The 8x8 transform is a High profile option this encoder does not
|
||||||
|
* implement: every macroblock is coded 16x16. Leaving the client's flag
|
||||||
|
* set would put transform_8x8_mode_flag=1 in the PPS we emit, and a decoder
|
||||||
|
* would then look for a transform_size_8x8_flag the PAK never writes,
|
||||||
|
* losing bitstream sync at the first macroblock. */
|
||||||
|
if (params->op == VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR) {
|
||||||
|
for (unsigned i = 0; i < params->h264_enc.h264_pps_count; i++)
|
||||||
|
params->h264_enc.h264_pps[i].base.flags.transform_8x8_mode_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
*pVideoSessionParameters = vk_video_session_parameters_to_handle(params);
|
*pVideoSessionParameters = vk_video_session_parameters_to_handle(params);
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -142,17 +152,18 @@ anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Baseline and Main are supported. Main is accepted so that CABAC
|
/* Baseline, Main and High. Main brings CABAC (entropy_coding_mode_flag,
|
||||||
* (entropy_coding_mode_flag == 1, forbidden in Baseline) can be selected;
|
* forbidden in Baseline), which the PAK does itself. High adds the 8x8
|
||||||
* the PAK performs the entropy coding. Main's inter-prediction features
|
* transform and custom scaling lists, and neither is mandatory: both are
|
||||||
* (B slices) are still not emitted — only I frames are produced. High is
|
* opted into per PPS, so a High stream that leaves them off is valid and
|
||||||
* rejected (8x8 transform / scaling lists not emitted). */
|
* is what this encoder produces. */
|
||||||
const VkVideoEncodeH264ProfileInfoKHR *h264_profile =
|
const VkVideoEncodeH264ProfileInfoKHR *h264_profile =
|
||||||
vk_find_struct_const(pVideoProfile->pNext, VIDEO_ENCODE_H264_PROFILE_INFO_KHR);
|
vk_find_struct_const(pVideoProfile->pNext, VIDEO_ENCODE_H264_PROFILE_INFO_KHR);
|
||||||
if (h264_profile) {
|
if (h264_profile) {
|
||||||
switch (h264_profile->stdProfileIdc) {
|
switch (h264_profile->stdProfileIdc) {
|
||||||
case STD_VIDEO_H264_PROFILE_IDC_BASELINE:
|
case STD_VIDEO_H264_PROFILE_IDC_BASELINE:
|
||||||
case STD_VIDEO_H264_PROFILE_IDC_MAIN:
|
case STD_VIDEO_H264_PROFILE_IDC_MAIN:
|
||||||
|
case STD_VIDEO_H264_PROFILE_IDC_HIGH:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
|
return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR;
|
||||||
@@ -208,7 +219,10 @@ anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice,
|
|||||||
* of them can be predicted from, though: each macroblock is coded against
|
* of them can be predicted from, though: each macroblock is coded against
|
||||||
* reference index 0, so multi-reference and B frames are still out. */
|
* reference index 0, so multi-reference and B frames are still out. */
|
||||||
pCapabilities->maxDpbSlots = ANV_VIDEO_MAX_DPB_SLOTS;
|
pCapabilities->maxDpbSlots = ANV_VIDEO_MAX_DPB_SLOTS;
|
||||||
pCapabilities->maxActiveReferencePictures = 1;
|
/* Two, so a B picture can name one reference in each list. Prediction
|
||||||
|
* still only uses reference index 0 of whichever list a macroblock is
|
||||||
|
* coded against. */
|
||||||
|
pCapabilities->maxActiveReferencePictures = 2;
|
||||||
|
|
||||||
struct VkVideoEncodeCapabilitiesKHR *enc_caps =
|
struct VkVideoEncodeCapabilitiesKHR *enc_caps =
|
||||||
(struct VkVideoEncodeCapabilitiesKHR *)
|
(struct VkVideoEncodeCapabilitiesKHR *)
|
||||||
@@ -274,8 +288,8 @@ anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice,
|
|||||||
* slice splitting). */
|
* slice splitting). */
|
||||||
h264_enc_ext->maxSliceCount = 68; /* 1088/16, covers up to 1080p */
|
h264_enc_ext->maxSliceCount = 68; /* 1088/16, covers up to 1080p */
|
||||||
h264_enc_ext->maxPPictureL0ReferenceCount = 1;
|
h264_enc_ext->maxPPictureL0ReferenceCount = 1;
|
||||||
h264_enc_ext->maxBPictureL0ReferenceCount = 0;
|
h264_enc_ext->maxBPictureL0ReferenceCount = 1;
|
||||||
h264_enc_ext->maxL1ReferenceCount = 0;
|
h264_enc_ext->maxL1ReferenceCount = 1;
|
||||||
h264_enc_ext->maxTemporalLayerCount = 1;
|
h264_enc_ext->maxTemporalLayerCount = 1;
|
||||||
h264_enc_ext->expectDyadicTemporalLayerPattern = VK_FALSE;
|
h264_enc_ext->expectDyadicTemporalLayerPattern = VK_FALSE;
|
||||||
h264_enc_ext->minQp = 0;
|
h264_enc_ext->minQp = 0;
|
||||||
|
|||||||
@@ -108,7 +108,10 @@ anv_h264_build_encode_slice_header(uint8_t *out_buf, uint32_t out_cap,
|
|||||||
|
|
||||||
bool is_idr = pic_info->flags.IdrPicFlag;
|
bool is_idr = pic_info->flags.IdrPicFlag;
|
||||||
unsigned nal_unit_type = is_idr ? 5 : 1;
|
unsigned nal_unit_type = is_idr ? 5 : 1;
|
||||||
unsigned nal_ref_idc = 1; /* I-frame is always a reference */
|
/* A picture nothing will reference must say so, or a decoder keeps it in
|
||||||
|
* the DPB and its frame_num accounting drifts: an IDR is always a
|
||||||
|
* reference, otherwise the client's is_reference decides. */
|
||||||
|
unsigned nal_ref_idc = (is_idr || pic_info->flags.is_reference) ? 1 : 0;
|
||||||
|
|
||||||
bw_put_bit(&bw, 0); /* forbidden_zero_bit */
|
bw_put_bit(&bw, 0); /* forbidden_zero_bit */
|
||||||
bw_put_u(&bw, nal_ref_idc, 2);
|
bw_put_u(&bw, nal_ref_idc, 2);
|
||||||
@@ -139,14 +142,24 @@ anv_h264_build_encode_slice_header(uint8_t *out_buf, uint32_t out_cap,
|
|||||||
if (pps->flags.redundant_pic_cnt_present_flag)
|
if (pps->flags.redundant_pic_cnt_present_flag)
|
||||||
bw_put_ue(&bw, 0);
|
bw_put_ue(&bw, 0);
|
||||||
|
|
||||||
/* P-slice reference-list syntax (H.264 7.3.3). B slices are out of scope, so
|
/* Inter reference-list syntax (H.264 7.3.3). */
|
||||||
* direct_spatial_mv_pred_flag is never emitted. */
|
bool is_b = (slice_hdr->slice_type == STD_VIDEO_H264_SLICE_TYPE_B);
|
||||||
bool is_p = (slice_hdr->slice_type == STD_VIDEO_H264_SLICE_TYPE_P);
|
bool is_p = is_b || (slice_hdr->slice_type == STD_VIDEO_H264_SLICE_TYPE_P);
|
||||||
|
if (is_b) {
|
||||||
|
/* direct_spatial_mv_pred_flag = 1: spatial direct mode, which derives
|
||||||
|
* its motion from neighbours instead of the co-located picture's stored
|
||||||
|
* vectors, so no direct MV buffer has to be read back. */
|
||||||
|
bw_put_bit(&bw, 1);
|
||||||
|
}
|
||||||
if (is_p) {
|
if (is_p) {
|
||||||
/* num_ref_idx_active_override_flag = 0: use the PPS default L0 count. */
|
/* num_ref_idx_active_override_flag = 0: use the PPS default counts. */
|
||||||
bw_put_bit(&bw, 0);
|
bw_put_bit(&bw, 0);
|
||||||
/* ref_pic_list_modification_flag_l0 = 0: default frame_num-ordered list. */
|
/* ref_pic_list_modification_flag_l0 = 0: default frame_num-ordered list. */
|
||||||
bw_put_bit(&bw, 0);
|
bw_put_bit(&bw, 0);
|
||||||
|
if (is_b) {
|
||||||
|
/* ref_pic_list_modification_flag_l1 = 0: default POC-ordered list. */
|
||||||
|
bw_put_bit(&bw, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pred_weight_table is absent (weighted_pred_flag is off). */
|
/* pred_weight_table is absent (weighted_pred_flag is off). */
|
||||||
|
|||||||
@@ -192,9 +192,9 @@ genX(hasvk_mfc_emit_static_state)(struct anv_cmd_buffer *cmd_buffer,
|
|||||||
avc_img.TrellisQuantizationChromaDisable = false;
|
avc_img.TrellisQuantizationChromaDisable = false;
|
||||||
avc_img.IntraMBConformanceMaxSize = 0xEE8;
|
avc_img.IntraMBConformanceMaxSize = 0xEE8;
|
||||||
avc_img.InterMBConformanceMaxSize = 0xBB8;
|
avc_img.InterMBConformanceMaxSize = 0xBB8;
|
||||||
avc_img.NumberofReferenceFrames = is_p ? 1 : 0;
|
avc_img.NumberofReferenceFrames = refs->l0_count + refs->l1_count;
|
||||||
avc_img.NumberofActiveReferencePicturesfromL0 = is_p ? 1 : 0;
|
avc_img.NumberofActiveReferencePicturesfromL0 = refs->l0_count;
|
||||||
avc_img.NumberofActiveReferencePicturesfromL1 = 0;
|
avc_img.NumberofActiveReferencePicturesfromL1 = refs->l1_count;
|
||||||
avc_img.InitialQPValue = 0; /* per-slice QP comes from SLICE_STATE */
|
avc_img.InitialQPValue = 0; /* per-slice QP comes from SLICE_STATE */
|
||||||
avc_img.PicOrderPresent = pps->flags.bottom_field_pic_order_in_frame_present_flag;
|
avc_img.PicOrderPresent = pps->flags.bottom_field_pic_order_in_frame_present_flag;
|
||||||
avc_img.DeltaPicOrderAlwaysZero = sps->flags.delta_pic_order_always_zero_flag;
|
avc_img.DeltaPicOrderAlwaysZero = sps->flags.delta_pic_order_always_zero_flag;
|
||||||
@@ -304,11 +304,12 @@ genX(hasvk_mfc_emit_static_state)(struct anv_cmd_buffer *cmd_buffer,
|
|||||||
anv_batch_emit(&cmd_buffer->batch, GENX(MFX_AVC_REF_IDX_STATE), ref_idx) {
|
anv_batch_emit(&cmd_buffer->batch, GENX(MFX_AVC_REF_IDX_STATE), ref_idx) {
|
||||||
ref_idx.ReferencePictureListSelect = list;
|
ref_idx.ReferencePictureListSelect = list;
|
||||||
memset(ref_idx.ReferenceListEntry, 0x80, sizeof(ref_idx.ReferenceListEntry));
|
memset(ref_idx.ReferenceListEntry, 0x80, sizeof(ref_idx.ReferenceListEntry));
|
||||||
if (is_p && list == 0) {
|
const uint8_t *slots = list == 0 ? refs->l0_slot : refs->l1_slot;
|
||||||
unsigned n = MIN2(refs->l0_count,
|
unsigned count = list == 0 ? refs->l0_count : refs->l1_count;
|
||||||
ARRAY_SIZE(ref_idx.ReferenceListEntry));
|
if (is_p) {
|
||||||
|
unsigned n = MIN2(count, ARRAY_SIZE(ref_idx.ReferenceListEntry));
|
||||||
for (unsigned i = 0; i < n; i++)
|
for (unsigned i = 0; i < n; i++)
|
||||||
ref_idx.ReferenceListEntry[i] = 0x20 | (refs->l0_slot[i] << 1);
|
ref_idx.ReferenceListEntry[i] = 0x20 | (slots[i] << 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,16 +329,19 @@ genX(hasvk_mfc_emit_slice)(struct anv_cmd_buffer *cmd_buffer,
|
|||||||
uint32_t dst_page_offset,
|
uint32_t dst_page_offset,
|
||||||
const struct anv_video_intra_refresh *intra_refresh)
|
const struct anv_video_intra_refresh *intra_refresh)
|
||||||
{
|
{
|
||||||
/* A P slice references the previous reconstructed frame; an I slice does
|
/* An I slice predicts from nothing; P and B slices both predict from L0,
|
||||||
* not. B slices are out of scope. */
|
* and a B slice additionally has L1 available. */
|
||||||
bool is_p = (slice_hdr->slice_type == STD_VIDEO_H264_SLICE_TYPE_P);
|
bool is_b = (slice_hdr->slice_type == STD_VIDEO_H264_SLICE_TYPE_B);
|
||||||
|
bool is_p = is_b || (slice_hdr->slice_type == STD_VIDEO_H264_SLICE_TYPE_P);
|
||||||
|
|
||||||
/* MFX_AVC_SLICE_STATE is not used by decode; fields are matched against the
|
/* MFX_AVC_SLICE_STATE is not used by decode; fields are matched against the
|
||||||
* VA-API reference encoder (gen6_mfc_avc_slice_state). The slice covers the
|
* VA-API reference encoder (gen6_mfc_avc_slice_state). The slice covers the
|
||||||
* macroblock range [slice_start_mb, slice_end_mb) in raster order. */
|
* macroblock range [slice_start_mb, slice_end_mb) in raster order. */
|
||||||
anv_batch_emit(&cmd_buffer->batch, GENX(MFX_AVC_SLICE_STATE), slice) {
|
anv_batch_emit(&cmd_buffer->batch, GENX(MFX_AVC_SLICE_STATE), slice) {
|
||||||
slice.SliceType = is_p ? PSlice : ISlice; /* P=0,B=1,I=2 */
|
slice.SliceType = is_b ? BSlice :
|
||||||
|
is_p ? PSlice : ISlice; /* P=0,B=1,I=2 */
|
||||||
slice.NumberofReferencePicturesinInterpredictionList0 = is_p ? 1 : 0;
|
slice.NumberofReferencePicturesinInterpredictionList0 = is_p ? 1 : 0;
|
||||||
|
slice.NumberofReferencePicturesinInterpredictionList1 = is_b ? 1 : 0;
|
||||||
slice.SliceQuantizationParameter = qp;
|
slice.SliceQuantizationParameter = qp;
|
||||||
slice.CABACInitIDC = is_p ? slice_hdr->cabac_init_idc : 0;
|
slice.CABACInitIDC = is_p ? slice_hdr->cabac_init_idc : 0;
|
||||||
slice.DisableDeblockingFilterIndicator = 1;
|
slice.DisableDeblockingFilterIndicator = 1;
|
||||||
|
|||||||
@@ -1237,6 +1237,14 @@ anv_h264_encode_video(struct anv_cmd_buffer *cmd_buffer,
|
|||||||
break;
|
break;
|
||||||
refs.l0_slot[refs.l0_count++] = s;
|
refs.l0_slot[refs.l0_count++] = s;
|
||||||
}
|
}
|
||||||
|
n = MIN2(ref_lists->num_ref_idx_l1_active_minus1 + 1,
|
||||||
|
ANV_VIDEO_MAX_DPB_SLOTS);
|
||||||
|
for (unsigned i = 0; i < n; i++) {
|
||||||
|
uint8_t s = ref_lists->RefPicList1[i];
|
||||||
|
if (s >= ANV_VIDEO_MAX_DPB_SLOTS || !refs.slot_valid[s])
|
||||||
|
break;
|
||||||
|
refs.l1_slot[refs.l1_count++] = s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* A client that supplies reference slots but no list still means the
|
/* A client that supplies reference slots but no list still means the
|
||||||
* first one, which is what the encoder used to assume unconditionally. */
|
* first one, which is what the encoder used to assume unconditionally. */
|
||||||
|
|||||||
Reference in new issue
Block a user