diff --git a/src/panfrost/vulkan/panvk_vX_sampler.c b/src/panfrost/vulkan/panvk_vX_sampler.c index 996a8875fce..c458e9e0d1b 100644 --- a/src/panfrost/vulkan/panvk_vX_sampler.c +++ b/src/panfrost/vulkan/panvk_vX_sampler.c @@ -56,6 +56,23 @@ panvk_translate_sampler_compare_func(const VkSamplerCreateInfo *pCreateInfo) return panfrost_flip_compare_func((enum mali_func)pCreateInfo->compareOp); } +#if PAN_ARCH >= 10 +static enum mali_reduction_mode +panvk_translate_reduction_mode(VkSamplerReductionMode reduction_mode) +{ + switch (reduction_mode) { + case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE: + return MALI_REDUCTION_MODE_AVERAGE; + case VK_SAMPLER_REDUCTION_MODE_MIN: + return MALI_REDUCTION_MODE_MINIMUM; + case VK_SAMPLER_REDUCTION_MODE_MAX: + return MALI_REDUCTION_MODE_MAXIMUM; + default: + unreachable("Invalid reduction mode"); + } +} +#endif + #if PAN_ARCH == 7 static void panvk_afbc_reswizzle_border_color(VkClearColorValue *border_color, VkFormat fmt) @@ -79,6 +96,79 @@ panvk_afbc_reswizzle_border_color(VkClearColorValue *border_color, VkFormat fmt) } #endif +static void +panvk_sampler_fill_desc(const struct VkSamplerCreateInfo *info, + struct mali_sampler_packed *desc, + VkClearColorValue border_color, + VkFilter min_filter, VkFilter mag_filter, + VkSamplerReductionMode reduction_mode) +{ + pan_pack(desc, SAMPLER, cfg) { + cfg.magnify_nearest = mag_filter == VK_FILTER_NEAREST; + cfg.minify_nearest = min_filter == VK_FILTER_NEAREST; + cfg.mipmap_mode = + panvk_translate_sampler_mipmap_mode(info->mipmapMode); + cfg.normalized_coordinates = !info->unnormalizedCoordinates; + cfg.clamp_integer_array_indices = false; + + /* Normalized float texture coordinates are rounded to fixed-point + * before rounding to integer coordinates. When round_to_nearest_even is + * enabled with VK_FILTER_NEAREST, the upper 2^-9 float coordinates in + * each texel are rounded up to the next texel. + * + * The Vulkan 1.4.304 spec seems to allow both rounding modes for all + * filters, but a CTS bug[1] causes test failures when round-to-nearest + * is used with VK_FILTER_NEAREST. + * + * Regardless, disabling round_to_nearest_even for NEAREST filters + * is a desirable precision improvement. + * + * [1]: https://gitlab.khronos.org/Tracker/vk-gl-cts/-/issues/5547 + */ + if (min_filter == VK_FILTER_NEAREST && + mag_filter == VK_FILTER_NEAREST) + cfg.round_to_nearest_even = false; + + cfg.lod_bias = info->mipLodBias; + cfg.minimum_lod = info->minLod; + cfg.maximum_lod = info->maxLod; + cfg.wrap_mode_s = + panvk_translate_sampler_address_mode(info->addressModeU); + cfg.wrap_mode_t = + panvk_translate_sampler_address_mode(info->addressModeV); + + /* " + * When unnormalizedCoordinates is VK_TRUE, images the sampler is used + * with in the shader have the following requirements: + * - The viewType must be either VK_IMAGE_VIEW_TYPE_1D or + * VK_IMAGE_VIEW_TYPE_2D. + * - The image view must have a single layer and a single mip level. + * " + * + * This means addressModeW should be ignored. We pick a default value + * that works for normalized_coordinates=false. + */ + cfg.wrap_mode_r = + info->unnormalizedCoordinates + ? MALI_WRAP_MODE_CLAMP_TO_EDGE + : panvk_translate_sampler_address_mode(info->addressModeW); + cfg.compare_function = panvk_translate_sampler_compare_func(info); + cfg.border_color_r = border_color.uint32[0]; + cfg.border_color_g = border_color.uint32[1]; + cfg.border_color_b = border_color.uint32[2]; + cfg.border_color_a = border_color.uint32[3]; + + if (info->anisotropyEnable && info->maxAnisotropy > 1) { + cfg.maximum_anisotropy = info->maxAnisotropy; + cfg.lod_algorithm = MALI_LOD_ALGORITHM_ANISOTROPIC; + } + +#if PAN_ARCH >= 10 + cfg.reduction_mode = panvk_translate_reduction_mode(reduction_mode); +#endif + } +} + VKAPI_ATTR VkResult VKAPI_CALL panvk_per_arch(CreateSampler)(VkDevice _device, const VkSamplerCreateInfo *pCreateInfo, @@ -105,82 +195,9 @@ panvk_per_arch(CreateSampler)(VkDevice _device, panvk_afbc_reswizzle_border_color(&border_color, fmt); #endif - pan_pack(&sampler->desc, SAMPLER, cfg) { - cfg.magnify_nearest = pCreateInfo->magFilter == VK_FILTER_NEAREST; - cfg.minify_nearest = pCreateInfo->minFilter == VK_FILTER_NEAREST; - cfg.mipmap_mode = - panvk_translate_sampler_mipmap_mode(pCreateInfo->mipmapMode); - cfg.normalized_coordinates = !pCreateInfo->unnormalizedCoordinates; - cfg.clamp_integer_array_indices = false; - - /* Normalized float texture coordinates are rounded to fixed-point - * before rounding to integer coordinates. When round_to_nearest_even is - * enabled with VK_FILTER_NEAREST, the upper 2^-9 float coordinates in - * each texel are rounded up to the next texel. - * - * The Vulkan 1.4.304 spec seems to allow both rounding modes for all - * filters, but a CTS bug[1] causes test failures when round-to-nearest - * is used with VK_FILTER_NEAREST. - * - * Regardless, disabling round_to_nearest_even for NEAREST filters - * is a desirable precision improvement. - * - * [1]: https://gitlab.khronos.org/Tracker/vk-gl-cts/-/issues/5547 - */ - if (pCreateInfo->minFilter == VK_FILTER_NEAREST && - pCreateInfo->magFilter == VK_FILTER_NEAREST) - cfg.round_to_nearest_even = false; - - cfg.lod_bias = pCreateInfo->mipLodBias; - cfg.minimum_lod = pCreateInfo->minLod; - cfg.maximum_lod = pCreateInfo->maxLod; - cfg.wrap_mode_s = - panvk_translate_sampler_address_mode(pCreateInfo->addressModeU); - cfg.wrap_mode_t = - panvk_translate_sampler_address_mode(pCreateInfo->addressModeV); - - /* " - * When unnormalizedCoordinates is VK_TRUE, images the sampler is used - * with in the shader have the following requirements: - * - The viewType must be either VK_IMAGE_VIEW_TYPE_1D or - * VK_IMAGE_VIEW_TYPE_2D. - * - The image view must have a single layer and a single mip level. - * " - * - * This means addressModeW should be ignored. We pick a default value - * that works for normalized_coordinates=false. - */ - cfg.wrap_mode_r = - pCreateInfo->unnormalizedCoordinates - ? MALI_WRAP_MODE_CLAMP_TO_EDGE - : panvk_translate_sampler_address_mode(pCreateInfo->addressModeW); - cfg.compare_function = panvk_translate_sampler_compare_func(pCreateInfo); - cfg.border_color_r = border_color.uint32[0]; - cfg.border_color_g = border_color.uint32[1]; - cfg.border_color_b = border_color.uint32[2]; - cfg.border_color_a = border_color.uint32[3]; - - if (pCreateInfo->anisotropyEnable && pCreateInfo->maxAnisotropy > 1) { - cfg.maximum_anisotropy = pCreateInfo->maxAnisotropy; - cfg.lod_algorithm = MALI_LOD_ALGORITHM_ANISOTROPIC; - } - -#if PAN_ARCH >= 10 - switch (sampler->vk.reduction_mode) { - case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE: - cfg.reduction_mode = MALI_REDUCTION_MODE_AVERAGE; - break; - case VK_SAMPLER_REDUCTION_MODE_MIN: - cfg.reduction_mode = MALI_REDUCTION_MODE_MINIMUM; - break; - case VK_SAMPLER_REDUCTION_MODE_MAX: - cfg.reduction_mode = MALI_REDUCTION_MODE_MAXIMUM; - break; - default: - unreachable("Invalid reduction mode"); - } -#endif - } + panvk_sampler_fill_desc(pCreateInfo, &sampler->desc, border_color, + pCreateInfo->minFilter, pCreateInfo->magFilter, + sampler->vk.reduction_mode); *pSampler = panvk_sampler_to_handle(sampler); return VK_SUCCESS;