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 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. 21 */ 22 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" 27 28 #include "util/u_format.h" 29 30 static inline uint32_t 31 nv50_tic_swizzle(const struct nv50_format *fmt, unsigned swz, bool tex_int) 32 { 33 switch (swz) { 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; 38 case PIPE_SWIZZLE_1: 39 return tex_int ? G80_TIC_SOURCE_ONE_INT : G80_TIC_SOURCE_ONE_FLOAT; 40 case PIPE_SWIZZLE_0: 41 default: 42 return G80_TIC_SOURCE_ZERO; 43 } 44 } 45 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) 50 { 51 uint32_t flags = 0; 52 53 if (templ->target == PIPE_TEXTURE_RECT || templ->target == PIPE_BUFFER) 54 flags |= NV50_TEXVIEW_SCALED_COORDS; 55 56 return nv50_create_texture_view(pipe, res, templ, flags, templ->target); 57 } 58 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, 63 uint32_t flags, 64 enum pipe_texture_target target) 65 { 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; 69 uint64_t addr; 70 uint32_t *tic; 71 uint32_t swz[4]; 72 uint32_t depth; 73 struct nv50_tic_entry *view; 74 struct nv50_miptree *mt = nv50_miptree(texture); 75 bool tex_int; 76 77 view = MALLOC_STRUCT(nv50_tic_entry); 78 if (!view) 79 return NULL; 80 81 view->pipe = *templ; 82 view->pipe.reference.count = 1; 83 view->pipe.texture = NULL; 84 view->pipe.context = pipe; 85 86 view->id = -1; 87 88 pipe_resource_reference(&view->pipe.texture, texture); 89 90 tic = &view->tic[0]; 91 92 desc = util_format_description(view->pipe.format); 93 94 /* TIC[0] */ 95 96 fmt = &nv50_format_table[view->pipe.format]; 97 98 tex_int = util_format_is_pure_integer(view->pipe.format); 99 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); 113 114 addr = mt->base.address; 115 116 depth = MAX2(mt->base.base.array_size, mt->base.base.depth0); 117 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; 122 } 123 124 tic[2] = 0x10001000 | G80_TIC_2_BORDER_SOURCE_COLOR; 125 126 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) 127 tic[2] |= G80_TIC_2_SRGB_CONVERSION; 128 129 if (!(flags & NV50_TEXVIEW_SCALED_COORDS)) 130 tic[2] |= G80_TIC_2_NORMALIZED_COORDS; 131 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; 136 tic[3] = 0; 137 tic[4] = /* width */ 138 view->pipe.u.buf.size / (desc->block.bits / 8); 139 tic[5] = 0; 140 } else { 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); 145 } 146 tic[6] = 147 tic[7] = 0; 148 tic[1] = addr; 149 tic[2] |= addr >> 32; 150 return &view->pipe; 151 } 152 153 tic[1] = addr; 154 tic[2] |= (addr >> 32) & 0xff; 155 156 tic[2] |= 157 ((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) | 158 ((mt->level[0].tile_mode & 0xf00) << (25 - 8)); 159 160 switch (target) { 161 case PIPE_TEXTURE_1D: 162 tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D; 163 break; 164 case PIPE_TEXTURE_2D: 165 tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D; 166 break; 167 case PIPE_TEXTURE_RECT: 168 tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP; 169 break; 170 case PIPE_TEXTURE_3D: 171 tic[2] |= G80_TIC_2_TEXTURE_TYPE_THREE_D; 172 break; 173 case PIPE_TEXTURE_CUBE: 174 depth /= 6; 175 tic[2] |= G80_TIC_2_TEXTURE_TYPE_CUBEMAP; 176 break; 177 case PIPE_TEXTURE_1D_ARRAY: 178 tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_ARRAY; 179 break; 180 case PIPE_TEXTURE_2D_ARRAY: 181 tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_ARRAY; 182 break; 183 case PIPE_TEXTURE_CUBE_ARRAY: 184 depth /= 6; 185 tic[2] |= G80_TIC_2_TEXTURE_TYPE_CUBE_ARRAY; 186 break; 187 case PIPE_BUFFER: 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; 190 break; 191 default: 192 unreachable("unexpected/invalid texture target"); 193 } 194 195 tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000; 196 197 tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x); 198 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; 203 else 204 tic[5] |= view->pipe.u.tex.last_level << G80_TIC_5_MAP_MIP_LEVEL__SHIFT; 205 206 tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */ 207 208 if (class_3d > NV50_3D_CLASS) 209 tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level; 210 else 211 tic[7] = 0; 212 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; 216 217 return &view->pipe; 218 } 219 220 static void 221 nv50_update_tic(struct nv50_context *nv50, struct nv50_tic_entry *tic, 222 struct nv04_resource *res) 223 { 224 uint64_t address = res->address; 225 if (res->base.target != PIPE_BUFFER) 226 return; 227 address += tic->pipe.u.buf.offset; 228 if (tic->tic[1] == (uint32_t)address && 229 (tic->tic[2] & 0xff) == address >> 32) 230 return; 231 232 nv50_screen_tic_unlock(nv50->screen, tic); 233 tic->id = -1; 234 tic->tic[1] = address; 235 tic->tic[2] &= 0xffffff00; 236 tic->tic[2] |= address >> 32; 237 } 238 239 static bool 240 nv50_validate_tic(struct nv50_context *nv50, int s) 241 { 242 struct nouveau_pushbuf *push = nv50->base.pushbuf; 243 struct nouveau_bo *txc = nv50->screen->txc; 244 unsigned i; 245 bool need_flush = false; 246 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; 251 252 if (!tic) { 253 BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 254 PUSH_DATA (push, (i << 1) | 0); 255 continue; 256 } 257 res = &nv50_miptree(tic->pipe.texture)->base; 258 nv50_update_tic(nv50, tic, res); 259 260 if (tic->id < 0) { 261 tic->id = nv50_screen_tic_alloc(nv50->screen, tic); 262 263 BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); 264 PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 265 PUSH_DATA (push, 1); 266 BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); 267 PUSH_DATA (push, 262144); 268 PUSH_DATA (push, 65536); 269 PUSH_DATA (push, 1); 270 PUSH_DATAh(push, txc->offset); 271 PUSH_DATA (push, txc->offset); 272 BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); 273 PUSH_DATA (push, 0); 274 PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 275 BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); 276 PUSH_DATA (push, 32); 277 PUSH_DATA (push, 1); 278 PUSH_DATA (push, 0); 279 PUSH_DATA (push, 1); 280 PUSH_DATA (push, 0); 281 PUSH_DATA (push, 1); 282 PUSH_DATA (push, 0); 283 PUSH_DATA (push, tic->id * 32); 284 PUSH_DATA (push, 0); 285 PUSH_DATA (push, 0); 286 BEGIN_NI04(push, NV50_2D(SIFC_DATA), 8); 287 PUSH_DATAp(push, &tic->tic[0], 8); 288 289 need_flush = true; 290 } else 291 if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 292 BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1); 293 PUSH_DATA (push, 0x20); 294 } 295 296 nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32); 297 298 res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; 299 res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; 300 301 BCTX_REFN(nv50->bufctx_3d, 3D_TEXTURES, res, RD); 302 303 BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 304 PUSH_DATA (push, (tic->id << 9) | (i << 1) | 1); 305 } 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); 309 } 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; 317 318 if (!tic) { 319 PUSH_DATA (push, 0); 320 PUSH_DATA (push, 0); 321 continue; 322 } 323 res = nv50_miptree(tic->pipe.texture); 324 PUSH_DATA (push, res->ms_x); 325 PUSH_DATA (push, res->ms_y); 326 } 327 } 328 nv50->state.num_textures[s] = nv50->num_textures[s]; 329 330 return need_flush; 331 } 332 333 void nv50_validate_textures(struct nv50_context *nv50) 334 { 335 bool need_flush; 336 337 need_flush = nv50_validate_tic(nv50, 0); 338 need_flush |= nv50_validate_tic(nv50, 1); 339 need_flush |= nv50_validate_tic(nv50, 2); 340 341 if (need_flush) { 342 BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TIC_FLUSH), 1); 343 PUSH_DATA (nv50->base.pushbuf, 0); 344 } 345 } 346 347 static bool 348 nv50_validate_tsc(struct nv50_context *nv50, int s) 349 { 350 struct nouveau_pushbuf *push = nv50->base.pushbuf; 351 unsigned i; 352 bool need_flush = false; 353 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]); 357 358 if (!tsc) { 359 BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 360 PUSH_DATA (push, (i << 4) | 0); 361 continue; 362 } 363 nv50->seamless_cube_map = tsc->seamless_cube_map; 364 if (tsc->id < 0) { 365 tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc); 366 367 nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc, 368 65536 + tsc->id * 32, 369 NOUVEAU_BO_VRAM, 32, tsc->tsc); 370 need_flush = true; 371 } 372 nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32); 373 374 BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 375 PUSH_DATA (push, (tsc->id << 12) | (i << 4) | 1); 376 } 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); 380 } 381 nv50->state.num_samplers[s] = nv50->num_samplers[s]; 382 383 return need_flush; 384 } 385 386 void nv50_validate_samplers(struct nv50_context *nv50) 387 { 388 bool need_flush; 389 390 need_flush = nv50_validate_tsc(nv50, 0); 391 need_flush |= nv50_validate_tsc(nv50, 1); 392 need_flush |= nv50_validate_tsc(nv50, 2); 393 394 if (need_flush) { 395 BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TSC_FLUSH), 1); 396 PUSH_DATA (nv50->base.pushbuf, 0); 397 } 398 } 399 400 /* There can be up to 4 different MS levels (1, 2, 4, 8). To simplify the 401 * shader logic, allow each one to take up 8 offsets. 402 */ 403 #define COMBINE(x, y) x, y 404 #define DUMMY 0, 0 405 static const uint32_t msaa_sample_xy_offsets[] = { 406 /* MS1 */ 407 COMBINE(0, 0), 408 DUMMY, 409 DUMMY, 410 DUMMY, 411 DUMMY, 412 DUMMY, 413 DUMMY, 414 DUMMY, 415 416 /* MS2 */ 417 COMBINE(0, 0), 418 COMBINE(1, 0), 419 DUMMY, 420 DUMMY, 421 DUMMY, 422 DUMMY, 423 DUMMY, 424 DUMMY, 425 426 /* MS4 */ 427 COMBINE(0, 0), 428 COMBINE(1, 0), 429 COMBINE(0, 1), 430 COMBINE(1, 1), 431 DUMMY, 432 DUMMY, 433 DUMMY, 434 DUMMY, 435 436 /* MS8 */ 437 COMBINE(0, 0), 438 COMBINE(1, 0), 439 COMBINE(0, 1), 440 COMBINE(1, 1), 441 COMBINE(2, 0), 442 COMBINE(3, 0), 443 COMBINE(2, 1), 444 COMBINE(3, 1), 445 }; 446 447 void nv50_upload_ms_info(struct nouveau_pushbuf *push) 448 { 449 BEGIN_NV04(push, NV50_3D(CB_ADDR), 1); 450 PUSH_DATA (push, (NV50_CB_AUX_MS_OFFSET << (8 - 2)) | NV50_CB_AUX); 451 BEGIN_NI04(push, NV50_3D(CB_DATA(0)), ARRAY_SIZE(msaa_sample_xy_offsets)); 452 PUSH_DATAp(push, msaa_sample_xy_offsets, ARRAY_SIZE(msaa_sample_xy_offsets)); 453 } 454