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 "nv50/nv50_context.h"
24 #include "nv50/nv50_resource.h"
25 #include "nv50/g80_texture.xml.h"
26 #include "nv50/g80_defs.xml.h"
28 #include "util/u_format.h"
30 static inline uint32_t
31 nv50_tic_swizzle(const struct nv50_format
*fmt
, unsigned swz
, bool tex_int
)
34 case PIPE_SWIZZLE_X
: return fmt
->tic
.src_x
;
35 case PIPE_SWIZZLE_Y
: return fmt
->tic
.src_y
;
36 case PIPE_SWIZZLE_Z
: return fmt
->tic
.src_z
;
37 case PIPE_SWIZZLE_W
: return fmt
->tic
.src_w
;
39 return tex_int
? G80_TIC_SOURCE_ONE_INT
: G80_TIC_SOURCE_ONE_FLOAT
;
42 return G80_TIC_SOURCE_ZERO
;
46 struct pipe_sampler_view
*
47 nv50_create_sampler_view(struct pipe_context
*pipe
,
48 struct pipe_resource
*res
,
49 const struct pipe_sampler_view
*templ
)
53 if (templ
->target
== PIPE_TEXTURE_RECT
|| templ
->target
== PIPE_BUFFER
)
54 flags
|= NV50_TEXVIEW_SCALED_COORDS
;
56 return nv50_create_texture_view(pipe
, res
, templ
, flags
, templ
->target
);
59 struct pipe_sampler_view
*
60 nv50_create_texture_view(struct pipe_context
*pipe
,
61 struct pipe_resource
*texture
,
62 const struct pipe_sampler_view
*templ
,
64 enum pipe_texture_target target
)
66 const uint32_t class_3d
= nouveau_context(pipe
)->screen
->class_3d
;
67 const struct util_format_description
*desc
;
68 const struct nv50_format
*fmt
;
73 struct nv50_tic_entry
*view
;
74 struct nv50_miptree
*mt
= nv50_miptree(texture
);
77 view
= MALLOC_STRUCT(nv50_tic_entry
);
82 view
->pipe
.reference
.count
= 1;
83 view
->pipe
.texture
= NULL
;
84 view
->pipe
.context
= pipe
;
88 pipe_resource_reference(&view
->pipe
.texture
, texture
);
92 desc
= util_format_description(view
->pipe
.format
);
96 fmt
= &nv50_format_table
[view
->pipe
.format
];
98 tex_int
= util_format_is_pure_integer(view
->pipe
.format
);
100 swz
[0] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_r
, tex_int
);
101 swz
[1] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_g
, tex_int
);
102 swz
[2] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_b
, tex_int
);
103 swz
[3] = nv50_tic_swizzle(fmt
, view
->pipe
.swizzle_a
, tex_int
);
104 tic
[0] = (fmt
->tic
.format
<< G80_TIC_0_COMPONENTS_SIZES__SHIFT
) |
105 (fmt
->tic
.type_r
<< G80_TIC_0_R_DATA_TYPE__SHIFT
) |
106 (fmt
->tic
.type_g
<< G80_TIC_0_G_DATA_TYPE__SHIFT
) |
107 (fmt
->tic
.type_b
<< G80_TIC_0_B_DATA_TYPE__SHIFT
) |
108 (fmt
->tic
.type_a
<< G80_TIC_0_A_DATA_TYPE__SHIFT
) |
109 (swz
[0] << G80_TIC_0_X_SOURCE__SHIFT
) |
110 (swz
[1] << G80_TIC_0_Y_SOURCE__SHIFT
) |
111 (swz
[2] << G80_TIC_0_Z_SOURCE__SHIFT
) |
112 (swz
[3] << G80_TIC_0_W_SOURCE__SHIFT
);
114 addr
= mt
->base
.address
;
116 depth
= MAX2(mt
->base
.base
.array_size
, mt
->base
.base
.depth0
);
118 if (mt
->base
.base
.array_size
> 1) {
119 /* there doesn't seem to be a base layer field in TIC */
120 addr
+= view
->pipe
.u
.tex
.first_layer
* mt
->layer_stride
;
121 depth
= view
->pipe
.u
.tex
.last_layer
- view
->pipe
.u
.tex
.first_layer
+ 1;
124 tic
[2] = 0x10001000 | G80_TIC_2_BORDER_SOURCE_COLOR
;
126 if (desc
->colorspace
== UTIL_FORMAT_COLORSPACE_SRGB
)
127 tic
[2] |= G80_TIC_2_SRGB_CONVERSION
;
129 if (!(flags
& NV50_TEXVIEW_SCALED_COORDS
))
130 tic
[2] |= G80_TIC_2_NORMALIZED_COORDS
;
132 if (unlikely(!nouveau_bo_memtype(nv04_resource(texture
)->bo
))) {
133 if (target
== PIPE_BUFFER
) {
134 addr
+= view
->pipe
.u
.buf
.offset
;
135 tic
[2] |= G80_TIC_2_LAYOUT_PITCH
| G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER
;
138 view
->pipe
.u
.buf
.size
/ (desc
->block
.bits
/ 8);
141 tic
[2] |= G80_TIC_2_LAYOUT_PITCH
| G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP
;
142 tic
[3] = mt
->level
[0].pitch
;
143 tic
[4] = mt
->base
.base
.width0
;
144 tic
[5] = (1 << 16) | (mt
->base
.base
.height0
);
149 tic
[2] |= addr
>> 32;
154 tic
[2] |= (addr
>> 32) & 0xff;
157 ((mt
->level
[0].tile_mode
& 0x0f0) << (22 - 4)) |
158 ((mt
->level
[0].tile_mode
& 0xf00) << (25 - 8));
161 case PIPE_TEXTURE_1D
:
162 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D
;
164 case PIPE_TEXTURE_2D
:
165 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D
;
167 case PIPE_TEXTURE_RECT
:
168 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP
;
170 case PIPE_TEXTURE_3D
:
171 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_THREE_D
;
173 case PIPE_TEXTURE_CUBE
:
175 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_CUBEMAP
;
177 case PIPE_TEXTURE_1D_ARRAY
:
178 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_ARRAY
;
180 case PIPE_TEXTURE_2D_ARRAY
:
181 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_ARRAY
;
183 case PIPE_TEXTURE_CUBE_ARRAY
:
185 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_CUBE_ARRAY
;
188 assert(0); /* should be linear and handled above ! */
189 tic
[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER
| G80_TIC_2_LAYOUT_PITCH
;
192 unreachable("unexpected/invalid texture target");
195 tic
[3] = (flags
& NV50_TEXVIEW_FILTER_MSAA8
) ? 0x20000000 : 0x00300000;
197 tic
[4] = (1 << 31) | (mt
->base
.base
.width0
<< mt
->ms_x
);
199 tic
[5] = (mt
->base
.base
.height0
<< mt
->ms_y
) & 0xffff;
200 tic
[5] |= depth
<< 16;
201 if (class_3d
> NV50_3D_CLASS
)
202 tic
[5] |= mt
->base
.base
.last_level
<< G80_TIC_5_MAP_MIP_LEVEL__SHIFT
;
204 tic
[5] |= view
->pipe
.u
.tex
.last_level
<< G80_TIC_5_MAP_MIP_LEVEL__SHIFT
;
206 tic
[6] = (mt
->ms_x
> 1) ? 0x88000000 : 0x03000000; /* sampling points */
208 if (class_3d
> NV50_3D_CLASS
)
209 tic
[7] = (view
->pipe
.u
.tex
.last_level
<< 4) | view
->pipe
.u
.tex
.first_level
;
213 if (unlikely(!(tic
[2] & G80_TIC_2_NORMALIZED_COORDS
)))
214 if (mt
->base
.base
.last_level
)
215 tic
[5] &= ~G80_TIC_5_MAP_MIP_LEVEL__MASK
;
221 nv50_update_tic(struct nv50_context
*nv50
, struct nv50_tic_entry
*tic
,
222 struct nv04_resource
*res
)
224 uint64_t address
= res
->address
;
225 if (res
->base
.target
!= PIPE_BUFFER
)
227 address
+= tic
->pipe
.u
.buf
.offset
;
228 if (tic
->tic
[1] == (uint32_t)address
&&
229 (tic
->tic
[2] & 0xff) == address
>> 32)
232 nv50_screen_tic_unlock(nv50
->screen
, tic
);
234 tic
->tic
[1] = address
;
235 tic
->tic
[2] &= 0xffffff00;
236 tic
->tic
[2] |= address
>> 32;
240 nv50_validate_tic(struct nv50_context
*nv50
, int s
)
242 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
243 struct nouveau_bo
*txc
= nv50
->screen
->txc
;
245 bool need_flush
= false;
247 assert(nv50
->num_textures
[s
] <= PIPE_MAX_SAMPLERS
);
248 for (i
= 0; i
< nv50
->num_textures
[s
]; ++i
) {
249 struct nv50_tic_entry
*tic
= nv50_tic_entry(nv50
->textures
[s
][i
]);
250 struct nv04_resource
*res
;
253 BEGIN_NV04(push
, NV50_3D(BIND_TIC(s
)), 1);
254 PUSH_DATA (push
, (i
<< 1) | 0);
257 res
= &nv50_miptree(tic
->pipe
.texture
)->base
;
258 nv50_update_tic(nv50
, tic
, res
);
261 tic
->id
= nv50_screen_tic_alloc(nv50
->screen
, tic
);
263 BEGIN_NV04(push
, NV50_2D(DST_FORMAT
), 2);
264 PUSH_DATA (push
, G80_SURFACE_FORMAT_R8_UNORM
);
266 BEGIN_NV04(push
, NV50_2D(DST_PITCH
), 5);
267 PUSH_DATA (push
, 262144);
268 PUSH_DATA (push
, 65536);
270 PUSH_DATAh(push
, txc
->offset
);
271 PUSH_DATA (push
, txc
->offset
);
272 BEGIN_NV04(push
, NV50_2D(SIFC_BITMAP_ENABLE
), 2);
274 PUSH_DATA (push
, G80_SURFACE_FORMAT_R8_UNORM
);
275 BEGIN_NV04(push
, NV50_2D(SIFC_WIDTH
), 10);
276 PUSH_DATA (push
, 32);
283 PUSH_DATA (push
, tic
->id
* 32);
286 BEGIN_NI04(push
, NV50_2D(SIFC_DATA
), 8);
287 PUSH_DATAp(push
, &tic
->tic
[0], 8);
291 if (res
->status
& NOUVEAU_BUFFER_STATUS_GPU_WRITING
) {
292 BEGIN_NV04(push
, NV50_3D(TEX_CACHE_CTL
), 1);
293 PUSH_DATA (push
, 0x20);
296 nv50
->screen
->tic
.lock
[tic
->id
/ 32] |= 1 << (tic
->id
% 32);
298 res
->status
&= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
299 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_READING
;
301 BCTX_REFN(nv50
->bufctx_3d
, 3D_TEXTURES
, res
, RD
);
303 BEGIN_NV04(push
, NV50_3D(BIND_TIC(s
)), 1);
304 PUSH_DATA (push
, (tic
->id
<< 9) | (i
<< 1) | 1);
306 for (; i
< nv50
->state
.num_textures
[s
]; ++i
) {
307 BEGIN_NV04(push
, NV50_3D(BIND_TIC(s
)), 1);
308 PUSH_DATA (push
, (i
<< 1) | 0);
310 if (nv50
->num_textures
[s
]) {
311 BEGIN_NV04(push
, NV50_3D(CB_ADDR
), 1);
312 PUSH_DATA (push
, ((NV50_CB_AUX_TEX_MS_OFFSET
+ 16 * s
* 2 * 4) << (8 - 2)) | NV50_CB_AUX
);
313 BEGIN_NI04(push
, NV50_3D(CB_DATA(0)), nv50
->num_textures
[s
] * 2);
314 for (i
= 0; i
< nv50
->num_textures
[s
]; i
++) {
315 struct nv50_tic_entry
*tic
= nv50_tic_entry(nv50
->textures
[s
][i
]);
316 struct nv50_miptree
*res
;
323 res
= nv50_miptree(tic
->pipe
.texture
);
324 PUSH_DATA (push
, res
->ms_x
);
325 PUSH_DATA (push
, res
->ms_y
);
328 nv50
->state
.num_textures
[s
] = nv50
->num_textures
[s
];
333 void nv50_validate_textures(struct nv50_context
*nv50
)
337 need_flush
= nv50_validate_tic(nv50
, 0);
338 need_flush
|= nv50_validate_tic(nv50
, 1);
339 need_flush
|= nv50_validate_tic(nv50
, 2);
342 BEGIN_NV04(nv50
->base
.pushbuf
, NV50_3D(TIC_FLUSH
), 1);
343 PUSH_DATA (nv50
->base
.pushbuf
, 0);
348 nv50_validate_tsc(struct nv50_context
*nv50
, int s
)
350 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
352 bool need_flush
= false;
354 assert(nv50
->num_samplers
[s
] <= PIPE_MAX_SAMPLERS
);
355 for (i
= 0; i
< nv50
->num_samplers
[s
]; ++i
) {
356 struct nv50_tsc_entry
*tsc
= nv50_tsc_entry(nv50
->samplers
[s
][i
]);
359 BEGIN_NV04(push
, NV50_3D(BIND_TSC(s
)), 1);
360 PUSH_DATA (push
, (i
<< 4) | 0);
363 nv50
->seamless_cube_map
= tsc
->seamless_cube_map
;
365 tsc
->id
= nv50_screen_tsc_alloc(nv50
->screen
, tsc
);
367 nv50_sifc_linear_u8(&nv50
->base
, nv50
->screen
->txc
,
368 65536 + tsc
->id
* 32,
369 NOUVEAU_BO_VRAM
, 32, tsc
->tsc
);
372 nv50
->screen
->tsc
.lock
[tsc
->id
/ 32] |= 1 << (tsc
->id
% 32);
374 BEGIN_NV04(push
, NV50_3D(BIND_TSC(s
)), 1);
375 PUSH_DATA (push
, (tsc
->id
<< 12) | (i
<< 4) | 1);
377 for (; i
< nv50
->state
.num_samplers
[s
]; ++i
) {
378 BEGIN_NV04(push
, NV50_3D(BIND_TSC(s
)), 1);
379 PUSH_DATA (push
, (i
<< 4) | 0);
381 nv50
->state
.num_samplers
[s
] = nv50
->num_samplers
[s
];
383 // TXF, in unlinked tsc mode, will always use sampler 0. So we have to
384 // ensure that it remains bound. Its contents don't matter, all samplers we
385 // ever create have the SRGB_CONVERSION bit set, so as long as the first
386 // entry is initialized, we're good to go. This is the only bit that has
387 // any effect on what TXF does.
388 if (!nv50
->samplers
[s
][0]) {
389 BEGIN_NV04(push
, NV50_3D(BIND_TSC(s
)), 1);
396 void nv50_validate_samplers(struct nv50_context
*nv50
)
400 need_flush
= nv50_validate_tsc(nv50
, 0);
401 need_flush
|= nv50_validate_tsc(nv50
, 1);
402 need_flush
|= nv50_validate_tsc(nv50
, 2);
405 BEGIN_NV04(nv50
->base
.pushbuf
, NV50_3D(TSC_FLUSH
), 1);
406 PUSH_DATA (nv50
->base
.pushbuf
, 0);
410 /* There can be up to 4 different MS levels (1, 2, 4, 8). To simplify the
411 * shader logic, allow each one to take up 8 offsets.
413 #define COMBINE(x, y) x, y
415 static const uint32_t msaa_sample_xy_offsets
[] = {
457 void nv50_upload_ms_info(struct nouveau_pushbuf
*push
)
459 BEGIN_NV04(push
, NV50_3D(CB_ADDR
), 1);
460 PUSH_DATA (push
, (NV50_CB_AUX_MS_OFFSET
<< (8 - 2)) | NV50_CB_AUX
);
461 BEGIN_NI04(push
, NV50_3D(CB_DATA(0)), ARRAY_SIZE(msaa_sample_xy_offsets
));
462 PUSH_DATAp(push
, msaa_sample_xy_offsets
, ARRAY_SIZE(msaa_sample_xy_offsets
));
465 void nv50_upload_tsc0(struct nv50_context
*nv50
)
467 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
468 u32 data
[8] = { G80_TSC_0_SRGB_CONVERSION
};
469 nv50_sifc_linear_u8(&nv50
->base
, nv50
->screen
->txc
,
470 65536 /* + tsc->id * 32 */,
471 NOUVEAU_BO_VRAM
, 32, data
);
472 BEGIN_NV04(push
, NV50_3D(TSC_FLUSH
), 1);