1 2 #include "util/u_framebuffer.h" 3 #include "util/u_math.h" 4 #include "util/u_viewport.h" 5 6 #include "nvc0/nvc0_context.h" 7 8 #if 0 9 static void 10 nvc0_validate_zcull(struct nvc0_context *nvc0) 11 { 12 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 13 struct pipe_framebuffer_state *fb = &nvc0->framebuffer; 14 struct nv50_surface *sf = nv50_surface(fb->zsbuf); 15 struct nv50_miptree *mt = nv50_miptree(sf->base.texture); 16 struct nouveau_bo *bo = mt->base.bo; 17 uint32_t size; 18 uint32_t offset = align(mt->total_size, 1 << 17); 19 unsigned width, height; 20 21 assert(mt->base.base.depth0 == 1 && mt->base.base.array_size < 2); 22 23 size = mt->total_size * 2; 24 25 height = align(fb->height, 32); 26 width = fb->width % 224; 27 if (width) 28 width = fb->width + (224 - width); 29 else 30 width = fb->width; 31 32 BEGIN_NVC0(push, NVC0_3D(ZCULL_REGION), 1); 33 PUSH_DATA (push, 0); 34 BEGIN_NVC0(push, NVC0_3D(ZCULL_ADDRESS_HIGH), 2); 35 PUSH_DATAh(push, bo->offset + offset); 36 PUSH_DATA (push, bo->offset + offset); 37 offset += 1 << 17; 38 BEGIN_NVC0(push, NVC0_3D(ZCULL_LIMIT_HIGH), 2); 39 PUSH_DATAh(push, bo->offset + offset); 40 PUSH_DATA (push, bo->offset + offset); 41 BEGIN_NVC0(push, SUBC_3D(0x07e0), 2); 42 PUSH_DATA (push, size); 43 PUSH_DATA (push, size >> 16); 44 BEGIN_NVC0(push, SUBC_3D(0x15c8), 1); /* bits 0x3 */ 45 PUSH_DATA (push, 2); 46 BEGIN_NVC0(push, NVC0_3D(ZCULL_WIDTH), 4); 47 PUSH_DATA (push, width); 48 PUSH_DATA (push, height); 49 PUSH_DATA (push, 1); 50 PUSH_DATA (push, 0); 51 BEGIN_NVC0(push, NVC0_3D(ZCULL_WINDOW_OFFSET_X), 2); 52 PUSH_DATA (push, 0); 53 PUSH_DATA (push, 0); 54 BEGIN_NVC0(push, NVC0_3D(ZCULL_INVALIDATE), 1); 55 PUSH_DATA (push, 0); 56 } 57 #endif 58 59 static inline void 60 nvc0_fb_set_null_rt(struct nouveau_pushbuf *push, unsigned i, unsigned layers) 61 { 62 BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(i)), 9); 63 PUSH_DATA (push, 0); 64 PUSH_DATA (push, 0); 65 PUSH_DATA (push, 64); // width 66 PUSH_DATA (push, 0); // height 67 PUSH_DATA (push, 0); // format 68 PUSH_DATA (push, 0); // tile mode 69 PUSH_DATA (push, layers); // layers 70 PUSH_DATA (push, 0); // layer stride 71 PUSH_DATA (push, 0); // base layer 72 } 73 74 static void 75 nvc0_validate_fb(struct nvc0_context *nvc0) 76 { 77 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 78 struct pipe_framebuffer_state *fb = &nvc0->framebuffer; 79 struct nvc0_screen *screen = nvc0->screen; 80 unsigned i, ms; 81 unsigned ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1; 82 unsigned nr_cbufs = fb->nr_cbufs; 83 bool serialize = false; 84 85 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB); 86 87 BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2); 88 PUSH_DATA (push, fb->width << 16); 89 PUSH_DATA (push, fb->height << 16); 90 91 for (i = 0; i < fb->nr_cbufs; ++i) { 92 struct nv50_surface *sf; 93 struct nv04_resource *res; 94 struct nouveau_bo *bo; 95 96 if (!fb->cbufs[i]) { 97 nvc0_fb_set_null_rt(push, i, 0); 98 continue; 99 } 100 101 sf = nv50_surface(fb->cbufs[i]); 102 res = nv04_resource(sf->base.texture); 103 bo = res->bo; 104 105 BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(i)), 9); 106 PUSH_DATAh(push, res->address + sf->offset); 107 PUSH_DATA (push, res->address + sf->offset); 108 if (likely(nouveau_bo_memtype(bo))) { 109 struct nv50_miptree *mt = nv50_miptree(sf->base.texture); 110 111 assert(sf->base.texture->target != PIPE_BUFFER); 112 113 PUSH_DATA(push, sf->width); 114 PUSH_DATA(push, sf->height); 115 PUSH_DATA(push, nvc0_format_table[sf->base.format].rt); 116 PUSH_DATA(push, (mt->layout_3d << 16) | 117 mt->level[sf->base.u.tex.level].tile_mode); 118 PUSH_DATA(push, sf->base.u.tex.first_layer + sf->depth); 119 PUSH_DATA(push, mt->layer_stride >> 2); 120 PUSH_DATA(push, sf->base.u.tex.first_layer); 121 122 ms_mode = mt->ms_mode; 123 } else { 124 if (res->base.target == PIPE_BUFFER) { 125 PUSH_DATA(push, 262144); 126 PUSH_DATA(push, 1); 127 } else { 128 PUSH_DATA(push, nv50_miptree(sf->base.texture)->level[0].pitch); 129 PUSH_DATA(push, sf->height); 130 } 131 PUSH_DATA(push, nvc0_format_table[sf->base.format].rt); 132 PUSH_DATA(push, 1 << 12); 133 PUSH_DATA(push, 1); 134 PUSH_DATA(push, 0); 135 PUSH_DATA(push, 0); 136 137 nvc0_resource_fence(res, NOUVEAU_BO_WR); 138 139 assert(!fb->zsbuf); 140 } 141 142 if (res->status & NOUVEAU_BUFFER_STATUS_GPU_READING) 143 serialize = true; 144 res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; 145 res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING; 146 147 /* only register for writing, otherwise we'd always serialize here */ 148 BCTX_REFN(nvc0->bufctx_3d, 3D_FB, res, WR); 149 } 150 151 if (fb->zsbuf) { 152 struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture); 153 struct nv50_surface *sf = nv50_surface(fb->zsbuf); 154 int unk = mt->base.base.target == PIPE_TEXTURE_2D; 155 156 BEGIN_NVC0(push, NVC0_3D(ZETA_ADDRESS_HIGH), 5); 157 PUSH_DATAh(push, mt->base.address + sf->offset); 158 PUSH_DATA (push, mt->base.address + sf->offset); 159 PUSH_DATA (push, nvc0_format_table[fb->zsbuf->format].rt); 160 PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode); 161 PUSH_DATA (push, mt->layer_stride >> 2); 162 BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1); 163 PUSH_DATA (push, 1); 164 BEGIN_NVC0(push, NVC0_3D(ZETA_HORIZ), 3); 165 PUSH_DATA (push, sf->width); 166 PUSH_DATA (push, sf->height); 167 PUSH_DATA (push, (unk << 16) | 168 (sf->base.u.tex.first_layer + sf->depth)); 169 BEGIN_NVC0(push, NVC0_3D(ZETA_BASE_LAYER), 1); 170 PUSH_DATA (push, sf->base.u.tex.first_layer); 171 172 ms_mode = mt->ms_mode; 173 174 if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING) 175 serialize = true; 176 mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; 177 mt->base.status &= ~NOUVEAU_BUFFER_STATUS_GPU_READING; 178 179 BCTX_REFN(nvc0->bufctx_3d, 3D_FB, &mt->base, WR); 180 } else { 181 BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1); 182 PUSH_DATA (push, 0); 183 } 184 185 if (nr_cbufs == 0 && !fb->zsbuf) { 186 assert(util_is_power_of_two(fb->samples)); 187 assert(fb->samples <= 8); 188 189 nvc0_fb_set_null_rt(push, 0, fb->layers); 190 191 if (fb->samples > 1) 192 ms_mode = ffs(fb->samples) - 1; 193 nr_cbufs = 1; 194 } 195 196 BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1); 197 PUSH_DATA (push, (076543210 << 4) | nr_cbufs); 198 IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_MODE), ms_mode); 199 200 ms = 1 << ms_mode; 201 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 202 PUSH_DATA (push, NVC0_CB_AUX_SIZE); 203 PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(4)); 204 PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(4)); 205 BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 2 * ms); 206 PUSH_DATA (push, NVC0_CB_AUX_SAMPLE_INFO); 207 for (i = 0; i < ms; i++) { 208 float xy[2]; 209 nvc0->base.pipe.get_sample_position(&nvc0->base.pipe, ms, i, xy); 210 PUSH_DATAf(push, xy[0]); 211 PUSH_DATAf(push, xy[1]); 212 } 213 214 if (screen->base.class_3d >= GM200_3D_CLASS) { 215 const uint8_t (*ptr)[2] = nvc0_get_sample_locations(ms); 216 uint32_t val[4] = {}; 217 218 for (i = 0; i < 16; i++) { 219 val[i / 4] |= ptr[i % ms][0] << (((i % 4) * 8) + 0); 220 val[i / 4] |= ptr[i % ms][1] << (((i % 4) * 8) + 4); 221 } 222 223 BEGIN_NVC0(push, SUBC_3D(0x11e0), 4); 224 PUSH_DATAp(push, val, 4); 225 } 226 227 if (serialize) 228 IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0); 229 230 NOUVEAU_DRV_STAT(&nvc0->screen->base, gpu_serialize_count, serialize); 231 } 232 233 static void 234 nvc0_validate_blend_colour(struct nvc0_context *nvc0) 235 { 236 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 237 238 BEGIN_NVC0(push, NVC0_3D(BLEND_COLOR(0)), 4); 239 PUSH_DATAf(push, nvc0->blend_colour.color[0]); 240 PUSH_DATAf(push, nvc0->blend_colour.color[1]); 241 PUSH_DATAf(push, nvc0->blend_colour.color[2]); 242 PUSH_DATAf(push, nvc0->blend_colour.color[3]); 243 } 244 245 static void 246 nvc0_validate_stencil_ref(struct nvc0_context *nvc0) 247 { 248 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 249 const ubyte *ref = &nvc0->stencil_ref.ref_value[0]; 250 251 IMMED_NVC0(push, NVC0_3D(STENCIL_FRONT_FUNC_REF), ref[0]); 252 IMMED_NVC0(push, NVC0_3D(STENCIL_BACK_FUNC_REF), ref[1]); 253 } 254 255 static void 256 nvc0_validate_stipple(struct nvc0_context *nvc0) 257 { 258 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 259 unsigned i; 260 261 BEGIN_NVC0(push, NVC0_3D(POLYGON_STIPPLE_PATTERN(0)), 32); 262 for (i = 0; i < 32; ++i) 263 PUSH_DATA(push, util_bswap32(nvc0->stipple.stipple[i])); 264 } 265 266 static void 267 nvc0_validate_scissor(struct nvc0_context *nvc0) 268 { 269 int i; 270 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 271 272 if (!(nvc0->dirty_3d & NVC0_NEW_3D_SCISSOR) && 273 nvc0->rast->pipe.scissor == nvc0->state.scissor) 274 return; 275 276 if (nvc0->state.scissor != nvc0->rast->pipe.scissor) 277 nvc0->scissors_dirty = (1 << NVC0_MAX_VIEWPORTS) - 1; 278 279 nvc0->state.scissor = nvc0->rast->pipe.scissor; 280 281 for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) { 282 struct pipe_scissor_state *s = &nvc0->scissors[i]; 283 if (!(nvc0->scissors_dirty & (1 << i))) 284 continue; 285 286 BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(i)), 2); 287 if (nvc0->rast->pipe.scissor) { 288 PUSH_DATA(push, (s->maxx << 16) | s->minx); 289 PUSH_DATA(push, (s->maxy << 16) | s->miny); 290 } else { 291 PUSH_DATA(push, (0xffff << 16) | 0); 292 PUSH_DATA(push, (0xffff << 16) | 0); 293 } 294 } 295 nvc0->scissors_dirty = 0; 296 } 297 298 static void 299 nvc0_validate_viewport(struct nvc0_context *nvc0) 300 { 301 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 302 int x, y, w, h, i; 303 float zmin, zmax; 304 305 for (i = 0; i < NVC0_MAX_VIEWPORTS; i++) { 306 struct pipe_viewport_state *vp = &nvc0->viewports[i]; 307 308 if (!(nvc0->viewports_dirty & (1 << i))) 309 continue; 310 311 BEGIN_NVC0(push, NVC0_3D(VIEWPORT_TRANSLATE_X(i)), 3); 312 PUSH_DATAf(push, vp->translate[0]); 313 PUSH_DATAf(push, vp->translate[1]); 314 PUSH_DATAf(push, vp->translate[2]); 315 316 BEGIN_NVC0(push, NVC0_3D(VIEWPORT_SCALE_X(i)), 3); 317 PUSH_DATAf(push, vp->scale[0]); 318 PUSH_DATAf(push, vp->scale[1]); 319 PUSH_DATAf(push, vp->scale[2]); 320 321 /* now set the viewport rectangle to viewport dimensions for clipping */ 322 323 x = util_iround(MAX2(0.0f, vp->translate[0] - fabsf(vp->scale[0]))); 324 y = util_iround(MAX2(0.0f, vp->translate[1] - fabsf(vp->scale[1]))); 325 w = util_iround(vp->translate[0] + fabsf(vp->scale[0])) - x; 326 h = util_iround(vp->translate[1] + fabsf(vp->scale[1])) - y; 327 328 BEGIN_NVC0(push, NVC0_3D(VIEWPORT_HORIZ(i)), 2); 329 PUSH_DATA (push, (w << 16) | x); 330 PUSH_DATA (push, (h << 16) | y); 331 332 /* If the halfz setting ever changes, the viewports will also get 333 * updated. The rast will get updated before the validate function has a 334 * chance to hit, so we can just use it directly without an atom 335 * dependency. 336 */ 337 util_viewport_zmin_zmax(vp, nvc0->rast->pipe.clip_halfz, &zmin, &zmax); 338 339 BEGIN_NVC0(push, NVC0_3D(DEPTH_RANGE_NEAR(i)), 2); 340 PUSH_DATAf(push, zmin); 341 PUSH_DATAf(push, zmax); 342 } 343 nvc0->viewports_dirty = 0; 344 } 345 346 static void 347 nvc0_validate_window_rects(struct nvc0_context *nvc0) 348 { 349 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 350 bool enable = nvc0->window_rect.rects > 0 || nvc0->window_rect.inclusive; 351 int i; 352 353 IMMED_NVC0(push, NVC0_3D(CLIP_RECTS_EN), enable); 354 if (!enable) 355 return; 356 357 IMMED_NVC0(push, NVC0_3D(CLIP_RECTS_MODE), !nvc0->window_rect.inclusive); 358 BEGIN_NVC0(push, NVC0_3D(CLIP_RECT_HORIZ(0)), NVC0_MAX_WINDOW_RECTANGLES * 2); 359 for (i = 0; i < nvc0->window_rect.rects; i++) { 360 struct pipe_scissor_state *s = &nvc0->window_rect.rect[i]; 361 PUSH_DATA(push, (s->maxx << 16) | s->minx); 362 PUSH_DATA(push, (s->maxy << 16) | s->miny); 363 } 364 for (; i < NVC0_MAX_WINDOW_RECTANGLES; i++) { 365 PUSH_DATA(push, 0); 366 PUSH_DATA(push, 0); 367 } 368 } 369 370 static inline void 371 nvc0_upload_uclip_planes(struct nvc0_context *nvc0, unsigned s) 372 { 373 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 374 struct nvc0_screen *screen = nvc0->screen; 375 376 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 377 PUSH_DATA (push, NVC0_CB_AUX_SIZE); 378 PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s)); 379 PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s)); 380 BEGIN_1IC0(push, NVC0_3D(CB_POS), PIPE_MAX_CLIP_PLANES * 4 + 1); 381 PUSH_DATA (push, NVC0_CB_AUX_UCP_INFO); 382 PUSH_DATAp(push, &nvc0->clip.ucp[0][0], PIPE_MAX_CLIP_PLANES * 4); 383 } 384 385 static inline void 386 nvc0_check_program_ucps(struct nvc0_context *nvc0, 387 struct nvc0_program *vp, uint8_t mask) 388 { 389 const unsigned n = util_logbase2(mask) + 1; 390 391 if (vp->vp.num_ucps >= n) 392 return; 393 nvc0_program_destroy(nvc0, vp); 394 395 vp->vp.num_ucps = n; 396 if (likely(vp == nvc0->vertprog)) 397 nvc0_vertprog_validate(nvc0); 398 else 399 if (likely(vp == nvc0->gmtyprog)) 400 nvc0_gmtyprog_validate(nvc0); 401 else 402 nvc0_tevlprog_validate(nvc0); 403 } 404 405 static void 406 nvc0_validate_clip(struct nvc0_context *nvc0) 407 { 408 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 409 struct nvc0_program *vp; 410 unsigned stage; 411 uint8_t clip_enable = nvc0->rast->pipe.clip_plane_enable; 412 413 if (nvc0->gmtyprog) { 414 stage = 3; 415 vp = nvc0->gmtyprog; 416 } else 417 if (nvc0->tevlprog) { 418 stage = 2; 419 vp = nvc0->tevlprog; 420 } else { 421 stage = 0; 422 vp = nvc0->vertprog; 423 } 424 425 if (clip_enable && vp->vp.num_ucps < PIPE_MAX_CLIP_PLANES) 426 nvc0_check_program_ucps(nvc0, vp, clip_enable); 427 428 if (nvc0->dirty_3d & (NVC0_NEW_3D_CLIP | (NVC0_NEW_3D_VERTPROG << stage))) 429 if (vp->vp.num_ucps > 0 && vp->vp.num_ucps <= PIPE_MAX_CLIP_PLANES) 430 nvc0_upload_uclip_planes(nvc0, stage); 431 432 clip_enable &= vp->vp.clip_enable; 433 clip_enable |= vp->vp.cull_enable; 434 435 if (nvc0->state.clip_enable != clip_enable) { 436 nvc0->state.clip_enable = clip_enable; 437 IMMED_NVC0(push, NVC0_3D(CLIP_DISTANCE_ENABLE), clip_enable); 438 } 439 if (nvc0->state.clip_mode != vp->vp.clip_mode) { 440 nvc0->state.clip_mode = vp->vp.clip_mode; 441 BEGIN_NVC0(push, NVC0_3D(CLIP_DISTANCE_MODE), 1); 442 PUSH_DATA (push, vp->vp.clip_mode); 443 } 444 } 445 446 static void 447 nvc0_validate_blend(struct nvc0_context *nvc0) 448 { 449 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 450 451 PUSH_SPACE(push, nvc0->blend->size); 452 PUSH_DATAp(push, nvc0->blend->state, nvc0->blend->size); 453 } 454 455 static void 456 nvc0_validate_zsa(struct nvc0_context *nvc0) 457 { 458 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 459 460 PUSH_SPACE(push, nvc0->zsa->size); 461 PUSH_DATAp(push, nvc0->zsa->state, nvc0->zsa->size); 462 } 463 464 static void 465 nvc0_validate_rasterizer(struct nvc0_context *nvc0) 466 { 467 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 468 469 PUSH_SPACE(push, nvc0->rast->size); 470 PUSH_DATAp(push, nvc0->rast->state, nvc0->rast->size); 471 } 472 473 static void 474 nvc0_constbufs_validate(struct nvc0_context *nvc0) 475 { 476 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 477 unsigned s; 478 479 for (s = 0; s < 5; ++s) { 480 while (nvc0->constbuf_dirty[s]) { 481 int i = ffs(nvc0->constbuf_dirty[s]) - 1; 482 nvc0->constbuf_dirty[s] &= ~(1 << i); 483 484 if (nvc0->constbuf[s][i].user) { 485 struct nouveau_bo *bo = nvc0->screen->uniform_bo; 486 const unsigned base = NVC0_CB_USR_INFO(s); 487 const unsigned size = nvc0->constbuf[s][0].size; 488 assert(i == 0); /* we really only want OpenGL uniforms here */ 489 assert(nvc0->constbuf[s][0].u.data); 490 491 if (nvc0->state.uniform_buffer_bound[s] < size) { 492 nvc0->state.uniform_buffer_bound[s] = align(size, 0x100); 493 494 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 495 PUSH_DATA (push, nvc0->state.uniform_buffer_bound[s]); 496 PUSH_DATAh(push, bo->offset + base); 497 PUSH_DATA (push, bo->offset + base); 498 BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1); 499 PUSH_DATA (push, (0 << 4) | 1); 500 } 501 nvc0_cb_bo_push(&nvc0->base, bo, NV_VRAM_DOMAIN(&nvc0->screen->base), 502 base, nvc0->state.uniform_buffer_bound[s], 503 0, (size + 3) / 4, 504 nvc0->constbuf[s][0].u.data); 505 } else { 506 struct nv04_resource *res = 507 nv04_resource(nvc0->constbuf[s][i].u.buf); 508 if (res) { 509 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 510 PUSH_DATA (push, nvc0->constbuf[s][i].size); 511 PUSH_DATAh(push, res->address + nvc0->constbuf[s][i].offset); 512 PUSH_DATA (push, res->address + nvc0->constbuf[s][i].offset); 513 BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1); 514 PUSH_DATA (push, (i << 4) | 1); 515 516 BCTX_REFN(nvc0->bufctx_3d, 3D_CB(s, i), res, RD); 517 518 nvc0->cb_dirty = 1; /* Force cache flush for UBO. */ 519 res->cb_bindings[s] |= 1 << i; 520 } else { 521 BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1); 522 PUSH_DATA (push, (i << 4) | 0); 523 } 524 if (i == 0) 525 nvc0->state.uniform_buffer_bound[s] = 0; 526 } 527 } 528 } 529 530 if (nvc0->screen->base.class_3d < NVE4_3D_CLASS) { 531 /* Invalidate all COMPUTE constbufs because they are aliased with 3D. */ 532 nvc0->dirty_cp |= NVC0_NEW_CP_CONSTBUF; 533 nvc0->constbuf_dirty[5] |= nvc0->constbuf_valid[5]; 534 nvc0->state.uniform_buffer_bound[5] = 0; 535 } 536 } 537 538 static void 539 nvc0_validate_buffers(struct nvc0_context *nvc0) 540 { 541 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 542 struct nvc0_screen *screen = nvc0->screen; 543 int i, s; 544 545 for (s = 0; s < 5; s++) { 546 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 547 PUSH_DATA (push, NVC0_CB_AUX_SIZE); 548 PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s)); 549 PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(s)); 550 BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 4 * NVC0_MAX_BUFFERS); 551 PUSH_DATA (push, NVC0_CB_AUX_BUF_INFO(0)); 552 for (i = 0; i < NVC0_MAX_BUFFERS; i++) { 553 if (nvc0->buffers[s][i].buffer) { 554 struct nv04_resource *res = 555 nv04_resource(nvc0->buffers[s][i].buffer); 556 PUSH_DATA (push, res->address + nvc0->buffers[s][i].buffer_offset); 557 PUSH_DATAh(push, res->address + nvc0->buffers[s][i].buffer_offset); 558 PUSH_DATA (push, nvc0->buffers[s][i].buffer_size); 559 PUSH_DATA (push, 0); 560 BCTX_REFN(nvc0->bufctx_3d, 3D_BUF, res, RDWR); 561 util_range_add(&res->valid_buffer_range, 562 nvc0->buffers[s][i].buffer_offset, 563 nvc0->buffers[s][i].buffer_offset + 564 nvc0->buffers[s][i].buffer_size); 565 } else { 566 PUSH_DATA (push, 0); 567 PUSH_DATA (push, 0); 568 PUSH_DATA (push, 0); 569 PUSH_DATA (push, 0); 570 } 571 } 572 } 573 574 } 575 576 static void 577 nvc0_validate_sample_mask(struct nvc0_context *nvc0) 578 { 579 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 580 581 unsigned mask[4] = 582 { 583 nvc0->sample_mask & 0xffff, 584 nvc0->sample_mask & 0xffff, 585 nvc0->sample_mask & 0xffff, 586 nvc0->sample_mask & 0xffff 587 }; 588 589 BEGIN_NVC0(push, NVC0_3D(MSAA_MASK(0)), 4); 590 PUSH_DATA (push, mask[0]); 591 PUSH_DATA (push, mask[1]); 592 PUSH_DATA (push, mask[2]); 593 PUSH_DATA (push, mask[3]); 594 } 595 596 static void 597 nvc0_validate_min_samples(struct nvc0_context *nvc0) 598 { 599 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 600 int samples; 601 602 samples = util_next_power_of_two(nvc0->min_samples); 603 if (samples > 1) { 604 // If we're using the incoming sample mask and doing sample shading, we 605 // have to do sample shading "to the max", otherwise there's no way to 606 // tell which sets of samples are covered by the current invocation. 607 // Similarly for reading the framebuffer. 608 if (nvc0->fragprog->fp.sample_mask_in || 609 nvc0->fragprog->fp.reads_framebuffer) 610 samples = util_framebuffer_get_num_samples(&nvc0->framebuffer); 611 samples |= NVC0_3D_SAMPLE_SHADING_ENABLE; 612 } 613 614 IMMED_NVC0(push, NVC0_3D(SAMPLE_SHADING), samples); 615 } 616 617 static void 618 nvc0_validate_driverconst(struct nvc0_context *nvc0) 619 { 620 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 621 struct nvc0_screen *screen = nvc0->screen; 622 int i; 623 624 for (i = 0; i < 5; ++i) { 625 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 626 PUSH_DATA (push, NVC0_CB_AUX_SIZE); 627 PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i)); 628 PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(i)); 629 BEGIN_NVC0(push, NVC0_3D(CB_BIND(i)), 1); 630 PUSH_DATA (push, (15 << 4) | 1); 631 } 632 633 nvc0->dirty_cp |= NVC0_NEW_CP_DRIVERCONST; 634 } 635 636 static void 637 nvc0_validate_fp_zsa_rast(struct nvc0_context *nvc0) 638 { 639 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 640 bool rasterizer_discard; 641 642 if (nvc0->rast && nvc0->rast->pipe.rasterizer_discard) { 643 rasterizer_discard = true; 644 } else { 645 bool zs = nvc0->zsa && 646 (nvc0->zsa->pipe.depth.enabled || nvc0->zsa->pipe.stencil[0].enabled); 647 rasterizer_discard = !zs && 648 (!nvc0->fragprog || !nvc0->fragprog->hdr[18]); 649 } 650 651 if (rasterizer_discard != nvc0->state.rasterizer_discard) { 652 nvc0->state.rasterizer_discard = rasterizer_discard; 653 IMMED_NVC0(push, NVC0_3D(RASTERIZE_ENABLE), !rasterizer_discard); 654 } 655 } 656 657 /* alpha test is disabled if there are no color RTs, so make sure we have at 658 * least one if alpha test is enabled. Note that this must run after 659 * nvc0_validate_fb, otherwise that will override the RT count setting. 660 */ 661 static void 662 nvc0_validate_zsa_fb(struct nvc0_context *nvc0) 663 { 664 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 665 666 if (nvc0->zsa && nvc0->zsa->pipe.alpha.enabled && 667 nvc0->framebuffer.zsbuf && 668 nvc0->framebuffer.nr_cbufs == 0) { 669 nvc0_fb_set_null_rt(push, 0, 0); 670 BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1); 671 PUSH_DATA (push, (076543210 << 4) | 1); 672 } 673 } 674 675 static void 676 nvc0_validate_rast_fb(struct nvc0_context *nvc0) 677 { 678 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 679 struct pipe_framebuffer_state *fb = &nvc0->framebuffer; 680 struct pipe_rasterizer_state *rast = &nvc0->rast->pipe; 681 682 if (!rast) 683 return; 684 685 if (rast->offset_units_unscaled) { 686 BEGIN_NVC0(push, NVC0_3D(POLYGON_OFFSET_UNITS), 1); 687 if (fb->zsbuf && fb->zsbuf->format == PIPE_FORMAT_Z16_UNORM) 688 PUSH_DATAf(push, rast->offset_units * (1 << 16)); 689 else 690 PUSH_DATAf(push, rast->offset_units * (1 << 24)); 691 } 692 } 693 694 695 static void 696 nvc0_validate_tess_state(struct nvc0_context *nvc0) 697 { 698 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 699 700 BEGIN_NVC0(push, NVC0_3D(TESS_LEVEL_OUTER(0)), 6); 701 PUSH_DATAp(push, nvc0->default_tess_outer, 4); 702 PUSH_DATAp(push, nvc0->default_tess_inner, 2); 703 } 704 705 /* If we have a frag shader bound which tries to read from the framebuffer, we 706 * have to make sure that the fb is bound as a texture in the expected 707 * location. For Fermi, that's in the special driver slot 16, while for Kepler 708 * it's a regular binding stored in the driver constbuf. 709 */ 710 static void 711 nvc0_validate_fbread(struct nvc0_context *nvc0) 712 { 713 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 714 struct nvc0_screen *screen = nvc0->screen; 715 struct pipe_context *pipe = &nvc0->base.pipe; 716 struct pipe_sampler_view *old_view = nvc0->fbtexture; 717 struct pipe_sampler_view *new_view = NULL; 718 719 if (nvc0->fragprog && 720 nvc0->fragprog->fp.reads_framebuffer && 721 nvc0->framebuffer.nr_cbufs && 722 nvc0->framebuffer.cbufs[0]) { 723 struct pipe_sampler_view tmpl; 724 struct pipe_surface *sf = nvc0->framebuffer.cbufs[0]; 725 726 tmpl.target = PIPE_TEXTURE_2D_ARRAY; 727 tmpl.format = sf->format; 728 tmpl.u.tex.first_level = tmpl.u.tex.last_level = sf->u.tex.level; 729 tmpl.u.tex.first_layer = sf->u.tex.first_layer; 730 tmpl.u.tex.last_layer = sf->u.tex.last_layer; 731 tmpl.swizzle_r = PIPE_SWIZZLE_X; 732 tmpl.swizzle_g = PIPE_SWIZZLE_Y; 733 tmpl.swizzle_b = PIPE_SWIZZLE_Z; 734 tmpl.swizzle_a = PIPE_SWIZZLE_W; 735 736 /* Bail if it's the same parameters */ 737 if (old_view && old_view->texture == sf->texture && 738 old_view->format == sf->format && 739 old_view->u.tex.first_level == sf->u.tex.level && 740 old_view->u.tex.first_layer == sf->u.tex.first_layer && 741 old_view->u.tex.last_layer == sf->u.tex.last_layer) 742 return; 743 744 new_view = pipe->create_sampler_view(pipe, sf->texture, &tmpl); 745 } else if (old_view == NULL) { 746 return; 747 } 748 749 if (old_view) 750 pipe_sampler_view_reference(&nvc0->fbtexture, NULL); 751 nvc0->fbtexture = new_view; 752 753 if (screen->default_tsc->id < 0) { 754 struct nv50_tsc_entry *tsc = nv50_tsc_entry(screen->default_tsc); 755 tsc->id = nvc0_screen_tsc_alloc(screen, tsc); 756 nvc0->base.push_data(&nvc0->base, screen->txc, 65536 + tsc->id * 32, 757 NV_VRAM_DOMAIN(&screen->base), 32, tsc->tsc); 758 screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32); 759 760 IMMED_NVC0(push, NVC0_3D(TSC_FLUSH), 0); 761 if (screen->base.class_3d < NVE4_3D_CLASS) { 762 BEGIN_NVC0(push, NVC0_3D(BIND_TSC2(0)), 1); 763 PUSH_DATA (push, (tsc->id << 12) | 1); 764 } 765 } 766 767 if (new_view) { 768 struct nv50_tic_entry *tic = nv50_tic_entry(new_view); 769 assert(tic->id < 0); 770 tic->id = nvc0_screen_tic_alloc(screen, tic); 771 nvc0->base.push_data(&nvc0->base, screen->txc, tic->id * 32, 772 NV_VRAM_DOMAIN(&screen->base), 32, tic->tic); 773 screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32); 774 775 if (screen->base.class_3d >= NVE4_3D_CLASS) { 776 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 777 PUSH_DATA (push, NVC0_CB_AUX_SIZE); 778 PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(4)); 779 PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(4)); 780 BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 1); 781 PUSH_DATA (push, NVC0_CB_AUX_FB_TEX_INFO); 782 PUSH_DATA (push, (screen->default_tsc->id << 20) | tic->id); 783 } else { 784 BEGIN_NVC0(push, NVC0_3D(BIND_TIC2(0)), 1); 785 PUSH_DATA (push, (tic->id << 9) | 1); 786 } 787 788 IMMED_NVC0(push, NVC0_3D(TIC_FLUSH), 0); 789 } 790 } 791 792 static void 793 nvc0_switch_pipe_context(struct nvc0_context *ctx_to) 794 { 795 struct nvc0_context *ctx_from = ctx_to->screen->cur_ctx; 796 unsigned s; 797 798 if (ctx_from) 799 ctx_to->state = ctx_from->state; 800 else 801 ctx_to->state = ctx_to->screen->save_state; 802 803 ctx_to->dirty_3d = ~0; 804 ctx_to->dirty_cp = ~0; 805 ctx_to->viewports_dirty = ~0; 806 ctx_to->scissors_dirty = ~0; 807 808 for (s = 0; s < 6; ++s) { 809 ctx_to->samplers_dirty[s] = ~0; 810 ctx_to->textures_dirty[s] = ~0; 811 ctx_to->constbuf_dirty[s] = (1 << NVC0_MAX_PIPE_CONSTBUFS) - 1; 812 ctx_to->buffers_dirty[s] = ~0; 813 ctx_to->images_dirty[s] = ~0; 814 } 815 816 /* Reset tfb as the shader that owns it may have been deleted. */ 817 ctx_to->state.tfb = NULL; 818 819 if (!ctx_to->vertex) 820 ctx_to->dirty_3d &= ~(NVC0_NEW_3D_VERTEX | NVC0_NEW_3D_ARRAYS); 821 if (!ctx_to->idxbuf.buffer) 822 ctx_to->dirty_3d &= ~NVC0_NEW_3D_IDXBUF; 823 824 if (!ctx_to->vertprog) 825 ctx_to->dirty_3d &= ~NVC0_NEW_3D_VERTPROG; 826 if (!ctx_to->fragprog) 827 ctx_to->dirty_3d &= ~NVC0_NEW_3D_FRAGPROG; 828 829 if (!ctx_to->blend) 830 ctx_to->dirty_3d &= ~NVC0_NEW_3D_BLEND; 831 if (!ctx_to->rast) 832 ctx_to->dirty_3d &= ~(NVC0_NEW_3D_RASTERIZER | NVC0_NEW_3D_SCISSOR); 833 if (!ctx_to->zsa) 834 ctx_to->dirty_3d &= ~NVC0_NEW_3D_ZSA; 835 836 ctx_to->screen->cur_ctx = ctx_to; 837 } 838 839 static struct nvc0_state_validate 840 validate_list_3d[] = { 841 { nvc0_validate_fb, NVC0_NEW_3D_FRAMEBUFFER }, 842 { nvc0_validate_blend, NVC0_NEW_3D_BLEND }, 843 { nvc0_validate_zsa, NVC0_NEW_3D_ZSA }, 844 { nvc0_validate_sample_mask, NVC0_NEW_3D_SAMPLE_MASK }, 845 { nvc0_validate_rasterizer, NVC0_NEW_3D_RASTERIZER }, 846 { nvc0_validate_blend_colour, NVC0_NEW_3D_BLEND_COLOUR }, 847 { nvc0_validate_stencil_ref, NVC0_NEW_3D_STENCIL_REF }, 848 { nvc0_validate_stipple, NVC0_NEW_3D_STIPPLE }, 849 { nvc0_validate_scissor, NVC0_NEW_3D_SCISSOR | NVC0_NEW_3D_RASTERIZER }, 850 { nvc0_validate_viewport, NVC0_NEW_3D_VIEWPORT }, 851 { nvc0_validate_window_rects, NVC0_NEW_3D_WINDOW_RECTS }, 852 { nvc0_vertprog_validate, NVC0_NEW_3D_VERTPROG }, 853 { nvc0_tctlprog_validate, NVC0_NEW_3D_TCTLPROG }, 854 { nvc0_tevlprog_validate, NVC0_NEW_3D_TEVLPROG }, 855 { nvc0_validate_tess_state, NVC0_NEW_3D_TESSFACTOR }, 856 { nvc0_gmtyprog_validate, NVC0_NEW_3D_GMTYPROG }, 857 { nvc0_validate_min_samples, NVC0_NEW_3D_MIN_SAMPLES | 858 NVC0_NEW_3D_FRAGPROG | 859 NVC0_NEW_3D_FRAMEBUFFER }, 860 { nvc0_fragprog_validate, NVC0_NEW_3D_FRAGPROG | NVC0_NEW_3D_RASTERIZER }, 861 { nvc0_validate_fp_zsa_rast, NVC0_NEW_3D_FRAGPROG | NVC0_NEW_3D_ZSA | 862 NVC0_NEW_3D_RASTERIZER }, 863 { nvc0_validate_zsa_fb, NVC0_NEW_3D_ZSA | NVC0_NEW_3D_FRAMEBUFFER }, 864 { nvc0_validate_rast_fb, NVC0_NEW_3D_RASTERIZER | NVC0_NEW_3D_FRAMEBUFFER }, 865 { nvc0_validate_clip, NVC0_NEW_3D_CLIP | NVC0_NEW_3D_RASTERIZER | 866 NVC0_NEW_3D_VERTPROG | 867 NVC0_NEW_3D_TEVLPROG | 868 NVC0_NEW_3D_GMTYPROG }, 869 { nvc0_constbufs_validate, NVC0_NEW_3D_CONSTBUF }, 870 { nvc0_validate_textures, NVC0_NEW_3D_TEXTURES }, 871 { nvc0_validate_samplers, NVC0_NEW_3D_SAMPLERS }, 872 { nve4_set_tex_handles, NVC0_NEW_3D_TEXTURES | NVC0_NEW_3D_SAMPLERS }, 873 { nvc0_validate_fbread, NVC0_NEW_3D_FRAGPROG | 874 NVC0_NEW_3D_FRAMEBUFFER }, 875 { nvc0_vertex_arrays_validate, NVC0_NEW_3D_VERTEX | NVC0_NEW_3D_ARRAYS }, 876 { nvc0_validate_surfaces, NVC0_NEW_3D_SURFACES }, 877 { nvc0_validate_buffers, NVC0_NEW_3D_BUFFERS }, 878 { nvc0_idxbuf_validate, NVC0_NEW_3D_IDXBUF }, 879 { nvc0_tfb_validate, NVC0_NEW_3D_TFB_TARGETS | NVC0_NEW_3D_GMTYPROG }, 880 { nvc0_validate_driverconst, NVC0_NEW_3D_DRIVERCONST }, 881 }; 882 883 bool 884 nvc0_state_validate(struct nvc0_context *nvc0, uint32_t mask, 885 struct nvc0_state_validate *validate_list, int size, 886 uint32_t *dirty, struct nouveau_bufctx *bufctx) 887 { 888 uint32_t state_mask; 889 int ret; 890 unsigned i; 891 892 if (nvc0->screen->cur_ctx != nvc0) 893 nvc0_switch_pipe_context(nvc0); 894 895 state_mask = *dirty & mask; 896 897 if (state_mask) { 898 for (i = 0; i < size; ++i) { 899 struct nvc0_state_validate *validate = &validate_list[i]; 900 901 if (state_mask & validate->states) 902 validate->func(nvc0); 903 } 904 *dirty &= ~state_mask; 905 906 nvc0_bufctx_fence(nvc0, bufctx, false); 907 } 908 909 nouveau_pushbuf_bufctx(nvc0->base.pushbuf, bufctx); 910 ret = nouveau_pushbuf_validate(nvc0->base.pushbuf); 911 912 return !ret; 913 } 914 915 bool 916 nvc0_state_validate_3d(struct nvc0_context *nvc0, uint32_t mask) 917 { 918 bool ret; 919 920 ret = nvc0_state_validate(nvc0, mask, validate_list_3d, 921 ARRAY_SIZE(validate_list_3d), &nvc0->dirty_3d, 922 nvc0->bufctx_3d); 923 924 if (unlikely(nvc0->state.flushed)) { 925 nvc0->state.flushed = false; 926 nvc0_bufctx_fence(nvc0, nvc0->bufctx_3d, true); 927 } 928 return ret; 929 } 930