2 * Copyright 2008 Ben Skeggs
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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
23 #include "nvc0_context.h"
24 #include "nvc0_resource.h"
25 #include "nv50/nv50_texture.xml.h"
27 #include "util/u_format.h"
29 #define NVE4_TIC_ENTRY_INVALID 0x000fffff
30 #define NVE4_TSC_ENTRY_INVALID 0xfff00000
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)
36 static INLINE
uint32_t
37 nv50_tic_swizzle(uint32_t tc
, unsigned swz
, boolean tex_int
)
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
:
52 return NV50_TIC_MAP_ZERO
;
56 struct pipe_sampler_view
*
57 nvc0_create_sampler_view(struct pipe_context
*pipe
,
58 struct pipe_resource
*res
,
59 const struct pipe_sampler_view
*templ
)
63 if (res
->target
== PIPE_TEXTURE_RECT
)
64 flags
|= NV50_TEXVIEW_SCALED_COORDS
;
66 return nvc0_create_texture_view(pipe
, res
, templ
, flags
, res
->target
);
69 struct pipe_sampler_view
*
70 nvc0_create_texture_view(struct pipe_context
*pipe
,
71 struct pipe_resource
*texture
,
72 const struct pipe_sampler_view
*templ
,
74 enum pipe_texture_target target
)
76 const struct util_format_description
*desc
;
81 struct nv50_tic_entry
*view
;
82 struct nv50_miptree
*mt
;
85 view
= MALLOC_STRUCT(nv50_tic_entry
);
88 mt
= nv50_miptree(texture
);
91 view
->pipe
.reference
.count
= 1;
92 view
->pipe
.texture
= NULL
;
93 view
->pipe
.context
= pipe
;
97 pipe_resource_reference(&view
->pipe
.texture
, texture
);
101 desc
= util_format_description(view
->pipe
.format
);
103 tic
[0] = nvc0_format_table
[view
->pipe
.format
].tic
;
105 tex_int
= util_format_is_pure_integer(view
->pipe
.format
);
107 swz
[0] = nv50_tic_swizzle(tic
[0], view
->pipe
.swizzle_r
, tex_int
);
108 swz
[1] = nv50_tic_swizzle(tic
[0], view
->pipe
.swizzle_g
, tex_int
);
109 swz
[2] = nv50_tic_swizzle(tic
[0], view
->pipe
.swizzle_b
, tex_int
);
110 swz
[3] = nv50_tic_swizzle(tic
[0], view
->pipe
.swizzle_a
, tex_int
);
111 tic
[0] = (tic
[0] & ~NV50_TIC_0_SWIZZLE__MASK
) |
112 (swz
[0] << NV50_TIC_0_MAPR__SHIFT
) |
113 (swz
[1] << NV50_TIC_0_MAPG__SHIFT
) |
114 (swz
[2] << NV50_TIC_0_MAPB__SHIFT
) |
115 (swz
[3] << NV50_TIC_0_MAPA__SHIFT
);
117 address
= mt
->base
.address
;
119 tic
[2] = 0x10001000 | NV50_TIC_2_NO_BORDER
;
121 if (desc
->colorspace
== UTIL_FORMAT_COLORSPACE_SRGB
)
122 tic
[2] |= NV50_TIC_2_COLORSPACE_SRGB
;
124 /* check for linear storage type */
125 if (unlikely(!nouveau_bo_memtype(nv04_resource(texture
)->bo
))) {
126 if (texture
->target
== PIPE_BUFFER
) {
128 view
->pipe
.u
.buf
.first_element
* desc
->block
.bits
/ 8;
129 tic
[2] |= NV50_TIC_2_LINEAR
| NV50_TIC_2_TARGET_BUFFER
;
132 view
->pipe
.u
.buf
.last_element
- view
->pipe
.u
.buf
.first_element
+ 1;
135 /* must be 2D texture without mip maps */
136 tic
[2] |= NV50_TIC_2_LINEAR
| NV50_TIC_2_TARGET_RECT
;
137 if (texture
->target
!= PIPE_TEXTURE_RECT
)
138 tic
[2] |= NV50_TIC_2_NORMALIZED_COORDS
;
139 tic
[3] = mt
->level
[0].pitch
;
140 tic
[4] = mt
->base
.base
.width0
;
141 tic
[5] = (1 << 16) | mt
->base
.base
.height0
;
146 tic
[2] |= address
>> 32;
150 if (!(flags
& NV50_TEXVIEW_SCALED_COORDS
))
151 tic
[2] |= NV50_TIC_2_NORMALIZED_COORDS
;
154 ((mt
->level
[0].tile_mode
& 0x0f0) << (22 - 4)) |
155 ((mt
->level
[0].tile_mode
& 0xf00) << (25 - 8));
157 depth
= MAX2(mt
->base
.base
.array_size
, mt
->base
.base
.depth0
);
159 if (mt
->base
.base
.array_size
> 1) {
160 /* there doesn't seem to be a base layer field in TIC */
161 address
+= view
->pipe
.u
.tex
.first_layer
* mt
->layer_stride
;
162 depth
= view
->pipe
.u
.tex
.last_layer
- view
->pipe
.u
.tex
.first_layer
+ 1;
165 tic
[2] |= address
>> 32;
168 case PIPE_TEXTURE_1D
:
169 tic
[2] |= NV50_TIC_2_TARGET_1D
;
171 /* case PIPE_TEXTURE_2D_MS: */
172 case PIPE_TEXTURE_2D
:
173 tic
[2] |= NV50_TIC_2_TARGET_2D
;
175 case PIPE_TEXTURE_RECT
:
176 tic
[2] |= NV50_TIC_2_TARGET_RECT
;
178 case PIPE_TEXTURE_3D
:
179 tic
[2] |= NV50_TIC_2_TARGET_3D
;
181 case PIPE_TEXTURE_CUBE
:
183 tic
[2] |= NV50_TIC_2_TARGET_CUBE
;
185 case PIPE_TEXTURE_1D_ARRAY
:
186 tic
[2] |= NV50_TIC_2_TARGET_1D_ARRAY
;
188 /* case PIPE_TEXTURE_2D_ARRAY_MS: */
189 case PIPE_TEXTURE_2D_ARRAY
:
190 tic
[2] |= NV50_TIC_2_TARGET_2D_ARRAY
;
192 case PIPE_TEXTURE_CUBE_ARRAY
:
194 tic
[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY
;
197 NOUVEAU_ERR("invalid texture target: %d\n", mt
->base
.base
.target
);
201 if (mt
->base
.base
.target
== PIPE_BUFFER
)
202 tic
[3] = mt
->base
.base
.width0
;
204 tic
[3] = (flags
& NV50_TEXVIEW_FILTER_MSAA8
) ? 0x20000000 : 0x00300000;
206 tic
[4] = (1 << 31) | (mt
->base
.base
.width0
<< mt
->ms_x
);
208 tic
[5] = (mt
->base
.base
.height0
<< mt
->ms_y
) & 0xffff;
209 tic
[5] |= depth
<< 16;
210 tic
[5] |= mt
->base
.base
.last_level
<< 28;
212 tic
[6] = (mt
->ms_x
> 1) ? 0x88000000 : 0x03000000; /* sampling points */
214 tic
[7] = (view
->pipe
.u
.tex
.last_level
<< 4) | view
->pipe
.u
.tex
.first_level
;
217 if (mt->base.base.target == PIPE_TEXTURE_2D_MS ||
218 mt->base.base.target == PIPE_TEXTURE_2D_ARRAY_MS)
219 tic[7] |= mt->ms_mode << 12;
226 nvc0_validate_tic(struct nvc0_context
*nvc0
, int s
)
228 uint32_t commands
[32];
229 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
230 struct nouveau_bo
*txc
= nvc0
->screen
->txc
;
233 boolean need_flush
= FALSE
;
235 for (i
= 0; i
< nvc0
->num_textures
[s
]; ++i
) {
236 struct nv50_tic_entry
*tic
= nv50_tic_entry(nvc0
->textures
[s
][i
]);
237 struct nv04_resource
*res
;
238 const boolean dirty
= !!(nvc0
->textures_dirty
[s
] & (1 << i
));
242 commands
[n
++] = (i
<< 1) | 0;
245 res
= nv04_resource(tic
->pipe
.texture
);
248 tic
->id
= nvc0_screen_tic_alloc(nvc0
->screen
, tic
);
250 PUSH_SPACE(push
, 17);
251 BEGIN_NVC0(push
, NVC0_M2MF(OFFSET_OUT_HIGH
), 2);
252 PUSH_DATAh(push
, txc
->offset
+ (tic
->id
* 32));
253 PUSH_DATA (push
, txc
->offset
+ (tic
->id
* 32));
254 BEGIN_NVC0(push
, NVC0_M2MF(LINE_LENGTH_IN
), 2);
255 PUSH_DATA (push
, 32);
257 BEGIN_NVC0(push
, NVC0_M2MF(EXEC
), 1);
258 PUSH_DATA (push
, 0x100111);
259 BEGIN_NIC0(push
, NVC0_M2MF(DATA
), 8);
260 PUSH_DATAp(push
, &tic
->tic
[0], 8);
264 if (res
->status
& NOUVEAU_BUFFER_STATUS_GPU_WRITING
) {
265 BEGIN_NVC0(push
, NVC0_3D(TEX_CACHE_CTL
), 1);
266 PUSH_DATA (push
, (tic
->id
<< 4) | 1);
268 nvc0
->screen
->tic
.lock
[tic
->id
/ 32] |= 1 << (tic
->id
% 32);
270 res
->status
&= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
271 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_READING
;
275 commands
[n
++] = (tic
->id
<< 9) | (i
<< 1) | 1;
277 BCTX_REFN(nvc0
->bufctx_3d
, TEX(s
, i
), res
, RD
);
279 for (; i
< nvc0
->state
.num_textures
[s
]; ++i
)
280 commands
[n
++] = (i
<< 1) | 0;
282 nvc0
->state
.num_textures
[s
] = nvc0
->num_textures
[s
];
285 BEGIN_NIC0(push
, NVC0_3D(BIND_TIC(s
)), n
);
286 PUSH_DATAp(push
, commands
, n
);
288 nvc0
->textures_dirty
[s
] = 0;
294 nve4_validate_tic(struct nvc0_context
*nvc0
, unsigned s
)
296 struct nouveau_bo
*txc
= nvc0
->screen
->txc
;
297 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
299 boolean need_flush
= FALSE
;
301 for (i
= 0; i
< nvc0
->num_textures
[s
]; ++i
) {
302 struct nv50_tic_entry
*tic
= nv50_tic_entry(nvc0
->textures
[s
][i
]);
303 struct nv04_resource
*res
;
304 const boolean dirty
= !!(nvc0
->textures_dirty
[s
] & (1 << i
));
307 nvc0
->tex_handles
[s
][i
] |= NVE4_TIC_ENTRY_INVALID
;
310 res
= nv04_resource(tic
->pipe
.texture
);
313 tic
->id
= nvc0_screen_tic_alloc(nvc0
->screen
, tic
);
315 PUSH_SPACE(push
, 16);
316 BEGIN_NVC0(push
, NVE4_P2MF(DST_ADDRESS_HIGH
), 2);
317 PUSH_DATAh(push
, txc
->offset
+ (tic
->id
* 32));
318 PUSH_DATA (push
, txc
->offset
+ (tic
->id
* 32));
319 BEGIN_NVC0(push
, NVE4_P2MF(LINE_LENGTH_IN
), 2);
320 PUSH_DATA (push
, 32);
322 BEGIN_1IC0(push
, NVE4_P2MF(EXEC
), 9);
323 PUSH_DATA (push
, 0x1001);
324 PUSH_DATAp(push
, &tic
->tic
[0], 8);
328 if (res
->status
& NOUVEAU_BUFFER_STATUS_GPU_WRITING
) {
329 BEGIN_NVC0(push
, NVC0_3D(TEX_CACHE_CTL
), 1);
330 PUSH_DATA (push
, (tic
->id
<< 4) | 1);
332 nvc0
->screen
->tic
.lock
[tic
->id
/ 32] |= 1 << (tic
->id
% 32);
334 res
->status
&= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
335 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_READING
;
337 nvc0
->tex_handles
[s
][i
] &= ~NVE4_TIC_ENTRY_INVALID
;
338 nvc0
->tex_handles
[s
][i
] |= tic
->id
;
340 BCTX_REFN(nvc0
->bufctx_3d
, TEX(s
, i
), res
, RD
);
342 for (; i
< nvc0
->state
.num_textures
[s
]; ++i
) {
343 nvc0
->tex_handles
[s
][i
] |= NVE4_TIC_ENTRY_INVALID
;
344 nvc0
->textures_dirty
[s
] |= 1 << i
;
347 nvc0
->state
.num_textures
[s
] = nvc0
->num_textures
[s
];
352 void nvc0_validate_textures(struct nvc0_context
*nvc0
)
356 if (nvc0
->screen
->base
.class_3d
>= NVE4_3D_CLASS
) {
357 need_flush
= nve4_validate_tic(nvc0
, 0);
358 need_flush
|= nve4_validate_tic(nvc0
, 3);
359 need_flush
|= nve4_validate_tic(nvc0
, 4);
361 need_flush
= nvc0_validate_tic(nvc0
, 0);
362 need_flush
|= nvc0_validate_tic(nvc0
, 3);
363 need_flush
|= nvc0_validate_tic(nvc0
, 4);
367 BEGIN_NVC0(nvc0
->base
.pushbuf
, NVC0_3D(TIC_FLUSH
), 1);
368 PUSH_DATA (nvc0
->base
.pushbuf
, 0);
373 nvc0_validate_tsc(struct nvc0_context
*nvc0
, int s
)
375 uint32_t commands
[16];
376 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
379 boolean need_flush
= FALSE
;
381 for (i
= 0; i
< nvc0
->num_samplers
[s
]; ++i
) {
382 struct nv50_tsc_entry
*tsc
= nv50_tsc_entry(nvc0
->samplers
[s
][i
]);
384 if (!(nvc0
->samplers_dirty
[s
] & (1 << i
)))
387 commands
[n
++] = (i
<< 4) | 0;
391 tsc
->id
= nvc0_screen_tsc_alloc(nvc0
->screen
, tsc
);
393 nvc0_m2mf_push_linear(&nvc0
->base
, nvc0
->screen
->txc
,
394 65536 + tsc
->id
* 32, NOUVEAU_BO_VRAM
,
398 nvc0
->screen
->tsc
.lock
[tsc
->id
/ 32] |= 1 << (tsc
->id
% 32);
400 commands
[n
++] = (tsc
->id
<< 12) | (i
<< 4) | 1;
402 for (; i
< nvc0
->state
.num_samplers
[s
]; ++i
)
403 commands
[n
++] = (i
<< 4) | 0;
405 nvc0
->state
.num_samplers
[s
] = nvc0
->num_samplers
[s
];
408 BEGIN_NIC0(push
, NVC0_3D(BIND_TSC(s
)), n
);
409 PUSH_DATAp(push
, commands
, n
);
411 nvc0
->samplers_dirty
[s
] = 0;
417 nve4_validate_tsc(struct nvc0_context
*nvc0
, int s
)
419 struct nouveau_bo
*txc
= nvc0
->screen
->txc
;
420 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
422 boolean need_flush
= FALSE
;
424 for (i
= 0; i
< nvc0
->num_samplers
[s
]; ++i
) {
425 struct nv50_tsc_entry
*tsc
= nv50_tsc_entry(nvc0
->samplers
[s
][i
]);
428 nvc0
->tex_handles
[s
][i
] |= NVE4_TSC_ENTRY_INVALID
;
432 tsc
->id
= nvc0_screen_tsc_alloc(nvc0
->screen
, tsc
);
434 PUSH_SPACE(push
, 16);
435 BEGIN_NVC0(push
, NVE4_P2MF(DST_ADDRESS_HIGH
), 2);
436 PUSH_DATAh(push
, txc
->offset
+ 65536 + (tsc
->id
* 32));
437 PUSH_DATA (push
, txc
->offset
+ 65536 + (tsc
->id
* 32));
438 BEGIN_NVC0(push
, NVE4_P2MF(LINE_LENGTH_IN
), 2);
439 PUSH_DATA (push
, 32);
441 BEGIN_1IC0(push
, NVE4_P2MF(EXEC
), 9);
442 PUSH_DATA (push
, 0x1001);
443 PUSH_DATAp(push
, &tsc
->tsc
[0], 8);
447 nvc0
->screen
->tsc
.lock
[tsc
->id
/ 32] |= 1 << (tsc
->id
% 32);
449 nvc0
->tex_handles
[s
][i
] &= ~NVE4_TSC_ENTRY_INVALID
;
450 nvc0
->tex_handles
[s
][i
] |= tsc
->id
<< 20;
452 for (; i
< nvc0
->state
.num_samplers
[s
]; ++i
) {
453 nvc0
->tex_handles
[s
][i
] |= NVE4_TSC_ENTRY_INVALID
;
454 nvc0
->samplers_dirty
[s
] |= 1 << i
;
457 nvc0
->state
.num_samplers
[s
] = nvc0
->num_samplers
[s
];
462 void nvc0_validate_samplers(struct nvc0_context
*nvc0
)
466 if (nvc0
->screen
->base
.class_3d
>= NVE4_3D_CLASS
) {
467 need_flush
= nve4_validate_tsc(nvc0
, 0);
468 need_flush
|= nve4_validate_tsc(nvc0
, 3);
469 need_flush
|= nve4_validate_tsc(nvc0
, 4);
471 need_flush
= nvc0_validate_tsc(nvc0
, 0);
472 need_flush
|= nvc0_validate_tsc(nvc0
, 3);
473 need_flush
|= nvc0_validate_tsc(nvc0
, 4);
477 BEGIN_NVC0(nvc0
->base
.pushbuf
, NVC0_3D(TSC_FLUSH
), 1);
478 PUSH_DATA (nvc0
->base
.pushbuf
, 0);
482 /* Upload the "diagonal" entries for the possible texture sources ($t == $s).
483 * At some point we might want to get a list of the combinations used by a
484 * shader and fill in those entries instead of having it extract the handles.
487 nve4_set_tex_handles(struct nvc0_context
*nvc0
)
489 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
493 if (nvc0
->screen
->base
.class_3d
< NVE4_3D_CLASS
)
495 address
= nvc0
->screen
->uniform_bo
->offset
+ (5 << 16);
497 for (s
= 0; s
< 5; ++s
, address
+= (1 << 9)) {
498 uint32_t dirty
= nvc0
->textures_dirty
[s
] | nvc0
->samplers_dirty
[s
];
501 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
502 PUSH_DATA (push
, 512);
503 PUSH_DATAh(push
, address
);
504 PUSH_DATA (push
, address
);
506 int i
= ffs(dirty
) - 1;
509 BEGIN_NVC0(push
, NVC0_3D(CB_POS
), 2);
510 PUSH_DATA (push
, (8 + i
) * 4);
511 PUSH_DATA (push
, nvc0
->tex_handles
[s
][i
]);
514 nvc0
->textures_dirty
[s
] = 0;
515 nvc0
->samplers_dirty
[s
] = 0;