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 <lionel.g.landwerlin@intel.com> Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>tags/17.3-branchpoint
@@ -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<<i` is set | |||
* if and only if the memory type `i` in the | |||
* VkPhysicalDeviceMemoryProperties structure for the physical | |||
* device is supported. | |||
* | |||
* All types are currently supported for images. | |||
*/ | |||
pMemoryRequirements->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: { |
@@ -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'), |
@@ -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); | |||
} |
@@ -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, |
@@ -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 |
@@ -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), |