1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2015 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "util/u_half.h"
29
30 #include "ilo_debug.h"
31 #include "ilo_state_surface.h"
32 #include "ilo_state_sampler.h"
33
34 static bool
sampler_validate_gen6_non_normalized(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)35 sampler_validate_gen6_non_normalized(const struct ilo_dev *dev,
36 const struct ilo_state_sampler_info *info)
37 {
38 const enum gen_texcoord_mode addr_ctrls[3] = {
39 info->tcx_ctrl, info->tcy_ctrl, info->tcz_ctrl,
40 };
41 int i;
42
43 ILO_DEV_ASSERT(dev, 6, 8);
44
45 /*
46 * From the Ivy Bridge PRM, volume 4 part 1, page 98:
47 *
48 * "The following state must be set as indicated if this field
49 * (Non-normalized Coordinate Enable) is enabled:
50 *
51 * - TCX/Y/Z Address Control Mode must be TEXCOORDMODE_CLAMP,
52 * TEXCOORDMODE_HALF_BORDER, or TEXCOORDMODE_CLAMP_BORDER.
53 * - Surface Type must be SURFTYPE_2D or SURFTYPE_3D.
54 * - Mag Mode Filter must be MAPFILTER_NEAREST or
55 * MAPFILTER_LINEAR.
56 * - Min Mode Filter must be MAPFILTER_NEAREST or
57 * MAPFILTER_LINEAR.
58 * - Mip Mode Filter must be MIPFILTER_NONE.
59 * - Min LOD must be 0.
60 * - Max LOD must be 0.
61 * - MIP Count must be 0.
62 * - Surface Min LOD must be 0.
63 * - Texture LOD Bias must be 0."
64 */
65 for (i = 0; i < 3; i++) {
66 switch (addr_ctrls[i]) {
67 case GEN6_TEXCOORDMODE_CLAMP:
68 case GEN6_TEXCOORDMODE_CLAMP_BORDER:
69 case GEN8_TEXCOORDMODE_HALF_BORDER:
70 break;
71 default:
72 assert(!"bad non-normalized coordinate wrap mode");
73 break;
74 }
75 }
76
77 assert(info->mip_filter == GEN6_MIPFILTER_NONE);
78
79 assert((info->min_filter == GEN6_MAPFILTER_NEAREST ||
80 info->min_filter == GEN6_MAPFILTER_LINEAR) &&
81 (info->mag_filter == GEN6_MAPFILTER_NEAREST ||
82 info->mag_filter == GEN6_MAPFILTER_LINEAR));
83
84 assert(info->min_lod == 0.0f &&
85 info->max_lod == 0.0f &&
86 info->lod_bias == 0.0f);
87
88 return true;
89 }
90
91 static bool
sampler_validate_gen6_sampler(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)92 sampler_validate_gen6_sampler(const struct ilo_dev *dev,
93 const struct ilo_state_sampler_info *info)
94 {
95 ILO_DEV_ASSERT(dev, 6, 8);
96
97 if (info->non_normalized &&
98 !sampler_validate_gen6_non_normalized(dev, info))
99 return false;
100
101 if (ilo_dev_gen(dev) < ILO_GEN(8)) {
102 assert(info->tcx_ctrl != GEN8_TEXCOORDMODE_HALF_BORDER &&
103 info->tcy_ctrl != GEN8_TEXCOORDMODE_HALF_BORDER &&
104 info->tcz_ctrl != GEN8_TEXCOORDMODE_HALF_BORDER);
105 }
106
107 return true;
108 }
109
110 static uint32_t
sampler_get_gen6_integer_filters(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)111 sampler_get_gen6_integer_filters(const struct ilo_dev *dev,
112 const struct ilo_state_sampler_info *info)
113 {
114 /*
115 * From the Sandy Bridge PRM, volume 4 part 1, page 103:
116 *
117 * "MIPFILTER_LINEAR is not supported for surface formats that do not
118 * support "Sampling Engine Filtering" as indicated in the Surface
119 * Formats table unless using the sample_c message type."
120 *
121 * "Only MAPFILTER_NEAREST is supported for surface formats that do not
122 * support "Sampling Engine Filtering" as indicated in the Surface
123 * Formats table unless using the sample_c message type.
124 */
125 const enum gen_mip_filter mip_filter =
126 (info->mip_filter == GEN6_MIPFILTER_LINEAR) ?
127 GEN6_MIPFILTER_NEAREST : info->mip_filter;
128 const enum gen_map_filter min_filter = GEN6_MAPFILTER_NEAREST;
129 const enum gen_map_filter mag_filter = GEN6_MAPFILTER_NEAREST;
130
131 ILO_DEV_ASSERT(dev, 6, 8);
132
133 return mip_filter << GEN6_SAMPLER_DW0_MIP_FILTER__SHIFT |
134 mag_filter << GEN6_SAMPLER_DW0_MAG_FILTER__SHIFT |
135 min_filter << GEN6_SAMPLER_DW0_MIN_FILTER__SHIFT;
136 }
137
138 static uint32_t
sampler_get_gen6_3d_filters(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)139 sampler_get_gen6_3d_filters(const struct ilo_dev *dev,
140 const struct ilo_state_sampler_info *info)
141 {
142 const enum gen_mip_filter mip_filter = info->mip_filter;
143 /*
144 * From the Sandy Bridge PRM, volume 4 part 1, page 103:
145 *
146 * "Only MAPFILTER_NEAREST and MAPFILTER_LINEAR are supported for
147 * surfaces of type SURFTYPE_3D."
148 */
149 const enum gen_map_filter min_filter =
150 (info->min_filter == GEN6_MAPFILTER_NEAREST ||
151 info->min_filter == GEN6_MAPFILTER_LINEAR) ?
152 info->min_filter : GEN6_MAPFILTER_LINEAR;
153 const enum gen_map_filter mag_filter =
154 (info->mag_filter == GEN6_MAPFILTER_NEAREST ||
155 info->mag_filter == GEN6_MAPFILTER_LINEAR) ?
156 info->mag_filter : GEN6_MAPFILTER_LINEAR;
157
158 ILO_DEV_ASSERT(dev, 6, 8);
159
160 return mip_filter << GEN6_SAMPLER_DW0_MIP_FILTER__SHIFT |
161 mag_filter << GEN6_SAMPLER_DW0_MAG_FILTER__SHIFT |
162 min_filter << GEN6_SAMPLER_DW0_MIN_FILTER__SHIFT;
163 }
164
165 static uint32_t
get_gen6_addr_controls(const struct ilo_dev * dev,enum gen_texcoord_mode tcx_ctrl,enum gen_texcoord_mode tcy_ctrl,enum gen_texcoord_mode tcz_ctrl)166 get_gen6_addr_controls(const struct ilo_dev *dev,
167 enum gen_texcoord_mode tcx_ctrl,
168 enum gen_texcoord_mode tcy_ctrl,
169 enum gen_texcoord_mode tcz_ctrl)
170 {
171 ILO_DEV_ASSERT(dev, 6, 8);
172
173 if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
174 return tcx_ctrl << GEN7_SAMPLER_DW3_U_WRAP__SHIFT |
175 tcy_ctrl << GEN7_SAMPLER_DW3_V_WRAP__SHIFT |
176 tcz_ctrl << GEN7_SAMPLER_DW3_R_WRAP__SHIFT;
177 } else {
178 return tcx_ctrl << GEN6_SAMPLER_DW1_U_WRAP__SHIFT |
179 tcy_ctrl << GEN6_SAMPLER_DW1_V_WRAP__SHIFT |
180 tcz_ctrl << GEN6_SAMPLER_DW1_R_WRAP__SHIFT;
181 }
182 }
183
184 static uint32_t
sampler_get_gen6_1d_addr_controls(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)185 sampler_get_gen6_1d_addr_controls(const struct ilo_dev *dev,
186 const struct ilo_state_sampler_info *info)
187 {
188 const enum gen_texcoord_mode tcx_ctrl =
189 (info->tcx_ctrl == GEN6_TEXCOORDMODE_CUBE) ?
190 GEN6_TEXCOORDMODE_CLAMP : info->tcx_ctrl;
191 /*
192 * From the Ivy Bridge PRM, volume 4 part 1, page 100:
193 *
194 * "If this field (TCY Address Control Mode) is set to
195 * TEXCOORDMODE_CLAMP_BORDER or TEXCOORDMODE_HALF_BORDER and a 1D
196 * surface is sampled, incorrect blending with the border color in the
197 * vertical direction may occur."
198 */
199 const enum gen_texcoord_mode tcy_ctrl = GEN6_TEXCOORDMODE_CLAMP;
200 const enum gen_texcoord_mode tcz_ctrl = GEN6_TEXCOORDMODE_CLAMP;
201
202 ILO_DEV_ASSERT(dev, 6, 8);
203
204 return get_gen6_addr_controls(dev, tcx_ctrl, tcy_ctrl, tcz_ctrl);
205 }
206
207 static uint32_t
sampler_get_gen6_2d_3d_addr_controls(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)208 sampler_get_gen6_2d_3d_addr_controls(const struct ilo_dev *dev,
209 const struct ilo_state_sampler_info *info)
210 {
211 const enum gen_texcoord_mode tcx_ctrl =
212 (info->tcx_ctrl == GEN6_TEXCOORDMODE_CUBE) ?
213 GEN6_TEXCOORDMODE_CLAMP : info->tcx_ctrl;
214 const enum gen_texcoord_mode tcy_ctrl =
215 (info->tcy_ctrl == GEN6_TEXCOORDMODE_CUBE) ?
216 GEN6_TEXCOORDMODE_CLAMP : info->tcy_ctrl;
217 /*
218 * From the Sandy Bridge PRM, volume 4 part 1, page 108:
219 *
220 * "[DevSNB]: if this field (TCZ Address Control Mode) is set to
221 * TEXCOORDMODE_CLAMP_BORDER samples outside the map will clamp to 0
222 * instead of boarder color"
223 *
224 * From the Ivy Bridge PRM, volume 4 part 1, page 100:
225 *
226 * "If this field is set to TEXCOORDMODE_CLAMP_BORDER for 3D maps on
227 * formats without an alpha channel, samples straddling the map in the
228 * Z direction may have their alpha channels off by 1."
229 *
230 * Do we want to do something here?
231 */
232 const enum gen_texcoord_mode tcz_ctrl =
233 (info->tcz_ctrl == GEN6_TEXCOORDMODE_CUBE) ?
234 GEN6_TEXCOORDMODE_CLAMP : info->tcz_ctrl;
235
236 ILO_DEV_ASSERT(dev, 6, 8);
237
238 return get_gen6_addr_controls(dev, tcx_ctrl, tcy_ctrl, tcz_ctrl);
239 }
240
241 static uint32_t
sampler_get_gen6_cube_addr_controls(const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)242 sampler_get_gen6_cube_addr_controls(const struct ilo_dev *dev,
243 const struct ilo_state_sampler_info *info)
244 {
245 /*
246 * From the Ivy Bridge PRM, volume 4 part 1, page 99:
247 *
248 * "When using cube map texture coordinates, only TEXCOORDMODE_CLAMP
249 * and TEXCOORDMODE_CUBE settings are valid, and each TC component
250 * must have the same Address Control mode.
251 *
252 * When TEXCOORDMODE_CUBE is not used accessing a cube map, the map's
253 * Cube Face Enable field must be programmed to 111111b (all faces
254 * enabled)."
255 *
256 * From the Haswell PRM, volume 2d, page 278:
257 *
258 * "When using cube map texture coordinates, each TC component must
259 * have the same Address Control Mode.
260 *
261 * When TEXCOORDMODE_CUBE is not used accessing a cube map, the map's
262 * Cube Face Enable field must be programmed to 111111b (all faces
263 * enabled)."
264 *
265 * We always enable all cube faces and only need to make sure all address
266 * control modes are the same.
267 */
268 const enum gen_texcoord_mode tcx_ctrl =
269 (ilo_dev_gen(dev) >= ILO_GEN(7.5) ||
270 info->tcx_ctrl == GEN6_TEXCOORDMODE_CUBE ||
271 info->tcx_ctrl == GEN6_TEXCOORDMODE_CLAMP) ?
272 info->tcx_ctrl : GEN6_TEXCOORDMODE_CLAMP;
273 const enum gen_texcoord_mode tcy_ctrl = tcx_ctrl;
274 const enum gen_texcoord_mode tcz_ctrl = tcx_ctrl;
275
276 ILO_DEV_ASSERT(dev, 6, 8);
277
278 return get_gen6_addr_controls(dev, tcx_ctrl, tcy_ctrl, tcz_ctrl);
279 }
280
281 static uint16_t
get_gen6_lod_bias(const struct ilo_dev * dev,float bias)282 get_gen6_lod_bias(const struct ilo_dev *dev, float bias)
283 {
284 /* [-16.0, 16.0) in S4.6 or S4.8 */
285 const int fbits = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 8 : 6;
286 const float max = 16.0f;
287 const float scale = (float) (1 << fbits);
288 const int mask = (1 << (1 + 4 + fbits)) - 1;
289 const int scaled_max = (16 << fbits) - 1;
290 int scaled;
291
292 ILO_DEV_ASSERT(dev, 6, 8);
293
294 if (bias > max)
295 bias = max;
296 else if (bias < -max)
297 bias = -max;
298
299 scaled = (int) (bias * scale);
300 if (scaled > scaled_max)
301 scaled = scaled_max;
302
303 return (scaled & mask);
304 }
305
306 static uint16_t
get_gen6_lod_clamp(const struct ilo_dev * dev,float clamp)307 get_gen6_lod_clamp(const struct ilo_dev *dev, float clamp)
308 {
309 /* [0.0, 13.0] in U4.6 or [0.0, 14.0] in U4.8 */
310 const int fbits = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 8 : 6;
311 const float max = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 14.0f : 13.0f;
312 const float scale = (float) (1 << fbits);
313
314 ILO_DEV_ASSERT(dev, 6, 8);
315
316 if (clamp > max)
317 clamp = max;
318 else if (clamp < 0.0f)
319 clamp = 0.0f;
320
321 return (int) (clamp * scale);
322 }
323
324 static bool
sampler_set_gen6_SAMPLER_STATE(struct ilo_state_sampler * sampler,const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)325 sampler_set_gen6_SAMPLER_STATE(struct ilo_state_sampler *sampler,
326 const struct ilo_dev *dev,
327 const struct ilo_state_sampler_info *info)
328 {
329 uint16_t lod_bias, max_lod, min_lod;
330 uint32_t dw0, dw1, dw3;
331
332 ILO_DEV_ASSERT(dev, 6, 8);
333
334 if (!sampler_validate_gen6_sampler(dev, info))
335 return false;
336
337 /*
338 * From the Ivy Bridge PRM, volume 4 part 1, page 15:
339 *
340 * "The per-pixel LOD is computed in an implementation-dependent manner
341 * and approximates the log2 of the texel/pixel ratio at the given
342 * pixel. The computation is typically based on the differential
343 * texel-space distances associated with a one-pixel differential
344 * distance along the screen x- and y-axes. These texel-space
345 * distances are computed by evaluating neighboring pixel texture
346 * coordinates, these coordinates being in units of texels on the base
347 * MIP level (multiplied by the corresponding surface size in
348 * texels)."
349 *
350 * Judging from the LOD computation pseudocode on page 16-18, the "base MIP
351 * level" should be given by SurfMinLod. To summarize, for the "sample"
352 * message,
353 *
354 * 1) LOD is set to log2(texel/pixel ratio). The number of texels is
355 * measured against level SurfMinLod.
356 * 2) Bias is added to LOD.
357 * 3) if pre-clamp is enabled, LOD is clamped to [MinLod, MaxLod] first
358 * 4) LOD is compared with Base to determine whether magnification or
359 * minification is needed.
360 * 5) If magnification is needed, or no mipmapping is requested, LOD is
361 * set to floor(MinLod).
362 * 6) LOD is clamped to [0, MIPCnt], and SurfMinLod is added to LOD.
363 *
364 * As an example, we could set SurfMinLod to GL_TEXTURE_BASE_LEVEL and Base
365 * to 0 to match GL. But GL expects LOD to be set to 0, instead of
366 * floor(MinLod), in 5). Since this is only an issue when MinLod is
367 * greater than or equal to one, and, with Base being 0, a non-zero MinLod
368 * implies minification, we only need to deal with the case when mipmapping
369 * is disabled. We can thus do:
370 *
371 * if (MipFilter == MIPFILTER_NONE && MinLod) {
372 * MinLod = 0;
373 * MagFilter = MinFilter;
374 * }
375 */
376
377 lod_bias = get_gen6_lod_bias(dev, info->lod_bias);
378 min_lod = get_gen6_lod_clamp(dev, info->min_lod);
379 max_lod = get_gen6_lod_clamp(dev, info->max_lod);
380
381 dw0 = GEN6_SAMPLER_DW0_LOD_PRECLAMP_ENABLE |
382 0 << GEN6_SAMPLER_DW0_BASE_LOD__SHIFT |
383 info->mip_filter << GEN6_SAMPLER_DW0_MIP_FILTER__SHIFT |
384 info->mag_filter << GEN6_SAMPLER_DW0_MAG_FILTER__SHIFT |
385 info->min_filter << GEN6_SAMPLER_DW0_MIN_FILTER__SHIFT;
386
387 if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
388 dw0 |= GEN7_SAMPLER_DW0_BORDER_COLOR_MODE_DX10_OGL |
389 lod_bias << GEN7_SAMPLER_DW0_LOD_BIAS__SHIFT;
390
391 if (info->min_filter == GEN6_MAPFILTER_ANISOTROPIC ||
392 info->mag_filter == GEN6_MAPFILTER_ANISOTROPIC)
393 dw0 |= GEN7_SAMPLER_DW0_ANISO_ALGO_EWA;
394 } else {
395 dw0 |= lod_bias << GEN6_SAMPLER_DW0_LOD_BIAS__SHIFT |
396 info->shadow_func << GEN6_SAMPLER_DW0_SHADOW_FUNC__SHIFT;
397
398 /*
399 * From the Sandy Bridge PRM, volume 4 part 1, page 102:
400 *
401 * "(Min and Mag State Not Equal) Must be set to 1 if any of the
402 * following are true:
403 *
404 * - Mag Mode Filter and Min Mode Filter are not the same
405 * - Address Rounding Enable: U address mag filter and U address
406 * min filter are not the same
407 * - Address Rounding Enable: V address mag filter and V address
408 * min filter are not the same
409 * - Address Rounding Enable: R address mag filter and R address
410 * min filter are not the same"
411 *
412 * We set address rounding for U, V, and R uniformly. Only need to
413 * check the filters.
414 */
415 if (info->min_filter != info->mag_filter)
416 dw0 |= GEN6_SAMPLER_DW0_MIN_MAG_NOT_EQUAL;
417 }
418
419 dw1 = 0;
420
421 if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
422 /*
423 * From the Ivy Bridge PRM, volume 4 part 1, page 96:
424 *
425 * "This field (Cube Surface Control Mode) must be set to
426 * CUBECTRLMODE_PROGRAMMED"
427 */
428 dw1 |= min_lod << GEN7_SAMPLER_DW1_MIN_LOD__SHIFT |
429 max_lod << GEN7_SAMPLER_DW1_MAX_LOD__SHIFT |
430 info->shadow_func << GEN7_SAMPLER_DW1_SHADOW_FUNC__SHIFT |
431 GEN7_SAMPLER_DW1_CUBECTRLMODE_PROGRAMMED;
432 } else {
433 dw1 |= min_lod << GEN6_SAMPLER_DW1_MIN_LOD__SHIFT |
434 max_lod << GEN6_SAMPLER_DW1_MAX_LOD__SHIFT |
435 GEN6_SAMPLER_DW1_CUBECTRLMODE_PROGRAMMED |
436 info->tcx_ctrl << GEN6_SAMPLER_DW1_U_WRAP__SHIFT |
437 info->tcy_ctrl << GEN6_SAMPLER_DW1_V_WRAP__SHIFT |
438 info->tcz_ctrl << GEN6_SAMPLER_DW1_R_WRAP__SHIFT;
439 }
440
441 dw3 = info->max_anisotropy << GEN6_SAMPLER_DW3_MAX_ANISO__SHIFT;
442
443 /* round the coordinates for linear filtering */
444 if (info->min_filter != GEN6_MAPFILTER_NEAREST) {
445 dw3 |= GEN6_SAMPLER_DW3_U_MIN_ROUND |
446 GEN6_SAMPLER_DW3_V_MIN_ROUND |
447 GEN6_SAMPLER_DW3_R_MIN_ROUND;
448 }
449 if (info->mag_filter != GEN6_MAPFILTER_NEAREST) {
450 dw3 |= GEN6_SAMPLER_DW3_U_MAG_ROUND |
451 GEN6_SAMPLER_DW3_V_MAG_ROUND |
452 GEN6_SAMPLER_DW3_R_MAG_ROUND;
453 }
454
455 if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
456 dw3 |= GEN7_SAMPLER_DW3_TRIQUAL_FULL |
457 info->tcx_ctrl << GEN7_SAMPLER_DW3_U_WRAP__SHIFT |
458 info->tcy_ctrl << GEN7_SAMPLER_DW3_V_WRAP__SHIFT |
459 info->tcz_ctrl << GEN7_SAMPLER_DW3_R_WRAP__SHIFT;
460
461 if (info->non_normalized)
462 dw3 |= GEN7_SAMPLER_DW3_NON_NORMALIZED_COORD;
463 } else {
464 if (info->non_normalized)
465 dw3 |= GEN6_SAMPLER_DW3_NON_NORMALIZED_COORD;
466 }
467
468 STATIC_ASSERT(ARRAY_SIZE(sampler->sampler) >= 3);
469 sampler->sampler[0] = dw0;
470 sampler->sampler[1] = dw1;
471 sampler->sampler[2] = dw3;
472
473 sampler->filter_integer = sampler_get_gen6_integer_filters(dev, info);
474 sampler->filter_3d = sampler_get_gen6_3d_filters(dev, info);
475 sampler->addr_ctrl_1d = sampler_get_gen6_1d_addr_controls(dev, info);
476 sampler->addr_ctrl_2d_3d = sampler_get_gen6_2d_3d_addr_controls(dev, info);
477 sampler->addr_ctrl_cube = sampler_get_gen6_cube_addr_controls(dev, info);
478
479 sampler->non_normalized = info->non_normalized;
480
481 /*
482 * From the Sandy Bridge PRM, volume 4 part 1, page 21:
483 *
484 * "[DevSNB] Errata: Incorrect behavior is observed in cases where the
485 * min and mag mode filters are different and SurfMinLOD is nonzero.
486 * The determination of MagMode uses the following equation instead of
487 * the one in the above pseudocode:
488 *
489 * MagMode = (LOD + SurfMinLOD - Base <= 0)"
490 *
491 * As a way to work around that, request Base to be set to SurfMinLod.
492 */
493 if (ilo_dev_gen(dev) == ILO_GEN(6) &&
494 info->min_filter != info->mag_filter)
495 sampler->base_to_surf_min_lod = true;
496
497 return true;
498 }
499
500 static bool
sampler_border_set_gen6_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border * border,const struct ilo_dev * dev,const struct ilo_state_sampler_border_info * info)501 sampler_border_set_gen6_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border *border,
502 const struct ilo_dev *dev,
503 const struct ilo_state_sampler_border_info *info)
504 {
505 uint32_t dw[12];
506 float rgba[4];
507
508 /*
509 * From the Ivy Bridge PRM, volume 4 part 1, page 117:
510 *
511 * "For ([DevSNB]), if border color is used, all formats must be
512 * provided. Hardware will choose the appropriate format based on
513 * Surface Format and Texture Border Color Mode. The values
514 * represented by each format should be the same (other than being
515 * subject to range-based clamping and precision) to avoid unexpected
516 * behavior."
517 *
518 * XXX We do not honor info->is_integer yet.
519 */
520
521 ILO_DEV_ASSERT(dev, 6, 6);
522
523 /* make a copy so that we can clamp for SNORM and UNORM */
524 memcpy(rgba, info->rgba.f, sizeof(rgba));
525
526 /* IEEE_FP */
527 dw[1] = fui(rgba[0]);
528 dw[2] = fui(rgba[1]);
529 dw[3] = fui(rgba[2]);
530 dw[4] = fui(rgba[3]);
531
532 /* FLOAT_16 */
533 dw[5] = util_float_to_half(rgba[0]) |
534 util_float_to_half(rgba[1]) << 16;
535 dw[6] = util_float_to_half(rgba[2]) |
536 util_float_to_half(rgba[3]) << 16;
537
538 /* clamp to [-1.0f, 1.0f] */
539 rgba[0] = CLAMP(rgba[0], -1.0f, 1.0f);
540 rgba[1] = CLAMP(rgba[1], -1.0f, 1.0f);
541 rgba[2] = CLAMP(rgba[2], -1.0f, 1.0f);
542 rgba[3] = CLAMP(rgba[3], -1.0f, 1.0f);
543
544 /* SNORM16 */
545 dw[9] = (int16_t) util_iround(rgba[0] * 32767.0f) |
546 (int16_t) util_iround(rgba[1] * 32767.0f) << 16;
547 dw[10] = (int16_t) util_iround(rgba[2] * 32767.0f) |
548 (int16_t) util_iround(rgba[3] * 32767.0f) << 16;
549
550 /* SNORM8 */
551 dw[11] = (int8_t) util_iround(rgba[0] * 127.0f) |
552 (int8_t) util_iround(rgba[1] * 127.0f) << 8 |
553 (int8_t) util_iround(rgba[2] * 127.0f) << 16 |
554 (int8_t) util_iround(rgba[3] * 127.0f) << 24;
555
556 /* clamp to [0.0f, 1.0f] */
557 rgba[0] = CLAMP(rgba[0], 0.0f, 1.0f);
558 rgba[1] = CLAMP(rgba[1], 0.0f, 1.0f);
559 rgba[2] = CLAMP(rgba[2], 0.0f, 1.0f);
560 rgba[3] = CLAMP(rgba[3], 0.0f, 1.0f);
561
562 /* UNORM8 */
563 dw[0] = (uint8_t) util_iround(rgba[0] * 255.0f) |
564 (uint8_t) util_iround(rgba[1] * 255.0f) << 8 |
565 (uint8_t) util_iround(rgba[2] * 255.0f) << 16 |
566 (uint8_t) util_iround(rgba[3] * 255.0f) << 24;
567
568 /* UNORM16 */
569 dw[7] = (uint16_t) util_iround(rgba[0] * 65535.0f) |
570 (uint16_t) util_iround(rgba[1] * 65535.0f) << 16;
571 dw[8] = (uint16_t) util_iround(rgba[2] * 65535.0f) |
572 (uint16_t) util_iround(rgba[3] * 65535.0f) << 16;
573
574 STATIC_ASSERT(ARRAY_SIZE(border->color) >= 12);
575 memcpy(border->color, dw, sizeof(dw));
576
577 return true;
578 }
579
580 static bool
sampler_border_set_gen7_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border * border,const struct ilo_dev * dev,const struct ilo_state_sampler_border_info * info)581 sampler_border_set_gen7_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border *border,
582 const struct ilo_dev *dev,
583 const struct ilo_state_sampler_border_info *info)
584 {
585 ILO_DEV_ASSERT(dev, 7, 8);
586
587 /*
588 * From the Ivy Bridge PRM, volume 4 part 1, page 116:
589 *
590 * "In DX10/OGL mode, the format of the border color is
591 * R32G32B32A32_FLOAT, regardless of the surface format chosen."
592 *
593 * From the Haswell PRM, volume 2d, page 240:
594 *
595 * "So, SW will have to program the table in SAMPLER_BORDER_COLOR_STATE
596 * at offsets DWORD16 to 19, as per the integer surface format type."
597 *
598 * From the Broadwell PRM, volume 2d, page 297:
599 *
600 * "DX10/OGL mode: the format of the border color depends on the format
601 * of the surface being sampled. If the map format is UINT, then the
602 * border color format is R32G32B32A32_UINT. If the map format is
603 * SINT, then the border color format is R32G32B32A32_SINT. Otherwise,
604 * the border color format is R32G32B32A32_FLOAT."
605 *
606 * XXX every Gen is different
607 */
608
609 STATIC_ASSERT(ARRAY_SIZE(border->color) >= 4);
610 memcpy(border->color, info->rgba.f, sizeof(info->rgba.f));
611
612 return true;
613 }
614
615 bool
ilo_state_sampler_init(struct ilo_state_sampler * sampler,const struct ilo_dev * dev,const struct ilo_state_sampler_info * info)616 ilo_state_sampler_init(struct ilo_state_sampler *sampler,
617 const struct ilo_dev *dev,
618 const struct ilo_state_sampler_info *info)
619 {
620 bool ret = true;
621
622 assert(ilo_is_zeroed(sampler, sizeof(*sampler)));
623
624 ret &= sampler_set_gen6_SAMPLER_STATE(sampler, dev, info);
625
626 assert(ret);
627
628 return ret;
629 }
630
631 bool
ilo_state_sampler_init_disabled(struct ilo_state_sampler * sampler,const struct ilo_dev * dev)632 ilo_state_sampler_init_disabled(struct ilo_state_sampler *sampler,
633 const struct ilo_dev *dev)
634 {
635 ILO_DEV_ASSERT(dev, 6, 8);
636
637 assert(ilo_is_zeroed(sampler, sizeof(*sampler)));
638
639 sampler->sampler[0] = GEN6_SAMPLER_DW0_DISABLE;
640 sampler->sampler[1] = 0;
641 sampler->sampler[2] = 0;
642
643 return true;
644 }
645
646 /**
647 * Modify \p sampler to work with \p surf. There will be loss of information.
648 * Callers should make a copy of the orignal sampler first.
649 */
650 bool
ilo_state_sampler_set_surface(struct ilo_state_sampler * sampler,const struct ilo_dev * dev,const struct ilo_state_surface * surf)651 ilo_state_sampler_set_surface(struct ilo_state_sampler *sampler,
652 const struct ilo_dev *dev,
653 const struct ilo_state_surface *surf)
654 {
655 uint32_t addr_ctrl;
656
657 ILO_DEV_ASSERT(dev, 6, 8);
658
659 if (sampler->non_normalized) {
660 /* see sampler_validate_gen6_non_normalized() */
661 assert(surf->type == GEN6_SURFTYPE_2D ||
662 surf->type == GEN6_SURFTYPE_3D);
663 assert(!surf->min_lod && !surf->mip_count);
664 }
665
666 if (sampler->base_to_surf_min_lod) {
667 const uint8_t base = surf->min_lod << GEN6_SAMPLER_DW0_BASE_LOD__RADIX;
668
669 sampler->sampler[0] =
670 (sampler->sampler[0] & ~GEN6_SAMPLER_DW0_BASE_LOD__MASK) |
671 base << GEN6_SAMPLER_DW0_BASE_LOD__SHIFT;
672 }
673
674 if (surf->is_integer || surf->type == GEN6_SURFTYPE_3D) {
675 const uint32_t mask = (GEN6_SAMPLER_DW0_MIP_FILTER__MASK |
676 GEN6_SAMPLER_DW0_MIN_FILTER__MASK |
677 GEN6_SAMPLER_DW0_MAG_FILTER__MASK);
678 const uint32_t filter = (surf->is_integer) ?
679 sampler->filter_integer : sampler->filter_3d;
680
681 assert((filter & mask) == filter);
682 sampler->sampler[0] = (sampler->sampler[0] & ~mask) |
683 filter;
684 }
685
686 switch (surf->type) {
687 case GEN6_SURFTYPE_1D:
688 addr_ctrl = sampler->addr_ctrl_1d;
689 break;
690 case GEN6_SURFTYPE_2D:
691 case GEN6_SURFTYPE_3D:
692 addr_ctrl = sampler->addr_ctrl_2d_3d;
693 break;
694 case GEN6_SURFTYPE_CUBE:
695 addr_ctrl = sampler->addr_ctrl_cube;
696 break;
697 default:
698 assert(!"unexpected surface type");
699 addr_ctrl = 0;
700 break;
701 }
702
703 if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
704 const uint32_t mask = (GEN7_SAMPLER_DW3_U_WRAP__MASK |
705 GEN7_SAMPLER_DW3_V_WRAP__MASK |
706 GEN7_SAMPLER_DW3_R_WRAP__MASK);
707
708 assert((addr_ctrl & mask) == addr_ctrl);
709 sampler->sampler[2] = (sampler->sampler[2] & ~mask) |
710 addr_ctrl;
711 } else {
712 const uint32_t mask = (GEN6_SAMPLER_DW1_U_WRAP__MASK |
713 GEN6_SAMPLER_DW1_V_WRAP__MASK |
714 GEN6_SAMPLER_DW1_R_WRAP__MASK);
715
716 assert((addr_ctrl & mask) == addr_ctrl);
717 sampler->sampler[1] = (sampler->sampler[1] & ~mask) |
718 addr_ctrl;
719 }
720
721 return true;
722 }
723
724 bool
ilo_state_sampler_border_init(struct ilo_state_sampler_border * border,const struct ilo_dev * dev,const struct ilo_state_sampler_border_info * info)725 ilo_state_sampler_border_init(struct ilo_state_sampler_border *border,
726 const struct ilo_dev *dev,
727 const struct ilo_state_sampler_border_info *info)
728 {
729 bool ret = true;
730
731 if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
732 ret &= sampler_border_set_gen7_SAMPLER_BORDER_COLOR_STATE(border,
733 dev, info);
734 } else {
735 ret &= sampler_border_set_gen6_SAMPLER_BORDER_COLOR_STATE(border,
736 dev, info);
737 }
738
739 assert(ret);
740
741 return ret;
742 }
743