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