1- use super :: { H264Encoder , MIN_BITSTREAM_BUFFER_SIZE } ;
1+ use super :: H264Encoder ;
22
33use crate :: encoder:: gop:: { GopFrameType , GopPosition } ;
4+ use crate :: encoder:: resources:: { record_dpb_barriers, MIN_BITSTREAM_BUFFER_SIZE } ;
45use crate :: error:: { PixelForgeError , Result } ;
56use ash:: vk;
67use tracing:: debug;
@@ -28,9 +29,9 @@ impl H264Encoder {
2829 // Rate control setup.
2930 let ( rc_mode, average_bitrate, max_bitrate, qp) = match self . config . rate_control_mode {
3031 crate :: encoder:: RateControlMode :: Cqp | crate :: encoder:: RateControlMode :: Disabled => (
31- vk:: VideoEncodeRateControlModeFlagsKHR :: VBR ,
32- 100_000_000 , // 100 Mbps
33- 100_000_000 ,
32+ vk:: VideoEncodeRateControlModeFlagsKHR :: DISABLED ,
33+ 0 ,
34+ 0 ,
3435 self . config . quality_level as i32 ,
3536 ) ,
3637 crate :: encoder:: RateControlMode :: Cbr => (
@@ -77,32 +78,16 @@ impl H264Encoder {
7778 ) ;
7879 }
7980
80- // Transition DPB image to video encode DPB layout if needed.
81- let dpb_barrier = vk:: ImageMemoryBarrier :: default ( )
82- . old_layout ( vk:: ImageLayout :: UNDEFINED )
83- . new_layout ( vk:: ImageLayout :: VIDEO_ENCODE_DPB_KHR )
84- . src_queue_family_index ( vk:: QUEUE_FAMILY_IGNORED )
85- . dst_queue_family_index ( vk:: QUEUE_FAMILY_IGNORED )
86- . image ( self . dpb_images [ self . current_dpb_slot as usize ] )
87- . subresource_range ( vk:: ImageSubresourceRange {
88- aspect_mask : vk:: ImageAspectFlags :: COLOR ,
89- base_mip_level : 0 ,
90- level_count : 1 ,
91- base_array_layer : 0 ,
92- layer_count : 1 ,
93- } )
94- . src_access_mask ( vk:: AccessFlags :: empty ( ) )
95- . dst_access_mask ( vk:: AccessFlags :: empty ( ) ) ;
96-
81+ // Transition DPB images for encode.
82+ let ref_dpb_slots: Vec < u8 > = self . l0_references . iter ( ) . map ( |r| r. dpb_slot ) . collect ( ) ;
9783 unsafe {
98- self . context . device ( ) . cmd_pipeline_barrier (
84+ record_dpb_barriers (
85+ self . context . device ( ) ,
9986 self . encode_command_buffer ,
100- vk:: PipelineStageFlags :: TOP_OF_PIPE ,
101- vk:: PipelineStageFlags :: BOTTOM_OF_PIPE , // Use BOTTOM_OF_PIPE as VIDEO_ENCODE requires sync2
102- vk:: DependencyFlags :: empty ( ) ,
103- & [ ] ,
104- & [ ] ,
105- & [ dpb_barrier] ,
87+ & self . dpb_images ,
88+ self . use_layered_dpb ,
89+ self . current_dpb_slot ,
90+ & ref_dpb_slots,
10691 ) ;
10792 }
10893
@@ -135,7 +120,7 @@ impl H264Encoder {
135120
136121 let slice_qp_delta = match self . config . rate_control_mode {
137122 crate :: encoder:: RateControlMode :: Cqp | crate :: encoder:: RateControlMode :: Disabled => {
138- ( ( self . config . quality_level as i32 ) - 26 ) as i8
123+ ( self . config . quality_level as i32 - 26 ) as i8
139124 }
140125 _ => 0 ,
141126 } ;
@@ -150,7 +135,7 @@ impl H264Encoder {
150135 reserved1 : 0 ,
151136 cabac_init_idc :
152137 ash:: vk:: native:: StdVideoH264CabacInitIdc_STD_VIDEO_H264_CABAC_INIT_IDC_0 ,
153- disable_deblocking_filter_idc : ash:: vk:: native:: StdVideoH264DisableDeblockingFilterIdc_STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_DISABLED ,
138+ disable_deblocking_filter_idc : ash:: vk:: native:: StdVideoH264DisableDeblockingFilterIdc_STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_ENABLED ,
154139 pWeightTable : std:: ptr:: null ( ) ,
155140 } ;
156141
@@ -278,9 +263,9 @@ impl H264Encoder {
278263 } ;
279264
280265 // Create slice NAL unit entry.
281- // constant_qp should only be set when rate control is DISABLED
266+ // constant_qp should only be set when rate control is DISABLED.
282267 let constant_qp = if rc_mode == vk:: VideoEncodeRateControlModeFlagsKHR :: DISABLED {
283- self . config . quality_level as i32
268+ qp
284269 } else {
285270 0
286271 } ;
@@ -297,8 +282,8 @@ impl H264Encoder {
297282 let src_picture_resource = vk:: VideoPictureResourceInfoKHR :: default ( )
298283 . coded_offset ( vk:: Offset2D { x : 0 , y : 0 } )
299284 . coded_extent ( vk:: Extent2D {
300- width : self . config . dimensions . width ,
301- height : self . config . dimensions . height ,
285+ width : self . aligned_width ,
286+ height : self . aligned_height ,
302287 } )
303288 . base_array_layer ( 0 )
304289 . image_view_binding ( self . input_image_view ) ;
@@ -307,8 +292,8 @@ impl H264Encoder {
307292 let setup_picture_resource = vk:: VideoPictureResourceInfoKHR :: default ( )
308293 . coded_offset ( vk:: Offset2D { x : 0 , y : 0 } )
309294 . coded_extent ( vk:: Extent2D {
310- width : self . config . dimensions . width ,
311- height : self . config . dimensions . height ,
295+ width : self . aligned_width ,
296+ height : self . aligned_height ,
312297 } )
313298 . base_array_layer ( 0 )
314299 . image_view_binding ( self . dpb_image_views [ self . current_dpb_slot as usize ] ) ;
@@ -333,8 +318,8 @@ impl H264Encoder {
333318 vk:: VideoPictureResourceInfoKHR :: default ( )
334319 . coded_offset ( vk:: Offset2D { x : 0 , y : 0 } )
335320 . coded_extent ( vk:: Extent2D {
336- width : self . config . dimensions . width ,
337- height : self . config . dimensions . height ,
321+ width : self . aligned_width ,
322+ height : self . aligned_height ,
338323 } )
339324 . base_array_layer ( 0 )
340325 . image_view_binding ( self . dpb_image_views [ ref_info. dpb_slot as usize ] ) ,
@@ -381,8 +366,8 @@ impl H264Encoder {
381366 let resource = vk:: VideoPictureResourceInfoKHR :: default ( )
382367 . coded_offset ( vk:: Offset2D { x : 0 , y : 0 } )
383368 . coded_extent ( vk:: Extent2D {
384- width : self . config . dimensions . width ,
385- height : self . config . dimensions . height ,
369+ width : self . aligned_width ,
370+ height : self . aligned_height ,
386371 } )
387372 . base_array_layer ( 0 )
388373 . image_view_binding ( image_view) ;
@@ -580,25 +565,27 @@ impl H264Encoder {
580565 ) ;
581566 }
582567
583- // Reset video coding state for the first frame, then set rate control.
568+ // Reset video coding state for the first frame.
569+ // Combine RESET + RATE_CONTROL + QUALITY_LEVEL into a single control command.
570+ // This matches FFmpeg's approach and is required for AMD RADV.
584571 if is_first_frame {
585- let reset_control_info = vk:: VideoCodingControlInfoKHR :: default ( )
586- . flags ( vk:: VideoCodingControlFlagsKHR :: RESET ) ;
587- unsafe {
588- ( self . video_queue_fn . fp ( ) . cmd_control_video_coding_khr ) (
589- self . encode_command_buffer ,
590- & reset_control_info,
591- ) ;
592- }
572+ let mut quality_level_info =
573+ vk:: VideoEncodeQualityLevelInfoKHR :: default ( ) . quality_level ( 0 ) ;
574+ quality_level_info. p_next =
575+ ( & mut rc_info as * mut vk:: VideoEncodeRateControlInfoKHR ) . cast ( ) ;
576+
577+ let mut control_info = vk:: VideoCodingControlInfoKHR :: default ( ) . flags (
578+ vk:: VideoCodingControlFlagsKHR :: RESET
579+ | vk:: VideoCodingControlFlagsKHR :: ENCODE_RATE_CONTROL
580+ | vk:: VideoCodingControlFlagsKHR :: ENCODE_QUALITY_LEVEL ,
581+ ) ;
582+ control_info. p_next =
583+ ( & mut quality_level_info as * mut vk:: VideoEncodeQualityLevelInfoKHR ) . cast ( ) ;
593584
594- // After RESET, set the rate control mode.
595- let mut rate_control = vk:: VideoCodingControlInfoKHR :: default ( )
596- . flags ( vk:: VideoCodingControlFlagsKHR :: ENCODE_RATE_CONTROL ) ;
597- rate_control. p_next = ( & mut rc_info as * mut vk:: VideoEncodeRateControlInfoKHR ) . cast ( ) ;
598585 unsafe {
599586 ( self . video_queue_fn . fp ( ) . cmd_control_video_coding_khr ) (
600587 self . encode_command_buffer ,
601- & rate_control ,
588+ & control_info ,
602589 ) ;
603590 }
604591 }
0 commit comments