vk: Add four unit tests for our lock-free data-structures
[mesa.git] / src / mesa / drivers / dri / i965 / brw_sampler_state.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keithw@vmware.com>
30 */
31
32 /**
33 * @file brw_sampler_state.c
34 *
35 * This file contains code for emitting SAMPLER_STATE structures, which
36 * specifies filter modes, wrap modes, border color, and so on.
37 */
38
39 #include "brw_context.h"
40 #include "brw_state.h"
41 #include "brw_defines.h"
42 #include "intel_batchbuffer.h"
43 #include "intel_mipmap_tree.h"
44
45 #include "main/macros.h"
46 #include "main/samplerobj.h"
47
48 /**
49 * Emit a 3DSTATE_SAMPLER_STATE_POINTERS_{VS,HS,GS,DS,PS} packet.
50 */
51 static void
52 gen7_emit_sampler_state_pointers_xs(struct brw_context *brw,
53 struct brw_stage_state *stage_state)
54 {
55 static const uint16_t packet_headers[] = {
56 [MESA_SHADER_VERTEX] = _3DSTATE_SAMPLER_STATE_POINTERS_VS,
57 [MESA_SHADER_GEOMETRY] = _3DSTATE_SAMPLER_STATE_POINTERS_GS,
58 [MESA_SHADER_FRAGMENT] = _3DSTATE_SAMPLER_STATE_POINTERS_PS,
59 };
60
61 /* Ivybridge requires a workaround flush before VS packets. */
62 if (brw->gen == 7 && !brw->is_haswell && !brw->is_baytrail &&
63 stage_state->stage == MESA_SHADER_VERTEX) {
64 gen7_emit_vs_workaround_flush(brw);
65 }
66
67 BEGIN_BATCH(2);
68 OUT_BATCH(packet_headers[stage_state->stage] << 16 | (2 - 2));
69 OUT_BATCH(stage_state->sampler_offset);
70 ADVANCE_BATCH();
71 }
72
73 /**
74 * Emit a SAMPLER_STATE structure, given all the fields.
75 */
76 void
77 brw_emit_sampler_state(struct brw_context *brw,
78 uint32_t *ss,
79 uint32_t batch_offset_for_sampler_state,
80 unsigned min_filter,
81 unsigned mag_filter,
82 unsigned mip_filter,
83 unsigned max_anisotropy,
84 unsigned address_rounding,
85 unsigned wrap_s,
86 unsigned wrap_t,
87 unsigned wrap_r,
88 unsigned min_lod,
89 unsigned max_lod,
90 int lod_bias,
91 unsigned base_level,
92 unsigned shadow_function,
93 bool non_normalized_coordinates,
94 uint32_t border_color_offset)
95 {
96 ss[0] = BRW_SAMPLER_LOD_PRECLAMP_ENABLE |
97 SET_FIELD(base_level, BRW_SAMPLER_BASE_MIPLEVEL) |
98 SET_FIELD(mip_filter, BRW_SAMPLER_MIP_FILTER) |
99 SET_FIELD(mag_filter, BRW_SAMPLER_MAG_FILTER) |
100 SET_FIELD(min_filter, BRW_SAMPLER_MIN_FILTER);
101
102 ss[2] = border_color_offset;
103 if (brw->gen < 6) {
104 ss[2] += brw->batch.bo->offset64; /* reloc */
105 drm_intel_bo_emit_reloc(brw->batch.bo,
106 batch_offset_for_sampler_state + 8,
107 brw->batch.bo, border_color_offset,
108 I915_GEM_DOMAIN_SAMPLER, 0);
109 }
110
111 ss[3] = SET_FIELD(max_anisotropy, BRW_SAMPLER_MAX_ANISOTROPY) |
112 SET_FIELD(address_rounding, BRW_SAMPLER_ADDRESS_ROUNDING);
113
114 if (brw->gen >= 7) {
115 ss[0] |= SET_FIELD(lod_bias & 0x1fff, GEN7_SAMPLER_LOD_BIAS);
116
117 if (min_filter == BRW_MAPFILTER_ANISOTROPIC)
118 ss[0] |= GEN7_SAMPLER_EWA_ANISOTROPIC_ALGORITHM;
119
120 ss[1] = SET_FIELD(min_lod, GEN7_SAMPLER_MIN_LOD) |
121 SET_FIELD(max_lod, GEN7_SAMPLER_MAX_LOD) |
122 SET_FIELD(shadow_function, GEN7_SAMPLER_SHADOW_FUNCTION);
123
124 ss[3] |= SET_FIELD(wrap_s, BRW_SAMPLER_TCX_WRAP_MODE) |
125 SET_FIELD(wrap_t, BRW_SAMPLER_TCY_WRAP_MODE) |
126 SET_FIELD(wrap_r, BRW_SAMPLER_TCZ_WRAP_MODE);
127
128 if (non_normalized_coordinates)
129 ss[3] |= GEN7_SAMPLER_NON_NORMALIZED_COORDINATES;
130 } else {
131 ss[0] |= SET_FIELD(lod_bias & 0x7ff, GEN4_SAMPLER_LOD_BIAS) |
132 SET_FIELD(shadow_function, GEN4_SAMPLER_SHADOW_FUNCTION);
133
134 if (brw->gen == 6 && min_filter != mag_filter)
135 ss[0] |= GEN6_SAMPLER_MIN_MAG_NOT_EQUAL;
136
137 ss[1] = SET_FIELD(min_lod, GEN4_SAMPLER_MIN_LOD) |
138 SET_FIELD(max_lod, GEN4_SAMPLER_MAX_LOD) |
139 SET_FIELD(wrap_s, BRW_SAMPLER_TCX_WRAP_MODE) |
140 SET_FIELD(wrap_t, BRW_SAMPLER_TCY_WRAP_MODE) |
141 SET_FIELD(wrap_r, BRW_SAMPLER_TCZ_WRAP_MODE);
142
143 if (brw->gen >= 6 && non_normalized_coordinates)
144 ss[3] |= GEN6_SAMPLER_NON_NORMALIZED_COORDINATES;
145 }
146 }
147
148 static uint32_t
149 translate_wrap_mode(struct brw_context *brw, GLenum wrap, bool using_nearest)
150 {
151 switch( wrap ) {
152 case GL_REPEAT:
153 return BRW_TEXCOORDMODE_WRAP;
154 case GL_CLAMP:
155 /* GL_CLAMP is the weird mode where coordinates are clamped to
156 * [0.0, 1.0], so linear filtering of coordinates outside of
157 * [0.0, 1.0] give you half edge texel value and half border
158 * color.
159 *
160 * Gen8+ supports this natively.
161 */
162 if (brw->gen >= 8)
163 return GEN8_TEXCOORDMODE_HALF_BORDER;
164
165 /* On Gen4-7.5, we clamp the coordinates in the fragment shader
166 * and set clamp_border here, which gets the result desired.
167 * We just use clamp(_to_edge) for nearest, because for nearest
168 * clamping to 1.0 gives border color instead of the desired
169 * edge texels.
170 */
171 if (using_nearest)
172 return BRW_TEXCOORDMODE_CLAMP;
173 else
174 return BRW_TEXCOORDMODE_CLAMP_BORDER;
175 case GL_CLAMP_TO_EDGE:
176 return BRW_TEXCOORDMODE_CLAMP;
177 case GL_CLAMP_TO_BORDER:
178 return BRW_TEXCOORDMODE_CLAMP_BORDER;
179 case GL_MIRRORED_REPEAT:
180 return BRW_TEXCOORDMODE_MIRROR;
181 case GL_MIRROR_CLAMP_TO_EDGE:
182 return BRW_TEXCOORDMODE_MIRROR_ONCE;
183 default:
184 return BRW_TEXCOORDMODE_WRAP;
185 }
186 }
187
188 /**
189 * Return true if the given wrap mode requires the border color to exist.
190 */
191 static bool
192 wrap_mode_needs_border_color(unsigned wrap_mode)
193 {
194 return wrap_mode == BRW_TEXCOORDMODE_CLAMP_BORDER ||
195 wrap_mode == GEN8_TEXCOORDMODE_HALF_BORDER;
196 }
197
198 /**
199 * Upload SAMPLER_BORDER_COLOR_STATE.
200 */
201 static void
202 upload_default_color(struct brw_context *brw,
203 const struct gl_sampler_object *sampler,
204 mesa_format format, GLenum base_format,
205 bool is_integer_format,
206 uint32_t *sdc_offset)
207 {
208 union gl_color_union color;
209
210 switch (base_format) {
211 case GL_DEPTH_COMPONENT:
212 /* GL specs that border color for depth textures is taken from the
213 * R channel, while the hardware uses A. Spam R into all the
214 * channels for safety.
215 */
216 color.ui[0] = sampler->BorderColor.ui[0];
217 color.ui[1] = sampler->BorderColor.ui[0];
218 color.ui[2] = sampler->BorderColor.ui[0];
219 color.ui[3] = sampler->BorderColor.ui[0];
220 break;
221 case GL_ALPHA:
222 color.ui[0] = 0u;
223 color.ui[1] = 0u;
224 color.ui[2] = 0u;
225 color.ui[3] = sampler->BorderColor.ui[3];
226 break;
227 case GL_INTENSITY:
228 color.ui[0] = sampler->BorderColor.ui[0];
229 color.ui[1] = sampler->BorderColor.ui[0];
230 color.ui[2] = sampler->BorderColor.ui[0];
231 color.ui[3] = sampler->BorderColor.ui[0];
232 break;
233 case GL_LUMINANCE:
234 color.ui[0] = sampler->BorderColor.ui[0];
235 color.ui[1] = sampler->BorderColor.ui[0];
236 color.ui[2] = sampler->BorderColor.ui[0];
237 color.ui[3] = float_as_int(1.0);
238 break;
239 case GL_LUMINANCE_ALPHA:
240 color.ui[0] = sampler->BorderColor.ui[0];
241 color.ui[1] = sampler->BorderColor.ui[0];
242 color.ui[2] = sampler->BorderColor.ui[0];
243 color.ui[3] = sampler->BorderColor.ui[3];
244 break;
245 default:
246 color.ui[0] = sampler->BorderColor.ui[0];
247 color.ui[1] = sampler->BorderColor.ui[1];
248 color.ui[2] = sampler->BorderColor.ui[2];
249 color.ui[3] = sampler->BorderColor.ui[3];
250 break;
251 }
252
253 /* In some cases we use an RGBA surface format for GL RGB textures,
254 * where we've initialized the A channel to 1.0. We also have to set
255 * the border color alpha to 1.0 in that case.
256 */
257 if (base_format == GL_RGB)
258 color.ui[3] = float_as_int(1.0);
259
260 if (brw->gen >= 8) {
261 /* On Broadwell, the border color is represented as four 32-bit floats,
262 * integers, or unsigned values, interpreted according to the surface
263 * format. This matches the sampler->BorderColor union exactly; just
264 * memcpy the values.
265 */
266 uint32_t *sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR,
267 4 * 4, 64, sdc_offset);
268 memcpy(sdc, color.ui, 4 * 4);
269 } else if (brw->is_haswell && is_integer_format) {
270 /* Haswell's integer border color support is completely insane:
271 * SAMPLER_BORDER_COLOR_STATE is 20 DWords. The first four are
272 * for float colors. The next 12 DWords are MBZ and only exist to
273 * pad it out to a 64 byte cacheline boundary. DWords 16-19 then
274 * contain integer colors; these are only used if SURFACE_STATE
275 * has the "Integer Surface Format" bit set. Even then, the
276 * arrangement of the RGBA data devolves into madness.
277 */
278 uint32_t *sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR,
279 20 * 4, 512, sdc_offset);
280 memset(sdc, 0, 20 * 4);
281 sdc = &sdc[16];
282
283 int bits_per_channel = _mesa_get_format_bits(format, GL_RED_BITS);
284
285 /* From the Haswell PRM, "Command Reference: Structures", Page 36:
286 * "If any color channel is missing from the surface format,
287 * corresponding border color should be programmed as zero and if
288 * alpha channel is missing, corresponding Alpha border color should
289 * be programmed as 1."
290 */
291 unsigned c[4] = { 0, 0, 0, 1 };
292 for (int i = 0; i < 4; i++) {
293 if (_mesa_format_has_color_component(format, i))
294 c[i] = color.ui[i];
295 }
296
297 switch (bits_per_channel) {
298 case 8:
299 /* Copy RGBA in order. */
300 for (int i = 0; i < 4; i++)
301 ((uint8_t *) sdc)[i] = c[i];
302 break;
303 case 10:
304 /* R10G10B10A2_UINT is treated like a 16-bit format. */
305 case 16:
306 ((uint16_t *) sdc)[0] = c[0]; /* R -> DWord 0, bits 15:0 */
307 ((uint16_t *) sdc)[1] = c[1]; /* G -> DWord 0, bits 31:16 */
308 /* DWord 1 is Reserved/MBZ! */
309 ((uint16_t *) sdc)[4] = c[2]; /* B -> DWord 2, bits 15:0 */
310 ((uint16_t *) sdc)[5] = c[3]; /* A -> DWord 3, bits 31:16 */
311 break;
312 case 32:
313 if (base_format == GL_RG) {
314 /* Careful inspection of the tables reveals that for RG32 formats,
315 * the green channel needs to go where blue normally belongs.
316 */
317 sdc[0] = c[0];
318 sdc[2] = c[1];
319 sdc[3] = 1;
320 } else {
321 /* Copy RGBA in order. */
322 for (int i = 0; i < 4; i++)
323 sdc[i] = c[i];
324 }
325 break;
326 default:
327 assert(!"Invalid number of bits per channel in integer format.");
328 break;
329 }
330 } else if (brw->gen == 5 || brw->gen == 6) {
331 struct gen5_sampler_default_color *sdc;
332
333 sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR,
334 sizeof(*sdc), 32, sdc_offset);
335
336 memset(sdc, 0, sizeof(*sdc));
337
338 UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[0], color.f[0]);
339 UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[1], color.f[1]);
340 UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[2], color.f[2]);
341 UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[3], color.f[3]);
342
343 UNCLAMPED_FLOAT_TO_USHORT(sdc->us[0], color.f[0]);
344 UNCLAMPED_FLOAT_TO_USHORT(sdc->us[1], color.f[1]);
345 UNCLAMPED_FLOAT_TO_USHORT(sdc->us[2], color.f[2]);
346 UNCLAMPED_FLOAT_TO_USHORT(sdc->us[3], color.f[3]);
347
348 UNCLAMPED_FLOAT_TO_SHORT(sdc->s[0], color.f[0]);
349 UNCLAMPED_FLOAT_TO_SHORT(sdc->s[1], color.f[1]);
350 UNCLAMPED_FLOAT_TO_SHORT(sdc->s[2], color.f[2]);
351 UNCLAMPED_FLOAT_TO_SHORT(sdc->s[3], color.f[3]);
352
353 sdc->hf[0] = _mesa_float_to_half(color.f[0]);
354 sdc->hf[1] = _mesa_float_to_half(color.f[1]);
355 sdc->hf[2] = _mesa_float_to_half(color.f[2]);
356 sdc->hf[3] = _mesa_float_to_half(color.f[3]);
357
358 sdc->b[0] = sdc->s[0] >> 8;
359 sdc->b[1] = sdc->s[1] >> 8;
360 sdc->b[2] = sdc->s[2] >> 8;
361 sdc->b[3] = sdc->s[3] >> 8;
362
363 sdc->f[0] = color.f[0];
364 sdc->f[1] = color.f[1];
365 sdc->f[2] = color.f[2];
366 sdc->f[3] = color.f[3];
367 } else {
368 float *sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR,
369 4 * 4, 32, sdc_offset);
370 memcpy(sdc, color.f, 4 * 4);
371 }
372 }
373
374 /**
375 * Sets the sampler state for a single unit based off of the sampler key
376 * entry.
377 */
378 void
379 brw_update_sampler_state(struct brw_context *brw,
380 GLenum target, bool tex_cube_map_seamless,
381 GLfloat tex_unit_lod_bias,
382 mesa_format format, GLenum base_format,
383 bool is_integer_format,
384 const struct gl_sampler_object *sampler,
385 uint32_t *sampler_state,
386 uint32_t batch_offset_for_sampler_state)
387 {
388 unsigned min_filter, mag_filter, mip_filter;
389
390 /* Select min and mip filters. */
391 switch (sampler->MinFilter) {
392 case GL_NEAREST:
393 min_filter = BRW_MAPFILTER_NEAREST;
394 mip_filter = BRW_MIPFILTER_NONE;
395 break;
396 case GL_LINEAR:
397 min_filter = BRW_MAPFILTER_LINEAR;
398 mip_filter = BRW_MIPFILTER_NONE;
399 break;
400 case GL_NEAREST_MIPMAP_NEAREST:
401 min_filter = BRW_MAPFILTER_NEAREST;
402 mip_filter = BRW_MIPFILTER_NEAREST;
403 break;
404 case GL_LINEAR_MIPMAP_NEAREST:
405 min_filter = BRW_MAPFILTER_LINEAR;
406 mip_filter = BRW_MIPFILTER_NEAREST;
407 break;
408 case GL_NEAREST_MIPMAP_LINEAR:
409 min_filter = BRW_MAPFILTER_NEAREST;
410 mip_filter = BRW_MIPFILTER_LINEAR;
411 break;
412 case GL_LINEAR_MIPMAP_LINEAR:
413 min_filter = BRW_MAPFILTER_LINEAR;
414 mip_filter = BRW_MIPFILTER_LINEAR;
415 break;
416 default:
417 unreachable("not reached");
418 }
419
420 /* Select mag filter. */
421 if (sampler->MagFilter == GL_LINEAR)
422 mag_filter = BRW_MAPFILTER_LINEAR;
423 else
424 mag_filter = BRW_MAPFILTER_NEAREST;
425
426 /* Enable anisotropic filtering if desired. */
427 unsigned max_anisotropy = BRW_ANISORATIO_2;
428 if (sampler->MaxAnisotropy > 1.0) {
429 min_filter = BRW_MAPFILTER_ANISOTROPIC;
430 mag_filter = BRW_MAPFILTER_ANISOTROPIC;
431
432 if (sampler->MaxAnisotropy > 2.0) {
433 max_anisotropy =
434 MIN2((sampler->MaxAnisotropy - 2) / 2, BRW_ANISORATIO_16);
435 }
436 }
437
438 /* Set address rounding bits if not using nearest filtering. */
439 unsigned address_rounding = 0;
440 if (min_filter != BRW_MAPFILTER_NEAREST) {
441 address_rounding |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN |
442 BRW_ADDRESS_ROUNDING_ENABLE_V_MIN |
443 BRW_ADDRESS_ROUNDING_ENABLE_R_MIN;
444 }
445 if (mag_filter != BRW_MAPFILTER_NEAREST) {
446 address_rounding |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG |
447 BRW_ADDRESS_ROUNDING_ENABLE_V_MAG |
448 BRW_ADDRESS_ROUNDING_ENABLE_R_MAG;
449 }
450
451 bool either_nearest =
452 sampler->MinFilter == GL_NEAREST || sampler->MagFilter == GL_NEAREST;
453 unsigned wrap_s = translate_wrap_mode(brw, sampler->WrapS, either_nearest);
454 unsigned wrap_t = translate_wrap_mode(brw, sampler->WrapT, either_nearest);
455 unsigned wrap_r = translate_wrap_mode(brw, sampler->WrapR, either_nearest);
456
457 if (target == GL_TEXTURE_CUBE_MAP ||
458 target == GL_TEXTURE_CUBE_MAP_ARRAY) {
459 /* Cube maps must use the same wrap mode for all three coordinate
460 * dimensions. Prior to Haswell, only CUBE and CLAMP are valid.
461 */
462 if ((tex_cube_map_seamless || sampler->CubeMapSeamless) &&
463 (sampler->MinFilter != GL_NEAREST ||
464 sampler->MagFilter != GL_NEAREST)) {
465 wrap_s = BRW_TEXCOORDMODE_CUBE;
466 wrap_t = BRW_TEXCOORDMODE_CUBE;
467 wrap_r = BRW_TEXCOORDMODE_CUBE;
468 } else {
469 wrap_s = BRW_TEXCOORDMODE_CLAMP;
470 wrap_t = BRW_TEXCOORDMODE_CLAMP;
471 wrap_r = BRW_TEXCOORDMODE_CLAMP;
472 }
473 } else if (target == GL_TEXTURE_1D) {
474 /* There's a bug in 1D texture sampling - it actually pays
475 * attention to the wrap_t value, though it should not.
476 * Override the wrap_t value here to GL_REPEAT to keep
477 * any nonexistent border pixels from floating in.
478 */
479 wrap_t = BRW_TEXCOORDMODE_WRAP;
480 }
481
482 /* Set shadow function. */
483 unsigned shadow_function = 0;
484 if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
485 shadow_function =
486 intel_translate_shadow_compare_func(sampler->CompareFunc);
487 }
488
489 const int lod_bits = brw->gen >= 7 ? 8 : 6;
490 const unsigned min_lod = U_FIXED(CLAMP(sampler->MinLod, 0, 13), lod_bits);
491 const unsigned max_lod = U_FIXED(CLAMP(sampler->MaxLod, 0, 13), lod_bits);
492 const int lod_bias =
493 S_FIXED(CLAMP(tex_unit_lod_bias + sampler->LodBias, -16, 15), lod_bits);
494 const unsigned base_level = U_FIXED(0, 1);
495
496 /* Upload the border color if necessary. If not, just point it at
497 * offset 0 (the start of the batch) - the color should be ignored,
498 * but that address won't fault in case something reads it anyway.
499 */
500 uint32_t border_color_offset = 0;
501 if (wrap_mode_needs_border_color(wrap_s) ||
502 wrap_mode_needs_border_color(wrap_t) ||
503 wrap_mode_needs_border_color(wrap_r)) {
504 upload_default_color(brw, sampler,
505 format, base_format, is_integer_format,
506 &border_color_offset);
507 }
508
509 const bool non_normalized_coords = target == GL_TEXTURE_RECTANGLE;
510
511 brw_emit_sampler_state(brw,
512 sampler_state,
513 batch_offset_for_sampler_state,
514 min_filter, mag_filter, mip_filter,
515 max_anisotropy,
516 address_rounding,
517 wrap_s, wrap_t, wrap_r,
518 min_lod, max_lod, lod_bias, base_level,
519 shadow_function,
520 non_normalized_coords,
521 border_color_offset);
522 }
523
524 static void
525 update_sampler_state(struct brw_context *brw,
526 int unit,
527 uint32_t *sampler_state,
528 uint32_t batch_offset_for_sampler_state)
529 {
530 struct gl_context *ctx = &brw->ctx;
531 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
532 const struct gl_texture_object *texObj = texUnit->_Current;
533 const struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
534
535 /* These don't use samplers at all. */
536 if (texObj->Target == GL_TEXTURE_BUFFER)
537 return;
538
539 struct gl_texture_image *firstImage = texObj->Image[0][texObj->BaseLevel];
540 brw_update_sampler_state(brw, texObj->Target, ctx->Texture.CubeMapSeamless,
541 texUnit->LodBias,
542 firstImage->TexFormat, firstImage->_BaseFormat,
543 texObj->_IsIntegerFormat,
544 sampler,
545 sampler_state, batch_offset_for_sampler_state);
546 }
547
548 static void
549 brw_upload_sampler_state_table(struct brw_context *brw,
550 struct gl_program *prog,
551 struct brw_stage_state *stage_state)
552 {
553 struct gl_context *ctx = &brw->ctx;
554 uint32_t sampler_count = stage_state->sampler_count;
555
556 GLbitfield SamplersUsed = prog->SamplersUsed;
557
558 if (sampler_count == 0)
559 return;
560
561 /* SAMPLER_STATE is 4 DWords on all platforms. */
562 const int dwords = 4;
563 const int size_in_bytes = dwords * sizeof(uint32_t);
564
565 uint32_t *sampler_state = brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE,
566 sampler_count * size_in_bytes,
567 32, &stage_state->sampler_offset);
568 memset(sampler_state, 0, sampler_count * size_in_bytes);
569
570 uint32_t batch_offset_for_sampler_state = stage_state->sampler_offset;
571
572 for (unsigned s = 0; s < sampler_count; s++) {
573 if (SamplersUsed & (1 << s)) {
574 const unsigned unit = prog->SamplerUnits[s];
575 if (ctx->Texture.Unit[unit]._Current) {
576 update_sampler_state(brw, unit, sampler_state,
577 batch_offset_for_sampler_state);
578 }
579 }
580
581 sampler_state += dwords;
582 batch_offset_for_sampler_state += size_in_bytes;
583 }
584
585 if (brw->gen >= 7) {
586 /* Emit a 3DSTATE_SAMPLER_STATE_POINTERS_XS packet. */
587 gen7_emit_sampler_state_pointers_xs(brw, stage_state);
588 } else {
589 /* Flag that the sampler state table pointer has changed; later atoms
590 * will handle it.
591 */
592 brw->ctx.NewDriverState |= BRW_NEW_SAMPLER_STATE_TABLE;
593 }
594 }
595
596 static void
597 brw_upload_fs_samplers(struct brw_context *brw)
598 {
599 /* BRW_NEW_FRAGMENT_PROGRAM */
600 struct gl_program *fs = (struct gl_program *) brw->fragment_program;
601 brw_upload_sampler_state_table(brw, fs, &brw->wm.base);
602 }
603
604 const struct brw_tracked_state brw_fs_samplers = {
605 .dirty = {
606 .mesa = _NEW_TEXTURE,
607 .brw = BRW_NEW_BATCH |
608 BRW_NEW_FRAGMENT_PROGRAM,
609 },
610 .emit = brw_upload_fs_samplers,
611 };
612
613 static void
614 brw_upload_vs_samplers(struct brw_context *brw)
615 {
616 /* BRW_NEW_VERTEX_PROGRAM */
617 struct gl_program *vs = (struct gl_program *) brw->vertex_program;
618 brw_upload_sampler_state_table(brw, vs, &brw->vs.base);
619 }
620
621
622 const struct brw_tracked_state brw_vs_samplers = {
623 .dirty = {
624 .mesa = _NEW_TEXTURE,
625 .brw = BRW_NEW_BATCH |
626 BRW_NEW_VERTEX_PROGRAM,
627 },
628 .emit = brw_upload_vs_samplers,
629 };
630
631
632 static void
633 brw_upload_gs_samplers(struct brw_context *brw)
634 {
635 /* BRW_NEW_GEOMETRY_PROGRAM */
636 struct gl_program *gs = (struct gl_program *) brw->geometry_program;
637 if (!gs)
638 return;
639
640 brw_upload_sampler_state_table(brw, gs, &brw->gs.base);
641 }
642
643
644 const struct brw_tracked_state brw_gs_samplers = {
645 .dirty = {
646 .mesa = _NEW_TEXTURE,
647 .brw = BRW_NEW_BATCH |
648 BRW_NEW_GEOMETRY_PROGRAM,
649 },
650 .emit = brw_upload_gs_samplers,
651 };