From 4de305cb8a3c68df8e89f8c1359f510a1089cfd3 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 7 Mar 2023 16:20:25 +0100 Subject: [PATCH] radv: move sampler related code to radv_sampler.c radv_device.c is getting too big and this follows the Vulkan common runtime infrastructure. Signed-off-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/meson.build | 1 + src/amd/vulkan/radv_device.c | 300 -------------------------------------- src/amd/vulkan/radv_sampler.c | 328 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 329 insertions(+), 300 deletions(-) create mode 100644 src/amd/vulkan/radv_sampler.c diff --git a/src/amd/vulkan/meson.build b/src/amd/vulkan/meson.build index 90ee3b6..8e65e34 100644 --- a/src/amd/vulkan/meson.build +++ b/src/amd/vulkan/meson.build @@ -106,6 +106,7 @@ libradv_files = files( 'radv_rra.c', 'radv_rt_common.c', 'radv_rt_shader.c', + 'radv_sampler.c', 'radv_sdma_copy_image.c', 'radv_shader.c', 'radv_shader.h', diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index d134247..7151283 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -2611,306 +2611,6 @@ radv_initialise_ds_surface(struct radv_device *device, struct radv_ds_buffer_inf ds->db_stencil_read_base = ds->db_stencil_write_base = s_offs >> 8; } -static unsigned -radv_tex_wrap(VkSamplerAddressMode address_mode) -{ - switch (address_mode) { - case VK_SAMPLER_ADDRESS_MODE_REPEAT: - return V_008F30_SQ_TEX_WRAP; - case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: - return V_008F30_SQ_TEX_MIRROR; - case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: - return V_008F30_SQ_TEX_CLAMP_LAST_TEXEL; - case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: - return V_008F30_SQ_TEX_CLAMP_BORDER; - case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: - return V_008F30_SQ_TEX_MIRROR_ONCE_LAST_TEXEL; - default: - unreachable("illegal tex wrap mode"); - break; - } -} - -static unsigned -radv_tex_compare(VkCompareOp op) -{ - switch (op) { - case VK_COMPARE_OP_NEVER: - return V_008F30_SQ_TEX_DEPTH_COMPARE_NEVER; - case VK_COMPARE_OP_LESS: - return V_008F30_SQ_TEX_DEPTH_COMPARE_LESS; - case VK_COMPARE_OP_EQUAL: - return V_008F30_SQ_TEX_DEPTH_COMPARE_EQUAL; - case VK_COMPARE_OP_LESS_OR_EQUAL: - return V_008F30_SQ_TEX_DEPTH_COMPARE_LESSEQUAL; - case VK_COMPARE_OP_GREATER: - return V_008F30_SQ_TEX_DEPTH_COMPARE_GREATER; - case VK_COMPARE_OP_NOT_EQUAL: - return V_008F30_SQ_TEX_DEPTH_COMPARE_NOTEQUAL; - case VK_COMPARE_OP_GREATER_OR_EQUAL: - return V_008F30_SQ_TEX_DEPTH_COMPARE_GREATEREQUAL; - case VK_COMPARE_OP_ALWAYS: - return V_008F30_SQ_TEX_DEPTH_COMPARE_ALWAYS; - default: - unreachable("illegal compare mode"); - break; - } -} - -static unsigned -radv_tex_filter(VkFilter filter, unsigned max_ansio) -{ - switch (filter) { - case VK_FILTER_NEAREST: - return (max_ansio > 1 ? V_008F38_SQ_TEX_XY_FILTER_ANISO_POINT - : V_008F38_SQ_TEX_XY_FILTER_POINT); - case VK_FILTER_LINEAR: - return (max_ansio > 1 ? V_008F38_SQ_TEX_XY_FILTER_ANISO_BILINEAR - : V_008F38_SQ_TEX_XY_FILTER_BILINEAR); - case VK_FILTER_CUBIC_EXT: - default: - fprintf(stderr, "illegal texture filter"); - return 0; - } -} - -static unsigned -radv_tex_mipfilter(VkSamplerMipmapMode mode) -{ - switch (mode) { - case VK_SAMPLER_MIPMAP_MODE_NEAREST: - return V_008F38_SQ_TEX_Z_FILTER_POINT; - case VK_SAMPLER_MIPMAP_MODE_LINEAR: - return V_008F38_SQ_TEX_Z_FILTER_LINEAR; - default: - return V_008F38_SQ_TEX_Z_FILTER_NONE; - } -} - -static unsigned -radv_tex_bordercolor(VkBorderColor bcolor) -{ - switch (bcolor) { - case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: - case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: - return V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK; - case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: - case VK_BORDER_COLOR_INT_OPAQUE_BLACK: - return V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_BLACK; - case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: - case VK_BORDER_COLOR_INT_OPAQUE_WHITE: - return V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE; - case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT: - case VK_BORDER_COLOR_INT_CUSTOM_EXT: - return V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER; - default: - break; - } - return 0; -} - -static unsigned -radv_tex_aniso_filter(unsigned filter) -{ - return MIN2(util_logbase2(filter), 4); -} - -static unsigned -radv_tex_filter_mode(VkSamplerReductionMode mode) -{ - switch (mode) { - case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE: - return V_008F30_SQ_IMG_FILTER_MODE_BLEND; - case VK_SAMPLER_REDUCTION_MODE_MIN: - return V_008F30_SQ_IMG_FILTER_MODE_MIN; - case VK_SAMPLER_REDUCTION_MODE_MAX: - return V_008F30_SQ_IMG_FILTER_MODE_MAX; - default: - break; - } - return 0; -} - -static uint32_t -radv_get_max_anisotropy(struct radv_device *device, const VkSamplerCreateInfo *pCreateInfo) -{ - if (device->force_aniso >= 0) - return device->force_aniso; - - if (pCreateInfo->anisotropyEnable && pCreateInfo->maxAnisotropy > 1.0f) - return (uint32_t)pCreateInfo->maxAnisotropy; - - return 0; -} - -static uint32_t -radv_register_border_color(struct radv_device *device, VkClearColorValue value) -{ - uint32_t slot; - - mtx_lock(&device->border_color_data.mutex); - - for (slot = 0; slot < RADV_BORDER_COLOR_COUNT; slot++) { - if (!device->border_color_data.used[slot]) { - /* Copy to the GPU wrt endian-ness. */ - util_memcpy_cpu_to_le32(&device->border_color_data.colors_gpu_ptr[slot], &value, - sizeof(VkClearColorValue)); - - device->border_color_data.used[slot] = true; - break; - } - } - - mtx_unlock(&device->border_color_data.mutex); - - return slot; -} - -static void -radv_unregister_border_color(struct radv_device *device, uint32_t slot) -{ - mtx_lock(&device->border_color_data.mutex); - - device->border_color_data.used[slot] = false; - - mtx_unlock(&device->border_color_data.mutex); -} - -static void -radv_init_sampler(struct radv_device *device, struct radv_sampler *sampler, - const VkSamplerCreateInfo *pCreateInfo) -{ - uint32_t max_aniso = radv_get_max_anisotropy(device, pCreateInfo); - uint32_t max_aniso_ratio = radv_tex_aniso_filter(max_aniso); - bool compat_mode = device->physical_device->rad_info.gfx_level == GFX8 || - device->physical_device->rad_info.gfx_level == GFX9; - unsigned filter_mode = V_008F30_SQ_IMG_FILTER_MODE_BLEND; - unsigned depth_compare_func = V_008F30_SQ_TEX_DEPTH_COMPARE_NEVER; - bool trunc_coord = - (pCreateInfo->minFilter == VK_FILTER_NEAREST && pCreateInfo->magFilter == VK_FILTER_NEAREST) || - device->physical_device->rad_info.conformant_trunc_coord; - bool uses_border_color = pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER || - pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER || - pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; - VkBorderColor border_color = - uses_border_color ? pCreateInfo->borderColor : VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - uint32_t border_color_ptr; - bool disable_cube_wrap = pCreateInfo->flags & VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT; - - const struct VkSamplerReductionModeCreateInfo *sampler_reduction = - vk_find_struct_const(pCreateInfo->pNext, SAMPLER_REDUCTION_MODE_CREATE_INFO); - if (sampler_reduction) - filter_mode = radv_tex_filter_mode(sampler_reduction->reductionMode); - - if (pCreateInfo->compareEnable) - depth_compare_func = radv_tex_compare(pCreateInfo->compareOp); - - sampler->border_color_slot = RADV_BORDER_COLOR_COUNT; - - if (border_color == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT || - border_color == VK_BORDER_COLOR_INT_CUSTOM_EXT) { - const VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color = - vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT); - - assert(custom_border_color); - - sampler->border_color_slot = - radv_register_border_color(device, custom_border_color->customBorderColor); - - /* Did we fail to find a slot? */ - if (sampler->border_color_slot == RADV_BORDER_COLOR_COUNT) { - fprintf(stderr, "WARNING: no free border color slots, defaulting to TRANS_BLACK.\n"); - border_color = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - } - } - - /* If we don't have a custom color, set the ptr to 0 */ - border_color_ptr = - sampler->border_color_slot != RADV_BORDER_COLOR_COUNT ? sampler->border_color_slot : 0; - - sampler->state[0] = - (S_008F30_CLAMP_X(radv_tex_wrap(pCreateInfo->addressModeU)) | - S_008F30_CLAMP_Y(radv_tex_wrap(pCreateInfo->addressModeV)) | - S_008F30_CLAMP_Z(radv_tex_wrap(pCreateInfo->addressModeW)) | - S_008F30_MAX_ANISO_RATIO(max_aniso_ratio) | S_008F30_DEPTH_COMPARE_FUNC(depth_compare_func) | - S_008F30_FORCE_UNNORMALIZED(pCreateInfo->unnormalizedCoordinates ? 1 : 0) | - S_008F30_ANISO_THRESHOLD(max_aniso_ratio >> 1) | S_008F30_ANISO_BIAS(max_aniso_ratio) | - S_008F30_DISABLE_CUBE_WRAP(disable_cube_wrap) | S_008F30_COMPAT_MODE(compat_mode) | - S_008F30_FILTER_MODE(filter_mode) | S_008F30_TRUNC_COORD(trunc_coord)); - sampler->state[1] = (S_008F34_MIN_LOD(radv_float_to_ufixed(CLAMP(pCreateInfo->minLod, 0, 15), 8)) | - S_008F34_MAX_LOD(radv_float_to_ufixed(CLAMP(pCreateInfo->maxLod, 0, 15), 8)) | - S_008F34_PERF_MIP(max_aniso_ratio ? max_aniso_ratio + 6 : 0)); - sampler->state[2] = (S_008F38_XY_MAG_FILTER(radv_tex_filter(pCreateInfo->magFilter, max_aniso)) | - S_008F38_XY_MIN_FILTER(radv_tex_filter(pCreateInfo->minFilter, max_aniso)) | - S_008F38_MIP_FILTER(radv_tex_mipfilter(pCreateInfo->mipmapMode))); - sampler->state[3] = S_008F3C_BORDER_COLOR_TYPE(radv_tex_bordercolor(border_color)); - - if (device->physical_device->rad_info.gfx_level >= GFX10) { - sampler->state[2] |= - S_008F38_LOD_BIAS(radv_float_to_sfixed(CLAMP(pCreateInfo->mipLodBias, -32, 31), 8)) | - S_008F38_ANISO_OVERRIDE_GFX10(device->instance->disable_aniso_single_level); - } else { - sampler->state[2] |= - S_008F38_LOD_BIAS(radv_float_to_sfixed(CLAMP(pCreateInfo->mipLodBias, -16, 16), 8)) | - S_008F38_DISABLE_LSB_CEIL(device->physical_device->rad_info.gfx_level <= GFX8) | - S_008F38_FILTER_PREC_FIX(1) | - S_008F38_ANISO_OVERRIDE_GFX8(device->instance->disable_aniso_single_level && - device->physical_device->rad_info.gfx_level >= GFX8); - } - - if (device->physical_device->rad_info.gfx_level >= GFX11) { - sampler->state[3] |= S_008F3C_BORDER_COLOR_PTR_GFX11(border_color_ptr); - } else { - sampler->state[3] |= S_008F3C_BORDER_COLOR_PTR_GFX6(border_color_ptr); - } -} - -VKAPI_ATTR VkResult VKAPI_CALL -radv_CreateSampler(VkDevice _device, const VkSamplerCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) -{ - RADV_FROM_HANDLE(radv_device, device, _device); - struct radv_sampler *sampler; - - const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion = - vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO); - - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); - - sampler = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*sampler), 8, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (!sampler) - return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - - vk_object_base_init(&device->vk, &sampler->base, VK_OBJECT_TYPE_SAMPLER); - - radv_init_sampler(device, sampler, pCreateInfo); - - sampler->ycbcr_sampler = - ycbcr_conversion ? vk_ycbcr_conversion_from_handle(ycbcr_conversion->conversion) : NULL; - *pSampler = radv_sampler_to_handle(sampler); - - return VK_SUCCESS; -} - -VKAPI_ATTR void VKAPI_CALL -radv_DestroySampler(VkDevice _device, VkSampler _sampler, const VkAllocationCallbacks *pAllocator) -{ - RADV_FROM_HANDLE(radv_device, device, _device); - RADV_FROM_HANDLE(radv_sampler, sampler, _sampler); - - if (!sampler) - return; - - if (sampler->border_color_slot != RADV_BORDER_COLOR_COUNT) - radv_unregister_border_color(device, sampler->border_color_slot); - - vk_object_base_finish(&sampler->base); - vk_free2(&device->vk.alloc, pAllocator, sampler); -} - - - VKAPI_ATTR VkResult VKAPI_CALL radv_GetMemoryFdKHR(VkDevice _device, const VkMemoryGetFdInfoKHR *pGetFdInfo, int *pFD) { diff --git a/src/amd/vulkan/radv_sampler.c b/src/amd/vulkan/radv_sampler.c new file mode 100644 index 0000000..79ab83d --- /dev/null +++ b/src/amd/vulkan/radv_sampler.c @@ -0,0 +1,328 @@ +/* + * Copyright © 2016 Red Hat. + * Copyright © 2016 Bas Nieuwenhuizen + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "radv_private.h" + +#include "vk_sampler.h" + +static unsigned +radv_tex_wrap(VkSamplerAddressMode address_mode) +{ + switch (address_mode) { + case VK_SAMPLER_ADDRESS_MODE_REPEAT: + return V_008F30_SQ_TEX_WRAP; + case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: + return V_008F30_SQ_TEX_MIRROR; + case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: + return V_008F30_SQ_TEX_CLAMP_LAST_TEXEL; + case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: + return V_008F30_SQ_TEX_CLAMP_BORDER; + case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: + return V_008F30_SQ_TEX_MIRROR_ONCE_LAST_TEXEL; + default: + unreachable("illegal tex wrap mode"); + break; + } +} + +static unsigned +radv_tex_compare(VkCompareOp op) +{ + switch (op) { + case VK_COMPARE_OP_NEVER: + return V_008F30_SQ_TEX_DEPTH_COMPARE_NEVER; + case VK_COMPARE_OP_LESS: + return V_008F30_SQ_TEX_DEPTH_COMPARE_LESS; + case VK_COMPARE_OP_EQUAL: + return V_008F30_SQ_TEX_DEPTH_COMPARE_EQUAL; + case VK_COMPARE_OP_LESS_OR_EQUAL: + return V_008F30_SQ_TEX_DEPTH_COMPARE_LESSEQUAL; + case VK_COMPARE_OP_GREATER: + return V_008F30_SQ_TEX_DEPTH_COMPARE_GREATER; + case VK_COMPARE_OP_NOT_EQUAL: + return V_008F30_SQ_TEX_DEPTH_COMPARE_NOTEQUAL; + case VK_COMPARE_OP_GREATER_OR_EQUAL: + return V_008F30_SQ_TEX_DEPTH_COMPARE_GREATEREQUAL; + case VK_COMPARE_OP_ALWAYS: + return V_008F30_SQ_TEX_DEPTH_COMPARE_ALWAYS; + default: + unreachable("illegal compare mode"); + break; + } +} + +static unsigned +radv_tex_filter(VkFilter filter, unsigned max_ansio) +{ + switch (filter) { + case VK_FILTER_NEAREST: + return (max_ansio > 1 ? V_008F38_SQ_TEX_XY_FILTER_ANISO_POINT + : V_008F38_SQ_TEX_XY_FILTER_POINT); + case VK_FILTER_LINEAR: + return (max_ansio > 1 ? V_008F38_SQ_TEX_XY_FILTER_ANISO_BILINEAR + : V_008F38_SQ_TEX_XY_FILTER_BILINEAR); + case VK_FILTER_CUBIC_EXT: + default: + fprintf(stderr, "illegal texture filter"); + return 0; + } +} + +static unsigned +radv_tex_mipfilter(VkSamplerMipmapMode mode) +{ + switch (mode) { + case VK_SAMPLER_MIPMAP_MODE_NEAREST: + return V_008F38_SQ_TEX_Z_FILTER_POINT; + case VK_SAMPLER_MIPMAP_MODE_LINEAR: + return V_008F38_SQ_TEX_Z_FILTER_LINEAR; + default: + return V_008F38_SQ_TEX_Z_FILTER_NONE; + } +} + +static unsigned +radv_tex_bordercolor(VkBorderColor bcolor) +{ + switch (bcolor) { + case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: + case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: + return V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK; + case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: + case VK_BORDER_COLOR_INT_OPAQUE_BLACK: + return V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_BLACK; + case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: + case VK_BORDER_COLOR_INT_OPAQUE_WHITE: + return V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE; + case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT: + case VK_BORDER_COLOR_INT_CUSTOM_EXT: + return V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER; + default: + break; + } + return 0; +} + +static unsigned +radv_tex_aniso_filter(unsigned filter) +{ + return MIN2(util_logbase2(filter), 4); +} + +static unsigned +radv_tex_filter_mode(VkSamplerReductionMode mode) +{ + switch (mode) { + case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE: + return V_008F30_SQ_IMG_FILTER_MODE_BLEND; + case VK_SAMPLER_REDUCTION_MODE_MIN: + return V_008F30_SQ_IMG_FILTER_MODE_MIN; + case VK_SAMPLER_REDUCTION_MODE_MAX: + return V_008F30_SQ_IMG_FILTER_MODE_MAX; + default: + break; + } + return 0; +} + +static uint32_t +radv_get_max_anisotropy(struct radv_device *device, const VkSamplerCreateInfo *pCreateInfo) +{ + if (device->force_aniso >= 0) + return device->force_aniso; + + if (pCreateInfo->anisotropyEnable && pCreateInfo->maxAnisotropy > 1.0f) + return (uint32_t)pCreateInfo->maxAnisotropy; + + return 0; +} + +static uint32_t +radv_register_border_color(struct radv_device *device, VkClearColorValue value) +{ + uint32_t slot; + + mtx_lock(&device->border_color_data.mutex); + + for (slot = 0; slot < RADV_BORDER_COLOR_COUNT; slot++) { + if (!device->border_color_data.used[slot]) { + /* Copy to the GPU wrt endian-ness. */ + util_memcpy_cpu_to_le32(&device->border_color_data.colors_gpu_ptr[slot], &value, + sizeof(VkClearColorValue)); + + device->border_color_data.used[slot] = true; + break; + } + } + + mtx_unlock(&device->border_color_data.mutex); + + return slot; +} + +static void +radv_unregister_border_color(struct radv_device *device, uint32_t slot) +{ + mtx_lock(&device->border_color_data.mutex); + + device->border_color_data.used[slot] = false; + + mtx_unlock(&device->border_color_data.mutex); +} + +static void +radv_init_sampler(struct radv_device *device, struct radv_sampler *sampler, + const VkSamplerCreateInfo *pCreateInfo) +{ + uint32_t max_aniso = radv_get_max_anisotropy(device, pCreateInfo); + uint32_t max_aniso_ratio = radv_tex_aniso_filter(max_aniso); + bool compat_mode = device->physical_device->rad_info.gfx_level == GFX8 || + device->physical_device->rad_info.gfx_level == GFX9; + unsigned filter_mode = V_008F30_SQ_IMG_FILTER_MODE_BLEND; + unsigned depth_compare_func = V_008F30_SQ_TEX_DEPTH_COMPARE_NEVER; + bool trunc_coord = + (pCreateInfo->minFilter == VK_FILTER_NEAREST && pCreateInfo->magFilter == VK_FILTER_NEAREST) || + device->physical_device->rad_info.conformant_trunc_coord; + bool uses_border_color = pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER || + pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER || + pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + VkBorderColor border_color = + uses_border_color ? pCreateInfo->borderColor : VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + uint32_t border_color_ptr; + bool disable_cube_wrap = pCreateInfo->flags & VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT; + + const struct VkSamplerReductionModeCreateInfo *sampler_reduction = + vk_find_struct_const(pCreateInfo->pNext, SAMPLER_REDUCTION_MODE_CREATE_INFO); + if (sampler_reduction) + filter_mode = radv_tex_filter_mode(sampler_reduction->reductionMode); + + if (pCreateInfo->compareEnable) + depth_compare_func = radv_tex_compare(pCreateInfo->compareOp); + + sampler->border_color_slot = RADV_BORDER_COLOR_COUNT; + + if (border_color == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT || + border_color == VK_BORDER_COLOR_INT_CUSTOM_EXT) { + const VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color = + vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT); + + assert(custom_border_color); + + sampler->border_color_slot = + radv_register_border_color(device, custom_border_color->customBorderColor); + + /* Did we fail to find a slot? */ + if (sampler->border_color_slot == RADV_BORDER_COLOR_COUNT) { + fprintf(stderr, "WARNING: no free border color slots, defaulting to TRANS_BLACK.\n"); + border_color = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + } + } + + /* If we don't have a custom color, set the ptr to 0 */ + border_color_ptr = + sampler->border_color_slot != RADV_BORDER_COLOR_COUNT ? sampler->border_color_slot : 0; + + sampler->state[0] = + (S_008F30_CLAMP_X(radv_tex_wrap(pCreateInfo->addressModeU)) | + S_008F30_CLAMP_Y(radv_tex_wrap(pCreateInfo->addressModeV)) | + S_008F30_CLAMP_Z(radv_tex_wrap(pCreateInfo->addressModeW)) | + S_008F30_MAX_ANISO_RATIO(max_aniso_ratio) | S_008F30_DEPTH_COMPARE_FUNC(depth_compare_func) | + S_008F30_FORCE_UNNORMALIZED(pCreateInfo->unnormalizedCoordinates ? 1 : 0) | + S_008F30_ANISO_THRESHOLD(max_aniso_ratio >> 1) | S_008F30_ANISO_BIAS(max_aniso_ratio) | + S_008F30_DISABLE_CUBE_WRAP(disable_cube_wrap) | S_008F30_COMPAT_MODE(compat_mode) | + S_008F30_FILTER_MODE(filter_mode) | S_008F30_TRUNC_COORD(trunc_coord)); + sampler->state[1] = (S_008F34_MIN_LOD(radv_float_to_ufixed(CLAMP(pCreateInfo->minLod, 0, 15), 8)) | + S_008F34_MAX_LOD(radv_float_to_ufixed(CLAMP(pCreateInfo->maxLod, 0, 15), 8)) | + S_008F34_PERF_MIP(max_aniso_ratio ? max_aniso_ratio + 6 : 0)); + sampler->state[2] = (S_008F38_XY_MAG_FILTER(radv_tex_filter(pCreateInfo->magFilter, max_aniso)) | + S_008F38_XY_MIN_FILTER(radv_tex_filter(pCreateInfo->minFilter, max_aniso)) | + S_008F38_MIP_FILTER(radv_tex_mipfilter(pCreateInfo->mipmapMode))); + sampler->state[3] = S_008F3C_BORDER_COLOR_TYPE(radv_tex_bordercolor(border_color)); + + if (device->physical_device->rad_info.gfx_level >= GFX10) { + sampler->state[2] |= + S_008F38_LOD_BIAS(radv_float_to_sfixed(CLAMP(pCreateInfo->mipLodBias, -32, 31), 8)) | + S_008F38_ANISO_OVERRIDE_GFX10(device->instance->disable_aniso_single_level); + } else { + sampler->state[2] |= + S_008F38_LOD_BIAS(radv_float_to_sfixed(CLAMP(pCreateInfo->mipLodBias, -16, 16), 8)) | + S_008F38_DISABLE_LSB_CEIL(device->physical_device->rad_info.gfx_level <= GFX8) | + S_008F38_FILTER_PREC_FIX(1) | + S_008F38_ANISO_OVERRIDE_GFX8(device->instance->disable_aniso_single_level && + device->physical_device->rad_info.gfx_level >= GFX8); + } + + if (device->physical_device->rad_info.gfx_level >= GFX11) { + sampler->state[3] |= S_008F3C_BORDER_COLOR_PTR_GFX11(border_color_ptr); + } else { + sampler->state[3] |= S_008F3C_BORDER_COLOR_PTR_GFX6(border_color_ptr); + } +} + +VKAPI_ATTR VkResult VKAPI_CALL +radv_CreateSampler(VkDevice _device, const VkSamplerCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) +{ + RADV_FROM_HANDLE(radv_device, device, _device); + struct radv_sampler *sampler; + + const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion = + vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO); + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); + + sampler = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*sampler), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!sampler) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + vk_object_base_init(&device->vk, &sampler->base, VK_OBJECT_TYPE_SAMPLER); + + radv_init_sampler(device, sampler, pCreateInfo); + + sampler->ycbcr_sampler = + ycbcr_conversion ? vk_ycbcr_conversion_from_handle(ycbcr_conversion->conversion) : NULL; + *pSampler = radv_sampler_to_handle(sampler); + + return VK_SUCCESS; +} + +VKAPI_ATTR void VKAPI_CALL +radv_DestroySampler(VkDevice _device, VkSampler _sampler, const VkAllocationCallbacks *pAllocator) +{ + RADV_FROM_HANDLE(radv_device, device, _device); + RADV_FROM_HANDLE(radv_sampler, sampler, _sampler); + + if (!sampler) + return; + + if (sampler->border_color_slot != RADV_BORDER_COLOR_COUNT) + radv_unregister_border_color(device, sampler->border_color_slot); + + vk_object_base_finish(&sampler->base); + vk_free2(&device->vk.alloc, pAllocator, sampler); +} -- 2.7.4