v3dx_state.c revision 7ec681f3
1/* 2 * Copyright © 2014-2017 Broadcom 3 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * 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 DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25#include "pipe/p_state.h" 26#include "util/format/u_format.h" 27#include "util/u_framebuffer.h" 28#include "util/u_inlines.h" 29#include "util/u_math.h" 30#include "util/u_memory.h" 31#include "util/half_float.h" 32#include "util/u_helpers.h" 33#include "util/u_upload_mgr.h" 34 35#include "v3d_context.h" 36#include "broadcom/common/v3d_tiling.h" 37#include "broadcom/common/v3d_macros.h" 38#include "broadcom/compiler/v3d_compiler.h" 39#include "broadcom/cle/v3dx_pack.h" 40 41static void 42v3d_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso) 43{ 44 free(hwcso); 45} 46 47static void 48v3d_set_blend_color(struct pipe_context *pctx, 49 const struct pipe_blend_color *blend_color) 50{ 51 struct v3d_context *v3d = v3d_context(pctx); 52 v3d->blend_color.f = *blend_color; 53 for (int i = 0; i < 4; i++) { 54 v3d->blend_color.hf[i] = 55 _mesa_float_to_half(blend_color->color[i]); 56 } 57 v3d->dirty |= V3D_DIRTY_BLEND_COLOR; 58} 59 60static void 61v3d_set_stencil_ref(struct pipe_context *pctx, 62 const struct pipe_stencil_ref stencil_ref) 63{ 64 struct v3d_context *v3d = v3d_context(pctx); 65 v3d->stencil_ref = stencil_ref; 66 v3d->dirty |= V3D_DIRTY_STENCIL_REF; 67} 68 69static void 70v3d_set_clip_state(struct pipe_context *pctx, 71 const struct pipe_clip_state *clip) 72{ 73 struct v3d_context *v3d = v3d_context(pctx); 74 v3d->clip = *clip; 75 v3d->dirty |= V3D_DIRTY_CLIP; 76} 77 78static void 79v3d_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 80{ 81 struct v3d_context *v3d = v3d_context(pctx); 82 v3d->sample_mask = sample_mask & ((1 << V3D_MAX_SAMPLES) - 1); 83 v3d->dirty |= V3D_DIRTY_SAMPLE_STATE; 84} 85 86static void * 87v3d_create_rasterizer_state(struct pipe_context *pctx, 88 const struct pipe_rasterizer_state *cso) 89{ 90 struct v3d_rasterizer_state *so; 91 92 so = CALLOC_STRUCT(v3d_rasterizer_state); 93 if (!so) 94 return NULL; 95 96 so->base = *cso; 97 98 /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835, 99 * BCM21553). 100 */ 101 so->point_size = MAX2(cso->point_size, .125f); 102 103 STATIC_ASSERT(sizeof(so->depth_offset) >= 104 cl_packet_length(DEPTH_OFFSET)); 105 v3dx_pack(&so->depth_offset, DEPTH_OFFSET, depth) { 106 depth.depth_offset_factor = cso->offset_scale; 107 depth.depth_offset_units = cso->offset_units; 108 } 109 110 /* The HW treats polygon offset units based on a Z24 buffer, so we 111 * need to scale up offset_units if we're only Z16. 112 */ 113 v3dx_pack(&so->depth_offset_z16, DEPTH_OFFSET, depth) { 114 depth.depth_offset_factor = cso->offset_scale; 115 depth.depth_offset_units = cso->offset_units * 256.0; 116 } 117 118 return so; 119} 120 121/* Blend state is baked into shaders. */ 122static void * 123v3d_create_blend_state(struct pipe_context *pctx, 124 const struct pipe_blend_state *cso) 125{ 126 struct v3d_blend_state *so; 127 128 so = CALLOC_STRUCT(v3d_blend_state); 129 if (!so) 130 return NULL; 131 132 so->base = *cso; 133 134 if (cso->independent_blend_enable) { 135 for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) { 136 so->blend_enables |= cso->rt[i].blend_enable << i; 137 138 /* V3D 4.x is when we got independent blend enables. */ 139 assert(V3D_VERSION >= 40 || 140 cso->rt[i].blend_enable == cso->rt[0].blend_enable); 141 } 142 } else { 143 if (cso->rt[0].blend_enable) 144 so->blend_enables = (1 << V3D_MAX_DRAW_BUFFERS) - 1; 145 } 146 147 return so; 148} 149 150static uint32_t 151translate_stencil_op(enum pipe_stencil_op op) 152{ 153 switch (op) { 154 case PIPE_STENCIL_OP_KEEP: return V3D_STENCIL_OP_KEEP; 155 case PIPE_STENCIL_OP_ZERO: return V3D_STENCIL_OP_ZERO; 156 case PIPE_STENCIL_OP_REPLACE: return V3D_STENCIL_OP_REPLACE; 157 case PIPE_STENCIL_OP_INCR: return V3D_STENCIL_OP_INCR; 158 case PIPE_STENCIL_OP_DECR: return V3D_STENCIL_OP_DECR; 159 case PIPE_STENCIL_OP_INCR_WRAP: return V3D_STENCIL_OP_INCWRAP; 160 case PIPE_STENCIL_OP_DECR_WRAP: return V3D_STENCIL_OP_DECWRAP; 161 case PIPE_STENCIL_OP_INVERT: return V3D_STENCIL_OP_INVERT; 162 } 163 unreachable("bad stencil op"); 164} 165 166static void * 167v3d_create_depth_stencil_alpha_state(struct pipe_context *pctx, 168 const struct pipe_depth_stencil_alpha_state *cso) 169{ 170 struct v3d_depth_stencil_alpha_state *so; 171 172 so = CALLOC_STRUCT(v3d_depth_stencil_alpha_state); 173 if (!so) 174 return NULL; 175 176 so->base = *cso; 177 178 if (cso->depth_enabled) { 179 switch (cso->depth_func) { 180 case PIPE_FUNC_LESS: 181 case PIPE_FUNC_LEQUAL: 182 so->ez_state = V3D_EZ_LT_LE; 183 break; 184 case PIPE_FUNC_GREATER: 185 case PIPE_FUNC_GEQUAL: 186 so->ez_state = V3D_EZ_GT_GE; 187 break; 188 case PIPE_FUNC_NEVER: 189 case PIPE_FUNC_EQUAL: 190 so->ez_state = V3D_EZ_UNDECIDED; 191 break; 192 default: 193 so->ez_state = V3D_EZ_DISABLED; 194 break; 195 } 196 197 /* If stencil is enabled and it's not a no-op, then it would 198 * break EZ updates. 199 */ 200 if (cso->stencil[0].enabled && 201 (cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP || 202 cso->stencil[0].func != PIPE_FUNC_ALWAYS || 203 (cso->stencil[1].enabled && 204 (cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP && 205 cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) { 206 so->ez_state = V3D_EZ_DISABLED; 207 } 208 } 209 210 const struct pipe_stencil_state *front = &cso->stencil[0]; 211 const struct pipe_stencil_state *back = &cso->stencil[1]; 212 213 if (front->enabled) { 214 STATIC_ASSERT(sizeof(so->stencil_front) >= 215 cl_packet_length(STENCIL_CFG)); 216 v3dx_pack(&so->stencil_front, STENCIL_CFG, config) { 217 config.front_config = true; 218 /* If !back->enabled, then the front values should be 219 * used for both front and back-facing primitives. 220 */ 221 config.back_config = !back->enabled; 222 223 config.stencil_write_mask = front->writemask; 224 config.stencil_test_mask = front->valuemask; 225 226 config.stencil_test_function = front->func; 227 config.stencil_pass_op = 228 translate_stencil_op(front->zpass_op); 229 config.depth_test_fail_op = 230 translate_stencil_op(front->zfail_op); 231 config.stencil_test_fail_op = 232 translate_stencil_op(front->fail_op); 233 } 234 } 235 if (back->enabled) { 236 STATIC_ASSERT(sizeof(so->stencil_back) >= 237 cl_packet_length(STENCIL_CFG)); 238 v3dx_pack(&so->stencil_back, STENCIL_CFG, config) { 239 config.front_config = false; 240 config.back_config = true; 241 242 config.stencil_write_mask = back->writemask; 243 config.stencil_test_mask = back->valuemask; 244 245 config.stencil_test_function = back->func; 246 config.stencil_pass_op = 247 translate_stencil_op(back->zpass_op); 248 config.depth_test_fail_op = 249 translate_stencil_op(back->zfail_op); 250 config.stencil_test_fail_op = 251 translate_stencil_op(back->fail_op); 252 } 253 } 254 255 return so; 256} 257 258static void 259v3d_set_polygon_stipple(struct pipe_context *pctx, 260 const struct pipe_poly_stipple *stipple) 261{ 262 struct v3d_context *v3d = v3d_context(pctx); 263 v3d->stipple = *stipple; 264 v3d->dirty |= V3D_DIRTY_STIPPLE; 265} 266 267static void 268v3d_set_scissor_states(struct pipe_context *pctx, 269 unsigned start_slot, 270 unsigned num_scissors, 271 const struct pipe_scissor_state *scissor) 272{ 273 struct v3d_context *v3d = v3d_context(pctx); 274 275 v3d->scissor = *scissor; 276 v3d->dirty |= V3D_DIRTY_SCISSOR; 277} 278 279static void 280v3d_set_viewport_states(struct pipe_context *pctx, 281 unsigned start_slot, 282 unsigned num_viewports, 283 const struct pipe_viewport_state *viewport) 284{ 285 struct v3d_context *v3d = v3d_context(pctx); 286 v3d->viewport = *viewport; 287 v3d->dirty |= V3D_DIRTY_VIEWPORT; 288} 289 290static void 291v3d_set_vertex_buffers(struct pipe_context *pctx, 292 unsigned start_slot, unsigned count, 293 unsigned unbind_num_trailing_slots, 294 bool take_ownership, 295 const struct pipe_vertex_buffer *vb) 296{ 297 struct v3d_context *v3d = v3d_context(pctx); 298 struct v3d_vertexbuf_stateobj *so = &v3d->vertexbuf; 299 300 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, 301 start_slot, count, 302 unbind_num_trailing_slots, 303 take_ownership); 304 so->count = util_last_bit(so->enabled_mask); 305 306 v3d->dirty |= V3D_DIRTY_VTXBUF; 307} 308 309static void 310v3d_blend_state_bind(struct pipe_context *pctx, void *hwcso) 311{ 312 struct v3d_context *v3d = v3d_context(pctx); 313 v3d->blend = hwcso; 314 v3d->dirty |= V3D_DIRTY_BLEND; 315} 316 317static void 318v3d_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso) 319{ 320 struct v3d_context *v3d = v3d_context(pctx); 321 v3d->rasterizer = hwcso; 322 v3d->dirty |= V3D_DIRTY_RASTERIZER; 323} 324 325static void 326v3d_zsa_state_bind(struct pipe_context *pctx, void *hwcso) 327{ 328 struct v3d_context *v3d = v3d_context(pctx); 329 v3d->zsa = hwcso; 330 v3d->dirty |= V3D_DIRTY_ZSA; 331} 332 333static void * 334v3d_vertex_state_create(struct pipe_context *pctx, unsigned num_elements, 335 const struct pipe_vertex_element *elements) 336{ 337 struct v3d_context *v3d = v3d_context(pctx); 338 struct v3d_vertex_stateobj *so = CALLOC_STRUCT(v3d_vertex_stateobj); 339 340 if (!so) 341 return NULL; 342 343 memcpy(so->pipe, elements, sizeof(*elements) * num_elements); 344 so->num_elements = num_elements; 345 346 for (int i = 0; i < so->num_elements; i++) { 347 const struct pipe_vertex_element *elem = &elements[i]; 348 const struct util_format_description *desc = 349 util_format_description(elem->src_format); 350 uint32_t r_size = desc->channel[0].size; 351 352 const uint32_t size = 353 cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD); 354 355 v3dx_pack(&so->attrs[i * size], 356 GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) { 357 /* vec_size == 0 means 4 */ 358 attr.vec_size = desc->nr_channels & 3; 359 attr.signed_int_type = (desc->channel[0].type == 360 UTIL_FORMAT_TYPE_SIGNED); 361 362 attr.normalized_int_type = desc->channel[0].normalized; 363 attr.read_as_int_uint = desc->channel[0].pure_integer; 364 attr.instance_divisor = MIN2(elem->instance_divisor, 365 0xffff); 366 367 switch (desc->channel[0].type) { 368 case UTIL_FORMAT_TYPE_FLOAT: 369 if (r_size == 32) { 370 attr.type = ATTRIBUTE_FLOAT; 371 } else { 372 assert(r_size == 16); 373 attr.type = ATTRIBUTE_HALF_FLOAT; 374 } 375 break; 376 377 case UTIL_FORMAT_TYPE_SIGNED: 378 case UTIL_FORMAT_TYPE_UNSIGNED: 379 switch (r_size) { 380 case 32: 381 attr.type = ATTRIBUTE_INT; 382 break; 383 case 16: 384 attr.type = ATTRIBUTE_SHORT; 385 break; 386 case 10: 387 attr.type = ATTRIBUTE_INT2_10_10_10; 388 break; 389 case 8: 390 attr.type = ATTRIBUTE_BYTE; 391 break; 392 default: 393 fprintf(stderr, 394 "format %s unsupported\n", 395 desc->name); 396 attr.type = ATTRIBUTE_BYTE; 397 abort(); 398 } 399 break; 400 401 default: 402 fprintf(stderr, 403 "format %s unsupported\n", 404 desc->name); 405 abort(); 406 } 407 } 408 } 409 410 /* Set up the default attribute values in case any of the vertex 411 * elements use them. 412 */ 413 uint32_t *attrs; 414 u_upload_alloc(v3d->state_uploader, 0, 415 V3D_MAX_VS_INPUTS * sizeof(float), 16, 416 &so->defaults_offset, &so->defaults, (void **)&attrs); 417 418 for (int i = 0; i < V3D_MAX_VS_INPUTS / 4; i++) { 419 attrs[i * 4 + 0] = 0; 420 attrs[i * 4 + 1] = 0; 421 attrs[i * 4 + 2] = 0; 422 if (i < so->num_elements && 423 util_format_is_pure_integer(so->pipe[i].src_format)) { 424 attrs[i * 4 + 3] = 1; 425 } else { 426 attrs[i * 4 + 3] = fui(1.0); 427 } 428 } 429 430 u_upload_unmap(v3d->state_uploader); 431 return so; 432} 433 434static void 435v3d_vertex_state_delete(struct pipe_context *pctx, void *hwcso) 436{ 437 struct v3d_vertex_stateobj *so = hwcso; 438 439 pipe_resource_reference(&so->defaults, NULL); 440 free(so); 441} 442 443static void 444v3d_vertex_state_bind(struct pipe_context *pctx, void *hwcso) 445{ 446 struct v3d_context *v3d = v3d_context(pctx); 447 v3d->vtx = hwcso; 448 v3d->dirty |= V3D_DIRTY_VTXSTATE; 449} 450 451static void 452v3d_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index, 453 bool take_ownership, 454 const struct pipe_constant_buffer *cb) 455{ 456 struct v3d_context *v3d = v3d_context(pctx); 457 struct v3d_constbuf_stateobj *so = &v3d->constbuf[shader]; 458 459 util_copy_constant_buffer(&so->cb[index], cb, take_ownership); 460 461 /* Note that the gallium frontend can unbind constant buffers by 462 * passing NULL here. 463 */ 464 if (unlikely(!cb)) { 465 so->enabled_mask &= ~(1 << index); 466 so->dirty_mask &= ~(1 << index); 467 return; 468 } 469 470 so->enabled_mask |= 1 << index; 471 so->dirty_mask |= 1 << index; 472 v3d->dirty |= V3D_DIRTY_CONSTBUF; 473} 474 475static void 476v3d_set_framebuffer_state(struct pipe_context *pctx, 477 const struct pipe_framebuffer_state *framebuffer) 478{ 479 struct v3d_context *v3d = v3d_context(pctx); 480 struct pipe_framebuffer_state *cso = &v3d->framebuffer; 481 482 v3d->job = NULL; 483 484 util_copy_framebuffer_state(cso, framebuffer); 485 486 v3d->swap_color_rb = 0; 487 v3d->blend_dst_alpha_one = 0; 488 for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) { 489 struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i]; 490 if (!cbuf) 491 continue; 492 struct v3d_surface *v3d_cbuf = v3d_surface(cbuf); 493 494 const struct util_format_description *desc = 495 util_format_description(cbuf->format); 496 497 /* For BGRA8 formats (DRI window system default format), we 498 * need to swap R and B, since the HW's format is RGBA8. On 499 * V3D 4.1+, the RCL can swap R and B on load/store. 500 */ 501 if (v3d->screen->devinfo.ver < 41 && v3d_cbuf->swap_rb) 502 v3d->swap_color_rb |= 1 << i; 503 504 if (desc->swizzle[3] == PIPE_SWIZZLE_1) 505 v3d->blend_dst_alpha_one |= 1 << i; 506 } 507 508 v3d->dirty |= V3D_DIRTY_FRAMEBUFFER; 509} 510 511static enum V3DX(Wrap_Mode) 512translate_wrap(uint32_t pipe_wrap) 513{ 514 switch (pipe_wrap) { 515 case PIPE_TEX_WRAP_REPEAT: 516 return V3D_WRAP_MODE_REPEAT; 517 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 518 return V3D_WRAP_MODE_CLAMP; 519 case PIPE_TEX_WRAP_MIRROR_REPEAT: 520 return V3D_WRAP_MODE_MIRROR; 521 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 522 return V3D_WRAP_MODE_BORDER; 523 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 524 return V3D_WRAP_MODE_MIRROR_ONCE; 525 default: 526 unreachable("Unknown wrap mode"); 527 } 528} 529 530#if V3D_VERSION >= 40 531static void 532v3d_upload_sampler_state_variant(void *map, 533 const struct pipe_sampler_state *cso, 534 enum v3d_sampler_state_variant variant) 535{ 536 v3dx_pack(map, SAMPLER_STATE, sampler) { 537 sampler.wrap_i_border = false; 538 539 sampler.wrap_s = translate_wrap(cso->wrap_s); 540 sampler.wrap_t = translate_wrap(cso->wrap_t); 541 sampler.wrap_r = translate_wrap(cso->wrap_r); 542 543 sampler.fixed_bias = cso->lod_bias; 544 sampler.depth_compare_function = cso->compare_func; 545 546 sampler.min_filter_nearest = 547 cso->min_img_filter == PIPE_TEX_FILTER_NEAREST; 548 sampler.mag_filter_nearest = 549 cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST; 550 sampler.mip_filter_nearest = 551 cso->min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR; 552 553 sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod), 554 15); 555 sampler.max_level_of_detail = MIN2(MAX2(cso->max_lod, 556 cso->min_lod), 15); 557 558 /* If we're not doing inter-miplevel filtering, we need to 559 * clamp the LOD so that we only sample from baselevel. 560 * However, we need to still allow the calculated LOD to be 561 * fractionally over the baselevel, so that the HW can decide 562 * between the min and mag filters. 563 */ 564 if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { 565 sampler.min_level_of_detail = 566 MIN2(sampler.min_level_of_detail, 1.0 / 256.0); 567 sampler.max_level_of_detail = 568 MIN2(sampler.max_level_of_detail, 1.0 / 256.0); 569 } 570 571 if (cso->max_anisotropy) { 572 sampler.anisotropy_enable = true; 573 574 if (cso->max_anisotropy > 8) 575 sampler.maximum_anisotropy = 3; 576 else if (cso->max_anisotropy > 4) 577 sampler.maximum_anisotropy = 2; 578 else if (cso->max_anisotropy > 2) 579 sampler.maximum_anisotropy = 1; 580 } 581 582 if (variant == V3D_SAMPLER_STATE_BORDER_0) { 583 sampler.border_color_mode = V3D_BORDER_COLOR_0000; 584 } else { 585 sampler.border_color_mode = V3D_BORDER_COLOR_FOLLOWS; 586 587 union pipe_color_union border; 588 589 /* First, reswizzle the border color for any 590 * mismatching we're doing between the texture's 591 * channel order in hardware (R) versus what it is at 592 * the GL level (ALPHA) 593 */ 594 switch (variant) { 595 case V3D_SAMPLER_STATE_F16_BGRA: 596 case V3D_SAMPLER_STATE_F16_BGRA_UNORM: 597 case V3D_SAMPLER_STATE_F16_BGRA_SNORM: 598 border.i[0] = cso->border_color.i[2]; 599 border.i[1] = cso->border_color.i[1]; 600 border.i[2] = cso->border_color.i[0]; 601 border.i[3] = cso->border_color.i[3]; 602 break; 603 604 case V3D_SAMPLER_STATE_F16_A: 605 case V3D_SAMPLER_STATE_F16_A_UNORM: 606 case V3D_SAMPLER_STATE_F16_A_SNORM: 607 case V3D_SAMPLER_STATE_32_A: 608 case V3D_SAMPLER_STATE_32_A_UNORM: 609 case V3D_SAMPLER_STATE_32_A_SNORM: 610 border.i[0] = cso->border_color.i[3]; 611 border.i[1] = 0; 612 border.i[2] = 0; 613 border.i[3] = 0; 614 break; 615 616 case V3D_SAMPLER_STATE_F16_LA: 617 case V3D_SAMPLER_STATE_F16_LA_UNORM: 618 case V3D_SAMPLER_STATE_F16_LA_SNORM: 619 border.i[0] = cso->border_color.i[0]; 620 border.i[1] = cso->border_color.i[3]; 621 border.i[2] = 0; 622 border.i[3] = 0; 623 break; 624 625 default: 626 border = cso->border_color; 627 } 628 629 /* Perform any clamping. */ 630 switch (variant) { 631 case V3D_SAMPLER_STATE_F16_UNORM: 632 case V3D_SAMPLER_STATE_F16_BGRA_UNORM: 633 case V3D_SAMPLER_STATE_F16_A_UNORM: 634 case V3D_SAMPLER_STATE_F16_LA_UNORM: 635 case V3D_SAMPLER_STATE_32_UNORM: 636 case V3D_SAMPLER_STATE_32_A_UNORM: 637 for (int i = 0; i < 4; i++) 638 border.f[i] = CLAMP(border.f[i], 0, 1); 639 break; 640 641 case V3D_SAMPLER_STATE_F16_SNORM: 642 case V3D_SAMPLER_STATE_F16_BGRA_SNORM: 643 case V3D_SAMPLER_STATE_F16_A_SNORM: 644 case V3D_SAMPLER_STATE_F16_LA_SNORM: 645 case V3D_SAMPLER_STATE_32_SNORM: 646 case V3D_SAMPLER_STATE_32_A_SNORM: 647 for (int i = 0; i < 4; i++) 648 border.f[i] = CLAMP(border.f[i], -1, 1); 649 break; 650 651 case V3D_SAMPLER_STATE_1010102U: 652 border.ui[0] = CLAMP(border.ui[0], 653 0, (1 << 10) - 1); 654 border.ui[1] = CLAMP(border.ui[1], 655 0, (1 << 10) - 1); 656 border.ui[2] = CLAMP(border.ui[2], 657 0, (1 << 10) - 1); 658 border.ui[3] = CLAMP(border.ui[3], 659 0, 3); 660 break; 661 662 case V3D_SAMPLER_STATE_16U: 663 for (int i = 0; i < 4; i++) 664 border.ui[i] = CLAMP(border.ui[i], 665 0, 0xffff); 666 break; 667 668 case V3D_SAMPLER_STATE_16I: 669 for (int i = 0; i < 4; i++) 670 border.i[i] = CLAMP(border.i[i], 671 -32768, 32767); 672 break; 673 674 case V3D_SAMPLER_STATE_8U: 675 for (int i = 0; i < 4; i++) 676 border.ui[i] = CLAMP(border.ui[i], 677 0, 0xff); 678 break; 679 680 case V3D_SAMPLER_STATE_8I: 681 for (int i = 0; i < 4; i++) 682 border.i[i] = CLAMP(border.i[i], 683 -128, 127); 684 break; 685 686 default: 687 break; 688 } 689 690 if (variant >= V3D_SAMPLER_STATE_32) { 691 sampler.border_color_word_0 = border.ui[0]; 692 sampler.border_color_word_1 = border.ui[1]; 693 sampler.border_color_word_2 = border.ui[2]; 694 sampler.border_color_word_3 = border.ui[3]; 695 } else { 696 sampler.border_color_word_0 = 697 _mesa_float_to_half(border.f[0]); 698 sampler.border_color_word_1 = 699 _mesa_float_to_half(border.f[1]); 700 sampler.border_color_word_2 = 701 _mesa_float_to_half(border.f[2]); 702 sampler.border_color_word_3 = 703 _mesa_float_to_half(border.f[3]); 704 } 705 } 706 } 707} 708#endif 709 710static void * 711v3d_create_sampler_state(struct pipe_context *pctx, 712 const struct pipe_sampler_state *cso) 713{ 714 UNUSED struct v3d_context *v3d = v3d_context(pctx); 715 struct v3d_sampler_state *so = CALLOC_STRUCT(v3d_sampler_state); 716 717 if (!so) 718 return NULL; 719 720 memcpy(so, cso, sizeof(*cso)); 721 722 enum V3DX(Wrap_Mode) wrap_s = translate_wrap(cso->wrap_s); 723 enum V3DX(Wrap_Mode) wrap_t = translate_wrap(cso->wrap_t); 724 enum V3DX(Wrap_Mode) wrap_r = translate_wrap(cso->wrap_r); 725 726 bool uses_border_color = (wrap_s == V3D_WRAP_MODE_BORDER || 727 wrap_t == V3D_WRAP_MODE_BORDER || 728 wrap_r == V3D_WRAP_MODE_BORDER); 729 so->border_color_variants = (uses_border_color && 730 (cso->border_color.ui[0] != 0 || 731 cso->border_color.ui[1] != 0 || 732 cso->border_color.ui[2] != 0 || 733 cso->border_color.ui[3] != 0)); 734 735#if V3D_VERSION >= 40 736 void *map; 737 int sampler_align = so->border_color_variants ? 32 : 8; 738 int sampler_size = align(cl_packet_length(SAMPLER_STATE), sampler_align); 739 int num_variants = (so->border_color_variants ? ARRAY_SIZE(so->sampler_state_offset) : 1); 740 u_upload_alloc(v3d->state_uploader, 0, 741 sampler_size * num_variants, 742 sampler_align, 743 &so->sampler_state_offset[0], 744 &so->sampler_state, 745 &map); 746 747 for (int i = 0; i < num_variants; i++) { 748 so->sampler_state_offset[i] = 749 so->sampler_state_offset[0] + i * sampler_size; 750 v3d_upload_sampler_state_variant(map + i * sampler_size, 751 cso, i); 752 } 753 754#else /* V3D_VERSION < 40 */ 755 v3dx_pack(&so->p0, TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1, p0) { 756 p0.s_wrap_mode = wrap_s; 757 p0.t_wrap_mode = wrap_t; 758 p0.r_wrap_mode = wrap_r; 759 } 760 761 v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) { 762 tex.depth_compare_function = cso->compare_func; 763 tex.fixed_bias = cso->lod_bias; 764 } 765#endif /* V3D_VERSION < 40 */ 766 return so; 767} 768 769static void 770v3d_sampler_states_bind(struct pipe_context *pctx, 771 enum pipe_shader_type shader, unsigned start, 772 unsigned nr, void **hwcso) 773{ 774 struct v3d_context *v3d = v3d_context(pctx); 775 struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader]; 776 777 assert(start == 0); 778 unsigned i; 779 unsigned new_nr = 0; 780 781 for (i = 0; i < nr; i++) { 782 if (hwcso[i]) 783 new_nr = i + 1; 784 stage_tex->samplers[i] = hwcso[i]; 785 } 786 787 for (; i < stage_tex->num_samplers; i++) { 788 stage_tex->samplers[i] = NULL; 789 } 790 791 stage_tex->num_samplers = new_nr; 792 793 v3d_flag_dirty_sampler_state(v3d, shader); 794} 795 796static void 797v3d_sampler_state_delete(struct pipe_context *pctx, 798 void *hwcso) 799{ 800 struct pipe_sampler_state *psampler = hwcso; 801 struct v3d_sampler_state *sampler = v3d_sampler_state(psampler); 802 803 pipe_resource_reference(&sampler->sampler_state, NULL); 804 free(psampler); 805} 806 807#if V3D_VERSION >= 40 808static uint32_t 809translate_swizzle(unsigned char pipe_swizzle) 810{ 811 switch (pipe_swizzle) { 812 case PIPE_SWIZZLE_0: 813 return 0; 814 case PIPE_SWIZZLE_1: 815 return 1; 816 case PIPE_SWIZZLE_X: 817 case PIPE_SWIZZLE_Y: 818 case PIPE_SWIZZLE_Z: 819 case PIPE_SWIZZLE_W: 820 return 2 + pipe_swizzle; 821 default: 822 unreachable("unknown swizzle"); 823 } 824} 825#endif 826 827static void 828v3d_setup_texture_shader_state(struct V3DX(TEXTURE_SHADER_STATE) *tex, 829 struct pipe_resource *prsc, 830 int base_level, int last_level, 831 int first_layer, int last_layer) 832{ 833 struct v3d_resource *rsc = v3d_resource(prsc); 834 int msaa_scale = prsc->nr_samples > 1 ? 2 : 1; 835 836 tex->image_width = prsc->width0 * msaa_scale; 837 tex->image_height = prsc->height0 * msaa_scale; 838 839#if V3D_VERSION >= 40 840 /* On 4.x, the height of a 1D texture is redefined to be the 841 * upper 14 bits of the width (which is only usable with txf). 842 */ 843 if (prsc->target == PIPE_TEXTURE_1D || 844 prsc->target == PIPE_TEXTURE_1D_ARRAY) { 845 tex->image_height = tex->image_width >> 14; 846 } 847 848 tex->image_width &= (1 << 14) - 1; 849 tex->image_height &= (1 << 14) - 1; 850#endif 851 852 if (prsc->target == PIPE_TEXTURE_3D) { 853 tex->image_depth = prsc->depth0; 854 } else { 855 tex->image_depth = (last_layer - first_layer) + 1; 856 } 857 858 tex->base_level = base_level; 859#if V3D_VERSION >= 40 860 tex->max_level = last_level; 861 /* Note that we don't have a job to reference the texture's sBO 862 * at state create time, so any time this sampler view is used 863 * we need to add the texture to the job. 864 */ 865 tex->texture_base_pointer = 866 cl_address(NULL, 867 rsc->bo->offset + 868 v3d_layer_offset(prsc, 0, first_layer)); 869#endif 870 tex->array_stride_64_byte_aligned = rsc->cube_map_stride / 64; 871 872 /* Since other platform devices may produce UIF images even 873 * when they're not big enough for V3D to assume they're UIF, 874 * we force images with level 0 as UIF to be always treated 875 * that way. 876 */ 877 tex->level_0_is_strictly_uif = 878 (rsc->slices[0].tiling == V3D_TILING_UIF_XOR || 879 rsc->slices[0].tiling == V3D_TILING_UIF_NO_XOR); 880 tex->level_0_xor_enable = (rsc->slices[0].tiling == V3D_TILING_UIF_XOR); 881 882 if (tex->level_0_is_strictly_uif) 883 tex->level_0_ub_pad = rsc->slices[0].ub_pad; 884 885#if V3D_VERSION >= 40 886 if (tex->uif_xor_disable || 887 tex->level_0_is_strictly_uif) { 888 tex->extended = true; 889 } 890#endif /* V3D_VERSION >= 40 */ 891} 892 893void 894v3dX(create_texture_shader_state_bo)(struct v3d_context *v3d, 895 struct v3d_sampler_view *so) 896{ 897 struct pipe_resource *prsc = so->texture; 898 const struct pipe_sampler_view *cso = &so->base; 899 struct v3d_screen *screen = v3d->screen; 900 901 void *map; 902 903#if V3D_VERSION >= 40 904 v3d_bo_unreference(&so->bo); 905 so->bo = v3d_bo_alloc(v3d->screen, 906 cl_packet_length(TEXTURE_SHADER_STATE), "sampler"); 907 map = v3d_bo_map(so->bo); 908#else /* V3D_VERSION < 40 */ 909 STATIC_ASSERT(sizeof(so->texture_shader_state) >= 910 cl_packet_length(TEXTURE_SHADER_STATE)); 911 map = &so->texture_shader_state; 912#endif 913 914 v3dx_pack(map, TEXTURE_SHADER_STATE, tex) { 915 v3d_setup_texture_shader_state(&tex, prsc, 916 cso->u.tex.first_level, 917 cso->u.tex.last_level, 918 cso->u.tex.first_layer, 919 cso->u.tex.last_layer); 920 921 tex.srgb = util_format_is_srgb(cso->format); 922 923#if V3D_VERSION >= 40 924 tex.swizzle_r = translate_swizzle(so->swizzle[0]); 925 tex.swizzle_g = translate_swizzle(so->swizzle[1]); 926 tex.swizzle_b = translate_swizzle(so->swizzle[2]); 927 tex.swizzle_a = translate_swizzle(so->swizzle[3]); 928#endif 929 930 if (prsc->nr_samples > 1 && V3D_VERSION < 40) { 931 /* Using texture views to reinterpret formats on our 932 * MSAA textures won't work, because we don't lay out 933 * the bits in memory as it's expected -- for example, 934 * RGBA8 and RGB10_A2 are compatible in the 935 * ARB_texture_view spec, but in HW we lay them out as 936 * 32bpp RGBA8 and 64bpp RGBA16F. Just assert for now 937 * to catch failures. 938 * 939 * We explicitly allow remapping S8Z24 to RGBA8888 for 940 * v3d_blit.c's stencil blits. 941 */ 942 assert((util_format_linear(cso->format) == 943 util_format_linear(prsc->format)) || 944 (prsc->format == PIPE_FORMAT_S8_UINT_Z24_UNORM && 945 cso->format == PIPE_FORMAT_R8G8B8A8_UNORM)); 946 uint32_t output_image_format = 947 v3d_get_rt_format(&screen->devinfo, cso->format); 948 uint32_t internal_type; 949 uint32_t internal_bpp; 950 v3d_get_internal_type_bpp_for_output_format(&screen->devinfo, 951 output_image_format, 952 &internal_type, 953 &internal_bpp); 954 955 switch (internal_type) { 956 case V3D_INTERNAL_TYPE_8: 957 tex.texture_type = TEXTURE_DATA_FORMAT_RGBA8; 958 break; 959 case V3D_INTERNAL_TYPE_16F: 960 tex.texture_type = TEXTURE_DATA_FORMAT_RGBA16F; 961 break; 962 default: 963 unreachable("Bad MSAA texture type"); 964 } 965 966 /* sRGB was stored in the tile buffer as linear and 967 * would have been encoded to sRGB on resolved tile 968 * buffer store. Note that this means we would need 969 * shader code if we wanted to read an MSAA sRGB 970 * texture without sRGB decode. 971 */ 972 tex.srgb = false; 973 } else { 974 tex.texture_type = v3d_get_tex_format(&screen->devinfo, 975 cso->format); 976 } 977 }; 978} 979 980static struct pipe_sampler_view * 981v3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, 982 const struct pipe_sampler_view *cso) 983{ 984 struct v3d_context *v3d = v3d_context(pctx); 985 struct v3d_screen *screen = v3d->screen; 986 struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view); 987 struct v3d_resource *rsc = v3d_resource(prsc); 988 989 if (!so) 990 return NULL; 991 992 so->base = *cso; 993 994 pipe_reference(NULL, &prsc->reference); 995 996 /* Compute the sampler view's swizzle up front. This will be plugged 997 * into either the sampler (for 16-bit returns) or the shader's 998 * texture key (for 32) 999 */ 1000 uint8_t view_swizzle[4] = { 1001 cso->swizzle_r, 1002 cso->swizzle_g, 1003 cso->swizzle_b, 1004 cso->swizzle_a 1005 }; 1006 const uint8_t *fmt_swizzle = 1007 v3d_get_format_swizzle(&screen->devinfo, so->base.format); 1008 util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle); 1009 1010 so->base.texture = prsc; 1011 so->base.reference.count = 1; 1012 so->base.context = pctx; 1013 1014 if (rsc->separate_stencil && 1015 cso->format == PIPE_FORMAT_X32_S8X24_UINT) { 1016 rsc = rsc->separate_stencil; 1017 prsc = &rsc->base; 1018 } 1019 1020 /* If we're sampling depth from depth/stencil, demote the format to 1021 * just depth. u_format will end up giving the answers for the 1022 * stencil channel, otherwise. 1023 */ 1024 enum pipe_format sample_format = cso->format; 1025 if (sample_format == PIPE_FORMAT_S8_UINT_Z24_UNORM) 1026 sample_format = PIPE_FORMAT_X8Z24_UNORM; 1027 1028#if V3D_VERSION >= 40 1029 const struct util_format_description *desc = 1030 util_format_description(sample_format); 1031 1032 if (util_format_is_pure_integer(sample_format) && 1033 !util_format_has_depth(desc)) { 1034 int chan = util_format_get_first_non_void_channel(sample_format); 1035 if (util_format_is_pure_uint(sample_format)) { 1036 switch (desc->channel[chan].size) { 1037 case 32: 1038 so->sampler_variant = V3D_SAMPLER_STATE_32; 1039 break; 1040 case 16: 1041 so->sampler_variant = V3D_SAMPLER_STATE_16U; 1042 break; 1043 case 10: 1044 so->sampler_variant = V3D_SAMPLER_STATE_1010102U; 1045 break; 1046 case 8: 1047 so->sampler_variant = V3D_SAMPLER_STATE_8U; 1048 break; 1049 } 1050 } else { 1051 switch (desc->channel[chan].size) { 1052 case 32: 1053 so->sampler_variant = V3D_SAMPLER_STATE_32; 1054 break; 1055 case 16: 1056 so->sampler_variant = V3D_SAMPLER_STATE_16I; 1057 break; 1058 case 8: 1059 so->sampler_variant = V3D_SAMPLER_STATE_8I; 1060 break; 1061 } 1062 } 1063 } else { 1064 if (v3d_get_tex_return_size(&screen->devinfo, sample_format, 1065 PIPE_TEX_COMPARE_NONE) == 32) { 1066 if (util_format_is_alpha(sample_format)) 1067 so->sampler_variant = V3D_SAMPLER_STATE_32_A; 1068 else 1069 so->sampler_variant = V3D_SAMPLER_STATE_32; 1070 } else { 1071 if (util_format_is_luminance_alpha(sample_format)) 1072 so->sampler_variant = V3D_SAMPLER_STATE_F16_LA; 1073 else if (util_format_is_alpha(sample_format)) 1074 so->sampler_variant = V3D_SAMPLER_STATE_F16_A; 1075 else if (fmt_swizzle[0] == PIPE_SWIZZLE_Z) 1076 so->sampler_variant = V3D_SAMPLER_STATE_F16_BGRA; 1077 else 1078 so->sampler_variant = V3D_SAMPLER_STATE_F16; 1079 1080 } 1081 1082 if (util_format_is_unorm(sample_format)) { 1083 so->sampler_variant += (V3D_SAMPLER_STATE_F16_UNORM - 1084 V3D_SAMPLER_STATE_F16); 1085 } else if (util_format_is_snorm(sample_format)){ 1086 so->sampler_variant += (V3D_SAMPLER_STATE_F16_SNORM - 1087 V3D_SAMPLER_STATE_F16); 1088 } 1089 } 1090#endif 1091 1092 /* V3D still doesn't support sampling from raster textures, so we will 1093 * have to copy to a temporary tiled texture. 1094 */ 1095 if (!rsc->tiled && !(prsc->target == PIPE_TEXTURE_1D || 1096 prsc->target == PIPE_TEXTURE_1D_ARRAY)) { 1097 struct v3d_resource *shadow_parent = rsc; 1098 struct pipe_resource tmpl = { 1099 .target = prsc->target, 1100 .format = prsc->format, 1101 .width0 = u_minify(prsc->width0, 1102 cso->u.tex.first_level), 1103 .height0 = u_minify(prsc->height0, 1104 cso->u.tex.first_level), 1105 .depth0 = 1, 1106 .array_size = 1, 1107 .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 1108 .last_level = cso->u.tex.last_level - cso->u.tex.first_level, 1109 .nr_samples = prsc->nr_samples, 1110 }; 1111 1112 /* Create the shadow texture. The rest of the sampler view 1113 * setup will use the shadow. 1114 */ 1115 prsc = v3d_resource_create(pctx->screen, &tmpl); 1116 if (!prsc) { 1117 free(so); 1118 return NULL; 1119 } 1120 rsc = v3d_resource(prsc); 1121 1122 /* Flag it as needing update of the contents from the parent. */ 1123 rsc->writes = shadow_parent->writes - 1; 1124 assert(rsc->tiled); 1125 1126 so->texture = prsc; 1127 } else { 1128 pipe_resource_reference(&so->texture, prsc); 1129 } 1130 1131 v3d_create_texture_shader_state_bo(v3d, so); 1132 1133 return &so->base; 1134} 1135 1136static void 1137v3d_sampler_view_destroy(struct pipe_context *pctx, 1138 struct pipe_sampler_view *psview) 1139{ 1140 struct v3d_sampler_view *sview = v3d_sampler_view(psview); 1141 1142 v3d_bo_unreference(&sview->bo); 1143 pipe_resource_reference(&psview->texture, NULL); 1144 pipe_resource_reference(&sview->texture, NULL); 1145 free(psview); 1146} 1147 1148static void 1149v3d_set_sampler_views(struct pipe_context *pctx, 1150 enum pipe_shader_type shader, 1151 unsigned start, unsigned nr, 1152 unsigned unbind_num_trailing_slots, 1153 bool take_ownership, 1154 struct pipe_sampler_view **views) 1155{ 1156 struct v3d_context *v3d = v3d_context(pctx); 1157 struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader]; 1158 unsigned i; 1159 unsigned new_nr = 0; 1160 1161 assert(start == 0); 1162 1163 for (i = 0; i < nr; i++) { 1164 if (views[i]) 1165 new_nr = i + 1; 1166 if (take_ownership) { 1167 pipe_sampler_view_reference(&stage_tex->textures[i], NULL); 1168 stage_tex->textures[i] = views[i]; 1169 } else { 1170 pipe_sampler_view_reference(&stage_tex->textures[i], views[i]); 1171 } 1172 } 1173 1174 for (; i < stage_tex->num_textures; i++) { 1175 pipe_sampler_view_reference(&stage_tex->textures[i], NULL); 1176 } 1177 1178 stage_tex->num_textures = new_nr; 1179 1180 v3d_flag_dirty_sampler_state(v3d, shader); 1181} 1182 1183static struct pipe_stream_output_target * 1184v3d_create_stream_output_target(struct pipe_context *pctx, 1185 struct pipe_resource *prsc, 1186 unsigned buffer_offset, 1187 unsigned buffer_size) 1188{ 1189 struct v3d_stream_output_target *target; 1190 1191 target = CALLOC_STRUCT(v3d_stream_output_target); 1192 if (!target) 1193 return NULL; 1194 1195 pipe_reference_init(&target->base.reference, 1); 1196 pipe_resource_reference(&target->base.buffer, prsc); 1197 1198 target->base.context = pctx; 1199 target->base.buffer_offset = buffer_offset; 1200 target->base.buffer_size = buffer_size; 1201 1202 return &target->base; 1203} 1204 1205static void 1206v3d_stream_output_target_destroy(struct pipe_context *pctx, 1207 struct pipe_stream_output_target *target) 1208{ 1209 pipe_resource_reference(&target->buffer, NULL); 1210 free(target); 1211} 1212 1213static void 1214v3d_set_stream_output_targets(struct pipe_context *pctx, 1215 unsigned num_targets, 1216 struct pipe_stream_output_target **targets, 1217 const unsigned *offsets) 1218{ 1219 struct v3d_context *ctx = v3d_context(pctx); 1220 struct v3d_streamout_stateobj *so = &ctx->streamout; 1221 unsigned i; 1222 1223 assert(num_targets <= ARRAY_SIZE(so->targets)); 1224 1225 /* Update recorded vertex counts when we are ending the recording of 1226 * transform feedback. We do this when we switch primitive types 1227 * at draw time, but if we haven't switched primitives in our last 1228 * draw we need to do it here as well. 1229 */ 1230 if (num_targets == 0 && so->num_targets > 0) 1231 v3d_update_primitive_counters(ctx); 1232 1233 for (i = 0; i < num_targets; i++) { 1234 if (offsets[i] != -1) 1235 so->offsets[i] = offsets[i]; 1236 1237 pipe_so_target_reference(&so->targets[i], targets[i]); 1238 } 1239 1240 for (; i < so->num_targets; i++) 1241 pipe_so_target_reference(&so->targets[i], NULL); 1242 1243 so->num_targets = num_targets; 1244 1245 /* Create primitive counters BO if needed */ 1246 if (num_targets > 0) 1247 v3d_ensure_prim_counts_allocated(ctx); 1248 1249 ctx->dirty |= V3D_DIRTY_STREAMOUT; 1250} 1251 1252static void 1253v3d_set_shader_buffers(struct pipe_context *pctx, 1254 enum pipe_shader_type shader, 1255 unsigned start, unsigned count, 1256 const struct pipe_shader_buffer *buffers, 1257 unsigned writable_bitmask) 1258{ 1259 struct v3d_context *v3d = v3d_context(pctx); 1260 struct v3d_ssbo_stateobj *so = &v3d->ssbo[shader]; 1261 unsigned mask = 0; 1262 1263 if (buffers) { 1264 for (unsigned i = 0; i < count; i++) { 1265 unsigned n = i + start; 1266 struct pipe_shader_buffer *buf = &so->sb[n]; 1267 1268 if ((buf->buffer == buffers[i].buffer) && 1269 (buf->buffer_offset == buffers[i].buffer_offset) && 1270 (buf->buffer_size == buffers[i].buffer_size)) 1271 continue; 1272 1273 mask |= 1 << n; 1274 1275 buf->buffer_offset = buffers[i].buffer_offset; 1276 buf->buffer_size = buffers[i].buffer_size; 1277 pipe_resource_reference(&buf->buffer, buffers[i].buffer); 1278 1279 if (buf->buffer) 1280 so->enabled_mask |= 1 << n; 1281 else 1282 so->enabled_mask &= ~(1 << n); 1283 } 1284 } else { 1285 mask = ((1 << count) - 1) << start; 1286 1287 for (unsigned i = 0; i < count; i++) { 1288 unsigned n = i + start; 1289 struct pipe_shader_buffer *buf = &so->sb[n]; 1290 1291 pipe_resource_reference(&buf->buffer, NULL); 1292 } 1293 1294 so->enabled_mask &= ~mask; 1295 } 1296 1297 v3d->dirty |= V3D_DIRTY_SSBO; 1298} 1299 1300static void 1301v3d_create_image_view_texture_shader_state(struct v3d_context *v3d, 1302 struct v3d_shaderimg_stateobj *so, 1303 int img) 1304{ 1305#if V3D_VERSION >= 40 1306 struct v3d_image_view *iview = &so->si[img]; 1307 1308 void *map; 1309 u_upload_alloc(v3d->uploader, 0, cl_packet_length(TEXTURE_SHADER_STATE), 1310 32, 1311 &iview->tex_state_offset, 1312 &iview->tex_state, 1313 &map); 1314 1315 struct pipe_resource *prsc = iview->base.resource; 1316 1317 v3dx_pack(map, TEXTURE_SHADER_STATE, tex) { 1318 v3d_setup_texture_shader_state(&tex, prsc, 1319 iview->base.u.tex.level, 1320 iview->base.u.tex.level, 1321 iview->base.u.tex.first_layer, 1322 iview->base.u.tex.last_layer); 1323 1324 tex.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X); 1325 tex.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y); 1326 tex.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z); 1327 tex.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W); 1328 1329 tex.texture_type = v3d_get_tex_format(&v3d->screen->devinfo, 1330 iview->base.format); 1331 }; 1332#else /* V3D_VERSION < 40 */ 1333 /* V3D 3.x doesn't use support shader image load/store operations on 1334 * textures, so it would get lowered in the shader to general memory 1335 * acceses. 1336 */ 1337#endif 1338} 1339 1340static void 1341v3d_set_shader_images(struct pipe_context *pctx, 1342 enum pipe_shader_type shader, 1343 unsigned start, unsigned count, 1344 unsigned unbind_num_trailing_slots, 1345 const struct pipe_image_view *images) 1346{ 1347 struct v3d_context *v3d = v3d_context(pctx); 1348 struct v3d_shaderimg_stateobj *so = &v3d->shaderimg[shader]; 1349 1350 if (images) { 1351 for (unsigned i = 0; i < count; i++) { 1352 unsigned n = i + start; 1353 struct v3d_image_view *iview = &so->si[n]; 1354 1355 if ((iview->base.resource == images[i].resource) && 1356 (iview->base.format == images[i].format) && 1357 (iview->base.access == images[i].access) && 1358 !memcmp(&iview->base.u, &images[i].u, 1359 sizeof(iview->base.u))) 1360 continue; 1361 1362 util_copy_image_view(&iview->base, &images[i]); 1363 1364 if (iview->base.resource) { 1365 so->enabled_mask |= 1 << n; 1366 v3d_create_image_view_texture_shader_state(v3d, 1367 so, 1368 n); 1369 } else { 1370 so->enabled_mask &= ~(1 << n); 1371 pipe_resource_reference(&iview->tex_state, NULL); 1372 } 1373 } 1374 } else { 1375 for (unsigned i = 0; i < count; i++) { 1376 unsigned n = i + start; 1377 struct v3d_image_view *iview = &so->si[n]; 1378 1379 pipe_resource_reference(&iview->base.resource, NULL); 1380 pipe_resource_reference(&iview->tex_state, NULL); 1381 } 1382 1383 if (count == 32) 1384 so->enabled_mask = 0; 1385 else 1386 so->enabled_mask &= ~(((1 << count) - 1) << start); 1387 } 1388 1389 v3d->dirty |= V3D_DIRTY_SHADER_IMAGE; 1390 1391 if (unbind_num_trailing_slots) { 1392 v3d_set_shader_images(pctx, shader, start + count, 1393 unbind_num_trailing_slots, 0, NULL); 1394 } 1395} 1396 1397void 1398v3dX(state_init)(struct pipe_context *pctx) 1399{ 1400 pctx->set_blend_color = v3d_set_blend_color; 1401 pctx->set_stencil_ref = v3d_set_stencil_ref; 1402 pctx->set_clip_state = v3d_set_clip_state; 1403 pctx->set_sample_mask = v3d_set_sample_mask; 1404 pctx->set_constant_buffer = v3d_set_constant_buffer; 1405 pctx->set_framebuffer_state = v3d_set_framebuffer_state; 1406 pctx->set_polygon_stipple = v3d_set_polygon_stipple; 1407 pctx->set_scissor_states = v3d_set_scissor_states; 1408 pctx->set_viewport_states = v3d_set_viewport_states; 1409 1410 pctx->set_vertex_buffers = v3d_set_vertex_buffers; 1411 1412 pctx->create_blend_state = v3d_create_blend_state; 1413 pctx->bind_blend_state = v3d_blend_state_bind; 1414 pctx->delete_blend_state = v3d_generic_cso_state_delete; 1415 1416 pctx->create_rasterizer_state = v3d_create_rasterizer_state; 1417 pctx->bind_rasterizer_state = v3d_rasterizer_state_bind; 1418 pctx->delete_rasterizer_state = v3d_generic_cso_state_delete; 1419 1420 pctx->create_depth_stencil_alpha_state = v3d_create_depth_stencil_alpha_state; 1421 pctx->bind_depth_stencil_alpha_state = v3d_zsa_state_bind; 1422 pctx->delete_depth_stencil_alpha_state = v3d_generic_cso_state_delete; 1423 1424 pctx->create_vertex_elements_state = v3d_vertex_state_create; 1425 pctx->delete_vertex_elements_state = v3d_vertex_state_delete; 1426 pctx->bind_vertex_elements_state = v3d_vertex_state_bind; 1427 1428 pctx->create_sampler_state = v3d_create_sampler_state; 1429 pctx->delete_sampler_state = v3d_sampler_state_delete; 1430 pctx->bind_sampler_states = v3d_sampler_states_bind; 1431 1432 pctx->create_sampler_view = v3d_create_sampler_view; 1433 pctx->sampler_view_destroy = v3d_sampler_view_destroy; 1434 pctx->set_sampler_views = v3d_set_sampler_views; 1435 1436 pctx->set_shader_buffers = v3d_set_shader_buffers; 1437 pctx->set_shader_images = v3d_set_shader_images; 1438 1439 pctx->create_stream_output_target = v3d_create_stream_output_target; 1440 pctx->stream_output_target_destroy = v3d_stream_output_target_destroy; 1441 pctx->set_stream_output_targets = v3d_set_stream_output_targets; 1442} 1443