@@ -15,8 +15,8 @@ use crate::{
1515 display:: { Display , DisplayPlaneProperties , DisplayPlanePropertiesRaw , DisplayProperties } ,
1616 format:: { DrmFormatModifierProperties , Format , FormatProperties } ,
1717 image:: {
18- ImageDrmFormatModifierInfo , ImageFormatInfo , ImageFormatProperties , ImageUsage ,
19- SparseImageFormatInfo , SparseImageFormatProperties ,
18+ sampler :: ComponentMapping , ImageDrmFormatModifierInfo , ImageFormatInfo ,
19+ ImageFormatProperties , ImageUsage , SparseImageFormatInfo , SparseImageFormatProperties ,
2020 } ,
2121 instance:: { Instance , InstanceOwned } ,
2222 macros:: { impl_id_counter, vulkan_bitflags, vulkan_enum} ,
@@ -30,9 +30,15 @@ use crate::{
3030 semaphore:: { ExternalSemaphoreInfo , ExternalSemaphoreProperties } ,
3131 Sharing ,
3232 } ,
33+ video:: {
34+ ProfileInfo , VideoCapabilities , VideoCodecOperation , VideoDecodeCapabilities ,
35+ VideoDecodeCodecCapabilities , VideoDecodeH264Capabilities , VideoFormatInfo ,
36+ VideoFormatProperties ,
37+ } ,
3338 DebugWrapper , ExtensionProperties , Requires , RequiresAllOf , RequiresOneOf , Validated ,
3439 ValidationError , Version , VulkanError , VulkanObject ,
3540} ;
41+ use ash:: vk:: VideoFormatPropertiesKHR ;
3642use bytemuck:: cast_slice;
3743use parking_lot:: RwLock ;
3844use std:: {
@@ -3106,6 +3112,289 @@ impl PhysicalDevice {
31063112 visual_id,
31073113 ) != 0
31083114 }
3115+
3116+ pub fn video_format_properties (
3117+ & self ,
3118+ video_format_info : VideoFormatInfo ,
3119+ ) -> Result < Vec < VideoFormatProperties > , Validated < VulkanError > > {
3120+ self . validate_video_format_info ( & video_format_info) ?;
3121+
3122+ unsafe { Ok ( self . video_format_properties_unchecked ( video_format_info) ?) }
3123+ }
3124+
3125+ fn validate_video_format_info (
3126+ & self ,
3127+ video_format_info : & VideoFormatInfo ,
3128+ ) -> Result < ( ) , Box < ValidationError > > {
3129+ if !self . supported_extensions . khr_video_queue || self . api_version ( ) < Version :: V1_3 {
3130+ return Err ( Box :: new ( ValidationError {
3131+ requires_one_of : RequiresOneOf ( & [ RequiresAllOf ( & [
3132+ Requires :: DeviceExtension ( "khr_video_queue" ) ,
3133+ // Requires::APIVersion(Version::V1_3), // ?
3134+ ] ) ] ) ,
3135+ ..Default :: default ( )
3136+ } ) ) ;
3137+ } else {
3138+ Ok ( ( ) )
3139+ }
3140+ }
3141+
3142+ #[ cfg_attr( not( feature = "document_unchecked" ) , doc( hidden) ) ]
3143+ pub unsafe fn video_format_properties_unchecked (
3144+ & self ,
3145+ video_format_info : VideoFormatInfo ,
3146+ ) -> Result < Vec < VideoFormatProperties > , VulkanError > {
3147+ loop {
3148+ let mut num_formats = 0 ;
3149+ let mut h264_profile_info_vk = None ;
3150+ let video_profile_info_vk = video_format_info
3151+ . profile_list_info
3152+ . profiles
3153+ . iter ( )
3154+ . map ( |profile| {
3155+ let mut profile_info_vk = ash:: vk:: VideoProfileInfoKHR {
3156+ video_codec_operation : profile. video_codec_operation . into ( ) ,
3157+ chroma_subsampling : profile. chroma_subsampling . into ( ) ,
3158+ luma_bit_depth : profile. luma_bit_depth . into ( ) ,
3159+ chroma_bit_depth : if let Some ( chroma_bit_depth) = profile. chroma_bit_depth {
3160+ chroma_bit_depth. into ( )
3161+ } else {
3162+ ash:: vk:: VideoComponentBitDepthFlagsKHR :: INVALID
3163+ } ,
3164+ ..Default :: default ( )
3165+ } ;
3166+
3167+ match profile. video_codec_operation {
3168+ VideoCodecOperation :: EncodeH264 => todo ! ( ) ,
3169+ VideoCodecOperation :: EncodeH265 => todo ! ( ) ,
3170+ VideoCodecOperation :: DecodeH264 => {
3171+ let crate :: video:: DecodeProfileInfo :: H264 ( codec_profile_info) =
3172+ & profile. codec_profile_info
3173+ else {
3174+ panic ! ( "Unexpected profile" ) ;
3175+ } ;
3176+
3177+ let next = h264_profile_info_vk. insert (
3178+ ash:: vk:: VideoDecodeH264ProfileInfoKHR {
3179+ std_profile_idc : codec_profile_info. std_profile_idc ,
3180+ picture_layout : codec_profile_info. picture_layout . into ( ) ,
3181+ ..Default :: default ( )
3182+ } ,
3183+ ) ;
3184+
3185+ // VUID-VkVideoProfileInfoKHR-videoCodecOperation-07179
3186+ profile_info_vk. p_next = next as * const _ as * const _ ;
3187+ }
3188+ VideoCodecOperation :: DecodeH265 => todo ! ( ) ,
3189+ }
3190+
3191+ profile_info_vk
3192+ } )
3193+ . collect :: < Vec < _ > > ( ) ;
3194+
3195+ let profile_list_info_vk = ash:: vk:: VideoProfileListInfoKHR {
3196+ profile_count : video_profile_info_vk. len ( ) as _ ,
3197+ p_profiles : video_profile_info_vk. as_ptr ( ) as _ ,
3198+ ..Default :: default ( )
3199+ } ;
3200+
3201+ let video_format_info_vk = ash:: vk:: PhysicalDeviceVideoFormatInfoKHR {
3202+ p_next : & profile_list_info_vk as * const _ as _ ,
3203+ image_usage : video_format_info. image_usage . into ( ) ,
3204+ ..Default :: default ( )
3205+ } ;
3206+
3207+ let fns = self . instance ( ) . fns ( ) ;
3208+
3209+ ( fns. khr_video_queue
3210+ . get_physical_device_video_format_properties_khr ) (
3211+ self . handle ( ) ,
3212+ & video_format_info_vk,
3213+ & mut num_formats,
3214+ std:: ptr:: null_mut ( ) ,
3215+ )
3216+ . result ( )
3217+ . map_err ( VulkanError :: from) ?;
3218+
3219+ let mut video_format_properties_vk =
3220+ vec ! [ VideoFormatPropertiesKHR :: default ( ) ; num_formats as usize ] ;
3221+
3222+ let result = ( fns
3223+ . khr_video_queue
3224+ . get_physical_device_video_format_properties_khr ) (
3225+ self . handle ( ) ,
3226+ & video_format_info_vk,
3227+ & mut num_formats,
3228+ video_format_properties_vk. as_mut_ptr ( ) ,
3229+ ) ;
3230+
3231+ match result {
3232+ ash:: vk:: Result :: SUCCESS => {
3233+ video_format_properties_vk. set_len ( num_formats as usize ) ;
3234+ return Ok ( video_format_properties_vk
3235+ . into_iter ( )
3236+ . filter_map ( |vk| {
3237+ Some ( VideoFormatProperties {
3238+ format : vk. format . try_into ( ) . ok ( ) ?,
3239+ component_mapping : ComponentMapping {
3240+ r : vk. component_mapping . r . try_into ( ) . ok ( ) ?,
3241+ g : vk. component_mapping . g . try_into ( ) . ok ( ) ?,
3242+ b : vk. component_mapping . b . try_into ( ) . ok ( ) ?,
3243+ a : vk. component_mapping . a . try_into ( ) . ok ( ) ?,
3244+ } ,
3245+ image_create_flags : vk. image_create_flags . try_into ( ) . ok ( ) ?,
3246+ image_type : vk. image_type . try_into ( ) . ok ( ) ?,
3247+ image_tiling : vk. image_tiling . try_into ( ) . ok ( ) ?,
3248+ image_usage_flags : vk. image_usage_flags . try_into ( ) . ok ( ) ?,
3249+ } )
3250+ } )
3251+ . collect ( ) ) ;
3252+ }
3253+ ash:: vk:: Result :: INCOMPLETE => ( ) ,
3254+ err => return Err ( VulkanError :: from ( err) ) ,
3255+ }
3256+ }
3257+ }
3258+
3259+ pub fn video_capabilities (
3260+ & self ,
3261+ profile_info : ProfileInfo ,
3262+ ) -> Result < VideoCapabilities , Validated < VulkanError > > {
3263+ self . validate_video_capabilities ( & profile_info) ?;
3264+
3265+ unsafe { Ok ( self . video_capabilities_unchecked ( profile_info) ?) }
3266+ }
3267+
3268+ fn validate_video_capabilities (
3269+ & self ,
3270+ profile_info : & ProfileInfo ,
3271+ ) -> Result < ( ) , Box < ValidationError > > {
3272+ if !self . supported_extensions . khr_video_queue || self . api_version ( ) < Version :: V1_3 {
3273+ return Err ( Box :: new ( ValidationError {
3274+ requires_one_of : RequiresOneOf ( & [ RequiresAllOf ( & [
3275+ Requires :: DeviceExtension ( "khr_video_queue" ) ,
3276+ // Requires::APIVersion(Version::V1_3), // ?
3277+ ] ) ] ) ,
3278+ ..Default :: default ( )
3279+ } ) ) ;
3280+ }
3281+
3282+ profile_info
3283+ . validate ( )
3284+ . map_err ( |err| err. add_context ( "profile_info" ) )
3285+ }
3286+
3287+ #[ cfg_attr( not( feature = "document_unchecked" ) , doc( hidden) ) ]
3288+ pub unsafe fn video_capabilities_unchecked (
3289+ & self ,
3290+ profile_info : ProfileInfo ,
3291+ ) -> Result < VideoCapabilities , VulkanError > {
3292+ let mut video_capabilities = ash:: vk:: VideoCapabilitiesKHR :: default ( ) ;
3293+ let mut decode_capabilities = ash:: vk:: VideoDecodeCapabilitiesKHR :: default ( ) ;
3294+ let mut h264_decode_capabilities = None ;
3295+ let mut h264_profile_info = None ;
3296+
3297+ let ProfileInfo {
3298+ video_codec_operation,
3299+ chroma_subsampling,
3300+ luma_bit_depth,
3301+ chroma_bit_depth,
3302+ codec_profile_info,
3303+ _ne : _,
3304+ } = profile_info;
3305+
3306+ let mut profile_info = ash:: vk:: VideoProfileInfoKHR {
3307+ video_codec_operation : video_codec_operation. into ( ) ,
3308+ chroma_subsampling : chroma_subsampling. into ( ) ,
3309+ luma_bit_depth : luma_bit_depth. into ( ) ,
3310+ chroma_bit_depth : if let Some ( chroma_bit_depth) = chroma_bit_depth {
3311+ chroma_bit_depth. into ( )
3312+ } else {
3313+ ash:: vk:: VideoComponentBitDepthFlagsKHR :: INVALID
3314+ } ,
3315+ ..Default :: default ( )
3316+ } ;
3317+
3318+ match video_codec_operation {
3319+ VideoCodecOperation :: EncodeH264 => todo ! ( ) ,
3320+ VideoCodecOperation :: EncodeH265 => todo ! ( ) ,
3321+ VideoCodecOperation :: DecodeH264 => {
3322+ let h264_decode_capabilities = h264_decode_capabilities
3323+ . insert ( ash:: vk:: VideoDecodeH264CapabilitiesKHR :: default ( ) ) ;
3324+
3325+ let codec_profile_info = match codec_profile_info {
3326+ crate :: video:: DecodeProfileInfo :: H264 ( p) => p,
3327+ _ => panic ! ( "invalid profile info for H264" ) ,
3328+ } ;
3329+
3330+ decode_capabilities. p_next = h264_decode_capabilities as * mut _ as * mut _ ;
3331+ video_capabilities. p_next = & mut decode_capabilities as * mut _ as * mut _ ;
3332+
3333+ let codec_profile_info =
3334+ h264_profile_info. insert ( ash:: vk:: VideoDecodeH264ProfileInfoKHR {
3335+ std_profile_idc : codec_profile_info. std_profile_idc ,
3336+ picture_layout : codec_profile_info. picture_layout . into ( ) ,
3337+ ..Default :: default ( )
3338+ } ) ;
3339+
3340+ // VUID-VkVideoProfileInfoKHR-videoCodecOperation-07179
3341+ profile_info. p_next = codec_profile_info as * const _ as * const _ ;
3342+ }
3343+ VideoCodecOperation :: DecodeH265 => todo ! ( ) ,
3344+ }
3345+
3346+ let fns = self . instance ( ) . fns ( ) ;
3347+ ( fns. khr_video_queue
3348+ . get_physical_device_video_capabilities_khr ) (
3349+ self . handle ( ) ,
3350+ & mut profile_info,
3351+ & mut video_capabilities,
3352+ )
3353+ . result ( )
3354+ . map_err ( VulkanError :: from) ?;
3355+
3356+ Ok ( VideoCapabilities {
3357+ flags : video_capabilities. flags . into ( ) ,
3358+ min_bitstream_buffer_offset_alignment : video_capabilities
3359+ . min_bitstream_buffer_offset_alignment ,
3360+ min_bitstream_buffer_size_alignment : video_capabilities
3361+ . min_bitstream_buffer_size_alignment ,
3362+ picture_access_granularity : [
3363+ video_capabilities. picture_access_granularity . width ,
3364+ video_capabilities. picture_access_granularity . height ,
3365+ ] ,
3366+ min_coded_extent : [
3367+ video_capabilities. min_coded_extent . width ,
3368+ video_capabilities. min_coded_extent . height ,
3369+ ] ,
3370+ max_coded_extent : [
3371+ video_capabilities. max_coded_extent . width ,
3372+ video_capabilities. max_coded_extent . height ,
3373+ ] ,
3374+ max_dpb_slots : video_capabilities. max_dpb_slots ,
3375+ max_active_reference_pictures : video_capabilities. max_active_reference_pictures ,
3376+ std_header_version : video_capabilities. std_header_version . into ( ) ,
3377+ decode_capabilities : VideoDecodeCapabilities {
3378+ flags : decode_capabilities. flags . into ( ) ,
3379+ codec_capabilities : match video_codec_operation {
3380+ VideoCodecOperation :: DecodeH264 => {
3381+ let h264_decode_capabilities = h264_decode_capabilities. unwrap ( ) ;
3382+ VideoDecodeCodecCapabilities :: H264 ( VideoDecodeH264Capabilities {
3383+ max_level_idc : h264_decode_capabilities. max_level_idc ,
3384+ field_offset_granularity : [
3385+ h264_decode_capabilities. field_offset_granularity . x ,
3386+ h264_decode_capabilities. field_offset_granularity . y ,
3387+ ] ,
3388+ _ne : crate :: NonExhaustive ( ( ) ) ,
3389+ } )
3390+ }
3391+ _ => unimplemented ! ( ) ,
3392+ } ,
3393+ _ne : crate :: NonExhaustive ( ( ) ) ,
3394+ } ,
3395+ _ne : crate :: NonExhaustive ( ( ) ) ,
3396+ } )
3397+ }
31093398}
31103399
31113400impl Debug for PhysicalDevice {
0 commit comments