From adad61239c43f4a06b8a97bf9c31b7d2a8148d6b Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Tue, 24 Sep 2019 16:33:39 +0200 Subject: [PATCH] radv: Deal with Android external formats. To abstract things a bit, this adds a helper function in radv_android.c. However, this means we have to link in radv_android.c on non-android as well, which means some scaffolding changes. Reviewed-by: Samuel Pitoiset --- src/amd/vulkan/meson.build | 2 +- src/amd/vulkan/radv_android.c | 20 +++++++++++ src/amd/vulkan/radv_formats.c | 24 +++++++------ src/amd/vulkan/radv_image.c | 66 +++++++++++++++++++++-------------- src/amd/vulkan/radv_private.h | 3 ++ 5 files changed, 76 insertions(+), 39 deletions(-) diff --git a/src/amd/vulkan/meson.build b/src/amd/vulkan/meson.build index 7fa945a346f..4243f66055f 100644 --- a/src/amd/vulkan/meson.build +++ b/src/amd/vulkan/meson.build @@ -67,6 +67,7 @@ libradv_files = files( 'winsys/amdgpu/radv_amdgpu_winsys.c', 'winsys/amdgpu/radv_amdgpu_winsys.h', 'winsys/amdgpu/radv_amdgpu_winsys_public.h', + 'radv_android.c', 'radv_cmd_buffer.c', 'radv_cs.h', 'radv_debug.c', @@ -143,7 +144,6 @@ if with_platform_android radv_flags += [ '-DVK_USE_PLATFORM_ANDROID_KHR' ] - libradv_files += files('radv_android.c') endif libvulkan_radeon = shared_library( diff --git a/src/amd/vulkan/radv_android.c b/src/amd/vulkan/radv_android.c index f3cbe2d4bd2..7833e6d8922 100644 --- a/src/amd/vulkan/radv_android.c +++ b/src/amd/vulkan/radv_android.c @@ -21,6 +21,7 @@ * IN THE SOFTWARE. */ +#ifdef ANDROID #include #include #include @@ -28,10 +29,13 @@ #include #include #include +#endif #include "radv_private.h" #include "vk_util.h" +#ifdef ANDROID + static int radv_hal_open(const struct hw_module_t* mod, const char* id, struct hw_device_t** dev); static int radv_hal_close(struct hw_device_t *dev); @@ -374,6 +378,7 @@ radv_QueueSignalReleaseImageANDROID( } return VK_SUCCESS; } +#endif #if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER @@ -579,3 +584,18 @@ radv_GetMemoryAndroidHardwareBufferANDROID( } #endif + +VkFormat +radv_select_android_external_format(const void *next, VkFormat default_format) +{ +#if RADV_SUPPORT_ANDROID_HARDWARE_BUFFER + const VkExternalFormatANDROID *android_format = + vk_find_struct_const(next, EXTERNAL_FORMAT_ANDROID); + + if (android_format && android_format->externalFormat) { + return (VkFormat)android_format->externalFormat; + } +#endif + + return default_format; +} diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c index c6e01d66fa6..0a84b064b21 100644 --- a/src/amd/vulkan/radv_formats.c +++ b/src/amd/vulkan/radv_formats.c @@ -1104,6 +1104,7 @@ void radv_GetPhysicalDeviceFormatProperties2( static VkResult radv_get_image_format_properties(struct radv_physical_device *physical_device, const VkPhysicalDeviceImageFormatInfo2 *info, + VkFormat format, VkImageFormatProperties *pImageFormatProperties) { @@ -1113,10 +1114,10 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph uint32_t maxMipLevels; uint32_t maxArraySize; VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT; - const struct vk_format_description *desc = vk_format_description(info->format); + const struct vk_format_description *desc = vk_format_description(format); enum chip_class chip_class = physical_device->rad_info.chip_class; - radv_physical_device_get_format_properties(physical_device, info->format, + radv_physical_device_get_format_properties(physical_device, format, &format_props); if (info->tiling == VK_IMAGE_TILING_LINEAR) { format_feature_flags = format_props.linearTilingFeatures; @@ -1129,7 +1130,7 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph if (format_feature_flags == 0) goto unsupported; - if (info->type != VK_IMAGE_TYPE_2D && vk_format_is_depth_or_stencil(info->format)) + if (info->type != VK_IMAGE_TYPE_2D && vk_format_is_depth_or_stencil(format)) goto unsupported; switch (info->type) { @@ -1179,9 +1180,9 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph } if (info->tiling == VK_IMAGE_TILING_LINEAR && - (info->format == VK_FORMAT_R32G32B32_SFLOAT || - info->format == VK_FORMAT_R32G32B32_SINT || - info->format == VK_FORMAT_R32G32B32_UINT)) { + (format == VK_FORMAT_R32G32B32_SFLOAT || + format == VK_FORMAT_R32G32B32_SINT || + format == VK_FORMAT_R32G32B32_UINT)) { /* R32G32B32 is a weird format and the driver currently only * supports the barely minimum. * TODO: Implement more if we really need to. @@ -1196,8 +1197,8 @@ static VkResult radv_get_image_format_properties(struct radv_physical_device *ph /* We can't create 3d compressed 128bpp images that can be rendered to on GFX9 */ if (physical_device->rad_info.chip_class >= GFX9 && info->type == VK_IMAGE_TYPE_3D && - vk_format_get_blocksizebits(info->format) == 128 && - vk_format_is_compressed(info->format) && + vk_format_get_blocksizebits(format) == 128 && + vk_format_is_compressed(format) && (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) && ((info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT) || (info->usage & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))) { @@ -1293,7 +1294,7 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties( .flags = createFlags, }; - return radv_get_image_format_properties(physical_device, &info, + return radv_get_image_format_properties(physical_device, &info, format, pImageFormatProperties); } @@ -1348,8 +1349,9 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties2( struct VkAndroidHardwareBufferUsageANDROID *android_usage = NULL; VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL; VkResult result; + VkFormat format = radv_select_android_external_format(base_info->pNext, base_info->format); - result = radv_get_image_format_properties(physical_device, base_info, + result = radv_get_image_format_properties(physical_device, base_info, format, &base_props->imageFormatProperties); if (result != VK_SUCCESS) return result; @@ -1416,7 +1418,7 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties2( } if (ycbcr_props) { - ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(base_info->format); + ycbcr_props->combinedImageSamplerDescriptorCount = vk_format_get_plane_count(format); } return VK_SUCCESS; diff --git a/src/amd/vulkan/radv_image.c b/src/amd/vulkan/radv_image.c index 9df7dd4ae81..316f883f676 100644 --- a/src/amd/vulkan/radv_image.c +++ b/src/amd/vulkan/radv_image.c @@ -36,15 +36,16 @@ static unsigned radv_choose_tiling(struct radv_device *device, - const VkImageCreateInfo *pCreateInfo) + const VkImageCreateInfo *pCreateInfo, + VkFormat format) { if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) { assert(pCreateInfo->samples <= 1); return RADEON_SURF_MODE_LINEAR_ALIGNED; } - if (!vk_format_is_compressed(pCreateInfo->format) && - !vk_format_is_depth_or_stencil(pCreateInfo->format) + if (!vk_format_is_compressed(format) && + !vk_format_is_depth_or_stencil(format) && device->physical_device->rad_info.chip_class <= GFX8) { /* this causes hangs in some VK CTS tests on GFX9. */ /* Textures with a very small height are recommended to be linear. */ @@ -64,7 +65,8 @@ radv_choose_tiling(struct radv_device *device, static bool radv_use_tc_compat_htile_for_image(struct radv_device *device, - const VkImageCreateInfo *pCreateInfo) + const VkImageCreateInfo *pCreateInfo, + VkFormat format) { /* TC-compat HTILE is only available for GFX8+. */ if (device->physical_device->rad_info.chip_class < GFX8) @@ -84,8 +86,8 @@ radv_use_tc_compat_htile_for_image(struct radv_device *device, * tests - disable for now. On GFX10 D32_SFLOAT is affected as well. */ if (pCreateInfo->samples >= 2 && - (pCreateInfo->format == VK_FORMAT_D32_SFLOAT_S8_UINT || - (pCreateInfo->format == VK_FORMAT_D32_SFLOAT && + (format == VK_FORMAT_D32_SFLOAT_S8_UINT || + (format == VK_FORMAT_D32_SFLOAT && device->physical_device->rad_info.chip_class == GFX10))) return false; @@ -93,9 +95,9 @@ radv_use_tc_compat_htile_for_image(struct radv_device *device, * supports 32-bit. Though, it's possible to enable TC-compat for * 16-bit depth surfaces if no Z planes are compressed. */ - if (pCreateInfo->format != VK_FORMAT_D32_SFLOAT_S8_UINT && - pCreateInfo->format != VK_FORMAT_D32_SFLOAT && - pCreateInfo->format != VK_FORMAT_D16_UNORM) + if (format != VK_FORMAT_D32_SFLOAT_S8_UINT && + format != VK_FORMAT_D32_SFLOAT && + format != VK_FORMAT_D16_UNORM) return false; if (pCreateInfo->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { @@ -113,7 +115,7 @@ radv_use_tc_compat_htile_for_image(struct radv_device *device, if (format_list->pViewFormats[i] == VK_FORMAT_UNDEFINED) continue; - if (pCreateInfo->format != format_list->pViewFormats[i]) + if (format != format_list->pViewFormats[i]) return false; } } else { @@ -143,7 +145,8 @@ radv_surface_has_scanout(struct radv_device *device, const struct radv_image_cre static bool radv_use_dcc_for_image(struct radv_device *device, const struct radv_image *image, - const VkImageCreateInfo *pCreateInfo) + const VkImageCreateInfo *pCreateInfo, + VkFormat format) { bool dcc_compatible_formats; bool blendable; @@ -166,8 +169,8 @@ radv_use_dcc_for_image(struct radv_device *device, if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) return false; - if (vk_format_is_subsampled(pCreateInfo->format) || - vk_format_get_plane_count(pCreateInfo->format) > 1) + if (vk_format_is_subsampled(format) || + vk_format_get_plane_count(format) > 1) return false; /* TODO: Enable DCC for mipmaps on GFX9+. */ @@ -189,7 +192,7 @@ radv_use_dcc_for_image(struct radv_device *device, /* Determine if the formats are DCC compatible. */ dcc_compatible_formats = - radv_is_colorbuffer_format_supported(pCreateInfo->format, + radv_is_colorbuffer_format_supported(format, &blendable); if (pCreateInfo->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { @@ -206,7 +209,7 @@ radv_use_dcc_for_image(struct radv_device *device, if (format_list->pViewFormats[i] == VK_FORMAT_UNDEFINED) continue; - if (!radv_dcc_formats_compatible(pCreateInfo->format, + if (!radv_dcc_formats_compatible(format, format_list->pViewFormats[i])) dcc_compatible_formats = false; } @@ -389,10 +392,11 @@ radv_init_surface(struct radv_device *device, const struct radv_image *image, struct radeon_surf *surface, unsigned plane_id, - const VkImageCreateInfo *pCreateInfo) + const VkImageCreateInfo *pCreateInfo, + VkFormat image_format) { - unsigned array_mode = radv_choose_tiling(device, pCreateInfo); - VkFormat format = vk_format_get_plane_format(pCreateInfo->format, plane_id); + unsigned array_mode = radv_choose_tiling(device, pCreateInfo, image_format); + VkFormat format = vk_format_get_plane_format(image_format, plane_id); const struct vk_format_description *desc = vk_format_description(format); bool is_depth, is_stencil; @@ -432,7 +436,7 @@ radv_init_surface(struct radv_device *device, if (is_depth) { surface->flags |= RADEON_SURF_ZBUFFER; - if (radv_use_tc_compat_htile_for_image(device, pCreateInfo)) + if (radv_use_tc_compat_htile_for_image(device, pCreateInfo, image_format)) surface->flags |= RADEON_SURF_TC_COMPATIBLE_HTILE; } @@ -441,13 +445,13 @@ radv_init_surface(struct radv_device *device, if (device->physical_device->rad_info.chip_class >= GFX9 && pCreateInfo->imageType == VK_IMAGE_TYPE_3D && - vk_format_get_blocksizebits(pCreateInfo->format) == 128 && - vk_format_is_compressed(pCreateInfo->format)) + vk_format_get_blocksizebits(image_format) == 128 && + vk_format_is_compressed(image_format)) surface->flags |= RADEON_SURF_NO_RENDER_TARGET; surface->flags |= RADEON_SURF_OPTIMIZE_FOR_SPACE; - if (!radv_use_dcc_for_image(device, image, pCreateInfo)) + if (!radv_use_dcc_for_image(device, image, pCreateInfo, image_format)) surface->flags |= RADEON_SURF_DISABLE_DCC; return 0; @@ -1439,9 +1443,11 @@ radv_image_create(VkDevice _device, RADV_FROM_HANDLE(radv_device, device, _device); const VkImageCreateInfo *pCreateInfo = create_info->vk_info; struct radv_image *image = NULL; + VkFormat format = radv_select_android_external_format(pCreateInfo->pNext, + pCreateInfo->format); assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO); - const unsigned plane_count = vk_format_get_plane_count(pCreateInfo->format); + const unsigned plane_count = vk_format_get_plane_count(format); const size_t image_struct_size = sizeof(*image) + sizeof(struct radv_image_plane) * plane_count; radv_assert(pCreateInfo->mipLevels > 0); @@ -1464,9 +1470,9 @@ radv_image_create(VkDevice _device, image->info.storage_samples = pCreateInfo->samples; image->info.array_size = pCreateInfo->arrayLayers; image->info.levels = pCreateInfo->mipLevels; - image->info.num_channels = vk_format_get_nr_components(pCreateInfo->format); + image->info.num_channels = vk_format_get_nr_components(format); - image->vk_format = pCreateInfo->format; + image->vk_format = format; image->tiling = pCreateInfo->tiling; image->usage = pCreateInfo->usage; image->flags = pCreateInfo->flags; @@ -1484,12 +1490,12 @@ radv_image_create(VkDevice _device, image->shareable = vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO) != NULL; - if (!vk_format_is_depth_or_stencil(pCreateInfo->format) && !image->shareable) { + if (!vk_format_is_depth_or_stencil(format) && !image->shareable) { image->info.surf_index = &device->image_mrt_offset_counter; } for (unsigned plane = 0; plane < image->plane_count; ++plane) { - radv_init_surface(device, image, &image->planes[plane].surface, plane, pCreateInfo); + radv_init_surface(device, image, &image->planes[plane].surface, plane, pCreateInfo, format); } ASSERTED VkResult result = radv_image_create_layout(device, *create_info, image); @@ -1632,8 +1638,14 @@ radv_image_view_init(struct radv_image_view *iview, iview->plane_id = radv_plane_from_aspect(pCreateInfo->subresourceRange.aspectMask); iview->aspect_mask = pCreateInfo->subresourceRange.aspectMask; iview->multiple_planes = vk_format_get_plane_count(image->vk_format) > 1 && iview->aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT; + iview->vk_format = pCreateInfo->format; + /* If the image has an Android external format, pCreateInfo->format will be + * VK_FORMAT_UNDEFINED. */ + if (iview->vk_format == VK_FORMAT_UNDEFINED) + iview->vk_format = image->vk_format; + if (iview->aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) { iview->vk_format = vk_format_stencil_only(iview->vk_format); } else if (iview->aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT) { diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 6ad055aacdc..f0a5fc19604 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1928,6 +1928,9 @@ uint64_t radv_ahb_usage_from_vk_usage(const VkImageCreateFlags vk_create, const VkImageUsageFlags vk_usage); +VkFormat +radv_select_android_external_format(const void *next, VkFormat default_format); + struct radv_image_view_extra_create_info { bool disable_compression; -- 2.30.2