diff --git a/src/vulkan/runtime/vk_sampler.c b/src/vulkan/runtime/vk_sampler.c index 30373e03521..bda852ebf90 100644 --- a/src/vulkan/runtime/vk_sampler.c +++ b/src/vulkan/runtime/vk_sampler.c @@ -22,7 +22,10 @@ */ #include "vk_sampler.h" + +#include "vk_format.h" #include "vk_util.h" +#include "vk_ycbcr_conversion.h" VkClearColorValue vk_border_color_value(VkBorderColor color) @@ -68,8 +71,7 @@ VkClearColorValue vk_sampler_border_color_value(const VkSamplerCreateInfo *pCreateInfo, VkFormat *format_out) { - if (pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT || - pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT) { + if (vk_border_color_is_custom(pCreateInfo->borderColor)) { const VkSamplerCustomBorderColorCreateInfoEXT *border_color_info = vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT); @@ -85,3 +87,83 @@ vk_sampler_border_color_value(const VkSamplerCreateInfo *pCreateInfo, } } +void * +vk_sampler_create(struct vk_device *device, + const VkSamplerCreateInfo *pCreateInfo, + const VkAllocationCallbacks *alloc, + size_t size) +{ + struct vk_sampler *sampler; + + sampler = vk_object_zalloc(device, alloc, size, VK_OBJECT_TYPE_SAMPLER); + if (!sampler) + return NULL; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); + + sampler->format = VK_FORMAT_UNDEFINED; + sampler->border_color = pCreateInfo->borderColor; + sampler->reduction_mode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; + + if (!vk_border_color_is_custom(pCreateInfo->borderColor)) { + sampler->border_color_value = + vk_border_color_value(pCreateInfo->borderColor); + } + + vk_foreach_struct_const(ext, pCreateInfo->pNext) { + switch (ext->sType) { + case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT: { + const VkSamplerCustomBorderColorCreateInfoEXT *cbc_info = (void *)ext; + if (!vk_border_color_is_custom(pCreateInfo->borderColor)) + break; + + sampler->border_color_value = cbc_info->customBorderColor; + if (cbc_info->format != VK_FORMAT_UNDEFINED) + sampler->format = cbc_info->format; + break; + } + + case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO: { + const VkSamplerReductionModeCreateInfo *rm_info = (void *)ext; + sampler->reduction_mode = rm_info->reductionMode; + break; + } + + case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO: { + const VkSamplerYcbcrConversionInfo *yc_info = (void *)ext; + VK_FROM_HANDLE(vk_ycbcr_conversion, conversion, yc_info->conversion); + + /* From the Vulkan 1.2.259 spec: + * + * "A VkSamplerYcbcrConversionInfo must be provided for samplers + * to be used with image views that access + * VK_IMAGE_ASPECT_COLOR_BIT if the format is one of the formats + * that require a sampler YCbCr conversion, or if the image view + * has an external format." + * + * This means that on Android we can end up with one of these even if + * YCbCr isn't being used at all. Leave sampler->ycbcr_conversion NULL + * if it isn't a YCbCr format. + */ + if (vk_format_get_ycbcr_info(conversion->state.format) == NULL) + break; + + sampler->ycbcr_conversion = conversion; + sampler->format = conversion->state.format; + break; + } + default: + break; + } + } + + return sampler; +} + +void +vk_sampler_destroy(struct vk_device *device, + const VkAllocationCallbacks *alloc, + struct vk_sampler *sampler) +{ + vk_object_free(device, alloc, sampler); +} diff --git a/src/vulkan/runtime/vk_sampler.h b/src/vulkan/runtime/vk_sampler.h index 82c4f07cc85..541b02916c2 100644 --- a/src/vulkan/runtime/vk_sampler.h +++ b/src/vulkan/runtime/vk_sampler.h @@ -23,14 +23,19 @@ #ifndef VK_SAMPLER_H #define VK_SAMPLER_H -#include - -#include "vulkan/vulkan_core.h" +#include "vk_object.h" #ifdef __cplusplus extern "C" { #endif +static inline bool +vk_border_color_is_custom(VkBorderColor color) +{ + return color == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT || + color == VK_BORDER_COLOR_INT_CUSTOM_EXT; +} + VkClearColorValue vk_border_color_value(VkBorderColor color); bool vk_border_color_is_int(VkBorderColor color); @@ -38,6 +43,54 @@ VkClearColorValue vk_sampler_border_color_value(const VkSamplerCreateInfo *pCreateInfo, VkFormat *format_out); +struct vk_sampler { + struct vk_object_base base; + + /** Format of paired image views or VK_FORMAT_UNDEFINED + * + * This is taken either from VkSamplerYcbcrConversionCreateInfo::format or + * VkSamplerCustomBorderColorCreateInfoEXT::format. + */ + VkFormat format; + + /** VkSamplerCreateInfo::borderColor */ + VkBorderColor border_color; + + /** Border color value + * + * If VkSamplerCreateInfo::borderColor is one of the Vulkan 1.0 enumerated + * border colors, this will be the VkClearColorValue representation of that + * value. VkSamplerCreateInfo::borderColor is VK_BORDER_COLOR_*_CUSTOM_EXT, + * this is VkSamplerCustomBorderColorCreateInfoEXT::customBorderColor. + */ + VkClearColorValue border_color_value; + + /** + * VkSamplerReductionModeCreateInfo::reductionMode or + * VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE. + */ + VkSamplerReductionMode reduction_mode; + + /** VkSamplerYcbcrConversionInfo::conversion or NULL + * + * We ensure that this is always NULL whenever vk_sampler::format is not a + * YCbCr format. This is important on Android where YCbCr conversion + * objects are required for all EXTERNAL formats, even if they are not + * YCbCr formats. + */ + struct vk_ycbcr_conversion *ycbcr_conversion; +}; +VK_DEFINE_NONDISP_HANDLE_CASTS(vk_sampler, base, VkSampler, + VK_OBJECT_TYPE_SAMPLER); + +void *vk_sampler_create(struct vk_device *device, + const VkSamplerCreateInfo *pCreateInfo, + const VkAllocationCallbacks *alloc, + size_t size); +void vk_sampler_destroy(struct vk_device *device, + const VkAllocationCallbacks *alloc, + struct vk_sampler *sampler); + #ifdef __cplusplus } #endif