1 /*
2  * Copyright 2008 Ben Skeggs
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 
23 #include "nvc0_context.h"
24 #include "nvc0_resource.h"
25 #include "nv50/nv50_texture.xml.h"
26 
27 #include "util/u_format.h"
28 
29 #define NVE4_TIC_ENTRY_INVALID 0x000fffff
30 #define NVE4_TSC_ENTRY_INVALID 0xfff00000
31 
32 #define NV50_TIC_0_SWIZZLE__MASK                      \
33    (NV50_TIC_0_MAPA__MASK | NV50_TIC_0_MAPB__MASK |   \
34     NV50_TIC_0_MAPG__MASK | NV50_TIC_0_MAPR__MASK)
35 
36 static INLINE uint32_t
nv50_tic_swizzle(uint32_t tc,unsigned swz,boolean tex_int)37 nv50_tic_swizzle(uint32_t tc, unsigned swz, boolean tex_int)
38 {
39    switch (swz) {
40    case PIPE_SWIZZLE_RED:
41       return (tc & NV50_TIC_0_MAPR__MASK) >> NV50_TIC_0_MAPR__SHIFT;
42    case PIPE_SWIZZLE_GREEN:
43       return (tc & NV50_TIC_0_MAPG__MASK) >> NV50_TIC_0_MAPG__SHIFT;
44    case PIPE_SWIZZLE_BLUE:
45       return (tc & NV50_TIC_0_MAPB__MASK) >> NV50_TIC_0_MAPB__SHIFT;
46    case PIPE_SWIZZLE_ALPHA:
47       return (tc & NV50_TIC_0_MAPA__MASK) >> NV50_TIC_0_MAPA__SHIFT;
48    case PIPE_SWIZZLE_ONE:
49       return tex_int ? NV50_TIC_MAP_ONE_INT : NV50_TIC_MAP_ONE_FLOAT;
50    case PIPE_SWIZZLE_ZERO:
51    default:
52       return NV50_TIC_MAP_ZERO;
53    }
54 }
55 
56 struct pipe_sampler_view *
nvc0_create_sampler_view(struct pipe_context * pipe,struct pipe_resource * texture,const struct pipe_sampler_view * templ)57 nvc0_create_sampler_view(struct pipe_context *pipe,
58                          struct pipe_resource *texture,
59                          const struct pipe_sampler_view *templ)
60 {
61    const struct util_format_description *desc;
62    uint64_t address;
63    uint32_t *tic;
64    uint32_t swz[4];
65    uint32_t depth;
66    struct nv50_tic_entry *view;
67    struct nv50_miptree *mt;
68    boolean tex_int;
69 
70    view = MALLOC_STRUCT(nv50_tic_entry);
71    if (!view)
72       return NULL;
73    mt = nv50_miptree(texture);
74 
75    view->pipe = *templ;
76    view->pipe.reference.count = 1;
77    view->pipe.texture = NULL;
78    view->pipe.context = pipe;
79 
80    view->id = -1;
81 
82    pipe_resource_reference(&view->pipe.texture, texture);
83 
84    tic = &view->tic[0];
85 
86    desc = util_format_description(view->pipe.format);
87 
88    tic[0] = nvc0_format_table[view->pipe.format].tic;
89 
90    tex_int = util_format_is_pure_integer(view->pipe.format);
91 
92    swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r, tex_int);
93    swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g, tex_int);
94    swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b, tex_int);
95    swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a, tex_int);
96    tic[0] = (tic[0] & ~NV50_TIC_0_SWIZZLE__MASK) |
97       (swz[0] << NV50_TIC_0_MAPR__SHIFT) |
98       (swz[1] << NV50_TIC_0_MAPG__SHIFT) |
99       (swz[2] << NV50_TIC_0_MAPB__SHIFT) |
100       (swz[3] << NV50_TIC_0_MAPA__SHIFT);
101 
102    address = mt->base.address;
103 
104    tic[2] = 0x10001000 | NV50_TIC_2_NO_BORDER;
105 
106    if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
107       tic[2] |= NV50_TIC_2_COLORSPACE_SRGB;
108 
109    /* check for linear storage type */
110    if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
111       if (texture->target == PIPE_BUFFER) {
112          address +=
113             view->pipe.u.buf.first_element * desc->block.bits / 8;
114          tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_BUFFER;
115          tic[3] = 0;
116          tic[4] = /* width */
117             view->pipe.u.buf.last_element - view->pipe.u.buf.first_element + 1;
118          tic[5] = 0;
119       } else {
120          /* must be 2D texture without mip maps */
121          tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_RECT;
122          if (texture->target != PIPE_TEXTURE_RECT)
123             tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;
124          tic[3] = mt->level[0].pitch;
125          tic[4] = mt->base.base.width0;
126          tic[5] = (1 << 16) | mt->base.base.height0;
127       }
128       tic[6] =
129       tic[7] = 0;
130       tic[1] = address;
131       tic[2] |= address >> 32;
132       return &view->pipe;
133    }
134 
135    if (mt->base.base.target != PIPE_TEXTURE_RECT)
136       tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;
137 
138    tic[2] |=
139       ((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) |
140       ((mt->level[0].tile_mode & 0xf00) << (25 - 8));
141 
142    depth = MAX2(mt->base.base.array_size, mt->base.base.depth0);
143 
144    if (mt->base.base.array_size > 1) {
145       /* there doesn't seem to be a base layer field in TIC */
146       address += view->pipe.u.tex.first_layer * mt->layer_stride;
147       depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1;
148    }
149    tic[1] = address;
150    tic[2] |= address >> 32;
151 
152    switch (mt->base.base.target) {
153    case PIPE_TEXTURE_1D:
154       tic[2] |= NV50_TIC_2_TARGET_1D;
155       break;
156 /* case PIPE_TEXTURE_2D_MS: */
157    case PIPE_TEXTURE_2D:
158       tic[2] |= NV50_TIC_2_TARGET_2D;
159       break;
160    case PIPE_TEXTURE_RECT:
161       tic[2] |= NV50_TIC_2_TARGET_RECT;
162       break;
163    case PIPE_TEXTURE_3D:
164       tic[2] |= NV50_TIC_2_TARGET_3D;
165       break;
166    case PIPE_TEXTURE_CUBE:
167       depth /= 6;
168       if (depth > 1)
169          tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
170       else
171          tic[2] |= NV50_TIC_2_TARGET_CUBE;
172       break;
173    case PIPE_TEXTURE_1D_ARRAY:
174       tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
175       break;
176 /* case PIPE_TEXTURE_2D_ARRAY_MS: */
177    case PIPE_TEXTURE_2D_ARRAY:
178       tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
179       break;
180    default:
181       NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target);
182       return FALSE;
183    }
184 
185    if (mt->base.base.target == PIPE_BUFFER)
186       tic[3] = mt->base.base.width0;
187    else
188       tic[3] = 0x00300000;
189 
190    tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);
191 
192    tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
193    tic[5] |= depth << 16;
194    tic[5] |= mt->base.base.last_level << 28;
195 
196    tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */
197 
198    tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
199 
200    /*
201    if (mt->base.base.target == PIPE_TEXTURE_2D_MS ||
202        mt->base.base.target == PIPE_TEXTURE_2D_ARRAY_MS)
203       tic[7] |= mt->ms_mode << 12;
204    */
205 
206    return &view->pipe;
207 }
208 
209 static boolean
nvc0_validate_tic(struct nvc0_context * nvc0,int s)210 nvc0_validate_tic(struct nvc0_context *nvc0, int s)
211 {
212    uint32_t commands[32];
213    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
214    struct nouveau_bo *txc = nvc0->screen->txc;
215    unsigned i;
216    unsigned n = 0;
217    boolean need_flush = FALSE;
218 
219    for (i = 0; i < nvc0->num_textures[s]; ++i) {
220       struct nv50_tic_entry *tic = nv50_tic_entry(nvc0->textures[s][i]);
221       struct nv04_resource *res;
222       const boolean dirty = !!(nvc0->textures_dirty[s] & (1 << i));
223 
224       if (!tic) {
225          if (dirty)
226             commands[n++] = (i << 1) | 0;
227          continue;
228       }
229       res = nv04_resource(tic->pipe.texture);
230 
231       if (tic->id < 0) {
232          tic->id = nvc0_screen_tic_alloc(nvc0->screen, tic);
233 
234          PUSH_SPACE(push, 17);
235          BEGIN_NVC0(push, NVC0_M2MF(OFFSET_OUT_HIGH), 2);
236          PUSH_DATAh(push, txc->offset + (tic->id * 32));
237          PUSH_DATA (push, txc->offset + (tic->id * 32));
238          BEGIN_NVC0(push, NVC0_M2MF(LINE_LENGTH_IN), 2);
239          PUSH_DATA (push, 32);
240          PUSH_DATA (push, 1);
241          BEGIN_NVC0(push, NVC0_M2MF(EXEC), 1);
242          PUSH_DATA (push, 0x100111);
243          BEGIN_NIC0(push, NVC0_M2MF(DATA), 8);
244          PUSH_DATAp(push, &tic->tic[0], 8);
245 
246          need_flush = TRUE;
247       } else
248       if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
249          BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1);
250          PUSH_DATA (push, (tic->id << 4) | 1);
251       }
252       nvc0->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
253 
254       res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING;
255       res->status |=  NOUVEAU_BUFFER_STATUS_GPU_READING;
256 
257       if (!dirty)
258          continue;
259       commands[n++] = (tic->id << 9) | (i << 1) | 1;
260 
261       BCTX_REFN(nvc0->bufctx_3d, TEX(s, i), res, RD);
262    }
263    for (; i < nvc0->state.num_textures[s]; ++i)
264       commands[n++] = (i << 1) | 0;
265 
266    nvc0->state.num_textures[s] = nvc0->num_textures[s];
267 
268    if (n) {
269       BEGIN_NIC0(push, NVC0_3D(BIND_TIC(s)), n);
270       PUSH_DATAp(push, commands, n);
271    }
272    nvc0->textures_dirty[s] = 0;
273 
274    return need_flush;
275 }
276 
277 static boolean
nve4_validate_tic(struct nvc0_context * nvc0,unsigned s)278 nve4_validate_tic(struct nvc0_context *nvc0, unsigned s)
279 {
280    struct nouveau_bo *txc = nvc0->screen->txc;
281    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
282    unsigned i;
283    boolean need_flush = FALSE;
284 
285    for (i = 0; i < nvc0->num_textures[s]; ++i) {
286       struct nv50_tic_entry *tic = nv50_tic_entry(nvc0->textures[s][i]);
287       struct nv04_resource *res;
288       const boolean dirty = !!(nvc0->textures_dirty[s] & (1 << i));
289 
290       if (!tic) {
291          nvc0->tex_handles[s][i] |= NVE4_TIC_ENTRY_INVALID;
292          continue;
293       }
294       res = nv04_resource(tic->pipe.texture);
295 
296       if (tic->id < 0) {
297          tic->id = nvc0_screen_tic_alloc(nvc0->screen, tic);
298 
299          PUSH_SPACE(push, 16);
300          BEGIN_NVC0(push, NVE4_P2MF(DST_ADDRESS_HIGH), 2);
301          PUSH_DATAh(push, txc->offset + (tic->id * 32));
302          PUSH_DATA (push, txc->offset + (tic->id * 32));
303          BEGIN_NVC0(push, NVE4_P2MF(LINE_LENGTH_IN), 2);
304          PUSH_DATA (push, 32);
305          PUSH_DATA (push, 1);
306          BEGIN_1IC0(push, NVE4_P2MF(EXEC), 9);
307          PUSH_DATA (push, 0x1001);
308          PUSH_DATAp(push, &tic->tic[0], 8);
309 
310          need_flush = TRUE;
311       } else
312       if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
313          BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1);
314          PUSH_DATA (push, (tic->id << 4) | 1);
315       }
316       nvc0->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32);
317 
318       res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING;
319       res->status |=  NOUVEAU_BUFFER_STATUS_GPU_READING;
320 
321       nvc0->tex_handles[s][i] &= ~NVE4_TIC_ENTRY_INVALID;
322       nvc0->tex_handles[s][i] |= tic->id;
323       if (dirty)
324          BCTX_REFN(nvc0->bufctx_3d, TEX(s, i), res, RD);
325    }
326    for (; i < nvc0->state.num_textures[s]; ++i)
327       nvc0->tex_handles[s][i] |= NVE4_TIC_ENTRY_INVALID;
328 
329    nvc0->state.num_textures[s] = nvc0->num_textures[s];
330 
331    return need_flush;
332 }
333 
nvc0_validate_textures(struct nvc0_context * nvc0)334 void nvc0_validate_textures(struct nvc0_context *nvc0)
335 {
336    boolean need_flush;
337 
338    if (nvc0->screen->base.class_3d >= NVE4_3D_CLASS) {
339       need_flush  = nve4_validate_tic(nvc0, 0);
340       need_flush |= nve4_validate_tic(nvc0, 3);
341       need_flush |= nve4_validate_tic(nvc0, 4);
342    } else {
343       need_flush  = nvc0_validate_tic(nvc0, 0);
344       need_flush |= nvc0_validate_tic(nvc0, 3);
345       need_flush |= nvc0_validate_tic(nvc0, 4);
346    }
347 
348    if (need_flush) {
349       BEGIN_NVC0(nvc0->base.pushbuf, NVC0_3D(TIC_FLUSH), 1);
350       PUSH_DATA (nvc0->base.pushbuf, 0);
351    }
352 }
353 
354 static boolean
nvc0_validate_tsc(struct nvc0_context * nvc0,int s)355 nvc0_validate_tsc(struct nvc0_context *nvc0, int s)
356 {
357    uint32_t commands[16];
358    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
359    unsigned i;
360    unsigned n = 0;
361    boolean need_flush = FALSE;
362 
363    for (i = 0; i < nvc0->num_samplers[s]; ++i) {
364       struct nv50_tsc_entry *tsc = nv50_tsc_entry(nvc0->samplers[s][i]);
365 
366       if (!(nvc0->samplers_dirty[s] & (1 << i)))
367          continue;
368       if (!tsc) {
369          commands[n++] = (i << 4) | 0;
370          continue;
371       }
372       if (tsc->id < 0) {
373          tsc->id = nvc0_screen_tsc_alloc(nvc0->screen, tsc);
374 
375          nvc0_m2mf_push_linear(&nvc0->base, nvc0->screen->txc,
376                                65536 + tsc->id * 32, NOUVEAU_BO_VRAM,
377                                32, tsc->tsc);
378          need_flush = TRUE;
379       }
380       nvc0->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32);
381 
382       commands[n++] = (tsc->id << 12) | (i << 4) | 1;
383    }
384    for (; i < nvc0->state.num_samplers[s]; ++i)
385       commands[n++] = (i << 4) | 0;
386 
387    nvc0->state.num_samplers[s] = nvc0->num_samplers[s];
388 
389    if (n) {
390       BEGIN_NIC0(push, NVC0_3D(BIND_TSC(s)), n);
391       PUSH_DATAp(push, commands, n);
392    }
393    nvc0->samplers_dirty[s] = 0;
394 
395    return need_flush;
396 }
397 
398 static boolean
nve4_validate_tsc(struct nvc0_context * nvc0,int s)399 nve4_validate_tsc(struct nvc0_context *nvc0, int s)
400 {
401    struct nouveau_bo *txc = nvc0->screen->txc;
402    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
403    unsigned i;
404    boolean need_flush = FALSE;
405 
406    for (i = 0; i < nvc0->num_samplers[s]; ++i) {
407       struct nv50_tsc_entry *tsc = nv50_tsc_entry(nvc0->samplers[s][i]);
408 
409       if (!tsc) {
410          nvc0->tex_handles[s][i] |= NVE4_TSC_ENTRY_INVALID;
411          continue;
412       }
413       if (tsc->id < 0) {
414          tsc->id = nvc0_screen_tsc_alloc(nvc0->screen, tsc);
415 
416          PUSH_SPACE(push, 16);
417          BEGIN_NVC0(push, NVE4_P2MF(DST_ADDRESS_HIGH), 2);
418          PUSH_DATAh(push, txc->offset + 65536 + (tsc->id * 32));
419          PUSH_DATA (push, txc->offset + 65536 + (tsc->id * 32));
420          BEGIN_NVC0(push, NVE4_P2MF(LINE_LENGTH_IN), 2);
421          PUSH_DATA (push, 32);
422          PUSH_DATA (push, 1);
423          BEGIN_1IC0(push, NVE4_P2MF(EXEC), 9);
424          PUSH_DATA (push, 0x1001);
425          PUSH_DATAp(push, &tsc->tsc[0], 8);
426 
427          need_flush = TRUE;
428       }
429       nvc0->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32);
430 
431       nvc0->tex_handles[s][i] &= ~NVE4_TSC_ENTRY_INVALID;
432       nvc0->tex_handles[s][i] |= tsc->id << 20;
433    }
434    for (; i < nvc0->state.num_samplers[s]; ++i)
435       nvc0->tex_handles[s][i] |= NVE4_TSC_ENTRY_INVALID;
436 
437    nvc0->state.num_samplers[s] = nvc0->num_samplers[s];
438 
439    return need_flush;
440 }
441 
nvc0_validate_samplers(struct nvc0_context * nvc0)442 void nvc0_validate_samplers(struct nvc0_context *nvc0)
443 {
444    boolean need_flush;
445 
446    if (nvc0->screen->base.class_3d >= NVE4_3D_CLASS) {
447       need_flush  = nve4_validate_tsc(nvc0, 0);
448       need_flush |= nve4_validate_tsc(nvc0, 3);
449       need_flush |= nve4_validate_tsc(nvc0, 4);
450    } else {
451       need_flush  = nvc0_validate_tsc(nvc0, 0);
452       need_flush |= nvc0_validate_tsc(nvc0, 3);
453       need_flush |= nvc0_validate_tsc(nvc0, 4);
454    }
455 
456    if (need_flush) {
457       BEGIN_NVC0(nvc0->base.pushbuf, NVC0_3D(TSC_FLUSH), 1);
458       PUSH_DATA (nvc0->base.pushbuf, 0);
459    }
460 }
461 
462 /* Upload the "diagonal" entries for the possible texture sources ($t == $s).
463  * At some point we might want to get a list of the combinations used by a
464  * shader and fill in those entries instead of having it extract the handles.
465  */
466 void
nve4_set_tex_handles(struct nvc0_context * nvc0)467 nve4_set_tex_handles(struct nvc0_context *nvc0)
468 {
469    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
470    uint64_t address;
471    unsigned s;
472 
473    if (nvc0->screen->base.class_3d < NVE4_3D_CLASS)
474       return;
475    address = nvc0->screen->uniform_bo->offset + (5 << 16);
476 
477    for (s = 0; s < 5; ++s, address += (1 << 9)) {
478       uint32_t dirty = nvc0->textures_dirty[s] | nvc0->samplers_dirty[s];
479       if (!dirty)
480          continue;
481       BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
482       PUSH_DATA (push, 512);
483       PUSH_DATAh(push, address);
484       PUSH_DATA (push, address);
485       do {
486          int i = ffs(dirty) - 1;
487          dirty &= ~(1 << i);
488 
489          BEGIN_NVC0(push, NVC0_3D(CB_POS), 2);
490          PUSH_DATA (push, (8 + i) * 4);
491          PUSH_DATA (push, nvc0->tex_handles[s][i]);
492       } while (dirty);
493 
494       nvc0->textures_dirty[s] = 0;
495       nvc0->samplers_dirty[s] = 0;
496    }
497 }
498