xref: /aosp_15_r20/external/mesa3d/src/nouveau/vulkan/nvk_sampler.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Collabora Ltd. and Red Hat Inc.
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker #include "nvk_sampler.h"
6*61046927SAndroid Build Coastguard Worker 
7*61046927SAndroid Build Coastguard Worker #include "nvk_device.h"
8*61046927SAndroid Build Coastguard Worker #include "nvk_entrypoints.h"
9*61046927SAndroid Build Coastguard Worker #include "nvk_physical_device.h"
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker #include "vk_format.h"
12*61046927SAndroid Build Coastguard Worker #include "vk_sampler.h"
13*61046927SAndroid Build Coastguard Worker 
14*61046927SAndroid Build Coastguard Worker #include "util/bitpack_helpers.h"
15*61046927SAndroid Build Coastguard Worker #include "util/format/format_utils.h"
16*61046927SAndroid Build Coastguard Worker #include "util/format_srgb.h"
17*61046927SAndroid Build Coastguard Worker 
18*61046927SAndroid Build Coastguard Worker #include "cla097.h"
19*61046927SAndroid Build Coastguard Worker #include "clb197.h"
20*61046927SAndroid Build Coastguard Worker #include "cl9097tex.h"
21*61046927SAndroid Build Coastguard Worker #include "cla097tex.h"
22*61046927SAndroid Build Coastguard Worker #include "clb197tex.h"
23*61046927SAndroid Build Coastguard Worker #include "drf.h"
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static void
__set_u32(uint32_t * o,uint32_t v,unsigned lo,unsigned hi)26*61046927SAndroid Build Coastguard Worker __set_u32(uint32_t *o, uint32_t v, unsigned lo, unsigned hi)
27*61046927SAndroid Build Coastguard Worker {
28*61046927SAndroid Build Coastguard Worker    assert(lo <= hi && hi < 32);
29*61046927SAndroid Build Coastguard Worker    *o |= util_bitpack_uint(v, lo % 32, hi % 32);
30*61046927SAndroid Build Coastguard Worker }
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker #define FIXED_FRAC_BITS 8
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static void
__set_ufixed(uint32_t * o,float v,unsigned lo,unsigned hi)35*61046927SAndroid Build Coastguard Worker __set_ufixed(uint32_t *o, float v, unsigned lo, unsigned hi)
36*61046927SAndroid Build Coastguard Worker {
37*61046927SAndroid Build Coastguard Worker    assert(lo <= hi && hi < 32);
38*61046927SAndroid Build Coastguard Worker    *o |= util_bitpack_ufixed_clamp(v, lo % 32, hi % 32, FIXED_FRAC_BITS);
39*61046927SAndroid Build Coastguard Worker }
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static void
__set_sfixed(uint32_t * o,float v,unsigned lo,unsigned hi)42*61046927SAndroid Build Coastguard Worker __set_sfixed(uint32_t *o, float v, unsigned lo, unsigned hi)
43*61046927SAndroid Build Coastguard Worker {
44*61046927SAndroid Build Coastguard Worker    assert(lo <= hi && hi < 32);
45*61046927SAndroid Build Coastguard Worker    *o |= util_bitpack_sfixed_clamp(v, lo % 32, hi % 32, FIXED_FRAC_BITS);
46*61046927SAndroid Build Coastguard Worker }
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker ALWAYS_INLINE static void
__set_bool(uint32_t * o,bool b,unsigned lo,unsigned hi)49*61046927SAndroid Build Coastguard Worker __set_bool(uint32_t *o, bool b, unsigned lo, unsigned hi)
50*61046927SAndroid Build Coastguard Worker {
51*61046927SAndroid Build Coastguard Worker    assert(lo == hi && hi < 32);
52*61046927SAndroid Build Coastguard Worker    *o |= util_bitpack_uint(b, lo % 32, hi % 32);
53*61046927SAndroid Build Coastguard Worker }
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker #define MW(x) x
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker #define SAMP_SET_U(o, NV, i, FIELD, val) \
58*61046927SAndroid Build Coastguard Worker    __set_u32(&(o)[i], (val), DRF_LO(NV##_TEXSAMP##i##_##FIELD),\
59*61046927SAndroid Build Coastguard Worker                              DRF_HI(NV##_TEXSAMP##i##_##FIELD))
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker #define SAMP_SET_UF(o, NV, i, FIELD, val) \
62*61046927SAndroid Build Coastguard Worker    __set_ufixed(&(o)[i], (val), DRF_LO(NV##_TEXSAMP##i##_##FIELD),\
63*61046927SAndroid Build Coastguard Worker                                 DRF_HI(NV##_TEXSAMP##i##_##FIELD))
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker #define SAMP_SET_SF(o, NV, i, FIELD, val) \
66*61046927SAndroid Build Coastguard Worker    __set_sfixed(&(o)[i], (val), DRF_LO(NV##_TEXSAMP##i##_##FIELD),\
67*61046927SAndroid Build Coastguard Worker                                 DRF_HI(NV##_TEXSAMP##i##_##FIELD))
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker #define SAMP_SET_B(o, NV, i, FIELD, b) \
70*61046927SAndroid Build Coastguard Worker    __set_bool(&(o)[i], (b), DRF_LO(NV##_TEXSAMP##i##_##FIELD),\
71*61046927SAndroid Build Coastguard Worker                             DRF_HI(NV##_TEXSAMP##i##_##FIELD))
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker #define SAMP_SET_E(o, NV, i, FIELD, E) \
74*61046927SAndroid Build Coastguard Worker    SAMP_SET_U((o), NV, i, FIELD, NV##_TEXSAMP##i##_##FIELD##_##E)
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker static inline uint32_t
vk_to_9097_address_mode(VkSamplerAddressMode addr_mode)77*61046927SAndroid Build Coastguard Worker vk_to_9097_address_mode(VkSamplerAddressMode addr_mode)
78*61046927SAndroid Build Coastguard Worker {
79*61046927SAndroid Build Coastguard Worker #define MODE(VK, NV) \
80*61046927SAndroid Build Coastguard Worker    [VK_SAMPLER_ADDRESS_MODE_##VK] = NV9097_TEXSAMP0_ADDRESS_U_##NV
81*61046927SAndroid Build Coastguard Worker    static const uint8_t vk_to_9097[] = {
82*61046927SAndroid Build Coastguard Worker       MODE(REPEAT,               WRAP),
83*61046927SAndroid Build Coastguard Worker       MODE(MIRRORED_REPEAT,      MIRROR),
84*61046927SAndroid Build Coastguard Worker       MODE(CLAMP_TO_EDGE,        CLAMP_TO_EDGE),
85*61046927SAndroid Build Coastguard Worker       MODE(CLAMP_TO_BORDER,      BORDER),
86*61046927SAndroid Build Coastguard Worker       MODE(MIRROR_CLAMP_TO_EDGE, MIRROR_ONCE_CLAMP_TO_EDGE),
87*61046927SAndroid Build Coastguard Worker    };
88*61046927SAndroid Build Coastguard Worker #undef MODE
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker    assert(addr_mode < ARRAY_SIZE(vk_to_9097));
91*61046927SAndroid Build Coastguard Worker    return vk_to_9097[addr_mode];
92*61046927SAndroid Build Coastguard Worker }
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker static uint32_t
vk_to_9097_texsamp_compare_op(VkCompareOp op)95*61046927SAndroid Build Coastguard Worker vk_to_9097_texsamp_compare_op(VkCompareOp op)
96*61046927SAndroid Build Coastguard Worker {
97*61046927SAndroid Build Coastguard Worker #define OP(VK, NV) \
98*61046927SAndroid Build Coastguard Worker    [VK_COMPARE_OP_##VK] = NV9097_TEXSAMP0_DEPTH_COMPARE_FUNC_##NV
99*61046927SAndroid Build Coastguard Worker    ASSERTED static const uint8_t vk_to_9097[] = {
100*61046927SAndroid Build Coastguard Worker       OP(NEVER,            ZC_NEVER),
101*61046927SAndroid Build Coastguard Worker       OP(LESS,             ZC_LESS),
102*61046927SAndroid Build Coastguard Worker       OP(EQUAL,            ZC_EQUAL),
103*61046927SAndroid Build Coastguard Worker       OP(LESS_OR_EQUAL,    ZC_LEQUAL),
104*61046927SAndroid Build Coastguard Worker       OP(GREATER,          ZC_GREATER),
105*61046927SAndroid Build Coastguard Worker       OP(NOT_EQUAL,        ZC_NOTEQUAL),
106*61046927SAndroid Build Coastguard Worker       OP(GREATER_OR_EQUAL, ZC_GEQUAL),
107*61046927SAndroid Build Coastguard Worker       OP(ALWAYS,           ZC_ALWAYS),
108*61046927SAndroid Build Coastguard Worker    };
109*61046927SAndroid Build Coastguard Worker #undef OP
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker    assert(op < ARRAY_SIZE(vk_to_9097));
112*61046927SAndroid Build Coastguard Worker    assert(op == vk_to_9097[op]);
113*61046927SAndroid Build Coastguard Worker 
114*61046927SAndroid Build Coastguard Worker    return op;
115*61046927SAndroid Build Coastguard Worker }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker static uint32_t
vk_to_9097_max_anisotropy(float max_anisotropy)118*61046927SAndroid Build Coastguard Worker vk_to_9097_max_anisotropy(float max_anisotropy)
119*61046927SAndroid Build Coastguard Worker {
120*61046927SAndroid Build Coastguard Worker    if (max_anisotropy >= 16)
121*61046927SAndroid Build Coastguard Worker       return NV9097_TEXSAMP0_MAX_ANISOTROPY_ANISO_16_TO_1;
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker    if (max_anisotropy >= 12)
124*61046927SAndroid Build Coastguard Worker       return NV9097_TEXSAMP0_MAX_ANISOTROPY_ANISO_12_TO_1;
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker    uint32_t aniso_u32 = MAX2(0.0f, max_anisotropy);
127*61046927SAndroid Build Coastguard Worker    return aniso_u32 >> 1;
128*61046927SAndroid Build Coastguard Worker }
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker static uint32_t
vk_to_9097_trilin_opt(float max_anisotropy)131*61046927SAndroid Build Coastguard Worker vk_to_9097_trilin_opt(float max_anisotropy)
132*61046927SAndroid Build Coastguard Worker {
133*61046927SAndroid Build Coastguard Worker    /* No idea if we want this but matching nouveau */
134*61046927SAndroid Build Coastguard Worker    if (max_anisotropy >= 12)
135*61046927SAndroid Build Coastguard Worker       return 0;
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker    if (max_anisotropy >= 4)
138*61046927SAndroid Build Coastguard Worker       return 6;
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker    if (max_anisotropy >= 2)
141*61046927SAndroid Build Coastguard Worker       return 4;
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker    return 0;
144*61046927SAndroid Build Coastguard Worker }
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker static void
nvk_sampler_fill_header(const struct nvk_physical_device * pdev,const struct VkSamplerCreateInfo * info,const struct vk_sampler * vk_sampler,uint32_t * samp)147*61046927SAndroid Build Coastguard Worker nvk_sampler_fill_header(const struct nvk_physical_device *pdev,
148*61046927SAndroid Build Coastguard Worker                         const struct VkSamplerCreateInfo *info,
149*61046927SAndroid Build Coastguard Worker                         const struct vk_sampler *vk_sampler,
150*61046927SAndroid Build Coastguard Worker                         uint32_t *samp)
151*61046927SAndroid Build Coastguard Worker {
152*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 0, ADDRESS_U,
153*61046927SAndroid Build Coastguard Worker               vk_to_9097_address_mode(info->addressModeU));
154*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 0, ADDRESS_V,
155*61046927SAndroid Build Coastguard Worker               vk_to_9097_address_mode(info->addressModeV));
156*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 0, ADDRESS_P,
157*61046927SAndroid Build Coastguard Worker               vk_to_9097_address_mode(info->addressModeW));
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker    if (info->compareEnable) {
160*61046927SAndroid Build Coastguard Worker       SAMP_SET_B(samp, NV9097, 0, DEPTH_COMPARE, true);
161*61046927SAndroid Build Coastguard Worker       SAMP_SET_U(samp, NV9097, 0, DEPTH_COMPARE_FUNC,
162*61046927SAndroid Build Coastguard Worker                  vk_to_9097_texsamp_compare_op(info->compareOp));
163*61046927SAndroid Build Coastguard Worker    }
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    SAMP_SET_B(samp, NV9097, 0, S_R_G_B_CONVERSION, true);
166*61046927SAndroid Build Coastguard Worker    SAMP_SET_E(samp, NV9097, 0, FONT_FILTER_WIDTH, SIZE_2);
167*61046927SAndroid Build Coastguard Worker    SAMP_SET_E(samp, NV9097, 0, FONT_FILTER_HEIGHT, SIZE_2);
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker    if (info->anisotropyEnable) {
170*61046927SAndroid Build Coastguard Worker       SAMP_SET_U(samp, NV9097, 0, MAX_ANISOTROPY,
171*61046927SAndroid Build Coastguard Worker                  vk_to_9097_max_anisotropy(info->maxAnisotropy));
172*61046927SAndroid Build Coastguard Worker    }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker    switch (info->magFilter) {
175*61046927SAndroid Build Coastguard Worker    case VK_FILTER_NEAREST:
176*61046927SAndroid Build Coastguard Worker       SAMP_SET_E(samp, NV9097, 1, MAG_FILTER, MAG_POINT);
177*61046927SAndroid Build Coastguard Worker       break;
178*61046927SAndroid Build Coastguard Worker    case VK_FILTER_LINEAR:
179*61046927SAndroid Build Coastguard Worker       SAMP_SET_E(samp, NV9097, 1, MAG_FILTER, MAG_LINEAR);
180*61046927SAndroid Build Coastguard Worker       break;
181*61046927SAndroid Build Coastguard Worker    default:
182*61046927SAndroid Build Coastguard Worker       unreachable("Invalid filter");
183*61046927SAndroid Build Coastguard Worker    }
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker    switch (info->minFilter) {
186*61046927SAndroid Build Coastguard Worker    case VK_FILTER_NEAREST:
187*61046927SAndroid Build Coastguard Worker       SAMP_SET_E(samp, NV9097, 1, MIN_FILTER, MIN_POINT);
188*61046927SAndroid Build Coastguard Worker       break;
189*61046927SAndroid Build Coastguard Worker    case VK_FILTER_LINEAR:
190*61046927SAndroid Build Coastguard Worker       if (info->anisotropyEnable)
191*61046927SAndroid Build Coastguard Worker          SAMP_SET_E(samp, NV9097, 1, MIN_FILTER, MIN_ANISO);
192*61046927SAndroid Build Coastguard Worker       else
193*61046927SAndroid Build Coastguard Worker          SAMP_SET_E(samp, NV9097, 1, MIN_FILTER, MIN_LINEAR);
194*61046927SAndroid Build Coastguard Worker       break;
195*61046927SAndroid Build Coastguard Worker    default:
196*61046927SAndroid Build Coastguard Worker       unreachable("Invalid filter");
197*61046927SAndroid Build Coastguard Worker    }
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker    switch (info->mipmapMode) {
200*61046927SAndroid Build Coastguard Worker    case VK_SAMPLER_MIPMAP_MODE_NEAREST:
201*61046927SAndroid Build Coastguard Worker       SAMP_SET_E(samp, NV9097, 1, MIP_FILTER, MIP_POINT);
202*61046927SAndroid Build Coastguard Worker       break;
203*61046927SAndroid Build Coastguard Worker    case VK_SAMPLER_MIPMAP_MODE_LINEAR:
204*61046927SAndroid Build Coastguard Worker       SAMP_SET_E(samp, NV9097, 1, MIP_FILTER, MIP_LINEAR);
205*61046927SAndroid Build Coastguard Worker       break;
206*61046927SAndroid Build Coastguard Worker    default:
207*61046927SAndroid Build Coastguard Worker       unreachable("Invalid mipmap mode");
208*61046927SAndroid Build Coastguard Worker    }
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker    assert(pdev->info.cls_eng3d >= KEPLER_A);
211*61046927SAndroid Build Coastguard Worker    if (info->flags & VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT) {
212*61046927SAndroid Build Coastguard Worker       SAMP_SET_E(samp, NVA097, 1, CUBEMAP_INTERFACE_FILTERING, USE_WRAP);
213*61046927SAndroid Build Coastguard Worker    } else {
214*61046927SAndroid Build Coastguard Worker       SAMP_SET_E(samp, NVA097, 1, CUBEMAP_INTERFACE_FILTERING, AUTO_SPAN_SEAM);
215*61046927SAndroid Build Coastguard Worker    }
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker    if (pdev->info.cls_eng3d >= MAXWELL_B) {
218*61046927SAndroid Build Coastguard Worker       switch (vk_sampler->reduction_mode) {
219*61046927SAndroid Build Coastguard Worker       case VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE:
220*61046927SAndroid Build Coastguard Worker          SAMP_SET_E(samp, NVB197, 1, REDUCTION_FILTER, RED_NONE);
221*61046927SAndroid Build Coastguard Worker          break;
222*61046927SAndroid Build Coastguard Worker       case VK_SAMPLER_REDUCTION_MODE_MIN:
223*61046927SAndroid Build Coastguard Worker          SAMP_SET_E(samp, NVB197, 1, REDUCTION_FILTER, RED_MINIMUM);
224*61046927SAndroid Build Coastguard Worker          break;
225*61046927SAndroid Build Coastguard Worker       case VK_SAMPLER_REDUCTION_MODE_MAX:
226*61046927SAndroid Build Coastguard Worker          SAMP_SET_E(samp, NVB197, 1, REDUCTION_FILTER, RED_MAXIMUM);
227*61046927SAndroid Build Coastguard Worker          break;
228*61046927SAndroid Build Coastguard Worker       default:
229*61046927SAndroid Build Coastguard Worker          unreachable("Invalid reduction mode");
230*61046927SAndroid Build Coastguard Worker       }
231*61046927SAndroid Build Coastguard Worker    }
232*61046927SAndroid Build Coastguard Worker 
233*61046927SAndroid Build Coastguard Worker    SAMP_SET_SF(samp, NV9097, 1, MIP_LOD_BIAS, info->mipLodBias);
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker    assert(pdev->info.cls_eng3d >= KEPLER_A);
236*61046927SAndroid Build Coastguard Worker    if (info->unnormalizedCoordinates) {
237*61046927SAndroid Build Coastguard Worker       SAMP_SET_E(samp, NVA097, 1, FLOAT_COORD_NORMALIZATION,
238*61046927SAndroid Build Coastguard Worker                                   FORCE_UNNORMALIZED_COORDS);
239*61046927SAndroid Build Coastguard Worker    } else {
240*61046927SAndroid Build Coastguard Worker       SAMP_SET_E(samp, NVA097, 1, FLOAT_COORD_NORMALIZATION,
241*61046927SAndroid Build Coastguard Worker                                   USE_HEADER_SETTING);
242*61046927SAndroid Build Coastguard Worker    }
243*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 1, TRILIN_OPT,
244*61046927SAndroid Build Coastguard Worker               vk_to_9097_trilin_opt(info->maxAnisotropy));
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker    SAMP_SET_UF(samp, NV9097, 2, MIN_LOD_CLAMP, info->minLod);
247*61046927SAndroid Build Coastguard Worker    SAMP_SET_UF(samp, NV9097, 2, MAX_LOD_CLAMP, info->maxLod);
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    VkClearColorValue bc = vk_sampler->border_color_value;
250*61046927SAndroid Build Coastguard Worker    uint8_t bc_srgb[3];
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker    const VkSamplerBorderColorComponentMappingCreateInfoEXT *swiz_info =
253*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(info->pNext,
254*61046927SAndroid Build Coastguard Worker                            SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT);
255*61046927SAndroid Build Coastguard Worker    if (swiz_info) {
256*61046927SAndroid Build Coastguard Worker       if (swiz_info->srgb) {
257*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; i < 3; i++)
258*61046927SAndroid Build Coastguard Worker             bc.float32[i] = util_format_linear_to_srgb_float(bc.float32[i]);
259*61046927SAndroid Build Coastguard Worker       }
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker       const bool is_int = vk_border_color_is_int(info->borderColor);
262*61046927SAndroid Build Coastguard Worker       bc = vk_swizzle_color_value(bc, swiz_info->components, is_int);
263*61046927SAndroid Build Coastguard Worker 
264*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < 3; i++)
265*61046927SAndroid Build Coastguard Worker          bc_srgb[i] = _mesa_float_to_unorm(bc.float32[i], 8);
266*61046927SAndroid Build Coastguard Worker    } else {
267*61046927SAndroid Build Coastguard Worker       /* Otherwise, we can assume no swizzle or that the border color is
268*61046927SAndroid Build Coastguard Worker        * transparent black or opaque white and there's nothing to do but
269*61046927SAndroid Build Coastguard Worker        * convert the (unswizzled) border color to sRGB.
270*61046927SAndroid Build Coastguard Worker        */
271*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < 3; i++)
272*61046927SAndroid Build Coastguard Worker          bc_srgb[i] = util_format_linear_float_to_srgb_8unorm(bc.float32[i]);
273*61046927SAndroid Build Coastguard Worker    }
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 2, S_R_G_B_BORDER_COLOR_R, bc_srgb[0]);
276*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 3, S_R_G_B_BORDER_COLOR_G, bc_srgb[1]);
277*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 3, S_R_G_B_BORDER_COLOR_B, bc_srgb[2]);
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 4, BORDER_COLOR_R, bc.uint32[0]);
280*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 5, BORDER_COLOR_G, bc.uint32[1]);
281*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 6, BORDER_COLOR_B, bc.uint32[2]);
282*61046927SAndroid Build Coastguard Worker    SAMP_SET_U(samp, NV9097, 7, BORDER_COLOR_A, bc.uint32[3]);
283*61046927SAndroid Build Coastguard Worker }
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
nvk_CreateSampler(VkDevice device,const VkSamplerCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSampler * pSampler)286*61046927SAndroid Build Coastguard Worker nvk_CreateSampler(VkDevice device,
287*61046927SAndroid Build Coastguard Worker                   const VkSamplerCreateInfo *pCreateInfo,
288*61046927SAndroid Build Coastguard Worker                   const VkAllocationCallbacks *pAllocator,
289*61046927SAndroid Build Coastguard Worker                   VkSampler *pSampler)
290*61046927SAndroid Build Coastguard Worker {
291*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
292*61046927SAndroid Build Coastguard Worker    struct nvk_physical_device *pdev = nvk_device_physical(dev);
293*61046927SAndroid Build Coastguard Worker    struct nvk_sampler *sampler;
294*61046927SAndroid Build Coastguard Worker    VkResult result;
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker    const VkOpaqueCaptureDescriptorDataCreateInfoEXT *cap_info =
297*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext,
298*61046927SAndroid Build Coastguard Worker                            OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT);
299*61046927SAndroid Build Coastguard Worker    struct nvk_sampler_capture cap = {};
300*61046927SAndroid Build Coastguard Worker    if (cap_info != NULL)
301*61046927SAndroid Build Coastguard Worker       memcpy(&cap, cap_info->opaqueCaptureDescriptorData, sizeof(cap));
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker    sampler = vk_sampler_create(&dev->vk, pCreateInfo,
304*61046927SAndroid Build Coastguard Worker                                pAllocator, sizeof(*sampler));
305*61046927SAndroid Build Coastguard Worker    if (!sampler)
306*61046927SAndroid Build Coastguard Worker       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    {
309*61046927SAndroid Build Coastguard Worker       uint32_t samp[8] = {};
310*61046927SAndroid Build Coastguard Worker       sampler->plane_count = 1;
311*61046927SAndroid Build Coastguard Worker       nvk_sampler_fill_header(pdev, pCreateInfo, &sampler->vk, samp);
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker       uint32_t desc_index = 0;
314*61046927SAndroid Build Coastguard Worker       if (cap_info != NULL) {
315*61046927SAndroid Build Coastguard Worker          desc_index = cap.planes[0].desc_index;
316*61046927SAndroid Build Coastguard Worker          result = nvk_descriptor_table_insert(dev, &dev->samplers,
317*61046927SAndroid Build Coastguard Worker                                               desc_index, samp, sizeof(samp));
318*61046927SAndroid Build Coastguard Worker       } else {
319*61046927SAndroid Build Coastguard Worker          result = nvk_descriptor_table_add(dev, &dev->samplers,
320*61046927SAndroid Build Coastguard Worker                                            samp, sizeof(samp), &desc_index);
321*61046927SAndroid Build Coastguard Worker       }
322*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
323*61046927SAndroid Build Coastguard Worker          vk_sampler_destroy(&dev->vk, pAllocator, &sampler->vk);
324*61046927SAndroid Build Coastguard Worker          return result;
325*61046927SAndroid Build Coastguard Worker       }
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker       sampler->planes[0].desc_index = desc_index;
328*61046927SAndroid Build Coastguard Worker    }
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker    /* In order to support CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT, we
331*61046927SAndroid Build Coastguard Worker     * need multiple sampler planes: at minimum we will need one for luminance
332*61046927SAndroid Build Coastguard Worker     * (the default), and one for chroma.  Each sampler plane needs its own
333*61046927SAndroid Build Coastguard Worker     * sampler table entry.  However, sampler table entries are very rare on
334*61046927SAndroid Build Coastguard Worker     * NVIDIA; we only have 4096 entries for the whole VkDevice, and each plane
335*61046927SAndroid Build Coastguard Worker     * would burn one of those. So we make sure to allocate only the minimum
336*61046927SAndroid Build Coastguard Worker     * amount that we actually need (i.e., either 1 or 2), and then just copy
337*61046927SAndroid Build Coastguard Worker     * the last sampler plane out as far as we need to fill the number of image
338*61046927SAndroid Build Coastguard Worker     * planes.
339*61046927SAndroid Build Coastguard Worker     */
340*61046927SAndroid Build Coastguard Worker 
341*61046927SAndroid Build Coastguard Worker    if (sampler->vk.ycbcr_conversion) {
342*61046927SAndroid Build Coastguard Worker       const VkFilter chroma_filter =
343*61046927SAndroid Build Coastguard Worker          sampler->vk.ycbcr_conversion->state.chroma_filter;
344*61046927SAndroid Build Coastguard Worker       if (pCreateInfo->magFilter != chroma_filter ||
345*61046927SAndroid Build Coastguard Worker           pCreateInfo->minFilter != chroma_filter) {
346*61046927SAndroid Build Coastguard Worker          VkSamplerCreateInfo plane2_info = *pCreateInfo;
347*61046927SAndroid Build Coastguard Worker          plane2_info.magFilter = chroma_filter;
348*61046927SAndroid Build Coastguard Worker          plane2_info.minFilter = chroma_filter;
349*61046927SAndroid Build Coastguard Worker 
350*61046927SAndroid Build Coastguard Worker          uint32_t samp[8] = {};
351*61046927SAndroid Build Coastguard Worker          sampler->plane_count = 2;
352*61046927SAndroid Build Coastguard Worker          nvk_sampler_fill_header(pdev, &plane2_info, &sampler->vk, samp);
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker          uint32_t desc_index = 0;
355*61046927SAndroid Build Coastguard Worker          if (cap_info != NULL) {
356*61046927SAndroid Build Coastguard Worker             desc_index = cap.planes[1].desc_index;
357*61046927SAndroid Build Coastguard Worker             result = nvk_descriptor_table_insert(dev, &dev->samplers,
358*61046927SAndroid Build Coastguard Worker                                                  desc_index,
359*61046927SAndroid Build Coastguard Worker                                                  samp, sizeof(samp));
360*61046927SAndroid Build Coastguard Worker          } else {
361*61046927SAndroid Build Coastguard Worker             result = nvk_descriptor_table_add(dev, &dev->samplers,
362*61046927SAndroid Build Coastguard Worker                                               samp, sizeof(samp),
363*61046927SAndroid Build Coastguard Worker                                               &desc_index);
364*61046927SAndroid Build Coastguard Worker          }
365*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS) {
366*61046927SAndroid Build Coastguard Worker             nvk_descriptor_table_remove(dev, &dev->samplers,
367*61046927SAndroid Build Coastguard Worker                                         sampler->planes[0].desc_index);
368*61046927SAndroid Build Coastguard Worker             vk_sampler_destroy(&dev->vk, pAllocator, &sampler->vk);
369*61046927SAndroid Build Coastguard Worker             return result;
370*61046927SAndroid Build Coastguard Worker          }
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker          sampler->planes[1].desc_index = desc_index;
373*61046927SAndroid Build Coastguard Worker       }
374*61046927SAndroid Build Coastguard Worker    }
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker    *pSampler = nvk_sampler_to_handle(sampler);
377*61046927SAndroid Build Coastguard Worker 
378*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
379*61046927SAndroid Build Coastguard Worker }
380*61046927SAndroid Build Coastguard Worker 
381*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
nvk_DestroySampler(VkDevice device,VkSampler _sampler,const VkAllocationCallbacks * pAllocator)382*61046927SAndroid Build Coastguard Worker nvk_DestroySampler(VkDevice device,
383*61046927SAndroid Build Coastguard Worker                    VkSampler _sampler,
384*61046927SAndroid Build Coastguard Worker                    const VkAllocationCallbacks *pAllocator)
385*61046927SAndroid Build Coastguard Worker {
386*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_device, dev, device);
387*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_sampler, sampler, _sampler);
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker    if (!sampler)
390*61046927SAndroid Build Coastguard Worker       return;
391*61046927SAndroid Build Coastguard Worker 
392*61046927SAndroid Build Coastguard Worker    for (uint8_t plane = 0; plane < sampler->plane_count; plane++) {
393*61046927SAndroid Build Coastguard Worker       nvk_descriptor_table_remove(dev, &dev->samplers,
394*61046927SAndroid Build Coastguard Worker                                   sampler->planes[plane].desc_index);
395*61046927SAndroid Build Coastguard Worker    }
396*61046927SAndroid Build Coastguard Worker 
397*61046927SAndroid Build Coastguard Worker    vk_sampler_destroy(&dev->vk, pAllocator, &sampler->vk);
398*61046927SAndroid Build Coastguard Worker }
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
nvk_GetSamplerOpaqueCaptureDescriptorDataEXT(VkDevice _device,const VkSamplerCaptureDescriptorDataInfoEXT * pInfo,void * pData)401*61046927SAndroid Build Coastguard Worker nvk_GetSamplerOpaqueCaptureDescriptorDataEXT(
402*61046927SAndroid Build Coastguard Worker     VkDevice _device,
403*61046927SAndroid Build Coastguard Worker     const VkSamplerCaptureDescriptorDataInfoEXT *pInfo,
404*61046927SAndroid Build Coastguard Worker     void *pData)
405*61046927SAndroid Build Coastguard Worker {
406*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(nvk_sampler, sampler, pInfo->sampler);
407*61046927SAndroid Build Coastguard Worker 
408*61046927SAndroid Build Coastguard Worker    struct nvk_sampler_capture cap = {};
409*61046927SAndroid Build Coastguard Worker    for (uint8_t p = 0; p < sampler->plane_count; p++)
410*61046927SAndroid Build Coastguard Worker       cap.planes[p].desc_index = sampler->planes[p].desc_index;
411*61046927SAndroid Build Coastguard Worker 
412*61046927SAndroid Build Coastguard Worker    memcpy(pData, &cap, sizeof(cap));
413*61046927SAndroid Build Coastguard Worker 
414*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
415*61046927SAndroid Build Coastguard Worker }
416