xref: /aosp_15_r20/external/mesa3d/src/panfrost/vulkan/panvk_vX_sampler.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 static void
swizzle_border_color(VkClearColorValue * border_color,VkFormat fmt)60 swizzle_border_color(VkClearColorValue *border_color, VkFormat fmt)
61 {
62    if (PAN_ARCH != 7)
63       return;
64 
65    enum pipe_format pfmt = vk_format_to_pipe_format(fmt);
66    if (panfrost_format_is_yuv(pfmt) || util_format_is_depth_or_stencil(pfmt))
67       return;
68 
69    const struct util_format_description *fdesc = util_format_description(pfmt);
70    if (fdesc->swizzle[0] == PIPE_SWIZZLE_Z &&
71        fdesc->swizzle[2] == PIPE_SWIZZLE_X) {
72       uint32_t red = border_color->uint32[0];
73 
74       border_color->uint32[0] = border_color->uint32[2];
75       border_color->uint32[2] = red;
76    }
77 }
78 
79 VKAPI_ATTR VkResult VKAPI_CALL
panvk_per_arch(CreateSampler)80 panvk_per_arch(CreateSampler)(VkDevice _device,
81                               const VkSamplerCreateInfo *pCreateInfo,
82                               const VkAllocationCallbacks *pAllocator,
83                               VkSampler *pSampler)
84 {
85    VK_FROM_HANDLE(panvk_device, device, _device);
86    struct panvk_sampler *sampler;
87 
88    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
89 
90    sampler =
91       vk_sampler_create(&device->vk, pCreateInfo, pAllocator, sizeof(*sampler));
92    if (!sampler)
93       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
94 
95    STATIC_ASSERT(sizeof(sampler->desc) >= pan_size(SAMPLER));
96 
97    VkFormat fmt;
98    VkClearColorValue border_color =
99       vk_sampler_border_color_value(pCreateInfo, &fmt);
100 
101    swizzle_border_color(&border_color, fmt);
102 
103    pan_pack(sampler->desc.opaque, SAMPLER, cfg) {
104       cfg.magnify_nearest = pCreateInfo->magFilter == VK_FILTER_NEAREST;
105       cfg.minify_nearest = pCreateInfo->minFilter == VK_FILTER_NEAREST;
106       cfg.mipmap_mode =
107          panvk_translate_sampler_mipmap_mode(pCreateInfo->mipmapMode);
108       cfg.normalized_coordinates = !pCreateInfo->unnormalizedCoordinates;
109 
110       cfg.lod_bias = pCreateInfo->mipLodBias;
111       cfg.minimum_lod = pCreateInfo->minLod;
112       cfg.maximum_lod = pCreateInfo->maxLod;
113       cfg.wrap_mode_s =
114          panvk_translate_sampler_address_mode(pCreateInfo->addressModeU);
115       cfg.wrap_mode_t =
116          panvk_translate_sampler_address_mode(pCreateInfo->addressModeV);
117 
118       /* "
119        * When unnormalizedCoordinates is VK_TRUE, images the sampler is used
120        * with in the shader have the following requirements:
121        * - The viewType must be either VK_IMAGE_VIEW_TYPE_1D or
122        *   VK_IMAGE_VIEW_TYPE_2D.
123        * - The image view must have a single layer and a single mip level.
124        * "
125        *
126        * This means addressModeW should be ignored. We pick a default value
127        * that works for normalized_coordinates=false.
128        */
129       cfg.wrap_mode_r =
130          pCreateInfo->unnormalizedCoordinates
131             ? MALI_WRAP_MODE_CLAMP_TO_EDGE
132             : panvk_translate_sampler_address_mode(pCreateInfo->addressModeW);
133       cfg.compare_function = panvk_translate_sampler_compare_func(pCreateInfo);
134       cfg.border_color_r = border_color.uint32[0];
135       cfg.border_color_g = border_color.uint32[1];
136       cfg.border_color_b = border_color.uint32[2];
137       cfg.border_color_a = border_color.uint32[3];
138 
139       if (pCreateInfo->anisotropyEnable && pCreateInfo->maxAnisotropy > 1) {
140          cfg.maximum_anisotropy = pCreateInfo->maxAnisotropy;
141          cfg.lod_algorithm = MALI_LOD_ALGORITHM_ANISOTROPIC;
142       }
143    }
144 
145    *pSampler = panvk_sampler_to_handle(sampler);
146    return VK_SUCCESS;
147 }
148 
149 VKAPI_ATTR void VKAPI_CALL
panvk_per_arch(DestroySampler)150 panvk_per_arch(DestroySampler)(VkDevice _device, VkSampler _sampler,
151                                const VkAllocationCallbacks *pAllocator)
152 {
153    VK_FROM_HANDLE(panvk_device, device, _device);
154    VK_FROM_HANDLE(panvk_sampler, sampler, _sampler);
155 
156    if (!sampler)
157       return;
158 
159    vk_sampler_destroy(&device->vk, pAllocator, &sampler->vk);
160 }
161