diff options
| author | Daniel Rakos <daniel.rakos@rastergrid.com> | 2023-12-20 13:48:52 +0100 |
|---|---|---|
| committer | Spencer Fricke <115671160+spencer-lunarg@users.noreply.github.com> | 2023-12-21 00:40:41 +0900 |
| commit | 87130b22e74cb208bf8ecd755dcf40dabd365dad (patch) | |
| tree | 6e164d21772a4af8f364db655129d5153e35a2cf | |
| parent | 64d9218726083ece79099341249890c75a5c4491 (diff) | |
| download | usermoji-87130b22e74cb208bf8ecd755dcf40dabd365dad.tar.xz | |
icd: Add video support
| -rw-r--r-- | icd/generated/function_definitions.h | 578 | ||||
| -rw-r--r-- | icd/mock_icd.h | 9 | ||||
| -rw-r--r-- | scripts/mock_icd_generator.py | 584 | ||||
| -rw-r--r-- | tests/icd/mock_icd_tests.cpp | 151 |
4 files changed, 1201 insertions, 121 deletions
diff --git a/icd/generated/function_definitions.h b/icd/generated/function_definitions.h index 8da94ffb..555e355c 100644 --- a/icd/generated/function_definitions.h +++ b/icd/generated/function_definitions.h @@ -108,6 +108,14 @@ static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceFormatProperties( // Don't set color bits for DS formats *pFormatProperties = { 0x00FFFE7F, 0x00FFFE7F, 0x00FFFE7F }; break; + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: + case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM: + // Set decode/encode bits for these formats + *pFormatProperties = { 0x1EFFFDFF, 0x1EFFFDFF, 0x00FFFDFF }; + break; default: break; } @@ -160,15 +168,15 @@ static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties( uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties) { - if (!pQueueFamilyProperties) { - *pQueueFamilyPropertyCount = 1; - } else { - if (*pQueueFamilyPropertyCount) { - pQueueFamilyProperties[0].queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_SPARSE_BINDING_BIT | VK_QUEUE_PROTECTED_BIT; - pQueueFamilyProperties[0].queueCount = 1; - pQueueFamilyProperties[0].timestampValidBits = 16; - pQueueFamilyProperties[0].minImageTransferGranularity = {1,1,1}; + if (pQueueFamilyProperties) { + std::vector<VkQueueFamilyProperties2KHR> props2(*pQueueFamilyPropertyCount, { + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR}); + GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, props2.data()); + for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; ++i) { + pQueueFamilyProperties[i] = props2[i].queueFamilyProperties; } + } else { + GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, nullptr); } } @@ -2729,19 +2737,326 @@ static VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceVideoCapabilitiesKHR( const VkVideoProfileInfoKHR* pVideoProfile, VkVideoCapabilitiesKHR* pCapabilities) { - // arbitrary - auto *decode_caps = lvl_find_mod_in_chain<VkVideoDecodeCapabilitiesKHR>(pCapabilities->pNext); - if (decode_caps) { - decode_caps->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR | VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; + // We include some reasonable set of capability combinations to cover a wide range of use cases + auto caps = pCapabilities; + auto caps_decode = lvl_find_mod_in_chain<VkVideoDecodeCapabilitiesKHR>(pCapabilities->pNext); + auto caps_decode_h264 = lvl_find_mod_in_chain<VkVideoDecodeH264CapabilitiesKHR>(pCapabilities->pNext); + auto caps_decode_h265 = lvl_find_mod_in_chain<VkVideoDecodeH265CapabilitiesKHR>(pCapabilities->pNext); + auto caps_encode = lvl_find_mod_in_chain<VkVideoEncodeCapabilitiesKHR>(pCapabilities->pNext); + auto caps_encode_h264 = lvl_find_mod_in_chain<VkVideoEncodeH264CapabilitiesKHR>(pCapabilities->pNext); + auto caps_encode_h265 = lvl_find_mod_in_chain<VkVideoEncodeH265CapabilitiesKHR>(pCapabilities->pNext); + + switch (pVideoProfile->videoCodecOperation) { + case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: { + auto profile = lvl_find_in_chain<VkVideoDecodeH264ProfileInfoKHR>(pVideoProfile->pNext); + if (profile->stdProfileIdc != STD_VIDEO_H264_PROFILE_IDC_BASELINE && + profile->stdProfileIdc != STD_VIDEO_H264_PROFILE_IDC_MAIN) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + + caps->flags = VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR; + caps->minBitstreamBufferOffsetAlignment = 256; + caps->minBitstreamBufferSizeAlignment = 256; + caps->pictureAccessGranularity = {16,16}; + caps->minCodedExtent = {16,16}; + caps->maxCodedExtent = {1920,1080}; + caps->maxDpbSlots = 33; + caps->maxActiveReferencePictures = 32; + std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME, + sizeof(caps->stdHeaderVersion.extensionName)); + caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION; + + switch (pVideoProfile->chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + if (profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR; + caps_decode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_6_2; + caps_decode_h264->fieldOffsetGranularity = {0,0}; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + if (profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR && + profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; + caps_decode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_5_0; + caps_decode_h264->fieldOffsetGranularity = {0,16}; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + if (profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR && + profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR + | VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; + caps_decode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_3_2; + caps_decode_h264->fieldOffsetGranularity = {0,1}; + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + } + case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: { + auto profile = lvl_find_in_chain<VkVideoDecodeH265ProfileInfoKHR>(pVideoProfile->pNext); + if (profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + + caps->flags = VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR; + caps->minBitstreamBufferOffsetAlignment = 64; + caps->minBitstreamBufferSizeAlignment = 64; + caps->pictureAccessGranularity = {32,32}; + caps->minCodedExtent = {48,48}; + caps->maxCodedExtent = {3840,2160}; + caps->maxDpbSlots = 16; + caps->maxActiveReferencePictures = 15; + std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME, + sizeof(caps->stdHeaderVersion.extensionName)); + caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION; + + switch (pVideoProfile->chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR; + caps_decode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_0; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; + caps_decode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_5_2; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR + | VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; + caps_decode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_4_1; + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + } + case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: { + auto profile = lvl_find_in_chain<VkVideoEncodeH264ProfileInfoKHR>(pVideoProfile->pNext); + if (profile->stdProfileIdc != STD_VIDEO_H264_PROFILE_IDC_BASELINE) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + + caps->flags = VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR; + caps->minBitstreamBufferOffsetAlignment = 4096; + caps->minBitstreamBufferSizeAlignment = 4096; + caps->pictureAccessGranularity = {16,16}; + caps->minCodedExtent = {160,128}; + caps->maxCodedExtent = {1920,1080}; + caps->maxDpbSlots = 10; + caps->maxActiveReferencePictures = 4; + std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME, + sizeof(caps->stdHeaderVersion.extensionName)); + caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION; + + switch (pVideoProfile->chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; + caps_encode->maxRateControlLayers = 4; + caps_encode->maxBitrate = 800000000; + caps_encode->maxQualityLevels = 4; + caps_encode->encodeInputPictureGranularity = {16,16}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR; + caps_encode_h264->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR; + caps_encode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_6_2; + caps_encode_h264->maxSliceCount = 8; + caps_encode_h264->maxPPictureL0ReferenceCount = 4; + caps_encode_h264->maxBPictureL0ReferenceCount = 3; + caps_encode_h264->maxL1ReferenceCount = 2; + caps_encode_h264->maxTemporalLayerCount = 4; + caps_encode_h264->expectDyadicTemporalLayerPattern = VK_FALSE; + caps_encode_h264->minQp = 0; + caps_encode_h264->maxQp = 51; + caps_encode_h264->prefersGopRemainingFrames = VK_FALSE; + caps_encode_h264->requiresGopRemainingFrames = VK_FALSE; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; + caps_encode->maxRateControlLayers = 1; + caps_encode->maxBitrate = 480000000; + caps_encode->maxQualityLevels = 3; + caps_encode->encodeInputPictureGranularity = {32,32}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR; + caps_encode_h264->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR; + caps_encode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_6_1; + caps_encode_h264->maxSliceCount = 4; + caps_encode_h264->maxPPictureL0ReferenceCount = 4; + caps_encode_h264->maxBPictureL0ReferenceCount = 0; + caps_encode_h264->maxL1ReferenceCount = 0; + caps_encode_h264->maxTemporalLayerCount = 4; + caps_encode_h264->expectDyadicTemporalLayerPattern = VK_TRUE; + caps_encode_h264->minQp = 0; + caps_encode_h264->maxQp = 30; + caps_encode_h264->prefersGopRemainingFrames = VK_TRUE; + caps_encode_h264->requiresGopRemainingFrames = VK_FALSE; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + caps_encode->flags = 0; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR; + caps_encode->maxRateControlLayers = 1; + caps_encode->maxBitrate = 240000000; + caps_encode->maxQualityLevels = 1; + caps_encode->encodeInputPictureGranularity = {1,1}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR; + caps_encode_h264->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR; + caps_encode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_5_1; + caps_encode_h264->maxSliceCount = 1; + caps_encode_h264->maxPPictureL0ReferenceCount = 0; + caps_encode_h264->maxBPictureL0ReferenceCount = 2; + caps_encode_h264->maxL1ReferenceCount = 2; + caps_encode_h264->maxTemporalLayerCount = 1; + caps_encode_h264->expectDyadicTemporalLayerPattern = VK_FALSE; + caps_encode_h264->minQp = 5; + caps_encode_h264->maxQp = 40; + caps_encode_h264->prefersGopRemainingFrames = VK_TRUE; + caps_encode_h264->requiresGopRemainingFrames = VK_TRUE; + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + } + case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: { + auto profile = lvl_find_in_chain<VkVideoEncodeH265ProfileInfoKHR>(pVideoProfile->pNext); + if (profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + + caps->flags = VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR; + caps->minBitstreamBufferOffsetAlignment = 1; + caps->minBitstreamBufferSizeAlignment = 1; + caps->pictureAccessGranularity = {8,8}; + caps->minCodedExtent = {64,48}; + caps->maxCodedExtent = {4096,2560}; + caps->maxDpbSlots = 8; + caps->maxActiveReferencePictures = 2; + std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME, sizeof(caps->stdHeaderVersion.extensionName)); + caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION; + + switch (pVideoProfile->chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + caps_encode->flags = 0; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR; + caps_encode->maxRateControlLayers = 1; + caps_encode->maxBitrate = 800000000; + caps_encode->maxQualityLevels = 1; + caps_encode->encodeInputPictureGranularity = {64,64}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR; + caps_encode_h265->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_PER_SLICE_SEGMENT_CONSTANT_QP_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_SEGMENTS_PER_TILE_BIT_KHR; + caps_encode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_2; + caps_encode_h265->maxSliceSegmentCount = 8; + caps_encode_h265->maxTiles = {1,1}; + caps_encode_h265->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR + | VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR; + caps_encode_h265->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR + | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR + | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR; + caps_encode_h265->maxPPictureL0ReferenceCount = 4; + caps_encode_h265->maxBPictureL0ReferenceCount = 3; + caps_encode_h265->maxL1ReferenceCount = 2; + caps_encode_h265->maxSubLayerCount = 1; + caps_encode_h265->expectDyadicTemporalSubLayerPattern = VK_FALSE; + caps_encode_h265->minQp = 16; + caps_encode_h265->maxQp = 32; + caps_encode_h265->prefersGopRemainingFrames = VK_FALSE; + caps_encode_h265->requiresGopRemainingFrames = VK_FALSE; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + caps_encode->flags = 0; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR; + caps_encode->maxRateControlLayers = 0; + caps_encode->maxBitrate = 480000000; + caps_encode->maxQualityLevels = 2; + caps_encode->encodeInputPictureGranularity = {32,32}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR; + caps_encode_h265->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_SEGMENT_TYPE_BIT_KHR; + caps_encode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_1; + caps_encode_h265->maxSliceSegmentCount = 4; + caps_encode_h265->maxTiles = {2,2}; + caps_encode_h265->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_KHR + | VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR; + caps_encode_h265->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR + | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR + | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR; + caps_encode_h265->maxPPictureL0ReferenceCount = 4; + caps_encode_h265->maxBPictureL0ReferenceCount = 0; + caps_encode_h265->maxL1ReferenceCount = 0; + caps_encode_h265->maxSubLayerCount = 1; + caps_encode_h265->expectDyadicTemporalSubLayerPattern = VK_FALSE; + caps_encode_h265->minQp = 0; + caps_encode_h265->maxQp = 51; + caps_encode_h265->prefersGopRemainingFrames = VK_TRUE; + caps_encode_h265->requiresGopRemainingFrames = VK_FALSE; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; + caps_encode->maxRateControlLayers = 2; + caps_encode->maxBitrate = 240000000; + caps_encode->maxQualityLevels = 3; + caps_encode->encodeInputPictureGranularity = {16,16}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR; + caps_encode_h265->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILES_PER_SLICE_SEGMENT_BIT_KHR; + caps_encode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_5_1; + caps_encode_h265->maxSliceSegmentCount = 1; + caps_encode_h265->maxTiles = {2,2}; + caps_encode_h265->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR; + caps_encode_h265->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR; + caps_encode_h265->maxPPictureL0ReferenceCount = 0; + caps_encode_h265->maxBPictureL0ReferenceCount = 2; + caps_encode_h265->maxL1ReferenceCount = 2; + caps_encode_h265->maxSubLayerCount = 4; + caps_encode_h265->expectDyadicTemporalSubLayerPattern = VK_TRUE; + caps_encode_h265->minQp = 16; + caps_encode_h265->maxQp = 51; + caps_encode_h265->prefersGopRemainingFrames = VK_TRUE; + caps_encode_h265->requiresGopRemainingFrames = VK_TRUE; + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + } + + default: + break; } - pCapabilities->flags = 0; - pCapabilities->minBitstreamBufferOffsetAlignment = 4; - pCapabilities->minBitstreamBufferSizeAlignment = 4; - pCapabilities->pictureAccessGranularity = {1, 1}; - pCapabilities->minCodedExtent = {4, 4}; - pCapabilities->maxCodedExtent = {16, 16}; - pCapabilities->maxDpbSlots = 4; - pCapabilities->maxActiveReferencePictures = 4; return VK_SUCCESS; } @@ -2751,22 +3066,147 @@ static VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceVideoFormatPropertiesKHR( uint32_t* pVideoFormatPropertyCount, VkVideoFormatPropertiesKHR* pVideoFormatProperties) { - if (!pVideoFormatProperties) { - *pVideoFormatPropertyCount = 2; - } else { - // arbitrary - pVideoFormatProperties[0].format = VK_FORMAT_R8G8B8A8_UNORM; - pVideoFormatProperties[0].imageCreateFlags = VK_IMAGE_TYPE_2D; - pVideoFormatProperties[0].imageType = VK_IMAGE_TYPE_2D; - pVideoFormatProperties[0].imageTiling = VK_IMAGE_TILING_OPTIMAL; - pVideoFormatProperties[0].imageUsageFlags = VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; - pVideoFormatProperties[1].format = VK_FORMAT_R8G8B8A8_SNORM; - pVideoFormatProperties[1].imageCreateFlags = VK_IMAGE_TYPE_2D; - pVideoFormatProperties[1].imageType = VK_IMAGE_TYPE_2D; - pVideoFormatProperties[1].imageTiling = VK_IMAGE_TILING_OPTIMAL; - pVideoFormatProperties[1].imageUsageFlags = VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + // We include some reasonable set of format combinations to cover a wide range of use cases + auto profile_list = lvl_find_in_chain<VkVideoProfileListInfoKHR>(pVideoFormatInfo->pNext); + if (profile_list->profileCount != 1) { + return VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR; + } + + std::vector<VkVideoFormatPropertiesKHR> format_props{}; + + VkVideoFormatPropertiesKHR props = {}; + props.sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR; + props.imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT + | VK_IMAGE_CREATE_ALIAS_BIT + | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT + | VK_IMAGE_CREATE_PROTECTED_BIT + | VK_IMAGE_CREATE_DISJOINT_BIT; + props.imageType = VK_IMAGE_TYPE_2D; + props.imageTiling = VK_IMAGE_TILING_OPTIMAL; + + switch (profile_list->pProfiles[0].videoCodecOperation) { + case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: + case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: + switch (profile_list->pProfiles[0].chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + props.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; + format_props.push_back(props); + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + props.imageUsageFlags = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + props.format = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + props.format = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16; + format_props.push_back(props); + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: + case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: + switch (profile_list->pProfiles[0].chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + props.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; + format_props.push_back(props); + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + props.format = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16; + format_props.push_back(props); + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + + default: + break; + } + + std::vector<VkVideoFormatPropertiesKHR> filtered_props; + for (const auto& fmt_props : format_props) { + if ((pVideoFormatInfo->imageUsage & fmt_props.imageUsageFlags) == pVideoFormatInfo->imageUsage) { + filtered_props.push_back(fmt_props); + } + } + if (pVideoFormatProperties != nullptr) { + for (uint32_t i = 0; i < (std::min)(*pVideoFormatPropertyCount, (uint32_t)filtered_props.size()); ++i) { + pVideoFormatProperties[i] = filtered_props[i]; + } } + *pVideoFormatPropertyCount = (uint32_t)filtered_props.size(); return VK_SUCCESS; } @@ -2900,6 +3340,26 @@ static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceFeatures2KHR( GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features); uint32_t num_bools = 0; // Count number of VkBool32s in extension structs VkBool32* feat_bools = nullptr; + auto vk_1_1_features = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan11Features>(pFeatures->pNext); + if (vk_1_1_features) { + vk_1_1_features->protectedMemory = VK_TRUE; + } + auto vk_1_3_features = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan13Features>(pFeatures->pNext); + if (vk_1_3_features) { + vk_1_3_features->synchronization2 = VK_TRUE; + } + auto prot_features = lvl_find_mod_in_chain<VkPhysicalDeviceProtectedMemoryFeatures>(pFeatures->pNext); + if (prot_features) { + prot_features->protectedMemory = VK_TRUE; + } + auto sync2_features = lvl_find_mod_in_chain<VkPhysicalDeviceSynchronization2FeaturesKHR>(pFeatures->pNext); + if (sync2_features) { + sync2_features->synchronization2 = VK_TRUE; + } + auto video_maintenance1_features = lvl_find_mod_in_chain<VkPhysicalDeviceVideoMaintenance1FeaturesKHR>(pFeatures->pNext); + if (video_maintenance1_features) { + video_maintenance1_features->videoMaintenance1 = VK_TRUE; + } const auto *desc_idx_features = lvl_find_in_chain<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(pFeatures->pNext); if (desc_idx_features) { const auto bool_size = sizeof(VkPhysicalDeviceDescriptorIndexingFeaturesEXT) - offsetof(VkPhysicalDeviceDescriptorIndexingFeaturesEXT, shaderInputAttachmentArrayDynamicIndexing); @@ -3090,10 +3550,54 @@ static VKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties2KHR( uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2* pQueueFamilyProperties) { - if (pQueueFamilyPropertyCount && pQueueFamilyProperties) { - GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, &pQueueFamilyProperties->queueFamilyProperties); + if (pQueueFamilyProperties) { + if (*pQueueFamilyPropertyCount >= 1) { + auto props = &pQueueFamilyProperties[0].queueFamilyProperties; + props->queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT + | VK_QUEUE_SPARSE_BINDING_BIT | VK_QUEUE_PROTECTED_BIT; + props->queueCount = 1; + props->timestampValidBits = 16; + props->minImageTransferGranularity = {1,1,1}; + } + if (*pQueueFamilyPropertyCount >= 2) { + auto props = &pQueueFamilyProperties[1].queueFamilyProperties; + props->queueFlags = VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT | VK_QUEUE_VIDEO_DECODE_BIT_KHR; + props->queueCount = 1; + props->timestampValidBits = 16; + props->minImageTransferGranularity = {1,1,1}; + + auto status_query_props = lvl_find_mod_in_chain<VkQueueFamilyQueryResultStatusPropertiesKHR>(pQueueFamilyProperties[1].pNext); + if (status_query_props) { + status_query_props->queryResultStatusSupport = VK_TRUE; + } + auto video_props = lvl_find_mod_in_chain<VkQueueFamilyVideoPropertiesKHR>(pQueueFamilyProperties[1].pNext); + if (video_props) { + video_props->videoCodecOperations = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR + | VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR; + } + } + if (*pQueueFamilyPropertyCount >= 3) { + auto props = &pQueueFamilyProperties[2].queueFamilyProperties; + props->queueFlags = VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT | VK_QUEUE_VIDEO_ENCODE_BIT_KHR; + props->queueCount = 1; + props->timestampValidBits = 16; + props->minImageTransferGranularity = {1,1,1}; + + auto status_query_props = lvl_find_mod_in_chain<VkQueueFamilyQueryResultStatusPropertiesKHR>(pQueueFamilyProperties[2].pNext); + if (status_query_props) { + status_query_props->queryResultStatusSupport = VK_TRUE; + } + auto video_props = lvl_find_mod_in_chain<VkQueueFamilyVideoPropertiesKHR>(pQueueFamilyProperties[2].pNext); + if (video_props) { + video_props->videoCodecOperations = VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR + | VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR; + } + } + if (*pQueueFamilyPropertyCount > 3) { + *pQueueFamilyPropertyCount = 3; + } } else { - GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, nullptr); + *pQueueFamilyPropertyCount = 3; } } diff --git a/icd/mock_icd.h b/icd/mock_icd.h index d72f8ee7..f5145cd7 100644 --- a/icd/mock_icd.h +++ b/icd/mock_icd.h @@ -27,6 +27,15 @@ #include <string> #include <vector> +#include "vk_video/vulkan_video_codecs_common.h" +#include "vk_video/vulkan_video_codec_h264std.h" +#include "vk_video/vulkan_video_codec_h264std_decode.h" +#include "vk_video/vulkan_video_codec_h264std_encode.h" +#include "vk_video/vulkan_video_codec_h265std.h" +#include "vk_video/vulkan_video_codec_h265std_decode.h" +#include "vk_video/vulkan_video_codec_h265std_encode.h" +#include "vulkan/vulkan.h" + #include "vulkan/vk_icd.h" #include "vk_typemap_helper.h" diff --git a/scripts/mock_icd_generator.py b/scripts/mock_icd_generator.py index a61af48c..a8c3dbc8 100644 --- a/scripts/mock_icd_generator.py +++ b/scripts/mock_icd_generator.py @@ -360,22 +360,66 @@ CUSTOM_C_INTERCEPTS = { GetPhysicalDeviceMemoryProperties(physicalDevice, &pMemoryProperties->memoryProperties); ''', 'vkGetPhysicalDeviceQueueFamilyProperties': ''' - if (!pQueueFamilyProperties) { - *pQueueFamilyPropertyCount = 1; - } else { - if (*pQueueFamilyPropertyCount) { - pQueueFamilyProperties[0].queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_SPARSE_BINDING_BIT | VK_QUEUE_PROTECTED_BIT; - pQueueFamilyProperties[0].queueCount = 1; - pQueueFamilyProperties[0].timestampValidBits = 16; - pQueueFamilyProperties[0].minImageTransferGranularity = {1,1,1}; + if (pQueueFamilyProperties) { + std::vector<VkQueueFamilyProperties2KHR> props2(*pQueueFamilyPropertyCount, { + VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR}); + GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, props2.data()); + for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; ++i) { + pQueueFamilyProperties[i] = props2[i].queueFamilyProperties; } + } else { + GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, nullptr); } ''', 'vkGetPhysicalDeviceQueueFamilyProperties2KHR': ''' - if (pQueueFamilyPropertyCount && pQueueFamilyProperties) { - GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, &pQueueFamilyProperties->queueFamilyProperties); + if (pQueueFamilyProperties) { + if (*pQueueFamilyPropertyCount >= 1) { + auto props = &pQueueFamilyProperties[0].queueFamilyProperties; + props->queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT + | VK_QUEUE_SPARSE_BINDING_BIT | VK_QUEUE_PROTECTED_BIT; + props->queueCount = 1; + props->timestampValidBits = 16; + props->minImageTransferGranularity = {1,1,1}; + } + if (*pQueueFamilyPropertyCount >= 2) { + auto props = &pQueueFamilyProperties[1].queueFamilyProperties; + props->queueFlags = VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT | VK_QUEUE_VIDEO_DECODE_BIT_KHR; + props->queueCount = 1; + props->timestampValidBits = 16; + props->minImageTransferGranularity = {1,1,1}; + + auto status_query_props = lvl_find_mod_in_chain<VkQueueFamilyQueryResultStatusPropertiesKHR>(pQueueFamilyProperties[1].pNext); + if (status_query_props) { + status_query_props->queryResultStatusSupport = VK_TRUE; + } + auto video_props = lvl_find_mod_in_chain<VkQueueFamilyVideoPropertiesKHR>(pQueueFamilyProperties[1].pNext); + if (video_props) { + video_props->videoCodecOperations = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR + | VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR; + } + } + if (*pQueueFamilyPropertyCount >= 3) { + auto props = &pQueueFamilyProperties[2].queueFamilyProperties; + props->queueFlags = VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT | VK_QUEUE_VIDEO_ENCODE_BIT_KHR; + props->queueCount = 1; + props->timestampValidBits = 16; + props->minImageTransferGranularity = {1,1,1}; + + auto status_query_props = lvl_find_mod_in_chain<VkQueueFamilyQueryResultStatusPropertiesKHR>(pQueueFamilyProperties[2].pNext); + if (status_query_props) { + status_query_props->queryResultStatusSupport = VK_TRUE; + } + auto video_props = lvl_find_mod_in_chain<VkQueueFamilyVideoPropertiesKHR>(pQueueFamilyProperties[2].pNext); + if (video_props) { + video_props->videoCodecOperations = VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR + | VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR; + } + } + if (*pQueueFamilyPropertyCount > 3) { + *pQueueFamilyPropertyCount = 3; + } } else { - GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, nullptr); + *pQueueFamilyPropertyCount = 3; } ''', 'vkGetPhysicalDeviceFeatures': ''' @@ -387,6 +431,26 @@ CUSTOM_C_INTERCEPTS = { GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features); uint32_t num_bools = 0; // Count number of VkBool32s in extension structs VkBool32* feat_bools = nullptr; + auto vk_1_1_features = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan11Features>(pFeatures->pNext); + if (vk_1_1_features) { + vk_1_1_features->protectedMemory = VK_TRUE; + } + auto vk_1_3_features = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan13Features>(pFeatures->pNext); + if (vk_1_3_features) { + vk_1_3_features->synchronization2 = VK_TRUE; + } + auto prot_features = lvl_find_mod_in_chain<VkPhysicalDeviceProtectedMemoryFeatures>(pFeatures->pNext); + if (prot_features) { + prot_features->protectedMemory = VK_TRUE; + } + auto sync2_features = lvl_find_mod_in_chain<VkPhysicalDeviceSynchronization2FeaturesKHR>(pFeatures->pNext); + if (sync2_features) { + sync2_features->synchronization2 = VK_TRUE; + } + auto video_maintenance1_features = lvl_find_mod_in_chain<VkPhysicalDeviceVideoMaintenance1FeaturesKHR>(pFeatures->pNext); + if (video_maintenance1_features) { + video_maintenance1_features->videoMaintenance1 = VK_TRUE; + } const auto *desc_idx_features = lvl_find_in_chain<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(pFeatures->pNext); if (desc_idx_features) { const auto bool_size = sizeof(VkPhysicalDeviceDescriptorIndexingFeaturesEXT) - offsetof(VkPhysicalDeviceDescriptorIndexingFeaturesEXT, shaderInputAttachmentArrayDynamicIndexing); @@ -424,6 +488,14 @@ CUSTOM_C_INTERCEPTS = { // Don't set color bits for DS formats *pFormatProperties = { 0x00FFFE7F, 0x00FFFE7F, 0x00FFFE7F }; break; + case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: + case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: + case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM: + // Set decode/encode bits for these formats + *pFormatProperties = { 0x1EFFFDFF, 0x1EFFFDFF, 0x00FFFDFF }; + break; default: break; } @@ -1020,39 +1092,471 @@ CUSTOM_C_INTERCEPTS = { } return VK_SUCCESS; ''', -'vkGetPhysicalDeviceVideoFormatPropertiesKHR': ''' - if (!pVideoFormatProperties) { - *pVideoFormatPropertyCount = 2; - } else { - // arbitrary - pVideoFormatProperties[0].format = VK_FORMAT_R8G8B8A8_UNORM; - pVideoFormatProperties[0].imageCreateFlags = VK_IMAGE_TYPE_2D; - pVideoFormatProperties[0].imageType = VK_IMAGE_TYPE_2D; - pVideoFormatProperties[0].imageTiling = VK_IMAGE_TILING_OPTIMAL; - pVideoFormatProperties[0].imageUsageFlags = VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; - pVideoFormatProperties[1].format = VK_FORMAT_R8G8B8A8_SNORM; - pVideoFormatProperties[1].imageCreateFlags = VK_IMAGE_TYPE_2D; - pVideoFormatProperties[1].imageType = VK_IMAGE_TYPE_2D; - pVideoFormatProperties[1].imageTiling = VK_IMAGE_TILING_OPTIMAL; - pVideoFormatProperties[1].imageUsageFlags = VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; +'vkGetPhysicalDeviceVideoCapabilitiesKHR': ''' + // We include some reasonable set of capability combinations to cover a wide range of use cases + auto caps = pCapabilities; + auto caps_decode = lvl_find_mod_in_chain<VkVideoDecodeCapabilitiesKHR>(pCapabilities->pNext); + auto caps_decode_h264 = lvl_find_mod_in_chain<VkVideoDecodeH264CapabilitiesKHR>(pCapabilities->pNext); + auto caps_decode_h265 = lvl_find_mod_in_chain<VkVideoDecodeH265CapabilitiesKHR>(pCapabilities->pNext); + auto caps_encode = lvl_find_mod_in_chain<VkVideoEncodeCapabilitiesKHR>(pCapabilities->pNext); + auto caps_encode_h264 = lvl_find_mod_in_chain<VkVideoEncodeH264CapabilitiesKHR>(pCapabilities->pNext); + auto caps_encode_h265 = lvl_find_mod_in_chain<VkVideoEncodeH265CapabilitiesKHR>(pCapabilities->pNext); + + switch (pVideoProfile->videoCodecOperation) { + case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: { + auto profile = lvl_find_in_chain<VkVideoDecodeH264ProfileInfoKHR>(pVideoProfile->pNext); + if (profile->stdProfileIdc != STD_VIDEO_H264_PROFILE_IDC_BASELINE && + profile->stdProfileIdc != STD_VIDEO_H264_PROFILE_IDC_MAIN) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + + caps->flags = VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR; + caps->minBitstreamBufferOffsetAlignment = 256; + caps->minBitstreamBufferSizeAlignment = 256; + caps->pictureAccessGranularity = {16,16}; + caps->minCodedExtent = {16,16}; + caps->maxCodedExtent = {1920,1080}; + caps->maxDpbSlots = 33; + caps->maxActiveReferencePictures = 32; + std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME, + sizeof(caps->stdHeaderVersion.extensionName)); + caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION; + + switch (pVideoProfile->chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + if (profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR; + caps_decode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_6_2; + caps_decode_h264->fieldOffsetGranularity = {0,0}; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + if (profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR && + profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; + caps_decode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_5_0; + caps_decode_h264->fieldOffsetGranularity = {0,16}; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + if (profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR && + profile->pictureLayout != VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR + | VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; + caps_decode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_3_2; + caps_decode_h264->fieldOffsetGranularity = {0,1}; + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + } + case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: { + auto profile = lvl_find_in_chain<VkVideoDecodeH265ProfileInfoKHR>(pVideoProfile->pNext); + if (profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + + caps->flags = VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR; + caps->minBitstreamBufferOffsetAlignment = 64; + caps->minBitstreamBufferSizeAlignment = 64; + caps->pictureAccessGranularity = {32,32}; + caps->minCodedExtent = {48,48}; + caps->maxCodedExtent = {3840,2160}; + caps->maxDpbSlots = 16; + caps->maxActiveReferencePictures = 15; + std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_EXTENSION_NAME, + sizeof(caps->stdHeaderVersion.extensionName)); + caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_DECODE_SPEC_VERSION; + + switch (pVideoProfile->chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR; + caps_decode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_0; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; + caps_decode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_5_2; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + caps_decode->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR + | VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; + caps_decode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_4_1; + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + } + case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: { + auto profile = lvl_find_in_chain<VkVideoEncodeH264ProfileInfoKHR>(pVideoProfile->pNext); + if (profile->stdProfileIdc != STD_VIDEO_H264_PROFILE_IDC_BASELINE) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + + caps->flags = VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR; + caps->minBitstreamBufferOffsetAlignment = 4096; + caps->minBitstreamBufferSizeAlignment = 4096; + caps->pictureAccessGranularity = {16,16}; + caps->minCodedExtent = {160,128}; + caps->maxCodedExtent = {1920,1080}; + caps->maxDpbSlots = 10; + caps->maxActiveReferencePictures = 4; + std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_EXTENSION_NAME, + sizeof(caps->stdHeaderVersion.extensionName)); + caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_ENCODE_SPEC_VERSION; + + switch (pVideoProfile->chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; + caps_encode->maxRateControlLayers = 4; + caps_encode->maxBitrate = 800000000; + caps_encode->maxQualityLevels = 4; + caps_encode->encodeInputPictureGranularity = {16,16}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR; + caps_encode_h264->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR; + caps_encode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_6_2; + caps_encode_h264->maxSliceCount = 8; + caps_encode_h264->maxPPictureL0ReferenceCount = 4; + caps_encode_h264->maxBPictureL0ReferenceCount = 3; + caps_encode_h264->maxL1ReferenceCount = 2; + caps_encode_h264->maxTemporalLayerCount = 4; + caps_encode_h264->expectDyadicTemporalLayerPattern = VK_FALSE; + caps_encode_h264->minQp = 0; + caps_encode_h264->maxQp = 51; + caps_encode_h264->prefersGopRemainingFrames = VK_FALSE; + caps_encode_h264->requiresGopRemainingFrames = VK_FALSE; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; + caps_encode->maxRateControlLayers = 1; + caps_encode->maxBitrate = 480000000; + caps_encode->maxQualityLevels = 3; + caps_encode->encodeInputPictureGranularity = {32,32}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR; + caps_encode_h264->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_PER_SLICE_CONSTANT_QP_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_GENERATE_PREFIX_NALU_BIT_KHR; + caps_encode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_6_1; + caps_encode_h264->maxSliceCount = 4; + caps_encode_h264->maxPPictureL0ReferenceCount = 4; + caps_encode_h264->maxBPictureL0ReferenceCount = 0; + caps_encode_h264->maxL1ReferenceCount = 0; + caps_encode_h264->maxTemporalLayerCount = 4; + caps_encode_h264->expectDyadicTemporalLayerPattern = VK_TRUE; + caps_encode_h264->minQp = 0; + caps_encode_h264->maxQp = 30; + caps_encode_h264->prefersGopRemainingFrames = VK_TRUE; + caps_encode_h264->requiresGopRemainingFrames = VK_FALSE; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + caps_encode->flags = 0; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR; + caps_encode->maxRateControlLayers = 1; + caps_encode->maxBitrate = 240000000; + caps_encode->maxQualityLevels = 1; + caps_encode->encodeInputPictureGranularity = {1,1}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR; + caps_encode_h264->flags = VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR + | VK_VIDEO_ENCODE_H264_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR; + caps_encode_h264->maxLevelIdc = STD_VIDEO_H264_LEVEL_IDC_5_1; + caps_encode_h264->maxSliceCount = 1; + caps_encode_h264->maxPPictureL0ReferenceCount = 0; + caps_encode_h264->maxBPictureL0ReferenceCount = 2; + caps_encode_h264->maxL1ReferenceCount = 2; + caps_encode_h264->maxTemporalLayerCount = 1; + caps_encode_h264->expectDyadicTemporalLayerPattern = VK_FALSE; + caps_encode_h264->minQp = 5; + caps_encode_h264->maxQp = 40; + caps_encode_h264->prefersGopRemainingFrames = VK_TRUE; + caps_encode_h264->requiresGopRemainingFrames = VK_TRUE; + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + } + case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: { + auto profile = lvl_find_in_chain<VkVideoEncodeH265ProfileInfoKHR>(pVideoProfile->pNext); + if (profile->stdProfileIdc != STD_VIDEO_H265_PROFILE_IDC_MAIN) { + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + + caps->flags = VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR; + caps->minBitstreamBufferOffsetAlignment = 1; + caps->minBitstreamBufferSizeAlignment = 1; + caps->pictureAccessGranularity = {8,8}; + caps->minCodedExtent = {64,48}; + caps->maxCodedExtent = {4096,2560}; + caps->maxDpbSlots = 8; + caps->maxActiveReferencePictures = 2; + std::strncpy(caps->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME, sizeof(caps->stdHeaderVersion.extensionName)); + caps->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION; + switch (pVideoProfile->chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + caps_encode->flags = 0; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR; + caps_encode->maxRateControlLayers = 1; + caps_encode->maxBitrate = 800000000; + caps_encode->maxQualityLevels = 1; + caps_encode->encodeInputPictureGranularity = {64,64}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR; + caps_encode_h265->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_PREDICTION_WEIGHT_TABLE_GENERATED_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L0_LIST_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_PER_SLICE_SEGMENT_CONSTANT_QP_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_SEGMENTS_PER_TILE_BIT_KHR; + caps_encode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_2; + caps_encode_h265->maxSliceSegmentCount = 8; + caps_encode_h265->maxTiles = {1,1}; + caps_encode_h265->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR + | VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR; + caps_encode_h265->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_KHR + | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR + | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR; + caps_encode_h265->maxPPictureL0ReferenceCount = 4; + caps_encode_h265->maxBPictureL0ReferenceCount = 3; + caps_encode_h265->maxL1ReferenceCount = 2; + caps_encode_h265->maxSubLayerCount = 1; + caps_encode_h265->expectDyadicTemporalSubLayerPattern = VK_FALSE; + caps_encode_h265->minQp = 16; + caps_encode_h265->maxQp = 32; + caps_encode_h265->prefersGopRemainingFrames = VK_FALSE; + caps_encode_h265->requiresGopRemainingFrames = VK_FALSE; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + caps_encode->flags = 0; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR; + caps_encode->maxRateControlLayers = 0; + caps_encode->maxBitrate = 480000000; + caps_encode->maxQualityLevels = 2; + caps_encode->encodeInputPictureGranularity = {32,32}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR; + caps_encode_h265->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_SEGMENT_TYPE_BIT_KHR; + caps_encode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_6_1; + caps_encode_h265->maxSliceSegmentCount = 4; + caps_encode_h265->maxTiles = {2,2}; + caps_encode_h265->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_KHR + | VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_KHR; + caps_encode_h265->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_KHR + | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_KHR + | VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR; + caps_encode_h265->maxPPictureL0ReferenceCount = 4; + caps_encode_h265->maxBPictureL0ReferenceCount = 0; + caps_encode_h265->maxL1ReferenceCount = 0; + caps_encode_h265->maxSubLayerCount = 1; + caps_encode_h265->expectDyadicTemporalSubLayerPattern = VK_FALSE; + caps_encode_h265->minQp = 0; + caps_encode_h265->maxQp = 51; + caps_encode_h265->prefersGopRemainingFrames = VK_TRUE; + caps_encode_h265->requiresGopRemainingFrames = VK_FALSE; + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + caps_encode->flags = VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR; + caps_encode->rateControlModes = VK_VIDEO_ENCODE_RATE_CONTROL_MODE_DISABLED_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR + | VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR; + caps_encode->maxRateControlLayers = 2; + caps_encode->maxBitrate = 240000000; + caps_encode->maxQualityLevels = 3; + caps_encode->encodeInputPictureGranularity = {16,16}; + caps_encode->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR + | VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_HAS_OVERRIDES_BIT_KHR; + caps_encode_h265->flags = VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_PER_PICTURE_TYPE_MIN_MAX_QP_BIT_KHR + | VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILES_PER_SLICE_SEGMENT_BIT_KHR; + caps_encode_h265->maxLevelIdc = STD_VIDEO_H265_LEVEL_IDC_5_1; + caps_encode_h265->maxSliceSegmentCount = 1; + caps_encode_h265->maxTiles = {2,2}; + caps_encode_h265->ctbSizes = VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_KHR; + caps_encode_h265->transformBlockSizes = VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_KHR; + caps_encode_h265->maxPPictureL0ReferenceCount = 0; + caps_encode_h265->maxBPictureL0ReferenceCount = 2; + caps_encode_h265->maxL1ReferenceCount = 2; + caps_encode_h265->maxSubLayerCount = 4; + caps_encode_h265->expectDyadicTemporalSubLayerPattern = VK_TRUE; + caps_encode_h265->minQp = 16; + caps_encode_h265->maxQp = 51; + caps_encode_h265->prefersGopRemainingFrames = VK_TRUE; + caps_encode_h265->requiresGopRemainingFrames = VK_TRUE; + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + } + + default: + break; } return VK_SUCCESS; ''', -'vkGetPhysicalDeviceVideoCapabilitiesKHR': ''' - // arbitrary - auto *decode_caps = lvl_find_mod_in_chain<VkVideoDecodeCapabilitiesKHR>(pCapabilities->pNext); - if (decode_caps) { - decode_caps->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR | VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR; - } - pCapabilities->flags = 0; - pCapabilities->minBitstreamBufferOffsetAlignment = 4; - pCapabilities->minBitstreamBufferSizeAlignment = 4; - pCapabilities->pictureAccessGranularity = {1, 1}; - pCapabilities->minCodedExtent = {4, 4}; - pCapabilities->maxCodedExtent = {16, 16}; - pCapabilities->maxDpbSlots = 4; - pCapabilities->maxActiveReferencePictures = 4; +'vkGetPhysicalDeviceVideoFormatPropertiesKHR': ''' + // We include some reasonable set of format combinations to cover a wide range of use cases + auto profile_list = lvl_find_in_chain<VkVideoProfileListInfoKHR>(pVideoFormatInfo->pNext); + if (profile_list->profileCount != 1) { + return VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR; + } + + std::vector<VkVideoFormatPropertiesKHR> format_props{}; + + VkVideoFormatPropertiesKHR props = {}; + props.sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR; + props.imageCreateFlags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT + | VK_IMAGE_CREATE_ALIAS_BIT + | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT + | VK_IMAGE_CREATE_PROTECTED_BIT + | VK_IMAGE_CREATE_DISJOINT_BIT; + props.imageType = VK_IMAGE_TYPE_2D; + props.imageTiling = VK_IMAGE_TILING_OPTIMAL; + + switch (profile_list->pProfiles[0].videoCodecOperation) { + case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: + case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: + switch (profile_list->pProfiles[0].chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + props.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; + format_props.push_back(props); + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + props.imageUsageFlags = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + props.format = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + props.format = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16; + format_props.push_back(props); + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + case VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR: + case VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR: + switch (profile_list->pProfiles[0].chromaSubsampling) { + case VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + props.format = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; + format_props.push_back(props); + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + props.format = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16; + format_props.push_back(props); + break; + case VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR: + props.format = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM; + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR; + format_props.push_back(props); + props.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR + | VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR; + format_props.push_back(props); + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + break; + + default: + break; + } + + std::vector<VkVideoFormatPropertiesKHR> filtered_props; + for (const auto& fmt_props : format_props) { + if ((pVideoFormatInfo->imageUsage & fmt_props.imageUsageFlags) == pVideoFormatInfo->imageUsage) { + filtered_props.push_back(fmt_props); + } + } + + if (pVideoFormatProperties != nullptr) { + for (uint32_t i = 0; i < (std::min)(*pVideoFormatPropertyCount, (uint32_t)filtered_props.size()); ++i) { + pVideoFormatProperties[i] = filtered_props[i]; + } + } + *pVideoFormatPropertyCount = (uint32_t)filtered_props.size(); return VK_SUCCESS; ''', 'vkGetDescriptorSetLayoutSupport':''' diff --git a/tests/icd/mock_icd_tests.cpp b/tests/icd/mock_icd_tests.cpp index ff2632b5..8d45ed12 100644 --- a/tests/icd/mock_icd_tests.cpp +++ b/tests/icd/mock_icd_tests.cpp @@ -159,28 +159,39 @@ TEST_F(MockICD, InitializationFunctions) { count = 0; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, nullptr); - ASSERT_EQ(count, 1); - VkQueueFamilyProperties queue_family_properties{}; - vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, &queue_family_properties); - ASSERT_EQ(count, 1); - ASSERT_EQ(queue_family_properties.queueFlags, 1 | 2 | 4 | 8 | 16); - ASSERT_EQ(queue_family_properties.queueCount, 1); - ASSERT_EQ(queue_family_properties.timestampValidBits, 16); - ASSERT_EQ(queue_family_properties.minImageTransferGranularity.width, 1); - ASSERT_EQ(queue_family_properties.minImageTransferGranularity.height, 1); - ASSERT_EQ(queue_family_properties.minImageTransferGranularity.depth, 1); + ASSERT_EQ(count, 3); + VkQueueFamilyProperties queue_family_properties[3] = {}; + vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queue_family_properties); + ASSERT_EQ(count, 3); + ASSERT_EQ(queue_family_properties[0].queueFlags, 1 | 2 | 4 | 8 | 16); + ASSERT_EQ(queue_family_properties[1].queueFlags, 4 | 16 | 32); + ASSERT_EQ(queue_family_properties[2].queueFlags, 4 | 16 | 64); + for (uint32_t i = 0; i < count; ++i) { + ASSERT_EQ(queue_family_properties[i].queueCount, 1); + ASSERT_EQ(queue_family_properties[i].timestampValidBits, 16); + ASSERT_EQ(queue_family_properties[i].minImageTransferGranularity.width, 1); + ASSERT_EQ(queue_family_properties[i].minImageTransferGranularity.height, 1); + ASSERT_EQ(queue_family_properties[i].minImageTransferGranularity.depth, 1); + } vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &count, nullptr); - ASSERT_EQ(count, 1); - VkQueueFamilyProperties2 queue_family_properties2{}; - vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &count, &queue_family_properties2); - ASSERT_EQ(count, 1); - ASSERT_EQ(queue_family_properties2.queueFamilyProperties.queueFlags, 1 | 2 | 4 | 8 | 16); - ASSERT_EQ(queue_family_properties2.queueFamilyProperties.queueCount, 1); - ASSERT_EQ(queue_family_properties2.queueFamilyProperties.timestampValidBits, 16); - ASSERT_EQ(queue_family_properties2.queueFamilyProperties.minImageTransferGranularity.width, 1); - ASSERT_EQ(queue_family_properties2.queueFamilyProperties.minImageTransferGranularity.height, 1); - ASSERT_EQ(queue_family_properties2.queueFamilyProperties.minImageTransferGranularity.depth, 1); + ASSERT_EQ(count, 3); + VkQueueFamilyProperties2 queue_family_properties2[3] = {}; + for (uint32_t i = 0; i < count; ++i) { + queue_family_properties2[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; + } + vkGetPhysicalDeviceQueueFamilyProperties2(physical_device, &count, queue_family_properties2); + ASSERT_EQ(count, 3); + ASSERT_EQ(queue_family_properties2[0].queueFamilyProperties.queueFlags, 1 | 2 | 4 | 8 | 16); + ASSERT_EQ(queue_family_properties2[1].queueFamilyProperties.queueFlags, 4 | 16 | 32); + ASSERT_EQ(queue_family_properties2[2].queueFamilyProperties.queueFlags, 4 | 16 | 64); + for (uint32_t i = 0; i < count; ++i) { + ASSERT_EQ(queue_family_properties2[i].queueFamilyProperties.queueCount, 1); + ASSERT_EQ(queue_family_properties2[i].queueFamilyProperties.timestampValidBits, 16); + ASSERT_EQ(queue_family_properties2[i].queueFamilyProperties.minImageTransferGranularity.width, 1); + ASSERT_EQ(queue_family_properties2[i].queueFamilyProperties.minImageTransferGranularity.height, 1); + ASSERT_EQ(queue_family_properties2[i].queueFamilyProperties.minImageTransferGranularity.depth, 1); + } VkDeviceCreateInfo dev_create_info{}; VkDevice device{}; @@ -1110,29 +1121,60 @@ TEST_F(MockICD, vkGetPhysicalDeviceVideoFormatPropertiesKHR) { vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoFormatPropertiesKHR")); ASSERT_NE(vkGetPhysicalDeviceVideoFormatPropertiesKHR, nullptr); + VkVideoDecodeH264ProfileInfoKHR decode_h264_profile_info{}; + decode_h264_profile_info.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR; + decode_h264_profile_info.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_BASELINE; + decode_h264_profile_info.pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR; + VkVideoProfileInfoKHR video_profile_info{}; + video_profile_info.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR; + video_profile_info.pNext = &decode_h264_profile_info; + video_profile_info.videoCodecOperation = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR; + video_profile_info.chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR; + video_profile_info.lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR; + video_profile_info.chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR; + VkVideoProfileListInfoKHR video_profile_list{}; + video_profile_list.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR; + video_profile_list.profileCount = 1; + video_profile_list.pProfiles = &video_profile_info; VkPhysicalDeviceVideoFormatInfoKHR video_format_info{}; + video_format_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR; + video_format_info.pNext = &video_profile_list; uint32_t count = 0; VkResult res = vkGetPhysicalDeviceVideoFormatPropertiesKHR(physical_device, &video_format_info, &count, nullptr); ASSERT_EQ(res, VK_SUCCESS); - ASSERT_EQ(count, 2); - std::array<VkVideoFormatPropertiesKHR, 2> video_format_properties{}; + ASSERT_EQ(count, 3); + std::array<VkVideoFormatPropertiesKHR, 3> video_format_properties{}; res = vkGetPhysicalDeviceVideoFormatPropertiesKHR(physical_device, &video_format_info, &count, video_format_properties.data()); ASSERT_EQ(res, VK_SUCCESS); - ASSERT_EQ(count, 2); - ASSERT_EQ(video_format_properties[0].format, VK_FORMAT_R8G8B8A8_UNORM); - ASSERT_EQ(video_format_properties[0].imageCreateFlags, VK_IMAGE_TYPE_2D); + ASSERT_EQ(count, 3); + ASSERT_EQ(video_format_properties[0].format, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM); + ASSERT_EQ(video_format_properties[0].imageCreateFlags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_ALIAS_BIT | + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT | VK_IMAGE_CREATE_PROTECTED_BIT | + VK_IMAGE_CREATE_DISJOINT_BIT); ASSERT_EQ(video_format_properties[0].imageType, VK_IMAGE_TYPE_2D); ASSERT_EQ(video_format_properties[0].imageTiling, VK_IMAGE_TILING_OPTIMAL); - ASSERT_EQ(video_format_properties[0].imageUsageFlags, VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | - VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR | - VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR); - ASSERT_EQ(video_format_properties[1].format, VK_FORMAT_R8G8B8A8_SNORM); - ASSERT_EQ(video_format_properties[1].imageCreateFlags, VK_IMAGE_TYPE_2D); + ASSERT_EQ(video_format_properties[0].imageUsageFlags, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR); + ASSERT_EQ(video_format_properties[1].format, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM); + ASSERT_EQ(video_format_properties[1].imageCreateFlags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_ALIAS_BIT | + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT | VK_IMAGE_CREATE_PROTECTED_BIT | + VK_IMAGE_CREATE_DISJOINT_BIT); ASSERT_EQ(video_format_properties[1].imageType, VK_IMAGE_TYPE_2D); ASSERT_EQ(video_format_properties[1].imageTiling, VK_IMAGE_TILING_OPTIMAL); - ASSERT_EQ(video_format_properties[1].imageUsageFlags, VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | - VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR | - VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR); + ASSERT_EQ(video_format_properties[1].imageUsageFlags, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR); + ASSERT_EQ(video_format_properties[2].format, VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM); + ASSERT_EQ(video_format_properties[2].imageCreateFlags, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_ALIAS_BIT | + VK_IMAGE_CREATE_EXTENDED_USAGE_BIT | VK_IMAGE_CREATE_PROTECTED_BIT | + VK_IMAGE_CREATE_DISJOINT_BIT); + ASSERT_EQ(video_format_properties[2].imageType, VK_IMAGE_TYPE_2D); + ASSERT_EQ(video_format_properties[2].imageTiling, VK_IMAGE_TILING_OPTIMAL); + ASSERT_EQ(video_format_properties[2].imageUsageFlags, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR); } TEST_F(MockICD, vkGetPhysicalDeviceVideoCapabilitiesKHR) { @@ -1140,21 +1182,42 @@ TEST_F(MockICD, vkGetPhysicalDeviceVideoCapabilitiesKHR) { vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceVideoCapabilitiesKHR")); ASSERT_NE(vkGetPhysicalDeviceVideoCapabilitiesKHR, nullptr); + VkVideoDecodeH264ProfileInfoKHR decode_h264_profile_info{}; + decode_h264_profile_info.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR; + decode_h264_profile_info.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_BASELINE; + decode_h264_profile_info.pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR; VkVideoProfileInfoKHR video_profile_info{}; + video_profile_info.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR; + video_profile_info.pNext = &decode_h264_profile_info; + video_profile_info.videoCodecOperation = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR; + video_profile_info.chromaSubsampling = VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR; + video_profile_info.lumaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR; + video_profile_info.chromaBitDepth = VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR; + VkVideoDecodeH264CapabilitiesKHR decode_h264_capabilities{}; + decode_h264_capabilities.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR; + VkVideoDecodeCapabilitiesKHR decode_capabilities{}; + decode_capabilities.sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR; + decode_capabilities.pNext = &decode_h264_capabilities; VkVideoCapabilitiesKHR video_capabilities{}; + video_capabilities.sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR; + video_capabilities.pNext = &decode_capabilities; VkResult res = vkGetPhysicalDeviceVideoCapabilitiesKHR(physical_device, &video_profile_info, &video_capabilities); ASSERT_EQ(res, VK_SUCCESS); - ASSERT_EQ(video_capabilities.flags, 0); - ASSERT_EQ(video_capabilities.minBitstreamBufferOffsetAlignment, 4); - ASSERT_EQ(video_capabilities.minBitstreamBufferSizeAlignment, 4); - ASSERT_EQ(video_capabilities.pictureAccessGranularity.width, 1); - ASSERT_EQ(video_capabilities.pictureAccessGranularity.height, 1); - ASSERT_EQ(video_capabilities.minCodedExtent.width, 4); - ASSERT_EQ(video_capabilities.minCodedExtent.height, 4); - ASSERT_EQ(video_capabilities.maxCodedExtent.width, 16); - ASSERT_EQ(video_capabilities.maxCodedExtent.height, 16); - ASSERT_EQ(video_capabilities.maxDpbSlots, 4); - ASSERT_EQ(video_capabilities.maxActiveReferencePictures, 4); + ASSERT_EQ(video_capabilities.flags, VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR); + ASSERT_EQ(video_capabilities.minBitstreamBufferOffsetAlignment, 256); + ASSERT_EQ(video_capabilities.minBitstreamBufferSizeAlignment, 256); + ASSERT_EQ(video_capabilities.pictureAccessGranularity.width, 16); + ASSERT_EQ(video_capabilities.pictureAccessGranularity.height, 16); + ASSERT_EQ(video_capabilities.minCodedExtent.width, 16); + ASSERT_EQ(video_capabilities.minCodedExtent.height, 16); + ASSERT_EQ(video_capabilities.maxCodedExtent.width, 1920); + ASSERT_EQ(video_capabilities.maxCodedExtent.height, 1080); + ASSERT_EQ(video_capabilities.maxDpbSlots, 33); + ASSERT_EQ(video_capabilities.maxActiveReferencePictures, 32); + ASSERT_EQ(decode_capabilities.flags, VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR); + ASSERT_EQ(decode_h264_capabilities.maxLevelIdc, STD_VIDEO_H264_LEVEL_IDC_6_2); + ASSERT_EQ(decode_h264_capabilities.fieldOffsetGranularity.x, 0); + ASSERT_EQ(decode_h264_capabilities.fieldOffsetGranularity.y, 0); } TEST_F(MockICD, vkGetDescriptorSetLayoutSupport) { |
