1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2012-2014 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Chia-I Wu <olv (at) lunarg.com> 26 */ 27 28 #include "core/ilo_builder_3d.h" 29 30 #include "ilo_common.h" 31 #include "ilo_blitter.h" 32 #include "ilo_resource.h" 33 #include "ilo_shader.h" 34 #include "ilo_state.h" 35 #include "ilo_render_gen.h" 36 37 #define DIRTY(state) (session->pipe_dirty & ILO_DIRTY_ ## state) 38 39 static inline uint32_t 40 gen6_so_SURFACE_STATE(struct ilo_builder *builder, 41 const struct pipe_stream_output_target *so, 42 const struct pipe_stream_output_info *so_info, 43 int so_index) 44 { 45 struct ilo_state_surface_buffer_info info; 46 struct ilo_state_surface surf; 47 48 ILO_DEV_ASSERT(builder->dev, 6, 6); 49 50 memset(&info, 0, sizeof(info)); 51 52 info.vma = ilo_resource_get_vma(so->buffer); 53 info.offset = so->buffer_offset + so_info->output[so_index].dst_offset * 4; 54 info.size = so->buffer_size - so_info->output[so_index].dst_offset * 4; 55 56 info.access = ILO_STATE_SURFACE_ACCESS_DP_SVB; 57 58 switch (so_info->output[so_index].num_components) { 59 case 1: 60 info.format = GEN6_FORMAT_R32_FLOAT; 61 info.format_size = 4; 62 break; 63 case 2: 64 info.format = GEN6_FORMAT_R32G32_FLOAT; 65 info.format_size = 8; 66 break; 67 case 3: 68 info.format = GEN6_FORMAT_R32G32B32_FLOAT; 69 info.format_size = 12; 70 break; 71 case 4: 72 info.format = GEN6_FORMAT_R32G32B32A32_FLOAT; 73 info.format_size = 16; 74 break; 75 default: 76 assert(!"unexpected SO components length"); 77 info.format = GEN6_FORMAT_R32_FLOAT; 78 info.format_size = 4; 79 break; 80 } 81 82 info.struct_size = 83 so_info->stride[so_info->output[so_index].output_buffer] * 4; 84 85 memset(&surf, 0, sizeof(surf)); 86 ilo_state_surface_init_for_buffer(&surf, builder->dev, &info); 87 88 return gen6_SURFACE_STATE(builder, &surf); 89 } 90 91 static void 92 gen6_emit_draw_surface_rt(struct ilo_render *r, 93 const struct ilo_state_vector *vec, 94 struct ilo_render_draw_session *session) 95 { 96 const struct ilo_shader_state *fs = vec->fs; 97 const struct ilo_fb_state *fb = &vec->fb; 98 uint32_t *surface_state; 99 int base, count, i; 100 101 ILO_DEV_ASSERT(r->dev, 6, 8); 102 103 if (!DIRTY(FS) && !DIRTY(FB)) 104 return; 105 if (!fs) 106 return; 107 108 session->binding_table_fs_changed = true; 109 110 base = ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_SURFACE_RT_BASE); 111 count = ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_SURFACE_RT_COUNT); 112 113 /* SURFACE_STATEs for render targets */ 114 surface_state = &r->state.wm.SURFACE_STATE[base]; 115 for (i = 0; i < count; i++) { 116 if (i < fb->state.nr_cbufs && fb->state.cbufs[i]) { 117 const struct ilo_surface_cso *surface = 118 (const struct ilo_surface_cso *) fb->state.cbufs[i]; 119 120 assert(surface->is_rt); 121 surface_state[i] = gen6_SURFACE_STATE(r->builder, &surface->u.rt); 122 } else { 123 surface_state[i] = gen6_SURFACE_STATE(r->builder, &fb->null_rt); 124 } 125 } 126 } 127 128 static void 129 gen6_emit_draw_surface_so(struct ilo_render *r, 130 const struct ilo_state_vector *vec, 131 struct ilo_render_draw_session *session) 132 { 133 const struct ilo_shader_state *vs = vec->vs; 134 const struct ilo_shader_state *gs = vec->gs; 135 const struct ilo_so_state *so = &vec->so; 136 const struct pipe_stream_output_info *so_info; 137 uint32_t *surface_state; 138 int base, count, i; 139 140 ILO_DEV_ASSERT(r->dev, 6, 6); 141 142 if (!DIRTY(VS) && !DIRTY(GS) && !DIRTY(SO)) 143 return; 144 145 if (gs) { 146 so_info = ilo_shader_get_kernel_so_info(gs); 147 base = ilo_shader_get_kernel_param(gs, 148 ILO_KERNEL_GS_GEN6_SURFACE_SO_BASE); 149 count = ilo_shader_get_kernel_param(gs, 150 ILO_KERNEL_GS_GEN6_SURFACE_SO_COUNT); 151 } else if (vs) { 152 so_info = ilo_shader_get_kernel_so_info(vs); 153 base = 0; 154 count = ilo_shader_get_kernel_param(vs, 155 ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT); 156 } else { 157 return; 158 } 159 160 session->binding_table_gs_changed = true; 161 162 /* SURFACE_STATEs for stream output targets */ 163 surface_state = &r->state.gs.SURFACE_STATE[base]; 164 for (i = 0; i < count; i++) { 165 if (so_info && i < so_info->num_outputs && 166 so_info->output[i].output_buffer < so->count && 167 so->states[so_info->output[i].output_buffer]) { 168 const struct pipe_stream_output_target *so_target = 169 so->states[so_info->output[i].output_buffer]; 170 171 surface_state[i] = gen6_so_SURFACE_STATE(r->builder, 172 so_target, so_info, i); 173 } else { 174 surface_state[i] = 0; 175 } 176 } 177 } 178 179 static void 180 gen6_emit_draw_surface_view(struct ilo_render *r, 181 const struct ilo_state_vector *vec, 182 int shader_type, 183 struct ilo_render_draw_session *session) 184 { 185 const struct ilo_view_state *view = &vec->view[shader_type]; 186 const struct ilo_shader_state *sh; 187 uint32_t *surface_state; 188 int base, count, i; 189 190 ILO_DEV_ASSERT(r->dev, 6, 8); 191 192 switch (shader_type) { 193 case PIPE_SHADER_VERTEX: 194 if (!DIRTY(VS) && !DIRTY(VIEW_VS)) 195 return; 196 if (!vec->vs) 197 return; 198 199 sh = vec->vs; 200 surface_state = r->state.vs.SURFACE_STATE; 201 session->binding_table_vs_changed = true; 202 break; 203 case PIPE_SHADER_FRAGMENT: 204 if (!DIRTY(FS) && !DIRTY(VIEW_FS)) 205 return; 206 if (!vec->fs) 207 return; 208 209 sh = vec->fs; 210 surface_state = r->state.wm.SURFACE_STATE; 211 session->binding_table_fs_changed = true; 212 break; 213 default: 214 return; 215 break; 216 } 217 218 base = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_TEX_BASE); 219 count = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_TEX_COUNT); 220 221 /* SURFACE_STATEs for sampler views */ 222 surface_state += base; 223 for (i = 0; i < count; i++) { 224 if (i < view->count && view->states[i]) { 225 const struct ilo_view_cso *cso = 226 (const struct ilo_view_cso *) view->states[i]; 227 228 surface_state[i] = gen6_SURFACE_STATE(r->builder, &cso->surface); 229 } else { 230 surface_state[i] = 0; 231 } 232 } 233 } 234 235 static void 236 gen6_emit_draw_surface_const(struct ilo_render *r, 237 const struct ilo_state_vector *vec, 238 int shader_type, 239 struct ilo_render_draw_session *session) 240 { 241 const struct ilo_cbuf_state *cbuf = &vec->cbuf[shader_type]; 242 const struct ilo_shader_state *sh; 243 uint32_t *surface_state; 244 int base, count, i; 245 246 ILO_DEV_ASSERT(r->dev, 6, 8); 247 248 switch (shader_type) { 249 case PIPE_SHADER_VERTEX: 250 if (!DIRTY(VS) && !DIRTY(CBUF)) 251 return; 252 if (!vec->vs) 253 return; 254 255 sh = vec->vs; 256 surface_state = r->state.vs.SURFACE_STATE; 257 session->binding_table_vs_changed = true; 258 break; 259 case PIPE_SHADER_FRAGMENT: 260 if (!DIRTY(FS) && !DIRTY(CBUF)) 261 return; 262 if (!vec->fs) 263 return; 264 265 sh = vec->fs; 266 surface_state = r->state.wm.SURFACE_STATE; 267 session->binding_table_fs_changed = true; 268 break; 269 default: 270 return; 271 break; 272 } 273 274 base = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_CONST_BASE); 275 count = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_CONST_COUNT); 276 277 /* SURFACE_STATEs for constant buffers */ 278 surface_state += base; 279 for (i = 0; i < count; i++) { 280 const struct ilo_cbuf_cso *cso = &cbuf->cso[i]; 281 282 if (cso->resource) 283 surface_state[i] = gen6_SURFACE_STATE(r->builder, &cso->surface); 284 else 285 surface_state[i] = 0; 286 } 287 } 288 289 static void 290 gen6_emit_draw_surface_binding_tables(struct ilo_render *r, 291 const struct ilo_state_vector *vec, 292 int shader_type, 293 struct ilo_render_draw_session *session) 294 { 295 int count; 296 297 ILO_DEV_ASSERT(r->dev, 6, 8); 298 299 /* BINDING_TABLE_STATE */ 300 switch (shader_type) { 301 case PIPE_SHADER_VERTEX: 302 if (!session->binding_table_vs_changed) 303 return; 304 if (!vec->vs) 305 return; 306 307 count = ilo_shader_get_kernel_param(vec->vs, 308 ILO_KERNEL_SURFACE_TOTAL_COUNT); 309 310 r->state.vs.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder, 311 r->state.vs.SURFACE_STATE, count); 312 break; 313 case PIPE_SHADER_GEOMETRY: 314 if (!session->binding_table_gs_changed) 315 return; 316 if (vec->gs) { 317 count = ilo_shader_get_kernel_param(vec->gs, 318 ILO_KERNEL_SURFACE_TOTAL_COUNT); 319 } else if (ilo_dev_gen(r->dev) == ILO_GEN(6) && vec->vs) { 320 count = ilo_shader_get_kernel_param(vec->vs, 321 ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT); 322 } else { 323 return; 324 } 325 326 r->state.gs.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder, 327 r->state.gs.SURFACE_STATE, count); 328 break; 329 case PIPE_SHADER_FRAGMENT: 330 if (!session->binding_table_fs_changed) 331 return; 332 if (!vec->fs) 333 return; 334 335 count = ilo_shader_get_kernel_param(vec->fs, 336 ILO_KERNEL_SURFACE_TOTAL_COUNT); 337 338 r->state.wm.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder, 339 r->state.wm.SURFACE_STATE, count); 340 break; 341 default: 342 break; 343 } 344 } 345 346 #undef DIRTY 347 348 int 349 ilo_render_get_draw_surface_states_len(const struct ilo_render *render, 350 const struct ilo_state_vector *vec) 351 { 352 int sh_type, len; 353 354 ILO_DEV_ASSERT(render->dev, 6, 8); 355 356 len = 0; 357 358 for (sh_type = 0; sh_type < PIPE_SHADER_TYPES; sh_type++) { 359 const int alignment = 360 (ilo_dev_gen(render->dev) >= ILO_GEN(8) ? 64 : 32) / 4; 361 int num_surfaces = 0; 362 363 switch (sh_type) { 364 case PIPE_SHADER_VERTEX: 365 if (vec->vs) { 366 num_surfaces = ilo_shader_get_kernel_param(vec->vs, 367 ILO_KERNEL_SURFACE_TOTAL_COUNT); 368 369 if (ilo_dev_gen(render->dev) == ILO_GEN(6)) { 370 num_surfaces += ilo_shader_get_kernel_param(vec->vs, 371 ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT); 372 } 373 } 374 break; 375 case PIPE_SHADER_GEOMETRY: 376 if (vec->gs) { 377 num_surfaces = ilo_shader_get_kernel_param(vec->gs, 378 ILO_KERNEL_SURFACE_TOTAL_COUNT); 379 } 380 break; 381 case PIPE_SHADER_FRAGMENT: 382 if (vec->fs) { 383 num_surfaces = ilo_shader_get_kernel_param(vec->fs, 384 ILO_KERNEL_SURFACE_TOTAL_COUNT); 385 } 386 break; 387 default: 388 break; 389 } 390 391 /* BINDING_TABLE_STATE and SURFACE_STATEs */ 392 if (num_surfaces) { 393 len += align(num_surfaces, alignment) + 394 align(GEN6_SURFACE_STATE__SIZE, alignment) * num_surfaces; 395 } 396 } 397 398 return len; 399 } 400 401 void 402 ilo_render_emit_draw_surface_states(struct ilo_render *render, 403 const struct ilo_state_vector *vec, 404 struct ilo_render_draw_session *session) 405 { 406 const unsigned surface_used = ilo_builder_surface_used(render->builder); 407 int shader_type; 408 409 ILO_DEV_ASSERT(render->dev, 6, 8); 410 411 /* 412 * upload all SURAFCE_STATEs together so that we know there are minimal 413 * paddings 414 */ 415 416 gen6_emit_draw_surface_rt(render, vec, session); 417 418 if (ilo_dev_gen(render->dev) == ILO_GEN(6)) 419 gen6_emit_draw_surface_so(render, vec, session); 420 421 for (shader_type = 0; shader_type < PIPE_SHADER_TYPES; shader_type++) { 422 gen6_emit_draw_surface_view(render, vec, shader_type, session); 423 gen6_emit_draw_surface_const(render, vec, shader_type, session); 424 } 425 426 /* this must be called after all SURFACE_STATEs have been uploaded */ 427 for (shader_type = 0; shader_type < PIPE_SHADER_TYPES; shader_type++) { 428 gen6_emit_draw_surface_binding_tables(render, vec, 429 shader_type, session); 430 } 431 432 assert(ilo_builder_surface_used(render->builder) <= surface_used + 433 ilo_render_get_draw_surface_states_len(render, vec)); 434 } 435 436 static void 437 gen6_emit_launch_grid_surface_view(struct ilo_render *r, 438 const struct ilo_state_vector *vec, 439 struct ilo_render_launch_grid_session *session) 440 { 441 const struct ilo_shader_state *cs = vec->cs; 442 const struct ilo_view_state *view = &vec->view[PIPE_SHADER_COMPUTE]; 443 uint32_t *surface_state = r->state.cs.SURFACE_STATE; 444 int base, count, i; 445 446 ILO_DEV_ASSERT(r->dev, 7, 7.5); 447 448 base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_TEX_BASE); 449 count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_TEX_COUNT); 450 451 /* SURFACE_STATEs for sampler views */ 452 surface_state += base; 453 for (i = 0; i < count; i++) { 454 if (i < view->count && view->states[i]) { 455 const struct ilo_view_cso *cso = 456 (const struct ilo_view_cso *) view->states[i]; 457 458 surface_state[i] = gen6_SURFACE_STATE(r->builder, &cso->surface); 459 } else { 460 surface_state[i] = 0; 461 } 462 } 463 } 464 465 static void 466 gen6_emit_launch_grid_surface_const(struct ilo_render *r, 467 const struct ilo_state_vector *vec, 468 struct ilo_render_launch_grid_session *session) 469 { 470 const struct ilo_shader_state *cs = vec->cs; 471 uint32_t *surface_state = r->state.cs.SURFACE_STATE; 472 struct ilo_state_surface_buffer_info info; 473 struct ilo_state_surface surf; 474 int base, count; 475 476 ILO_DEV_ASSERT(r->dev, 7, 7.5); 477 478 base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_CONST_BASE); 479 count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_CONST_COUNT); 480 481 if (!count) 482 return; 483 484 memset(&info, 0, sizeof(info)); 485 486 info.vma = ilo_resource_get_vma(session->input->buffer); 487 info.offset = session->input->buffer_offset; 488 info.size = session->input->buffer_size; 489 490 info.access = ILO_STATE_SURFACE_ACCESS_DP_UNTYPED; 491 info.format = GEN6_FORMAT_RAW; 492 info.format_size = 1; 493 info.struct_size = 1; 494 info.readonly = true; 495 496 memset(&surf, 0, sizeof(surf)); 497 ilo_state_surface_init_for_buffer(&surf, r->dev, &info); 498 499 assert(count == 1 && session->input->buffer); 500 surface_state[base] = gen6_SURFACE_STATE(r->builder, &surf); 501 } 502 503 static void 504 gen6_emit_launch_grid_surface_cs_resource(struct ilo_render *r, 505 const struct ilo_state_vector *vec, 506 struct ilo_render_launch_grid_session *session) 507 { 508 ILO_DEV_ASSERT(r->dev, 7, 7.5); 509 510 /* TODO */ 511 assert(!vec->cs_resource.count); 512 } 513 514 static void 515 gen6_emit_launch_grid_surface_global(struct ilo_render *r, 516 const struct ilo_state_vector *vec, 517 struct ilo_render_launch_grid_session *session) 518 { 519 const struct ilo_shader_state *cs = vec->cs; 520 const struct ilo_global_binding_cso *bindings = 521 util_dynarray_begin(&vec->global_binding.bindings); 522 uint32_t *surface_state = r->state.cs.SURFACE_STATE; 523 int base, count, i; 524 525 ILO_DEV_ASSERT(r->dev, 7, 7.5); 526 527 base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_CS_SURFACE_GLOBAL_BASE); 528 count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_CS_SURFACE_GLOBAL_COUNT); 529 530 if (!count) 531 return; 532 533 if (base + count > ARRAY_SIZE(r->state.cs.SURFACE_STATE)) { 534 ilo_warn("too many global bindings\n"); 535 count = ARRAY_SIZE(r->state.cs.SURFACE_STATE) - base; 536 } 537 538 /* SURFACE_STATEs for global bindings */ 539 surface_state += base; 540 for (i = 0; i < count; i++) { 541 if (i < vec->global_binding.count && bindings[i].resource) { 542 struct ilo_state_surface_buffer_info info; 543 struct ilo_state_surface surf; 544 545 assert(bindings[i].resource->target == PIPE_BUFFER); 546 547 memset(&info, 0, sizeof(info)); 548 549 info.vma = ilo_resource_get_vma(bindings[i].resource); 550 info.size = info.vma->vm_size; 551 552 info.access = ILO_STATE_SURFACE_ACCESS_DP_UNTYPED; 553 info.format = GEN6_FORMAT_RAW; 554 info.format_size = 1; 555 info.struct_size = 1; 556 557 memset(&surf, 0, sizeof(surf)); 558 ilo_state_surface_init_for_buffer(&surf, r->dev, &info); 559 560 surface_state[i] = gen6_SURFACE_STATE(r->builder, &surf); 561 } else { 562 surface_state[i] = 0; 563 } 564 } 565 } 566 567 static void 568 gen6_emit_launch_grid_surface_binding_table(struct ilo_render *r, 569 const struct ilo_state_vector *vec, 570 struct ilo_render_launch_grid_session *session) 571 { 572 const struct ilo_shader_state *cs = vec->cs; 573 int count; 574 575 ILO_DEV_ASSERT(r->dev, 7, 7.5); 576 577 count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_TOTAL_COUNT); 578 if (count) { 579 r->state.cs.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder, 580 r->state.cs.SURFACE_STATE, count); 581 } 582 } 583 584 int 585 ilo_render_get_launch_grid_surface_states_len(const struct ilo_render *render, 586 const struct ilo_state_vector *vec) 587 { 588 const int alignment = 32 / 4; 589 int num_surfaces; 590 int len = 0; 591 592 ILO_DEV_ASSERT(render->dev, 7, 7.5); 593 594 num_surfaces = ilo_shader_get_kernel_param(vec->cs, 595 ILO_KERNEL_SURFACE_TOTAL_COUNT); 596 597 /* BINDING_TABLE_STATE and SURFACE_STATEs */ 598 if (num_surfaces) { 599 len += align(num_surfaces, alignment) + 600 align(GEN6_SURFACE_STATE__SIZE, alignment) * num_surfaces; 601 } 602 603 return len; 604 } 605 606 void 607 ilo_render_emit_launch_grid_surface_states(struct ilo_render *render, 608 const struct ilo_state_vector *vec, 609 struct ilo_render_launch_grid_session *session) 610 { 611 const unsigned surface_used = ilo_builder_surface_used(render->builder); 612 613 ILO_DEV_ASSERT(render->dev, 7, 7.5); 614 615 /* idrt depends on the binding table */ 616 assert(!session->idrt_size); 617 618 gen6_emit_launch_grid_surface_view(render, vec, session); 619 gen6_emit_launch_grid_surface_const(render, vec, session); 620 gen6_emit_launch_grid_surface_cs_resource(render, vec, session); 621 gen6_emit_launch_grid_surface_global(render, vec, session); 622 gen6_emit_launch_grid_surface_binding_table(render, vec, session); 623 624 assert(ilo_builder_surface_used(render->builder) <= surface_used + 625 ilo_render_get_launch_grid_surface_states_len(render, vec)); 626 } 627