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