@@ -77,11 +77,53 @@ static inline const char *string_AHardwareBufferGpuUsage(uint64_t usage) {
7777 return " AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP" ;
7878 } else if (usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE) {
7979 return " AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE" ;
80+ } else if (usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
81+ return " AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT" ;
8082 } else {
8183 return " Unknown AHARDWAREBUFFER_USAGE_GPU" ;
8284 }
8385}
8486
87+ static inline const char *string_AHardwareBufferFormat (uint32_t format) {
88+ switch (format) {
89+ case (uint32_t )AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
90+ return " AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM" ;
91+ case (uint32_t )AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
92+ return " AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM" ;
93+ case (uint32_t )AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
94+ return " AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM" ;
95+ case (uint32_t )AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
96+ return " AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM" ;
97+ case (uint32_t )AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
98+ return " AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT" ;
99+ case (uint32_t )AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
100+ return " AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM" ;
101+ case (uint32_t )AHARDWAREBUFFER_FORMAT_BLOB:
102+ return " AHARDWAREBUFFER_FORMAT_BLOB" ;
103+ case (uint32_t )AHARDWAREBUFFER_FORMAT_D16_UNORM:
104+ return " AHARDWAREBUFFER_FORMAT_D16_UNORM" ;
105+ case (uint32_t )AHARDWAREBUFFER_FORMAT_D24_UNORM:
106+ return " AHARDWAREBUFFER_FORMAT_D24_UNORM" ;
107+ case (uint32_t )AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
108+ return " AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT" ;
109+ case (uint32_t )AHARDWAREBUFFER_FORMAT_D32_FLOAT:
110+ return " AHARDWAREBUFFER_FORMAT_D32_FLOAT" ;
111+ case (uint32_t )AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
112+ return " AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT" ;
113+ case (uint32_t )AHARDWAREBUFFER_FORMAT_S8_UINT:
114+ return " AHARDWAREBUFFER_FORMAT_S8_UINT" ;
115+ case (uint32_t )AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
116+ return " AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420" ;
117+ case (uint32_t )AHARDWAREBUFFER_FORMAT_YCbCr_P010:
118+ return " AHARDWAREBUFFER_FORMAT_YCbCr_P010" ;
119+ case (uint32_t )AHARDWAREBUFFER_FORMAT_R8_UNORM:
120+ return " AHARDWAREBUFFER_FORMAT_R8_UNORM" ;
121+ default :
122+ break ;
123+ }
124+ return " Unkown AHardwareBuffer_Format" ;
125+ }
126+
85127static uint32_t FullMipChainLevels (VkExtent3D extent) {
86128 // uint cast applies floor()
87129 return 1u + static_cast <uint32_t >(log2 (std::max ({extent.height , extent.width , extent.depth })));
@@ -163,22 +205,6 @@ bool CoreChecks::ValidateAllocateMemoryANDROID(const VkMemoryAllocateInfo &alloc
163205 AHardwareBuffer_Desc ahb_desc = {};
164206 AHardwareBuffer_describe (import_ahb_info->buffer , &ahb_desc);
165207
166- // Validate AHardwareBuffer_Desc::usage is a valid usage for imported AHB
167- //
168- // BLOB & GPU_DATA_BUFFER combo specifically allowed
169- if ((AHARDWAREBUFFER_FORMAT_BLOB != ahb_desc.format ) || (0 == (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER))) {
170- // Otherwise, must be a combination from the AHardwareBuffer Format and Usage Equivalence tables
171- // Usage must have at least one bit from the table. It may have additional bits not in the table
172- uint64_t ahb_equiv_usage_bits = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
173- AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP | AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE |
174- AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
175- if (0 == (ahb_desc.usage & ahb_equiv_usage_bits)) {
176- skip |= LogError (" VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01881" , device, ahb_loc,
177- " AHardwareBuffer_Desc's usage (0x%" PRIx64 " ) is not compatible with Vulkan. (AHB = %p)." ,
178- ahb_desc.usage , import_ahb_info->buffer );
179- }
180- }
181-
182208 // Collect external buffer info
183209 VkPhysicalDeviceExternalBufferInfo pdebi = vku::InitStructHelper ();
184210 pdebi.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
@@ -254,18 +280,21 @@ bool CoreChecks::ValidateAllocateMemoryANDROID(const VkMemoryAllocateInfo &alloc
254280 allocate_info.memoryTypeIndex , ahb_loc.Fields ().c_str (), ahb_props.memoryTypeBits , import_ahb_info->buffer );
255281 }
256282
283+ VkImageUsageFlags dedicated_image_usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; // dummy init value
284+
257285 // Checks for allocations without a dedicated allocation requirement
258286 if ((nullptr == mem_ded_alloc_info) || (VK_NULL_HANDLE == mem_ded_alloc_info->image )) {
259287 // the Android hardware buffer must have a format of AHARDWAREBUFFER_FORMAT_BLOB and a usage that includes
260288 // AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER
261289 if ((uint64_t )AHARDWAREBUFFER_FORMAT_BLOB != ahb_desc.format ) {
262290 skip |= LogError (" VUID-VkMemoryAllocateInfo-pNext-02384" , device, ahb_loc,
263- " AHardwareBuffer_Desc's format (%" PRIu32 " ) is not AHARDWAREBUFFER_FORMAT_BLOB. (AHB = %p)." ,
264- ahb_desc.format , import_ahb_info->buffer );
291+ " AHardwareBuffer_Desc's format %s (%" PRIu32
292+ " ) is not AHARDWAREBUFFER_FORMAT_BLOB (0x21). (AHB = %p)." ,
293+ string_AHardwareBufferFormat (ahb_desc.format ), ahb_desc.format , import_ahb_info->buffer );
265294 } else if ((ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) == 0 ) {
266295 skip |= LogError (" VUID-VkMemoryAllocateInfo-pNext-02384" , device, ahb_loc,
267296 " AHardwareBuffer's usage (0x%" PRIx64
268- " ) does not include AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER. (AHB = %p)." ,
297+ " ) does not include AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER (0x1000000) . (AHB = %p)." ,
269298 ahb_desc.usage , import_ahb_info->buffer );
270299 }
271300 } else { // Checks specific to import with a dedicated allocation requirement
@@ -282,6 +311,8 @@ bool CoreChecks::ValidateAllocateMemoryANDROID(const VkMemoryAllocateInfo &alloc
282311 const auto *ici = &image_state->create_info ;
283312 const Location &dedicated_image_loc = allocate_info_loc.dot (Struct::VkMemoryDedicatedAllocateInfo, Field::image);
284313
314+ dedicated_image_usage = ici->usage ;
315+
285316 // the format of image must be VK_FORMAT_UNDEFINED or the format returned by
286317 // vkGetAndroidHardwareBufferPropertiesANDROID
287318 if (VK_FORMAT_UNDEFINED != ici->format ) {
@@ -312,19 +343,21 @@ bool CoreChecks::ValidateAllocateMemoryANDROID(const VkMemoryAllocateInfo &alloc
312343
313344 if ((ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE) != 0 ) {
314345 if ((ici->mipLevels != 1 ) && (ici->mipLevels != FullMipChainLevels (ici->extent ))) {
315- skip |= LogError (
316- " VUID-VkMemoryAllocateInfo-pNext-02389" , mem_ded_alloc_info->image , ahb_loc,
317- " AHardwareBuffer_Desc's usage includes AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE but %s mipLevels (%" PRIu32
318- " ) is neither 1 nor full mip "
319- " chain levels (%" PRIu32 " ). (AHB = %p)." ,
320- dedicated_image_loc.Fields ().c_str (), ici->mipLevels , FullMipChainLevels (ici->extent ),
321- import_ahb_info->buffer );
346+ skip |= LogError (" VUID-VkMemoryAllocateInfo-pNext-02389" , mem_ded_alloc_info->image , ahb_loc,
347+ " AHardwareBuffer_Desc's usage (0x%" PRIx64
348+ " ) includes AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE but %s mipLevels (%" PRIu32
349+ " ) is neither 1 nor full mip chain levels (%" PRIu32 " ). (AHB = %p)." ,
350+ ahb_desc.usage , dedicated_image_loc.Fields ().c_str (), ici->mipLevels ,
351+ FullMipChainLevels (ici->extent ), import_ahb_info->buffer );
322352 }
323353 } else {
324354 if (ici->mipLevels != 1 ) {
325- skip |= LogError (" VUID-VkMemoryAllocateInfo-pNext-02586" , mem_ded_alloc_info->image , ahb_loc,
326- " AHardwareBuffer_Desc's usage is 0x%" PRIx64 " but %s mipLevels is %" PRIu32 " . (AHB = %p)." ,
327- ahb_desc.usage , dedicated_image_loc.Fields ().c_str (), ici->mipLevels , import_ahb_info->buffer );
355+ skip |=
356+ LogError (" VUID-VkMemoryAllocateInfo-pNext-02586" , mem_ded_alloc_info->image , ahb_loc,
357+ " AHardwareBuffer_Desc's usage (0x%" PRIx64
358+ " ) is missing 0x4000000 (AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE) but %s mipLevels is %" PRIu32
359+ " . (AHB = %p)." ,
360+ ahb_desc.usage , dedicated_image_loc.Fields ().c_str (), ici->mipLevels , import_ahb_info->buffer );
328361 }
329362 }
330363
@@ -352,16 +385,40 @@ bool CoreChecks::ValidateAllocateMemoryANDROID(const VkMemoryAllocateInfo &alloc
352385 for (const auto &[vk_usage, ahb_usage] : ahb_usage_map_v2a) {
353386 if (ici->usage & vk_usage) {
354387 if (0 == (ahb_usage & ahb_desc.usage )) {
355- skip |= LogError (
356- " VUID-VkMemoryAllocateInfo-pNext-02390" , mem_ded_alloc_info->image , dedicated_image_loc,
357- " was created with %s, but the AHB equivalent (%s) is not in AHardwareBuffer_Desc.usage (0x%" PRIx64
358- " ). (AHB = %p)." ,
359- string_VkImageUsageFlags (vk_usage).c_str (), string_AHardwareBufferGpuUsage (ahb_usage), ahb_desc.usage ,
360- import_ahb_info->buffer );
388+ skip |= LogError (" VUID-VkMemoryAllocateInfo-pNext-02390" , mem_ded_alloc_info->image , dedicated_image_loc,
389+ " was created with %s, but the AHB equivalent 0x%" PRIx64
390+ " (%s) is not in AHardwareBuffer_Desc.usage (0x%" PRIx64 " ). (AHB = %p)." ,
391+ string_VkImageUsageFlags (vk_usage).c_str (), ahb_usage,
392+ string_AHardwareBufferGpuUsage (ahb_usage), ahb_desc.usage , import_ahb_info->buffer );
361393 }
362394 }
363395 }
364396 }
397+
398+ // Validate AHardwareBuffer_Desc::usage is a valid usage for imported AHB
399+ const bool is_gpu_data = ((ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) != 0 );
400+ // BLOB & GPU_DATA_BUFFER combo specifically allowed
401+ bool usage_exception_1 = is_gpu_data && AHARDWAREBUFFER_FORMAT_BLOB == ahb_desc.format ;
402+ // Recently using VK_IMAGE_USAGE_STORAGE_BIT was also allowed
403+ bool usage_exception_2 = is_gpu_data && ((dedicated_image_usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0 );
404+ if (!usage_exception_1 && !usage_exception_2) {
405+ // Otherwise, must be a combination from the AHardwareBuffer Format and Usage Equivalence tables
406+ // Usage must have at least one bit from the table. It may have additional bits not in the table
407+ uint64_t ahb_equiv_usage_bits = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
408+ AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP | AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE |
409+ AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
410+ if (0 == (ahb_desc.usage & ahb_equiv_usage_bits)) {
411+ skip |= LogError (
412+ " VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01881" , device, ahb_loc,
413+ " AHardwareBuffer_Desc's usage (0x%" PRIx64
414+ " ) is not compatible with Vulkan. (Format = %s) (AHB = %p). There are 3 valid combinations:\n "
415+ " 1. Use FORMAT_BLOB with USAGE_GPU_DATA_BUFFER\n "
416+ " 2. Use USAGE_GPU_DATA_BUFFER with a dedicated VkImage with VK_IMAGE_USAGE_STORAGE_BIT\n "
417+ " 3. Use AHB usage GPU_SAMPLED_IMAGE, GPU_FRAMEBUFFER, GPU_CUBE_MAP, GPU_MIPMAP_COMPLETE, or PROTECTED_CONTENT" ,
418+ ahb_desc.usage , string_AHardwareBufferFormat (ahb_desc.format ), import_ahb_info->buffer );
419+ }
420+ }
421+
365422 } else { // Not an import
366423 // auto exp_mem_alloc_info = vku::FindStructInPNextChain<VkExportMemoryAllocateInfo>(allocate_info.pNext);
367424 // auto mem_ded_alloc_info = vku::FindStructInPNextChain<VkMemoryDedicatedAllocateInfo>(allocate_info.pNext);
0 commit comments