@@ -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+ VideoCapabilities , VideoCodecOperation , VideoDecodeCapabilities ,
35+ VideoDecodeCodecCapabilities , VideoDecodeH264Capabilities , VideoFormatInfo ,
36+ VideoFormatProperties , VideoProfileInfo ,
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,285 @@ 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 :: DecodeH264 => {
3169+ let crate :: video:: VideoDecodeProfileInfo :: H264 ( codec_profile_info) =
3170+ & profile. codec_profile_info
3171+ else {
3172+ panic ! ( "Unexpected profile" ) ;
3173+ } ;
3174+
3175+ let next = h264_profile_info_vk. insert (
3176+ ash:: vk:: VideoDecodeH264ProfileInfoKHR {
3177+ std_profile_idc : codec_profile_info. std_profile_idc ,
3178+ picture_layout : codec_profile_info. picture_layout . into ( ) ,
3179+ ..Default :: default ( )
3180+ } ,
3181+ ) ;
3182+
3183+ // VUID-VkVideoProfileInfoKHR-videoCodecOperation-07179
3184+ profile_info_vk. p_next = next as * const _ as * const _ ;
3185+ }
3186+ VideoCodecOperation :: DecodeH265 => todo ! ( ) ,
3187+ }
3188+
3189+ profile_info_vk
3190+ } )
3191+ . collect :: < Vec < _ > > ( ) ;
3192+
3193+ let profile_list_info_vk = ash:: vk:: VideoProfileListInfoKHR {
3194+ profile_count : video_profile_info_vk. len ( ) as _ ,
3195+ p_profiles : video_profile_info_vk. as_ptr ( ) as _ ,
3196+ ..Default :: default ( )
3197+ } ;
3198+
3199+ let video_format_info_vk = ash:: vk:: PhysicalDeviceVideoFormatInfoKHR {
3200+ p_next : & profile_list_info_vk as * const _ as _ ,
3201+ image_usage : video_format_info. image_usage . into ( ) ,
3202+ ..Default :: default ( )
3203+ } ;
3204+
3205+ let fns = self . instance ( ) . fns ( ) ;
3206+
3207+ ( fns. khr_video_queue
3208+ . get_physical_device_video_format_properties_khr ) (
3209+ self . handle ( ) ,
3210+ & video_format_info_vk,
3211+ & mut num_formats,
3212+ std:: ptr:: null_mut ( ) ,
3213+ )
3214+ . result ( )
3215+ . map_err ( VulkanError :: from) ?;
3216+
3217+ let mut video_format_properties_vk =
3218+ vec ! [ VideoFormatPropertiesKHR :: default ( ) ; num_formats as usize ] ;
3219+
3220+ let result = ( fns
3221+ . khr_video_queue
3222+ . get_physical_device_video_format_properties_khr ) (
3223+ self . handle ( ) ,
3224+ & video_format_info_vk,
3225+ & mut num_formats,
3226+ video_format_properties_vk. as_mut_ptr ( ) ,
3227+ ) ;
3228+
3229+ match result {
3230+ ash:: vk:: Result :: SUCCESS => {
3231+ video_format_properties_vk. set_len ( num_formats as usize ) ;
3232+ return Ok ( video_format_properties_vk
3233+ . into_iter ( )
3234+ . filter_map ( |vk| {
3235+ Some ( VideoFormatProperties {
3236+ format : vk. format . try_into ( ) . ok ( ) ?,
3237+ component_mapping : ComponentMapping {
3238+ r : vk. component_mapping . r . try_into ( ) . ok ( ) ?,
3239+ g : vk. component_mapping . g . try_into ( ) . ok ( ) ?,
3240+ b : vk. component_mapping . b . try_into ( ) . ok ( ) ?,
3241+ a : vk. component_mapping . a . try_into ( ) . ok ( ) ?,
3242+ } ,
3243+ image_create_flags : vk. image_create_flags . try_into ( ) . ok ( ) ?,
3244+ image_type : vk. image_type . try_into ( ) . ok ( ) ?,
3245+ image_tiling : vk. image_tiling . try_into ( ) . ok ( ) ?,
3246+ image_usage_flags : vk. image_usage_flags . try_into ( ) . ok ( ) ?,
3247+ } )
3248+ } )
3249+ . collect ( ) ) ;
3250+ }
3251+ ash:: vk:: Result :: INCOMPLETE => ( ) ,
3252+ err => return Err ( VulkanError :: from ( err) ) ,
3253+ }
3254+ }
3255+ }
3256+
3257+ pub fn video_capabilities (
3258+ & self ,
3259+ profile_info : VideoProfileInfo ,
3260+ ) -> Result < VideoCapabilities , Validated < VulkanError > > {
3261+ self . validate_video_capabilities ( & profile_info) ?;
3262+
3263+ unsafe { Ok ( self . video_capabilities_unchecked ( profile_info) ?) }
3264+ }
3265+
3266+ fn validate_video_capabilities (
3267+ & self ,
3268+ profile_info : & VideoProfileInfo ,
3269+ ) -> Result < ( ) , Box < ValidationError > > {
3270+ if !self . supported_extensions . khr_video_queue || self . api_version ( ) < Version :: V1_3 {
3271+ return Err ( Box :: new ( ValidationError {
3272+ requires_one_of : RequiresOneOf ( & [ RequiresAllOf ( & [
3273+ Requires :: DeviceExtension ( "khr_video_queue" ) ,
3274+ // Requires::APIVersion(Version::V1_3), // ?
3275+ ] ) ] ) ,
3276+ ..Default :: default ( )
3277+ } ) ) ;
3278+ }
3279+
3280+ profile_info
3281+ . validate ( )
3282+ . map_err ( |err| err. add_context ( "profile_info" ) )
3283+ }
3284+
3285+ #[ cfg_attr( not( feature = "document_unchecked" ) , doc( hidden) ) ]
3286+ pub unsafe fn video_capabilities_unchecked (
3287+ & self ,
3288+ profile_info : VideoProfileInfo ,
3289+ ) -> Result < VideoCapabilities , VulkanError > {
3290+ let mut video_capabilities = ash:: vk:: VideoCapabilitiesKHR :: default ( ) ;
3291+ let mut decode_capabilities = ash:: vk:: VideoDecodeCapabilitiesKHR :: default ( ) ;
3292+ let mut h264_decode_capabilities = None ;
3293+ let mut h264_profile_info = None ;
3294+
3295+ let VideoProfileInfo {
3296+ video_codec_operation,
3297+ chroma_subsampling,
3298+ luma_bit_depth,
3299+ chroma_bit_depth,
3300+ codec_profile_info,
3301+ _ne : _,
3302+ } = profile_info;
3303+
3304+ let mut profile_info = ash:: vk:: VideoProfileInfoKHR {
3305+ video_codec_operation : video_codec_operation. into ( ) ,
3306+ chroma_subsampling : chroma_subsampling. into ( ) ,
3307+ luma_bit_depth : luma_bit_depth. into ( ) ,
3308+ chroma_bit_depth : if let Some ( chroma_bit_depth) = chroma_bit_depth {
3309+ chroma_bit_depth. into ( )
3310+ } else {
3311+ ash:: vk:: VideoComponentBitDepthFlagsKHR :: INVALID
3312+ } ,
3313+ ..Default :: default ( )
3314+ } ;
3315+
3316+ match video_codec_operation {
3317+ VideoCodecOperation :: DecodeH264 => {
3318+ let h264_decode_capabilities = h264_decode_capabilities
3319+ . insert ( ash:: vk:: VideoDecodeH264CapabilitiesKHR :: default ( ) ) ;
3320+
3321+ let codec_profile_info = match codec_profile_info {
3322+ crate :: video:: VideoDecodeProfileInfo :: H264 ( p) => p,
3323+ _ => panic ! ( "invalid profile info for H264" ) ,
3324+ } ;
3325+
3326+ decode_capabilities. p_next = h264_decode_capabilities as * mut _ as * mut _ ;
3327+ video_capabilities. p_next = & mut decode_capabilities as * mut _ as * mut _ ;
3328+
3329+ let codec_profile_info =
3330+ h264_profile_info. insert ( ash:: vk:: VideoDecodeH264ProfileInfoKHR {
3331+ std_profile_idc : codec_profile_info. std_profile_idc ,
3332+ picture_layout : codec_profile_info. picture_layout . into ( ) ,
3333+ ..Default :: default ( )
3334+ } ) ;
3335+
3336+ // VUID-VkVideoProfileInfoKHR-videoCodecOperation-07179
3337+ profile_info. p_next = codec_profile_info as * const _ as * const _ ;
3338+ }
3339+ VideoCodecOperation :: DecodeH265 => todo ! ( ) ,
3340+ }
3341+
3342+ let fns = self . instance ( ) . fns ( ) ;
3343+ ( fns. khr_video_queue
3344+ . get_physical_device_video_capabilities_khr ) (
3345+ self . handle ( ) ,
3346+ & mut profile_info,
3347+ & mut video_capabilities,
3348+ )
3349+ . result ( )
3350+ . map_err ( VulkanError :: from) ?;
3351+
3352+ Ok ( VideoCapabilities {
3353+ flags : video_capabilities. flags . into ( ) ,
3354+ min_bitstream_buffer_offset_alignment : video_capabilities
3355+ . min_bitstream_buffer_offset_alignment ,
3356+ min_bitstream_buffer_size_alignment : video_capabilities
3357+ . min_bitstream_buffer_size_alignment ,
3358+ picture_access_granularity : [
3359+ video_capabilities. picture_access_granularity . width ,
3360+ video_capabilities. picture_access_granularity . height ,
3361+ ] ,
3362+ min_coded_extent : [
3363+ video_capabilities. min_coded_extent . width ,
3364+ video_capabilities. min_coded_extent . height ,
3365+ ] ,
3366+ max_coded_extent : [
3367+ video_capabilities. max_coded_extent . width ,
3368+ video_capabilities. max_coded_extent . height ,
3369+ ] ,
3370+ max_dpb_slots : video_capabilities. max_dpb_slots ,
3371+ max_active_reference_pictures : video_capabilities. max_active_reference_pictures ,
3372+ std_header_version : video_capabilities. std_header_version . into ( ) ,
3373+ decode_capabilities : VideoDecodeCapabilities {
3374+ flags : decode_capabilities. flags . into ( ) ,
3375+ codec_capabilities : match video_codec_operation {
3376+ VideoCodecOperation :: DecodeH264 => {
3377+ let h264_decode_capabilities = h264_decode_capabilities. unwrap ( ) ;
3378+ VideoDecodeCodecCapabilities :: H264 ( VideoDecodeH264Capabilities {
3379+ max_level_idc : h264_decode_capabilities. max_level_idc ,
3380+ field_offset_granularity : [
3381+ h264_decode_capabilities. field_offset_granularity . x ,
3382+ h264_decode_capabilities. field_offset_granularity . y ,
3383+ ] ,
3384+ _ne : crate :: NonExhaustive ( ( ) ) ,
3385+ } )
3386+ }
3387+ _ => unimplemented ! ( ) ,
3388+ } ,
3389+ _ne : crate :: NonExhaustive ( ( ) ) ,
3390+ } ,
3391+ _ne : crate :: NonExhaustive ( ( ) ) ,
3392+ } )
3393+ }
31093394}
31103395
31113396impl Debug for PhysicalDevice {
0 commit comments