From b24b93d58431a4349eecddb07304f6eda648e997 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Mon, 19 Jun 2017 16:57:00 +0100 Subject: [PATCH] anv: enable VK_KHR_sampler_ycbcr_conversion v2: Make GetImageMemoryRequirements2KHR() iterate over all pInfo structs (Lionel) Handle VkSamplerYcbcrConversionImageFormatPropertiesKHR (Andrew/Jason) Iterator over BindImageMemory2KHR's pNext structs correctly (Jason) v3: Revert GetImageMemoryRequirements2KHR() change from v2 (Jason) Signed-off-by: Lionel Landwerlin Reviewed-by: Jason Ekstrand --- src/intel/vulkan/anv_device.c | 45 ++++++++++++++++ src/intel/vulkan/anv_extensions.py | 1 + src/intel/vulkan/anv_formats.c | 83 +++++++++++++++++++++++++++--- src/intel/vulkan/anv_image.c | 21 +++++++- src/intel/vulkan/anv_private.h | 4 ++ src/intel/vulkan/genX_state.c | 50 ++++++++++++++---- 6 files changed, 186 insertions(+), 18 deletions(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index d576bb55315..70db6f88beb 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -703,6 +703,13 @@ void anv_GetPhysicalDeviceFeatures2KHR( break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR: { + VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR *features = + (VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR *) ext; + features->samplerYcbcrConversion = true; + break; + } + default: anv_debug_ignored_stype(ext->sType); break; @@ -1829,6 +1836,44 @@ void anv_GetImageMemoryRequirements2KHR( anv_GetImageMemoryRequirements(_device, pInfo->image, &pMemoryRequirements->memoryRequirements); + vk_foreach_struct_const(ext, pInfo->pNext) { + switch (ext->sType) { + case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR: { + ANV_FROM_HANDLE(anv_image, image, pInfo->image); + ANV_FROM_HANDLE(anv_device, device, _device); + struct anv_physical_device *pdevice = &device->instance->physicalDevice; + const VkImagePlaneMemoryRequirementsInfoKHR *plane_reqs = + (const VkImagePlaneMemoryRequirementsInfoKHR *) ext; + uint32_t plane = anv_image_aspect_to_plane(image->aspects, + plane_reqs->planeAspect); + + assert(image->planes[plane].offset == 0); + + /* The Vulkan spec (git aaed022) says: + * + * memoryTypeBits is a bitfield and contains one bit set for every + * supported memory type for the resource. The bit `1<memoryRequirements.memoryTypeBits = + (1ull << pdevice->memory.type_count) - 1; + + pMemoryRequirements->memoryRequirements.size = image->planes[plane].size; + pMemoryRequirements->memoryRequirements.alignment = + image->planes[plane].alignment; + break; + } + + default: + anv_debug_ignored_stype(ext->sType); + break; + } + } + vk_foreach_struct(ext, pMemoryRequirements->pNext) { switch (ext->sType) { case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR: { diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py index 491e7086838..a828a668d65 100644 --- a/src/intel/vulkan/anv_extensions.py +++ b/src/intel/vulkan/anv_extensions.py @@ -74,6 +74,7 @@ EXTENSIONS = [ Extension('VK_KHR_push_descriptor', 1, True), Extension('VK_KHR_relaxed_block_layout', 1, True), Extension('VK_KHR_sampler_mirror_clamp_to_edge', 1, True), + Extension('VK_KHR_sampler_ycbcr_conversion', 1, True), Extension('VK_KHR_shader_draw_parameters', 1, True), Extension('VK_KHR_storage_buffer_storage_class', 1, True), Extension('VK_KHR_surface', 25, 'ANV_HAS_SURFACE'), diff --git a/src/intel/vulkan/anv_formats.c b/src/intel/vulkan/anv_formats.c index 879eb072b10..cece065398e 100644 --- a/src/intel/vulkan/anv_formats.c +++ b/src/intel/vulkan/anv_formats.c @@ -683,7 +683,8 @@ static VkResult anv_get_image_format_properties( struct anv_physical_device *physical_device, const VkPhysicalDeviceImageFormatInfo2KHR *info, - VkImageFormatProperties *pImageFormatProperties) + VkImageFormatProperties *pImageFormatProperties, + VkSamplerYcbcrConversionImageFormatPropertiesKHR *pYcbcrImageFormatProperties) { VkFormatProperties format_props; VkFormatFeatureFlags format_feature_flags; @@ -816,6 +817,11 @@ anv_get_image_format_properties( .maxResourceSize = UINT32_MAX, }; + if (pYcbcrImageFormatProperties) { + pYcbcrImageFormatProperties->combinedImageSamplerDescriptorCount = + format->n_planes; + } + return VK_SUCCESS; unsupported: @@ -852,7 +858,7 @@ VkResult anv_GetPhysicalDeviceImageFormatProperties( }; return anv_get_image_format_properties(physical_device, &info, - pImageFormatProperties); + pImageFormatProperties, NULL); } static const VkExternalMemoryPropertiesKHR prime_fd_props = { @@ -874,13 +880,9 @@ VkResult anv_GetPhysicalDeviceImageFormatProperties2KHR( ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice); const VkPhysicalDeviceExternalImageFormatInfoKHR *external_info = NULL; VkExternalImageFormatPropertiesKHR *external_props = NULL; + VkSamplerYcbcrConversionImageFormatPropertiesKHR *ycbcr_props = NULL; VkResult result; - result = anv_get_image_format_properties(physical_device, base_info, - &base_props->imageFormatProperties); - if (result != VK_SUCCESS) - goto fail; - /* Extract input structs */ vk_foreach_struct_const(s, base_info->pNext) { switch (s->sType) { @@ -899,12 +901,20 @@ VkResult anv_GetPhysicalDeviceImageFormatProperties2KHR( case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR: external_props = (void *) s; break; + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR: + ycbcr_props = (void *) s; + break; default: anv_debug_ignored_stype(s->sType); break; } } + result = anv_get_image_format_properties(physical_device, base_info, + &base_props->imageFormatProperties, ycbcr_props); + if (result != VK_SUCCESS) + goto fail; + /* From the Vulkan 1.0.42 spec: * * If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2KHR will @@ -1006,3 +1016,62 @@ void anv_GetPhysicalDeviceExternalBufferPropertiesKHR( pExternalBufferProperties->externalMemoryProperties = (VkExternalMemoryPropertiesKHR) {0}; } + +VkResult anv_CreateSamplerYcbcrConversionKHR( + VkDevice _device, + const VkSamplerYcbcrConversionCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSamplerYcbcrConversionKHR* pYcbcrConversion) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + struct anv_ycbcr_conversion *conversion; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR); + + conversion = vk_alloc2(&device->alloc, pAllocator, sizeof(*conversion), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!conversion) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + + memset(conversion, 0, sizeof(*conversion)); + + conversion->format = anv_get_format(pCreateInfo->format); + conversion->ycbcr_model = pCreateInfo->ycbcrModel; + conversion->ycbcr_range = pCreateInfo->ycbcrRange; + conversion->mapping[0] = pCreateInfo->components.r; + conversion->mapping[1] = pCreateInfo->components.g; + conversion->mapping[2] = pCreateInfo->components.b; + conversion->mapping[3] = pCreateInfo->components.a; + conversion->chroma_offsets[0] = pCreateInfo->xChromaOffset; + conversion->chroma_offsets[1] = pCreateInfo->yChromaOffset; + conversion->chroma_filter = pCreateInfo->chromaFilter; + + bool has_chroma_subsampled = false; + for (uint32_t p = 0; p < conversion->format->n_planes; p++) { + if (conversion->format->planes[p].has_chroma && + (conversion->format->planes[p].denominator_scales[0] > 1 || + conversion->format->planes[p].denominator_scales[1] > 1)) + has_chroma_subsampled = true; + } + conversion->chroma_reconstruction = has_chroma_subsampled && + (conversion->chroma_offsets[0] == VK_CHROMA_LOCATION_COSITED_EVEN_KHR || + conversion->chroma_offsets[1] == VK_CHROMA_LOCATION_COSITED_EVEN_KHR); + + *pYcbcrConversion = anv_ycbcr_conversion_to_handle(conversion); + + return VK_SUCCESS; +} + +void anv_DestroySamplerYcbcrConversionKHR( + VkDevice _device, + VkSamplerYcbcrConversionKHR YcbcrConversion, + const VkAllocationCallbacks* pAllocator) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + ANV_FROM_HANDLE(anv_ycbcr_conversion, conversion, YcbcrConversion); + + if (!conversion) + return; + + vk_free2(&device->alloc, pAllocator, conversion); +} diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index 78daf4dc55f..487ff275940 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -516,6 +516,7 @@ anv_image_create(VkDevice _device, image->samples = pCreateInfo->samples; image->usage = pCreateInfo->usage; image->tiling = pCreateInfo->tiling; + image->disjoint = pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR; const struct anv_format *format = anv_get_format(image->vk_format); assert(format != NULL); @@ -613,9 +614,25 @@ VkResult anv_BindImageMemory2KHR( const VkBindImageMemoryInfoKHR *bind_info = &pBindInfos[i]; ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory); ANV_FROM_HANDLE(anv_image, image, bind_info->image); - uint32_t aspect_bit; + VkImageAspectFlags aspects = image->aspects; + + vk_foreach_struct_const(s, bind_info->pNext) { + switch (s->sType) { + case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR: { + const VkBindImagePlaneMemoryInfoKHR *plane_info = + (const VkBindImagePlaneMemoryInfoKHR *) s; - anv_foreach_image_aspect_bit(aspect_bit, image, image->aspects) { + aspects = plane_info->planeAspect; + break; + } + default: + anv_debug_ignored_stype(s->sType); + break; + } + } + + uint32_t aspect_bit; + anv_foreach_image_aspect_bit(aspect_bit, image, aspects) { uint32_t plane = anv_image_aspect_to_plane(image->aspects, 1UL << aspect_bit); anv_image_bind_memory_plane(device, image, plane, diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 75b7044de81..de0f49de39f 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2338,6 +2338,9 @@ struct anv_image { VkDeviceSize size; uint32_t alignment; + /* Whether the image is made of several underlying buffer objects rather a + * single one with different offsets. + */ bool disjoint; /** @@ -2862,6 +2865,7 @@ ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_sampler, VkSampler) ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_semaphore, VkSemaphore) ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_shader_module, VkShaderModule) ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_debug_report_callback, VkDebugReportCallbackEXT) +ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_ycbcr_conversion, VkSamplerYcbcrConversionKHR) /* Gen-specific function declarations */ #ifdef genX diff --git a/src/intel/vulkan/genX_state.c b/src/intel/vulkan/genX_state.c index 91da05cddbf..b7e4e5bceab 100644 --- a/src/intel/vulkan/genX_state.c +++ b/src/intel/vulkan/genX_state.c @@ -33,6 +33,8 @@ #include "genxml/gen_macros.h" #include "genxml/genX_pack.h" +#include "vk_util.h" + VkResult genX(init_device_state)(struct anv_device *device) { @@ -176,12 +178,44 @@ VkResult genX(CreateSampler)( uint32_t border_color_offset = device->border_colors.offset + pCreateInfo->borderColor * 64; - bool enable_min_filter_addr_rounding = - pCreateInfo->minFilter != VK_FILTER_NEAREST; - bool enable_mag_filter_addr_rounding = - pCreateInfo->magFilter != VK_FILTER_NEAREST; + vk_foreach_struct(ext, pCreateInfo->pNext) { + switch (ext->sType) { + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR: { + VkSamplerYcbcrConversionInfoKHR *pSamplerConversion = + (VkSamplerYcbcrConversionInfoKHR *) ext; + ANV_FROM_HANDLE(anv_ycbcr_conversion, conversion, + pSamplerConversion->conversion); + + if (conversion == NULL) + break; + + sampler->n_planes = conversion->format->n_planes; + sampler->conversion = conversion; + break; + } + default: + anv_debug_ignored_stype(ext->sType); + break; + } + } for (unsigned p = 0; p < sampler->n_planes; p++) { + const bool plane_has_chroma = + sampler->conversion && sampler->conversion->format->planes[p].has_chroma; + const VkFilter min_filter = + plane_has_chroma ? sampler->conversion->chroma_filter : pCreateInfo->minFilter; + const VkFilter mag_filter = + plane_has_chroma ? sampler->conversion->chroma_filter : pCreateInfo->magFilter; + const bool enable_min_filter_addr_rounding = min_filter != VK_FILTER_NEAREST; + const bool enable_mag_filter_addr_rounding = mag_filter != VK_FILTER_NEAREST; + /* From Broadwell PRM, SAMPLER_STATE: + * "Mip Mode Filter must be set to MIPFILTER_NONE for Planar YUV surfaces." + */ + const uint32_t mip_filter_mode = + (sampler->conversion && + isl_format_is_yuv(sampler->conversion->format->planes[0].isl_format)) ? + MIPFILTER_NONE : vk_to_gen_mipmap_mode[pCreateInfo->mipmapMode]; + struct GENX(SAMPLER_STATE) sampler_state = { .SamplerDisable = false, .TextureBorderColorMode = DX10OGL, @@ -195,11 +229,9 @@ VkResult genX(CreateSampler)( #if GEN_GEN == 8 .BaseMipLevel = 0.0, #endif - .MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipmapMode], - .MagModeFilter = vk_to_gen_tex_filter(pCreateInfo->magFilter, - pCreateInfo->anisotropyEnable), - .MinModeFilter = vk_to_gen_tex_filter(pCreateInfo->minFilter, - pCreateInfo->anisotropyEnable), + .MipModeFilter = mip_filter_mode, + .MagModeFilter = vk_to_gen_tex_filter(mag_filter, pCreateInfo->anisotropyEnable), + .MinModeFilter = vk_to_gen_tex_filter(min_filter, pCreateInfo->anisotropyEnable), .TextureLODBias = anv_clamp_f(pCreateInfo->mipLodBias, -16, 15.996), .AnisotropicAlgorithm = EWAApproximation, .MinLOD = anv_clamp_f(pCreateInfo->minLod, 0, 14), -- 2.30.2