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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
23 #include "nvc0/nvc0_context.h"
24 #include "nvc0/nvc0_resource.h"
25 #include "nvc0/gm107_texture.xml.h"
26 #include "nv50/g80_texture.xml.h"
27 #include "nv50/g80_defs.xml.h"
29 #include "util/u_format.h"
31 #define NVE4_TIC_ENTRY_INVALID 0x000fffff
32 #define NVE4_TSC_ENTRY_INVALID 0xfff00000
34 static inline uint32_t
35 nv50_tic_swizzle(const struct nvc0_format
*fmt
, unsigned swz
, bool tex_int
)
38 case PIPE_SWIZZLE_RED
: return fmt
->tic
.src_x
;
39 case PIPE_SWIZZLE_GREEN
: return fmt
->tic
.src_y
;
40 case PIPE_SWIZZLE_BLUE
: return fmt
->tic
.src_z
;
41 case PIPE_SWIZZLE_ALPHA
: return fmt
->tic
.src_w
;
42 case PIPE_SWIZZLE_ONE
:
43 return tex_int
? G80_TIC_SOURCE_ONE_INT
: G80_TIC_SOURCE_ONE_FLOAT
;
44 case PIPE_SWIZZLE_ZERO
:
46 return G80_TIC_SOURCE_ZERO
;
50 struct pipe_sampler_view
*
51 nvc0_create_sampler_view(struct pipe_context
*pipe
,
52 struct pipe_resource
*res
,
53 const struct pipe_sampler_view
*templ
)
57 if (templ
->target
== PIPE_TEXTURE_RECT
|| templ
->target
== PIPE_BUFFER
)
58 flags
|= NV50_TEXVIEW_SCALED_COORDS
;
60 return nvc0_create_texture_view(pipe
, res
, templ
, flags
, templ
->target
);
63 static struct pipe_sampler_view
*
64 gm107_create_texture_view(struct pipe_context
*pipe
,
65 struct pipe_resource
*texture
,
66 const struct pipe_sampler_view
*templ
,
68 enum pipe_texture_target target
)
70 const struct util_format_description
*desc
;
71 const struct nvc0_format
*fmt
;
75 uint32_t width
, height
;
77 struct nv50_tic_entry
*view
;
78 struct nv50_miptree
*mt
;
81 view
= MALLOC_STRUCT(nv50_tic_entry
);
84 mt
= nv50_miptree(texture
);
87 view
->pipe
.reference
.count
= 1;
88 view
->pipe
.texture
= NULL
;
89 view
->pipe
.context
= pipe
;
93 pipe_resource_reference(&view
->pipe
.texture
, texture
);
97 desc
= util_format_description(view
->pipe
.format
);
98 tex_int
= util_format_is_pure_integer(view
->pipe
.format
);
100 fmt
= &nvc0_format_table
[view
->pipe
.format
];
101 swz
[0] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_r
, tex_int
);
102 swz
[1] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_g
, tex_int
);
103 swz
[2] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_b
, tex_int
);
104 swz
[3] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_a
, tex_int
);
106 tic
[0] = fmt
->tic
.format
<< GM107_TIC2_0_COMPONENTS_SIZES__SHIFT
;
107 tic
[0] |= fmt
->tic
.type_r
<< GM107_TIC2_0_R_DATA_TYPE__SHIFT
;
108 tic
[0] |= fmt
->tic
.type_g
<< GM107_TIC2_0_G_DATA_TYPE__SHIFT
;
109 tic
[0] |= fmt
->tic
.type_b
<< GM107_TIC2_0_B_DATA_TYPE__SHIFT
;
110 tic
[0] |= fmt
->tic
.type_a
<< GM107_TIC2_0_A_DATA_TYPE__SHIFT
;
111 tic
[0] |= swz
[0] << GM107_TIC2_0_X_SOURCE__SHIFT
;
112 tic
[0] |= swz
[1] << GM107_TIC2_0_Y_SOURCE__SHIFT
;
113 tic
[0] |= swz
[2] << GM107_TIC2_0_Z_SOURCE__SHIFT
;
114 tic
[0] |= swz
[3] << GM107_TIC2_0_W_SOURCE__SHIFT
;
116 address
= mt
->base
.address
;
118 tic
[3] = GM107_TIC2_3_LOD_ANISO_QUALITY_2
;
119 tic
[4] = GM107_TIC2_4_SECTOR_PROMOTION_PROMOTE_TO_2_V
;
120 tic
[4] |= GM107_TIC2_4_BORDER_SIZE_SAMPLER_COLOR
;
122 if (desc
->colorspace
== UTIL_FORMAT_COLORSPACE_SRGB
)
123 tic
[4] |= GM107_TIC2_4_SRGB_CONVERSION
;
125 if (!(flags
& NV50_TEXVIEW_SCALED_COORDS
))
126 tic
[5] = GM107_TIC2_5_NORMALIZED_COORDS
;
130 /* check for linear storage type */
131 if (unlikely(!nouveau_bo_memtype(nv04_resource(texture
)->bo
))) {
132 if (texture
->target
== PIPE_BUFFER
) {
133 assert(!(tic
[5] & GM107_TIC2_5_NORMALIZED_COORDS
));
134 width
= view
->pipe
.u
.buf
.last_element
- view
->pipe
.u
.buf
.first_element
;
136 view
->pipe
.u
.buf
.first_element
* desc
->block
.bits
/ 8;
137 tic
[2] = GM107_TIC2_2_HEADER_VERSION_ONE_D_BUFFER
;
138 tic
[3] |= width
>> 16;
139 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_ONE_D_BUFFER
;
140 tic
[4] |= width
& 0xffff;
142 assert(!(mt
->level
[0].pitch
& 0x1f));
143 /* must be 2D texture without mip maps */
144 tic
[2] = GM107_TIC2_2_HEADER_VERSION_PITCH
;
145 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_TWO_D_NO_MIPMAP
;
146 tic
[3] |= mt
->level
[0].pitch
>> 5;
147 tic
[4] |= mt
->base
.base
.width0
- 1;
148 tic
[5] |= 0 << GM107_TIC2_5_DEPTH_MINUS_ONE__SHIFT
;
149 tic
[5] |= mt
->base
.base
.height0
- 1;
152 tic
[2] |= address
>> 32;
158 tic
[2] = GM107_TIC2_2_HEADER_VERSION_BLOCKLINEAR
;
160 ((mt
->level
[0].tile_mode
& 0x0f0) >> 4 << 3) |
161 ((mt
->level
[0].tile_mode
& 0xf00) >> 8 << 6);
163 depth
= MAX2(mt
->base
.base
.array_size
, mt
->base
.base
.depth0
);
165 if (mt
->base
.base
.array_size
> 1) {
166 /* there doesn't seem to be a base layer field in TIC */
167 address
+= view
->pipe
.u
.tex
.first_layer
* mt
->layer_stride
;
168 depth
= view
->pipe
.u
.tex
.last_layer
- view
->pipe
.u
.tex
.first_layer
+ 1;
171 tic
[2] |= address
>> 32;
174 case PIPE_TEXTURE_1D
:
175 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_ONE_D
;
177 case PIPE_TEXTURE_2D
:
178 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_TWO_D
;
180 case PIPE_TEXTURE_RECT
:
181 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_TWO_D
;
183 case PIPE_TEXTURE_3D
:
184 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_THREE_D
;
186 case PIPE_TEXTURE_CUBE
:
188 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_CUBEMAP
;
190 case PIPE_TEXTURE_1D_ARRAY
:
191 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_ONE_D_ARRAY
;
193 case PIPE_TEXTURE_2D_ARRAY
:
194 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_TWO_D_ARRAY
;
196 case PIPE_TEXTURE_CUBE_ARRAY
:
198 tic
[4] |= GM107_TIC2_4_TEXTURE_TYPE_CUBE_ARRAY
;
201 unreachable("unexpected/invalid texture target");
204 tic
[3] |= (flags
& NV50_TEXVIEW_FILTER_MSAA8
) ?
205 GM107_TIC2_3_USE_HEADER_OPT_CONTROL
:
206 GM107_TIC2_3_LOD_ANISO_QUALITY_HIGH
|
207 GM107_TIC2_3_LOD_ISO_QUALITY_HIGH
;
209 if (flags
& NV50_TEXVIEW_ACCESS_RESOLVE
) {
210 width
= mt
->base
.base
.width0
<< mt
->ms_x
;
211 height
= mt
->base
.base
.height0
<< mt
->ms_y
;
213 width
= mt
->base
.base
.width0
;
214 height
= mt
->base
.base
.height0
;
219 tic
[5] |= (height
- 1) & 0xffff;
220 tic
[5] |= (depth
- 1) << GM107_TIC2_5_DEPTH_MINUS_ONE__SHIFT
;
221 tic
[3] |= mt
->base
.base
.last_level
<< GM107_TIC2_3_MAX_MIP_LEVEL__SHIFT
;
223 /* sampling points: (?) */
224 if ((flags
& NV50_TEXVIEW_ACCESS_RESOLVE
) && mt
->ms_x
> 1) {
225 tic
[6] = GM107_TIC2_6_ANISO_FINE_SPREAD_MODIFIER_CONST_TWO
;
226 tic
[6] |= GM107_TIC2_6_MAX_ANISOTROPY_2_TO_1
;
228 tic
[6] = GM107_TIC2_6_ANISO_FINE_SPREAD_FUNC_TWO
;
229 tic
[6] |= GM107_TIC2_6_ANISO_COARSE_SPREAD_FUNC_ONE
;
232 tic
[7] = (view
->pipe
.u
.tex
.last_level
<< 4) | view
->pipe
.u
.tex
.first_level
;
233 tic
[7] |= mt
->ms_mode
<< GM107_TIC2_7_MULTI_SAMPLE_COUNT__SHIFT
;
238 static struct pipe_sampler_view
*
239 gf100_create_texture_view(struct pipe_context
*pipe
,
240 struct pipe_resource
*texture
,
241 const struct pipe_sampler_view
*templ
,
243 enum pipe_texture_target target
)
245 const struct util_format_description
*desc
;
246 const struct nvc0_format
*fmt
;
250 uint32_t width
, height
;
252 struct nv50_tic_entry
*view
;
253 struct nv50_miptree
*mt
;
256 view
= MALLOC_STRUCT(nv50_tic_entry
);
259 mt
= nv50_miptree(texture
);
262 view
->pipe
.reference
.count
= 1;
263 view
->pipe
.texture
= NULL
;
264 view
->pipe
.context
= pipe
;
268 pipe_resource_reference(&view
->pipe
.texture
, texture
);
272 desc
= util_format_description(view
->pipe
.format
);
274 fmt
= &nvc0_format_table
[view
->pipe
.format
];
276 tex_int
= util_format_is_pure_integer(view
->pipe
.format
);
278 swz
[0] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_r
, tex_int
);
279 swz
[1] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_g
, tex_int
);
280 swz
[2] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_b
, tex_int
);
281 swz
[3] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_a
, tex_int
);
282 tic
[0] = (fmt
->tic
.format
<< G80_TIC_0_COMPONENTS_SIZES__SHIFT
) |
283 (fmt
->tic
.type_r
<< G80_TIC_0_R_DATA_TYPE__SHIFT
) |
284 (fmt
->tic
.type_g
<< G80_TIC_0_G_DATA_TYPE__SHIFT
) |
285 (fmt
->tic
.type_b
<< G80_TIC_0_B_DATA_TYPE__SHIFT
) |
286 (fmt
->tic
.type_a
<< G80_TIC_0_A_DATA_TYPE__SHIFT
) |
287 (swz
[0] << G80_TIC_0_X_SOURCE__SHIFT
) |
288 (swz
[1] << G80_TIC_0_Y_SOURCE__SHIFT
) |
289 (swz
[2] << G80_TIC_0_Z_SOURCE__SHIFT
) |
290 (swz
[3] << G80_TIC_0_W_SOURCE__SHIFT
);
292 address
= mt
->base
.address
;
294 tic
[2] = 0x10001000 | G80_TIC_2_BORDER_SOURCE_COLOR
;
296 if (desc
->colorspace
== UTIL_FORMAT_COLORSPACE_SRGB
)
297 tic
[2] |= G80_TIC_2_SRGB_CONVERSION
;
299 if (!(flags
& NV50_TEXVIEW_SCALED_COORDS
))
300 tic
[2] |= G80_TIC_2_NORMALIZED_COORDS
;
302 /* check for linear storage type */
303 if (unlikely(!nouveau_bo_memtype(nv04_resource(texture
)->bo
))) {
304 if (texture
->target
== PIPE_BUFFER
) {
305 assert(!(tic
[2] & G80_TIC_2_NORMALIZED_COORDS
));
307 view
->pipe
.u
.buf
.first_element
* desc
->block
.bits
/ 8;
308 tic
[2] |= G80_TIC_2_LAYOUT_PITCH
| G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER
;
311 view
->pipe
.u
.buf
.last_element
- view
->pipe
.u
.buf
.first_element
+ 1;
314 /* must be 2D texture without mip maps */
315 tic
[2] |= G80_TIC_2_LAYOUT_PITCH
| G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP
;
316 tic
[3] = mt
->level
[0].pitch
;
317 tic
[4] = mt
->base
.base
.width0
;
318 tic
[5] = (1 << 16) | mt
->base
.base
.height0
;
323 tic
[2] |= address
>> 32;
328 ((mt
->level
[0].tile_mode
& 0x0f0) << (22 - 4)) |
329 ((mt
->level
[0].tile_mode
& 0xf00) << (25 - 8));
331 depth
= MAX2(mt
->base
.base
.array_size
, mt
->base
.base
.depth0
);
333 if (mt
->base
.base
.array_size
> 1) {
334 /* there doesn't seem to be a base layer field in TIC */
335 address
+= view
->pipe
.u
.tex
.first_layer
* mt
->layer_stride
;
336 depth
= view
->pipe
.u
.tex
.last_layer
- view
->pipe
.u
.tex
.first_layer
+ 1;
339 tic
[2] |= address
>> 32;
342 case PIPE_TEXTURE_1D
:
343 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D
;
345 case PIPE_TEXTURE_2D
:
346 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D
;
348 case PIPE_TEXTURE_RECT
:
349 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D
;
351 case PIPE_TEXTURE_3D
:
352 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_THREE_D
;
354 case PIPE_TEXTURE_CUBE
:
356 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_CUBEMAP
;
358 case PIPE_TEXTURE_1D_ARRAY
:
359 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_ARRAY
;
361 case PIPE_TEXTURE_2D_ARRAY
:
362 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_ARRAY
;
364 case PIPE_TEXTURE_CUBE_ARRAY
:
366 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_CUBE_ARRAY
;
369 unreachable("unexpected/invalid texture target");
372 tic
[3] = (flags
& NV50_TEXVIEW_FILTER_MSAA8
) ? 0x20000000 : 0x00300000;
374 if (flags
& NV50_TEXVIEW_ACCESS_RESOLVE
) {
375 width
= mt
->base
.base
.width0
<< mt
->ms_x
;
376 height
= mt
->base
.base
.height0
<< mt
->ms_y
;
378 width
= mt
->base
.base
.width0
;
379 height
= mt
->base
.base
.height0
;
382 tic
[4] = (1 << 31) | width
;
384 tic
[5] = height
& 0xffff;
385 tic
[5] |= depth
<< 16;
386 tic
[5] |= mt
->base
.base
.last_level
<< 28;
388 /* sampling points: (?) */
389 if (flags
& NV50_TEXVIEW_ACCESS_RESOLVE
)
390 tic
[6] = (mt
->ms_x
> 1) ? 0x88000000 : 0x03000000;
394 tic
[7] = (view
->pipe
.u
.tex
.last_level
<< 4) | view
->pipe
.u
.tex
.first_level
;
395 tic
[7] |= mt
->ms_mode
<< 12;
400 struct pipe_sampler_view
*
401 nvc0_create_texture_view(struct pipe_context
*pipe
,
402 struct pipe_resource
*texture
,
403 const struct pipe_sampler_view
*templ
,
405 enum pipe_texture_target target
)
407 if (nvc0_context(pipe
)->screen
->tic
.maxwell
)
408 return gm107_create_texture_view(pipe
, texture
, templ
, flags
, target
);
409 return gf100_create_texture_view(pipe
, texture
, templ
, flags
, target
);
413 nvc0_update_tic(struct nvc0_context
*nvc0
, struct nv50_tic_entry
*tic
,
414 struct nv04_resource
*res
)
416 uint64_t address
= res
->address
;
417 if (res
->base
.target
!= PIPE_BUFFER
)
419 address
+= tic
->pipe
.u
.buf
.first_element
*
420 util_format_get_blocksize(tic
->pipe
.format
);
421 if (tic
->tic
[1] == (uint32_t)address
&&
422 (tic
->tic
[2] & 0xff) == address
>> 32)
425 nvc0_screen_tic_unlock(nvc0
->screen
, tic
);
427 tic
->tic
[1] = address
;
428 tic
->tic
[2] &= 0xffffff00;
429 tic
->tic
[2] |= address
>> 32;
433 nvc0_validate_tic(struct nvc0_context
*nvc0
, int s
)
435 uint32_t commands
[32];
436 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
437 struct nouveau_bo
*txc
= nvc0
->screen
->txc
;
440 bool need_flush
= false;
442 for (i
= 0; i
< nvc0
->num_textures
[s
]; ++i
) {
443 struct nv50_tic_entry
*tic
= nv50_tic_entry(nvc0
->textures
[s
][i
]);
444 struct nv04_resource
*res
;
445 const bool dirty
= !!(nvc0
->textures_dirty
[s
] & (1 << i
));
449 commands
[n
++] = (i
<< 1) | 0;
452 res
= nv04_resource(tic
->pipe
.texture
);
453 nvc0_update_tic(nvc0
, tic
, res
);
456 tic
->id
= nvc0_screen_tic_alloc(nvc0
->screen
, tic
);
458 PUSH_SPACE(push
, 17);
459 BEGIN_NVC0(push
, NVC0_M2MF(OFFSET_OUT_HIGH
), 2);
460 PUSH_DATAh(push
, txc
->offset
+ (tic
->id
* 32));
461 PUSH_DATA (push
, txc
->offset
+ (tic
->id
* 32));
462 BEGIN_NVC0(push
, NVC0_M2MF(LINE_LENGTH_IN
), 2);
463 PUSH_DATA (push
, 32);
465 BEGIN_NVC0(push
, NVC0_M2MF(EXEC
), 1);
466 PUSH_DATA (push
, 0x100111);
467 BEGIN_NIC0(push
, NVC0_M2MF(DATA
), 8);
468 PUSH_DATAp(push
, &tic
->tic
[0], 8);
472 if (res
->status
& NOUVEAU_BUFFER_STATUS_GPU_WRITING
) {
473 BEGIN_NVC0(push
, NVC0_3D(TEX_CACHE_CTL
), 1);
474 PUSH_DATA (push
, (tic
->id
<< 4) | 1);
475 NOUVEAU_DRV_STAT(&nvc0
->screen
->base
, tex_cache_flush_count
, 1);
477 nvc0
->screen
->tic
.lock
[tic
->id
/ 32] |= 1 << (tic
->id
% 32);
479 res
->status
&= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
480 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_READING
;
484 commands
[n
++] = (tic
->id
<< 9) | (i
<< 1) | 1;
486 BCTX_REFN(nvc0
->bufctx_3d
, TEX(s
, i
), res
, RD
);
488 for (; i
< nvc0
->state
.num_textures
[s
]; ++i
)
489 commands
[n
++] = (i
<< 1) | 0;
491 nvc0
->state
.num_textures
[s
] = nvc0
->num_textures
[s
];
494 BEGIN_NIC0(push
, NVC0_3D(BIND_TIC(s
)), n
);
495 PUSH_DATAp(push
, commands
, n
);
497 nvc0
->textures_dirty
[s
] = 0;
503 nve4_validate_tic(struct nvc0_context
*nvc0
, unsigned s
)
505 struct nouveau_bo
*txc
= nvc0
->screen
->txc
;
506 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
508 bool need_flush
= false;
510 for (i
= 0; i
< nvc0
->num_textures
[s
]; ++i
) {
511 struct nv50_tic_entry
*tic
= nv50_tic_entry(nvc0
->textures
[s
][i
]);
512 struct nv04_resource
*res
;
513 const bool dirty
= !!(nvc0
->textures_dirty
[s
] & (1 << i
));
516 nvc0
->tex_handles
[s
][i
] |= NVE4_TIC_ENTRY_INVALID
;
519 res
= nv04_resource(tic
->pipe
.texture
);
520 nvc0_update_tic(nvc0
, tic
, res
);
523 tic
->id
= nvc0_screen_tic_alloc(nvc0
->screen
, tic
);
525 PUSH_SPACE(push
, 16);
526 BEGIN_NVC0(push
, NVE4_P2MF(UPLOAD_DST_ADDRESS_HIGH
), 2);
527 PUSH_DATAh(push
, txc
->offset
+ (tic
->id
* 32));
528 PUSH_DATA (push
, txc
->offset
+ (tic
->id
* 32));
529 BEGIN_NVC0(push
, NVE4_P2MF(UPLOAD_LINE_LENGTH_IN
), 2);
530 PUSH_DATA (push
, 32);
532 BEGIN_1IC0(push
, NVE4_P2MF(UPLOAD_EXEC
), 9);
533 PUSH_DATA (push
, 0x1001);
534 PUSH_DATAp(push
, &tic
->tic
[0], 8);
538 if (res
->status
& NOUVEAU_BUFFER_STATUS_GPU_WRITING
) {
539 BEGIN_NVC0(push
, NVC0_3D(TEX_CACHE_CTL
), 1);
540 PUSH_DATA (push
, (tic
->id
<< 4) | 1);
542 nvc0
->screen
->tic
.lock
[tic
->id
/ 32] |= 1 << (tic
->id
% 32);
544 res
->status
&= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
545 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_READING
;
547 nvc0
->tex_handles
[s
][i
] &= ~NVE4_TIC_ENTRY_INVALID
;
548 nvc0
->tex_handles
[s
][i
] |= tic
->id
;
550 BCTX_REFN(nvc0
->bufctx_3d
, TEX(s
, i
), res
, RD
);
552 for (; i
< nvc0
->state
.num_textures
[s
]; ++i
) {
553 nvc0
->tex_handles
[s
][i
] |= NVE4_TIC_ENTRY_INVALID
;
554 nvc0
->textures_dirty
[s
] |= 1 << i
;
557 nvc0
->state
.num_textures
[s
] = nvc0
->num_textures
[s
];
562 void nvc0_validate_textures(struct nvc0_context
*nvc0
)
564 bool need_flush
= false;
567 for (i
= 0; i
< 5; i
++) {
568 if (nvc0
->screen
->base
.class_3d
>= NVE4_3D_CLASS
)
569 need_flush
|= nve4_validate_tic(nvc0
, i
);
571 need_flush
|= nvc0_validate_tic(nvc0
, i
);
575 BEGIN_NVC0(nvc0
->base
.pushbuf
, NVC0_3D(TIC_FLUSH
), 1);
576 PUSH_DATA (nvc0
->base
.pushbuf
, 0);
581 nvc0_validate_tsc(struct nvc0_context
*nvc0
, int s
)
583 uint32_t commands
[16];
584 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
587 bool need_flush
= false;
589 for (i
= 0; i
< nvc0
->num_samplers
[s
]; ++i
) {
590 struct nv50_tsc_entry
*tsc
= nv50_tsc_entry(nvc0
->samplers
[s
][i
]);
592 if (!(nvc0
->samplers_dirty
[s
] & (1 << i
)))
595 commands
[n
++] = (i
<< 4) | 0;
599 tsc
->id
= nvc0_screen_tsc_alloc(nvc0
->screen
, tsc
);
601 nvc0_m2mf_push_linear(&nvc0
->base
, nvc0
->screen
->txc
,
602 65536 + tsc
->id
* 32, NV_VRAM_DOMAIN(&nvc0
->screen
->base
),
606 nvc0
->screen
->tsc
.lock
[tsc
->id
/ 32] |= 1 << (tsc
->id
% 32);
608 commands
[n
++] = (tsc
->id
<< 12) | (i
<< 4) | 1;
610 for (; i
< nvc0
->state
.num_samplers
[s
]; ++i
)
611 commands
[n
++] = (i
<< 4) | 0;
613 nvc0
->state
.num_samplers
[s
] = nvc0
->num_samplers
[s
];
616 BEGIN_NIC0(push
, NVC0_3D(BIND_TSC(s
)), n
);
617 PUSH_DATAp(push
, commands
, n
);
619 nvc0
->samplers_dirty
[s
] = 0;
625 nve4_validate_tsc(struct nvc0_context
*nvc0
, int s
)
627 struct nouveau_bo
*txc
= nvc0
->screen
->txc
;
628 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
630 bool need_flush
= false;
632 for (i
= 0; i
< nvc0
->num_samplers
[s
]; ++i
) {
633 struct nv50_tsc_entry
*tsc
= nv50_tsc_entry(nvc0
->samplers
[s
][i
]);
636 nvc0
->tex_handles
[s
][i
] |= NVE4_TSC_ENTRY_INVALID
;
640 tsc
->id
= nvc0_screen_tsc_alloc(nvc0
->screen
, tsc
);
642 PUSH_SPACE(push
, 16);
643 BEGIN_NVC0(push
, NVE4_P2MF(UPLOAD_DST_ADDRESS_HIGH
), 2);
644 PUSH_DATAh(push
, txc
->offset
+ 65536 + (tsc
->id
* 32));
645 PUSH_DATA (push
, txc
->offset
+ 65536 + (tsc
->id
* 32));
646 BEGIN_NVC0(push
, NVE4_P2MF(UPLOAD_LINE_LENGTH_IN
), 2);
647 PUSH_DATA (push
, 32);
649 BEGIN_1IC0(push
, NVE4_P2MF(UPLOAD_EXEC
), 9);
650 PUSH_DATA (push
, 0x1001);
651 PUSH_DATAp(push
, &tsc
->tsc
[0], 8);
655 nvc0
->screen
->tsc
.lock
[tsc
->id
/ 32] |= 1 << (tsc
->id
% 32);
657 nvc0
->tex_handles
[s
][i
] &= ~NVE4_TSC_ENTRY_INVALID
;
658 nvc0
->tex_handles
[s
][i
] |= tsc
->id
<< 20;
660 for (; i
< nvc0
->state
.num_samplers
[s
]; ++i
) {
661 nvc0
->tex_handles
[s
][i
] |= NVE4_TSC_ENTRY_INVALID
;
662 nvc0
->samplers_dirty
[s
] |= 1 << i
;
665 nvc0
->state
.num_samplers
[s
] = nvc0
->num_samplers
[s
];
670 void nvc0_validate_samplers(struct nvc0_context
*nvc0
)
672 bool need_flush
= false;
675 for (i
= 0; i
< 5; i
++) {
676 if (nvc0
->screen
->base
.class_3d
>= NVE4_3D_CLASS
)
677 need_flush
|= nve4_validate_tsc(nvc0
, i
);
679 need_flush
|= nvc0_validate_tsc(nvc0
, i
);
683 BEGIN_NVC0(nvc0
->base
.pushbuf
, NVC0_3D(TSC_FLUSH
), 1);
684 PUSH_DATA (nvc0
->base
.pushbuf
, 0);
688 /* Upload the "diagonal" entries for the possible texture sources ($t == $s).
689 * At some point we might want to get a list of the combinations used by a
690 * shader and fill in those entries instead of having it extract the handles.
693 nve4_set_tex_handles(struct nvc0_context
*nvc0
)
695 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
699 if (nvc0
->screen
->base
.class_3d
< NVE4_3D_CLASS
)
701 address
= nvc0
->screen
->uniform_bo
->offset
+ (5 << 16);
703 for (s
= 0; s
< 5; ++s
, address
+= (1 << 10)) {
704 uint32_t dirty
= nvc0
->textures_dirty
[s
] | nvc0
->samplers_dirty
[s
];
707 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
708 PUSH_DATA (push
, 1024);
709 PUSH_DATAh(push
, address
);
710 PUSH_DATA (push
, address
);
712 int i
= ffs(dirty
) - 1;
715 BEGIN_NVC0(push
, NVC0_3D(CB_POS
), 2);
716 PUSH_DATA (push
, (8 + i
) * 4);
717 PUSH_DATA (push
, nvc0
->tex_handles
[s
][i
]);
720 nvc0
->textures_dirty
[s
] = 0;
721 nvc0
->samplers_dirty
[s
] = 0;
726 static const uint8_t nve4_su_format_map
[PIPE_FORMAT_COUNT
];
727 static const uint16_t nve4_su_format_aux_map
[PIPE_FORMAT_COUNT
];
728 static const uint16_t nve4_suldp_lib_offset
[PIPE_FORMAT_COUNT
];
731 nve4_set_surface_info(struct nouveau_pushbuf
*push
,
732 struct pipe_surface
*psf
,
733 struct nvc0_screen
*screen
)
735 struct nv50_surface
*sf
= nv50_surface(psf
);
736 struct nv04_resource
*res
;
738 uint32_t *const info
= push
->cur
;
741 if (psf
&& !nve4_su_format_map
[psf
->format
])
742 NOUVEAU_ERR("unsupported surface format, try is_format_supported() !\n");
746 if (!psf
|| !nve4_su_format_map
[psf
->format
]) {
747 memset(info
, 0, 16 * sizeof(*info
));
749 info
[0] = 0xbadf0000;
750 info
[1] = 0x80004000;
751 info
[12] = nve4_suldp_lib_offset
[PIPE_FORMAT_R32G32B32A32_UINT
] +
752 screen
->lib_code
->start
;
755 res
= nv04_resource(sf
->base
.texture
);
757 address
= res
->address
+ sf
->offset
;
760 info
[9] = sf
->height
;
761 info
[10] = sf
->depth
;
762 switch (res
->base
.target
) {
763 case PIPE_TEXTURE_1D_ARRAY
:
766 case PIPE_TEXTURE_2D
:
767 case PIPE_TEXTURE_RECT
:
770 case PIPE_TEXTURE_3D
:
773 case PIPE_TEXTURE_2D_ARRAY
:
774 case PIPE_TEXTURE_CUBE
:
775 case PIPE_TEXTURE_CUBE_ARRAY
:
782 log2cpp
= (0xf000 & nve4_su_format_aux_map
[sf
->base
.format
]) >> 12;
784 info
[12] = nve4_suldp_lib_offset
[sf
->base
.format
] + screen
->lib_code
->start
;
786 /* limit in bytes for raw access */
787 info
[13] = (0x06 << 22) | ((sf
->width
<< log2cpp
) - 1);
789 info
[1] = nve4_su_format_map
[sf
->base
.format
];
792 switch (util_format_get_blocksizebits(sf
->base
.format
)) {
793 case 16: info
[1] |= 1 << 16; break;
794 case 32: info
[1] |= 2 << 16; break;
795 case 64: info
[1] |= 3 << 16; break;
796 case 128: info
[1] |= 4 << 16; break;
801 info
[1] |= log2cpp
<< 16;
803 info
[1] |= (0x0f00 & nve4_su_format_aux_map
[sf
->base
.format
]);
806 if (res
->base
.target
== PIPE_BUFFER
) {
807 info
[0] = address
>> 8;
808 info
[2] = sf
->width
- 1;
809 info
[2] |= (0xff & nve4_su_format_aux_map
[sf
->base
.format
]) << 22;
818 struct nv50_miptree
*mt
= nv50_miptree(&res
->base
);
819 struct nv50_miptree_level
*lvl
= &mt
->level
[sf
->base
.u
.tex
.level
];
820 const unsigned z
= sf
->base
.u
.tex
.first_layer
;
824 address
+= nvc0_mt_zslice_offset(mt
, psf
->u
.tex
.level
, z
);
825 /* doesn't work if z passes z-tile boundary */
826 assert(sf
->depth
== 1);
828 address
+= mt
->layer_stride
* z
;
831 info
[0] = address
>> 8;
832 info
[2] = sf
->width
- 1;
833 /* NOTE: this is really important: */
834 info
[2] |= (0xff & nve4_su_format_aux_map
[sf
->base
.format
]) << 22;
835 info
[3] = (0x88 << 24) | (lvl
->pitch
/ 64);
836 info
[4] = sf
->height
- 1;
837 info
[4] |= (lvl
->tile_mode
& 0x0f0) << 25;
838 info
[4] |= NVC0_TILE_SHIFT_Y(lvl
->tile_mode
) << 22;
839 info
[5] = mt
->layer_stride
>> 8;
840 info
[6] = sf
->depth
- 1;
841 info
[6] |= (lvl
->tile_mode
& 0xf00) << 21;
842 info
[6] |= NVC0_TILE_SHIFT_Z(lvl
->tile_mode
) << 22;
850 nvc0_update_surface_bindings(struct nvc0_context
*nvc0
)
856 nve4_update_surface_bindings(struct nvc0_context
*nvc0
)
862 nvc0_validate_surfaces(struct nvc0_context
*nvc0
)
864 if (nvc0
->screen
->base
.class_3d
>= NVE4_3D_CLASS
) {
865 nve4_update_surface_bindings(nvc0
);
867 nvc0_update_surface_bindings(nvc0
);
872 static const uint8_t nve4_su_format_map
[PIPE_FORMAT_COUNT
] =
874 [PIPE_FORMAT_R32G32B32A32_FLOAT
] = GK104_IMAGE_FORMAT_RGBA32_FLOAT
,
875 [PIPE_FORMAT_R32G32B32A32_SINT
] = GK104_IMAGE_FORMAT_RGBA32_SINT
,
876 [PIPE_FORMAT_R32G32B32A32_UINT
] = GK104_IMAGE_FORMAT_RGBA32_UINT
,
877 [PIPE_FORMAT_R16G16B16A16_FLOAT
] = GK104_IMAGE_FORMAT_RGBA16_FLOAT
,
878 [PIPE_FORMAT_R16G16B16A16_UNORM
] = GK104_IMAGE_FORMAT_RGBA16_UNORM
,
879 [PIPE_FORMAT_R16G16B16A16_SNORM
] = GK104_IMAGE_FORMAT_RGBA16_SNORM
,
880 [PIPE_FORMAT_R16G16B16A16_SINT
] = GK104_IMAGE_FORMAT_RGBA16_SINT
,
881 [PIPE_FORMAT_R16G16B16A16_UINT
] = GK104_IMAGE_FORMAT_RGBA16_UINT
,
882 [PIPE_FORMAT_R8G8B8A8_UNORM
] = GK104_IMAGE_FORMAT_RGBA8_UNORM
,
883 [PIPE_FORMAT_R8G8B8A8_SNORM
] = GK104_IMAGE_FORMAT_RGBA8_SNORM
,
884 [PIPE_FORMAT_R8G8B8A8_SINT
] = GK104_IMAGE_FORMAT_RGBA8_SINT
,
885 [PIPE_FORMAT_R8G8B8A8_UINT
] = GK104_IMAGE_FORMAT_RGBA8_UINT
,
886 [PIPE_FORMAT_R11G11B10_FLOAT
] = GK104_IMAGE_FORMAT_R11G11B10_FLOAT
,
887 [PIPE_FORMAT_R10G10B10A2_UNORM
] = GK104_IMAGE_FORMAT_RGB10_A2_UNORM
,
888 /* [PIPE_FORMAT_R10G10B10A2_UINT] = GK104_IMAGE_FORMAT_RGB10_A2_UINT, */
889 [PIPE_FORMAT_R32G32_FLOAT
] = GK104_IMAGE_FORMAT_RG32_FLOAT
,
890 [PIPE_FORMAT_R32G32_SINT
] = GK104_IMAGE_FORMAT_RG32_SINT
,
891 [PIPE_FORMAT_R32G32_UINT
] = GK104_IMAGE_FORMAT_RG32_UINT
,
892 [PIPE_FORMAT_R16G16_FLOAT
] = GK104_IMAGE_FORMAT_RG16_FLOAT
,
893 [PIPE_FORMAT_R16G16_UNORM
] = GK104_IMAGE_FORMAT_RG16_UNORM
,
894 [PIPE_FORMAT_R16G16_SNORM
] = GK104_IMAGE_FORMAT_RG16_SNORM
,
895 [PIPE_FORMAT_R16G16_SINT
] = GK104_IMAGE_FORMAT_RG16_SINT
,
896 [PIPE_FORMAT_R16G16_UINT
] = GK104_IMAGE_FORMAT_RG16_UINT
,
897 [PIPE_FORMAT_R8G8_UNORM
] = GK104_IMAGE_FORMAT_RG8_UNORM
,
898 [PIPE_FORMAT_R8G8_SNORM
] = GK104_IMAGE_FORMAT_RG8_SNORM
,
899 [PIPE_FORMAT_R8G8_SINT
] = GK104_IMAGE_FORMAT_RG8_SINT
,
900 [PIPE_FORMAT_R8G8_UINT
] = GK104_IMAGE_FORMAT_RG8_UINT
,
901 [PIPE_FORMAT_R32_FLOAT
] = GK104_IMAGE_FORMAT_R32_FLOAT
,
902 [PIPE_FORMAT_R32_SINT
] = GK104_IMAGE_FORMAT_R32_SINT
,
903 [PIPE_FORMAT_R32_UINT
] = GK104_IMAGE_FORMAT_R32_UINT
,
904 [PIPE_FORMAT_R16_FLOAT
] = GK104_IMAGE_FORMAT_R16_FLOAT
,
905 [PIPE_FORMAT_R16_UNORM
] = GK104_IMAGE_FORMAT_R16_UNORM
,
906 [PIPE_FORMAT_R16_SNORM
] = GK104_IMAGE_FORMAT_R16_SNORM
,
907 [PIPE_FORMAT_R16_SINT
] = GK104_IMAGE_FORMAT_R16_SINT
,
908 [PIPE_FORMAT_R16_UINT
] = GK104_IMAGE_FORMAT_R16_UINT
,
909 [PIPE_FORMAT_R8_UNORM
] = GK104_IMAGE_FORMAT_R8_UNORM
,
910 [PIPE_FORMAT_R8_SNORM
] = GK104_IMAGE_FORMAT_R8_SNORM
,
911 [PIPE_FORMAT_R8_SINT
] = GK104_IMAGE_FORMAT_R8_SINT
,
912 [PIPE_FORMAT_R8_UINT
] = GK104_IMAGE_FORMAT_R8_UINT
,
915 /* Auxiliary format description values for surface instructions.
916 * (log2(bytes per pixel) << 12) | (unk8 << 8) | unk22
918 static const uint16_t nve4_su_format_aux_map
[PIPE_FORMAT_COUNT
] =
920 [PIPE_FORMAT_R32G32B32A32_FLOAT
] = 0x4842,
921 [PIPE_FORMAT_R32G32B32A32_SINT
] = 0x4842,
922 [PIPE_FORMAT_R32G32B32A32_UINT
] = 0x4842,
924 [PIPE_FORMAT_R16G16B16A16_UNORM
] = 0x3933,
925 [PIPE_FORMAT_R16G16B16A16_SNORM
] = 0x3933,
926 [PIPE_FORMAT_R16G16B16A16_SINT
] = 0x3933,
927 [PIPE_FORMAT_R16G16B16A16_UINT
] = 0x3933,
928 [PIPE_FORMAT_R16G16B16A16_FLOAT
] = 0x3933,
930 [PIPE_FORMAT_R32G32_FLOAT
] = 0x3433,
931 [PIPE_FORMAT_R32G32_SINT
] = 0x3433,
932 [PIPE_FORMAT_R32G32_UINT
] = 0x3433,
934 [PIPE_FORMAT_R10G10B10A2_UNORM
] = 0x2a24,
935 /* [PIPE_FORMAT_R10G10B10A2_UINT] = 0x2a24, */
936 [PIPE_FORMAT_R8G8B8A8_UNORM
] = 0x2a24,
937 [PIPE_FORMAT_R8G8B8A8_SNORM
] = 0x2a24,
938 [PIPE_FORMAT_R8G8B8A8_SINT
] = 0x2a24,
939 [PIPE_FORMAT_R8G8B8A8_UINT
] = 0x2a24,
940 [PIPE_FORMAT_R11G11B10_FLOAT
] = 0x2a24,
942 [PIPE_FORMAT_R16G16_UNORM
] = 0x2524,
943 [PIPE_FORMAT_R16G16_SNORM
] = 0x2524,
944 [PIPE_FORMAT_R16G16_SINT
] = 0x2524,
945 [PIPE_FORMAT_R16G16_UINT
] = 0x2524,
946 [PIPE_FORMAT_R16G16_FLOAT
] = 0x2524,
948 [PIPE_FORMAT_R32_SINT
] = 0x2024,
949 [PIPE_FORMAT_R32_UINT
] = 0x2024,
950 [PIPE_FORMAT_R32_FLOAT
] = 0x2024,
952 [PIPE_FORMAT_R8G8_UNORM
] = 0x1615,
953 [PIPE_FORMAT_R8G8_SNORM
] = 0x1615,
954 [PIPE_FORMAT_R8G8_SINT
] = 0x1615,
955 [PIPE_FORMAT_R8G8_UINT
] = 0x1615,
957 [PIPE_FORMAT_R16_UNORM
] = 0x1115,
958 [PIPE_FORMAT_R16_SNORM
] = 0x1115,
959 [PIPE_FORMAT_R16_SINT
] = 0x1115,
960 [PIPE_FORMAT_R16_UINT
] = 0x1115,
961 [PIPE_FORMAT_R16_FLOAT
] = 0x1115,
963 [PIPE_FORMAT_R8_UNORM
] = 0x0206,
964 [PIPE_FORMAT_R8_SNORM
] = 0x0206,
965 [PIPE_FORMAT_R8_SINT
] = 0x0206,
966 [PIPE_FORMAT_R8_UINT
] = 0x0206
969 /* NOTE: These are hardcoded offsets for the shader library.
970 * TODO: Automate them.
972 static const uint16_t nve4_suldp_lib_offset
[PIPE_FORMAT_COUNT
] =
974 [PIPE_FORMAT_R32G32B32A32_FLOAT
] = 0x218,
975 [PIPE_FORMAT_R32G32B32A32_SINT
] = 0x218,
976 [PIPE_FORMAT_R32G32B32A32_UINT
] = 0x218,
977 [PIPE_FORMAT_R16G16B16A16_UNORM
] = 0x248,
978 [PIPE_FORMAT_R16G16B16A16_SNORM
] = 0x2b8,
979 [PIPE_FORMAT_R16G16B16A16_SINT
] = 0x330,
980 [PIPE_FORMAT_R16G16B16A16_UINT
] = 0x388,
981 [PIPE_FORMAT_R16G16B16A16_FLOAT
] = 0x3d8,
982 [PIPE_FORMAT_R32G32_FLOAT
] = 0x428,
983 [PIPE_FORMAT_R32G32_SINT
] = 0x468,
984 [PIPE_FORMAT_R32G32_UINT
] = 0x468,
985 [PIPE_FORMAT_R10G10B10A2_UNORM
] = 0x4a8,
986 /* [PIPE_FORMAT_R10G10B10A2_UINT] = 0x530, */
987 [PIPE_FORMAT_R8G8B8A8_UNORM
] = 0x588,
988 [PIPE_FORMAT_R8G8B8A8_SNORM
] = 0x5f8,
989 [PIPE_FORMAT_R8G8B8A8_SINT
] = 0x670,
990 [PIPE_FORMAT_R8G8B8A8_UINT
] = 0x6c8,
991 [PIPE_FORMAT_B5G6R5_UNORM
] = 0x718,
992 [PIPE_FORMAT_B5G5R5X1_UNORM
] = 0x7a0,
993 [PIPE_FORMAT_R16G16_UNORM
] = 0x828,
994 [PIPE_FORMAT_R16G16_SNORM
] = 0x890,
995 [PIPE_FORMAT_R16G16_SINT
] = 0x8f0,
996 [PIPE_FORMAT_R16G16_UINT
] = 0x948,
997 [PIPE_FORMAT_R16G16_FLOAT
] = 0x998,
998 [PIPE_FORMAT_R32_FLOAT
] = 0x9e8,
999 [PIPE_FORMAT_R32_SINT
] = 0xa30,
1000 [PIPE_FORMAT_R32_UINT
] = 0xa30,
1001 [PIPE_FORMAT_R8G8_UNORM
] = 0xa78,
1002 [PIPE_FORMAT_R8G8_SNORM
] = 0xae0,
1003 [PIPE_FORMAT_R8G8_UINT
] = 0xb48,
1004 [PIPE_FORMAT_R8G8_SINT
] = 0xb98,
1005 [PIPE_FORMAT_R16_UNORM
] = 0xbe8,
1006 [PIPE_FORMAT_R16_SNORM
] = 0xc48,
1007 [PIPE_FORMAT_R16_SINT
] = 0xca0,
1008 [PIPE_FORMAT_R16_UINT
] = 0xce8,
1009 [PIPE_FORMAT_R16_FLOAT
] = 0xd30,
1010 [PIPE_FORMAT_R8_UNORM
] = 0xd88,
1011 [PIPE_FORMAT_R8_SNORM
] = 0xde0,
1012 [PIPE_FORMAT_R8_SINT
] = 0xe38,
1013 [PIPE_FORMAT_R8_UINT
] = 0xe88,
1014 [PIPE_FORMAT_R11G11B10_FLOAT
] = 0xed0