aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Rakos <daniel.rakos@rastergrid.com>2023-12-20 13:48:52 +0100
committerSpencer Fricke <115671160+spencer-lunarg@users.noreply.github.com>2023-12-21 00:40:41 +0900
commit87130b22e74cb208bf8ecd755dcf40dabd365dad (patch)
tree6e164d21772a4af8f364db655129d5153e35a2cf
parent64d9218726083ece79099341249890c75a5c4491 (diff)
downloadusermoji-87130b22e74cb208bf8ecd755dcf40dabd365dad.tar.xz
icd: Add video support
-rw-r--r--icd/generated/function_definitions.h578
-rw-r--r--icd/mock_icd.h9
-rw-r--r--scripts/mock_icd_generator.py584
-rw-r--r--tests/icd/mock_icd_tests.cpp151
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) {