• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2021 Collabora Ltd.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "genxml/gen_macros.h"
7 
8 #include "panvk_device.h"
9 #include "panvk_entrypoints.h"
10 #include "panvk_sampler.h"
11 
12 #include "pan_encoder.h"
13 #include "pan_format.h"
14 
15 #include "vk_format.h"
16 #include "vk_log.h"
17 
18 static enum mali_mipmap_mode
panvk_translate_sampler_mipmap_mode(VkSamplerMipmapMode mode)19 panvk_translate_sampler_mipmap_mode(VkSamplerMipmapMode mode)
20 {
21    switch (mode) {
22    case VK_SAMPLER_MIPMAP_MODE_NEAREST:
23       return MALI_MIPMAP_MODE_NEAREST;
24    case VK_SAMPLER_MIPMAP_MODE_LINEAR:
25       return MALI_MIPMAP_MODE_TRILINEAR;
26    default:
27       unreachable("Invalid mipmap mode");
28    }
29 }
30 
31 static unsigned
panvk_translate_sampler_address_mode(VkSamplerAddressMode mode)32 panvk_translate_sampler_address_mode(VkSamplerAddressMode mode)
33 {
34    switch (mode) {
35    case VK_SAMPLER_ADDRESS_MODE_REPEAT:
36       return MALI_WRAP_MODE_REPEAT;
37    case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT:
38       return MALI_WRAP_MODE_MIRRORED_REPEAT;
39    case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
40       return MALI_WRAP_MODE_CLAMP_TO_EDGE;
41    case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER:
42       return MALI_WRAP_MODE_CLAMP_TO_BORDER;
43    case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE:
44       return MALI_WRAP_MODE_MIRRORED_CLAMP_TO_EDGE;
45    default:
46       unreachable("Invalid wrap");
47    }
48 }
49 
50 static enum mali_func
panvk_translate_sampler_compare_func(const VkSamplerCreateInfo * pCreateInfo)51 panvk_translate_sampler_compare_func(const VkSamplerCreateInfo *pCreateInfo)
52 {
53    if (!pCreateInfo->compareEnable)
54       return MALI_FUNC_NEVER;
55 
56    return panfrost_flip_compare_func((enum mali_func)pCreateInfo->compareOp);
57 }
58 
59 #if PAN_ARCH == 7
60 static void
panvk_afbc_reswizzle_border_color(VkClearColorValue * border_color,VkFormat fmt)61 panvk_afbc_reswizzle_border_color(VkClearColorValue *border_color, VkFormat fmt)
62 {
63    /* Doing border color reswizzle implies disabling support for
64     * customBorderColorWithoutFormat. */
65 
66    enum pipe_format pfmt = vk_format_to_pipe_format(fmt);
67    if (panfrost_format_is_yuv(pfmt) || util_format_is_depth_or_stencil(pfmt) ||
68        !panfrost_format_supports_afbc(PAN_ARCH, pfmt))
69       return;
70 
71    const struct util_format_description *fdesc = util_format_description(pfmt);
72    if (fdesc->swizzle[0] == PIPE_SWIZZLE_Z &&
73        fdesc->swizzle[2] == PIPE_SWIZZLE_X) {
74       uint32_t red = border_color->uint32[0];
75 
76       border_color->uint32[0] = border_color->uint32[2];
77       border_color->uint32[2] = red;
78    }
79 }
80 #endif
81 
82 VKAPI_ATTR VkResult VKAPI_CALL
panvk_per_arch(CreateSampler)83 panvk_per_arch(CreateSampler)(VkDevice _device,
84                               const VkSamplerCreateInfo *pCreateInfo,
85                               const VkAllocationCallbacks *pAllocator,
86                               VkSampler *pSampler)
87 {
88    VK_FROM_HANDLE(panvk_device, device, _device);
89    struct panvk_sampler *sampler;
90 
91    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
92 
93    sampler =
94       vk_sampler_create(&device->vk, pCreateInfo, pAllocator, sizeof(*sampler));
95    if (!sampler)
96       return panvk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
97 
98    STATIC_ASSERT(sizeof(sampler->desc) >= pan_size(SAMPLER));
99 
100    VkFormat fmt;
101    VkClearColorValue border_color =
102       vk_sampler_border_color_value(pCreateInfo, &fmt);
103 
104 #if PAN_ARCH == 7
105    panvk_afbc_reswizzle_border_color(&border_color, fmt);
106 #endif
107 
108    pan_pack(&sampler->desc, SAMPLER, cfg) {
109       cfg.magnify_nearest = pCreateInfo->magFilter == VK_FILTER_NEAREST;
110       cfg.minify_nearest = pCreateInfo->minFilter == VK_FILTER_NEAREST;
111       cfg.mipmap_mode =
112          panvk_translate_sampler_mipmap_mode(pCreateInfo->mipmapMode);
113       cfg.normalized_coordinates = !pCreateInfo->unnormalizedCoordinates;
114       cfg.clamp_integer_array_indices = false;
115 
116       /* Normalized float texture coordinates are rounded to fixed-point
117        * before rounding to integer coordinates. When round_to_nearest_even is
118        * enabled with VK_FILTER_NEAREST, the upper 2^-9 float coordinates in
119        * each texel are rounded up to the next texel.
120        *
121        * The Vulkan 1.4.304 spec seems to allow both rounding modes for all
122        * filters, but a CTS bug[1] causes test failures when round-to-nearest
123        * is used with VK_FILTER_NEAREST.
124        *
125        * Regardless, disabling round_to_nearest_even for NEAREST filters
126        * is a desirable precision improvement.
127        *
128        * [1]: https://gitlab.khronos.org/Tracker/vk-gl-cts/-/issues/5547
129        */
130       if (pCreateInfo->minFilter == VK_FILTER_NEAREST &&
131           pCreateInfo->magFilter == VK_FILTER_NEAREST)
132          cfg.round_to_nearest_even = false;
133 
134       cfg.lod_bias = pCreateInfo->mipLodBias;
135       cfg.minimum_lod = pCreateInfo->minLod;
136       cfg.maximum_lod = pCreateInfo->maxLod;
137       cfg.wrap_mode_s =
138          panvk_translate_sampler_address_mode(pCreateInfo->addressModeU);
139       cfg.wrap_mode_t =
140          panvk_translate_sampler_address_mode(pCreateInfo->addressModeV);
141 
142       /* "
143        * When unnormalizedCoordinates is VK_TRUE, images the sampler is used
144        * with in the shader have the following requirements:
145        * - The viewType must be either VK_IMAGE_VIEW_TYPE_1D or
146        *   VK_IMAGE_VIEW_TYPE_2D.
147        * - The image view must have a single layer and a single mip level.
148        * "
149        *
150        * This means addressModeW should be ignored. We pick a default value
151        * that works for normalized_coordinates=false.
152        */
153       cfg.wrap_mode_r =
154          pCreateInfo->unnormalizedCoordinates
155             ? MALI_WRAP_MODE_CLAMP_TO_EDGE
156             : panvk_translate_sampler_address_mode(pCreateInfo->addressModeW);
157       cfg.compare_function = panvk_translate_sampler_compare_func(pCreateInfo);
158       cfg.border_color_r = border_color.uint32[0];
159       cfg.border_color_g = border_color.uint32[1];
160       cfg.border_color_b = border_color.uint32[2];
161       cfg.border_color_a = border_color.uint32[3];
162 
163       if (pCreateInfo->anisotropyEnable && pCreateInfo->maxAnisotropy > 1) {
164          cfg.maximum_anisotropy = pCreateInfo->maxAnisotropy;
165          cfg.lod_algorithm = MALI_LOD_ALGORITHM_ANISOTROPIC;
166       }
167 
168 #if PAN_ARCH >= 10
169       switch (sampler->vk.reduction_mode) {
170       case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE:
171          cfg.reduction_mode = MALI_REDUCTION_MODE_AVERAGE;
172          break;
173       case VK_SAMPLER_REDUCTION_MODE_MIN:
174          cfg.reduction_mode = MALI_REDUCTION_MODE_MINIMUM;
175          break;
176       case VK_SAMPLER_REDUCTION_MODE_MAX:
177          cfg.reduction_mode = MALI_REDUCTION_MODE_MAXIMUM;
178          break;
179       default:
180          unreachable("Invalid reduction mode");
181       }
182 #endif
183    }
184 
185    *pSampler = panvk_sampler_to_handle(sampler);
186    return VK_SUCCESS;
187 }
188 
189 VKAPI_ATTR void VKAPI_CALL
panvk_per_arch(DestroySampler)190 panvk_per_arch(DestroySampler)(VkDevice _device, VkSampler _sampler,
191                                const VkAllocationCallbacks *pAllocator)
192 {
193    VK_FROM_HANDLE(panvk_device, device, _device);
194    VK_FROM_HANDLE(panvk_sampler, sampler, _sampler);
195 
196    if (!sampler)
197       return;
198 
199    vk_sampler_destroy(&device->vk, pAllocator, &sampler->vk);
200 }
201