1 /* 2 * Copyright 2007 VMware, Inc. 3 * Copyright 2016 Advanced Micro Devices, Inc. 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 * on the rights to use, copy, modify, merge, publish, distribute, sub 9 * license, and/or sell copies of the Software, and to permit persons to whom 10 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22 * USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 /** 26 * \file 27 * 28 * Common helper functions for PBO up- and downloads. 29 */ 30 31 #include "state_tracker/st_context.h" 32 #include "state_tracker/st_pbo.h" 33 #include "state_tracker/st_cb_bufferobjects.h" 34 35 #include "pipe/p_context.h" 36 #include "pipe/p_defines.h" 37 #include "pipe/p_screen.h" 38 #include "cso_cache/cso_context.h" 39 #include "tgsi/tgsi_ureg.h" 40 #include "util/u_format.h" 41 #include "util/u_inlines.h" 42 #include "util/u_upload_mgr.h" 43 44 /* Conversion to apply in the fragment shader. */ 45 enum st_pbo_conversion { 46 ST_PBO_CONVERT_NONE = 0, 47 ST_PBO_CONVERT_UINT_TO_SINT, 48 ST_PBO_CONVERT_SINT_TO_UINT, 49 50 ST_NUM_PBO_CONVERSIONS 51 }; 52 53 /* Final setup of buffer addressing information. 54 * 55 * buf_offset is in pixels. 56 * 57 * Returns false if something (e.g. alignment) prevents PBO upload/download. 58 */ 59 bool 60 st_pbo_addresses_setup(struct st_context *st, 61 struct pipe_resource *buf, intptr_t buf_offset, 62 struct st_pbo_addresses *addr) 63 { 64 unsigned skip_pixels; 65 66 /* Check alignment against texture buffer requirements. */ 67 { 68 unsigned ofs = (buf_offset * addr->bytes_per_pixel) % st->ctx->Const.TextureBufferOffsetAlignment; 69 if (ofs != 0) { 70 if (ofs % addr->bytes_per_pixel != 0) 71 return false; 72 73 skip_pixels = ofs / addr->bytes_per_pixel; 74 buf_offset -= skip_pixels; 75 } else { 76 skip_pixels = 0; 77 } 78 } 79 80 assert(buf_offset >= 0); 81 82 addr->buffer = buf; 83 addr->first_element = buf_offset; 84 addr->last_element = buf_offset + skip_pixels + addr->width - 1 85 + (addr->height - 1 + (addr->depth - 1) * addr->image_height) * addr->pixels_per_row; 86 87 if (addr->last_element - addr->first_element > st->ctx->Const.MaxTextureBufferSize - 1) 88 return false; 89 90 /* This should be ensured by Mesa before calling our callbacks */ 91 assert((addr->last_element + 1) * addr->bytes_per_pixel <= buf->width0); 92 93 addr->constants.xoffset = -addr->xoffset + skip_pixels; 94 addr->constants.yoffset = -addr->yoffset; 95 addr->constants.stride = addr->pixels_per_row; 96 addr->constants.image_size = addr->pixels_per_row * addr->image_height; 97 addr->constants.layer_offset = 0; 98 99 return true; 100 } 101 102 /* Validate and fill buffer addressing information based on GL pixelstore 103 * attributes. 104 * 105 * Returns false if some aspect of the addressing (e.g. alignment) prevents 106 * PBO upload/download. 107 */ 108 bool 109 st_pbo_addresses_pixelstore(struct st_context *st, 110 GLenum gl_target, bool skip_images, 111 const struct gl_pixelstore_attrib *store, 112 const void *pixels, 113 struct st_pbo_addresses *addr) 114 { 115 struct pipe_resource *buf = st_buffer_object(store->BufferObj)->buffer; 116 intptr_t buf_offset = (intptr_t) pixels; 117 118 if (buf_offset % addr->bytes_per_pixel) 119 return false; 120 121 /* Convert to texels */ 122 buf_offset = buf_offset / addr->bytes_per_pixel; 123 124 /* Determine image height */ 125 if (gl_target == GL_TEXTURE_1D_ARRAY) { 126 addr->image_height = 1; 127 } else { 128 addr->image_height = store->ImageHeight > 0 ? store->ImageHeight : addr->height; 129 } 130 131 /* Compute the stride, taking store->Alignment into account */ 132 { 133 unsigned pixels_per_row = store->RowLength > 0 ? 134 store->RowLength : addr->width; 135 unsigned bytes_per_row = pixels_per_row * addr->bytes_per_pixel; 136 unsigned remainder = bytes_per_row % store->Alignment; 137 unsigned offset_rows; 138 139 if (remainder > 0) 140 bytes_per_row += store->Alignment - remainder; 141 142 if (bytes_per_row % addr->bytes_per_pixel) 143 return false; 144 145 addr->pixels_per_row = bytes_per_row / addr->bytes_per_pixel; 146 147 offset_rows = store->SkipRows; 148 if (skip_images) 149 offset_rows += addr->image_height * store->SkipImages; 150 151 buf_offset += store->SkipPixels + addr->pixels_per_row * offset_rows; 152 } 153 154 if (!st_pbo_addresses_setup(st, buf, buf_offset, addr)) 155 return false; 156 157 /* Support GL_PACK_INVERT_MESA */ 158 if (store->Invert) { 159 addr->constants.xoffset += (addr->height - 1) * addr->constants.stride; 160 addr->constants.stride = -addr->constants.stride; 161 } 162 163 return true; 164 } 165 166 /* For download from a framebuffer, we may have to invert the Y axis. The 167 * setup is as follows: 168 * - set viewport to inverted, so that the position sysval is correct for 169 * texel fetches 170 * - this function adjusts the fragment shader's constant buffer to compute 171 * the correct destination addresses. 172 */ 173 void 174 st_pbo_addresses_invert_y(struct st_pbo_addresses *addr, 175 unsigned viewport_height) 176 { 177 addr->constants.xoffset += 178 (viewport_height - 1 + 2 * addr->constants.yoffset) * addr->constants.stride; 179 addr->constants.stride = -addr->constants.stride; 180 } 181 182 /* Setup all vertex pipeline state, rasterizer state, and fragment shader 183 * constants, and issue the draw call for PBO upload/download. 184 * 185 * The caller is responsible for saving and restoring state, as well as for 186 * setting other fragment shader state (fragment shader, samplers), and 187 * framebuffer/viewport/DSA/blend state. 188 */ 189 bool 190 st_pbo_draw(struct st_context *st, const struct st_pbo_addresses *addr, 191 unsigned surface_width, unsigned surface_height) 192 { 193 struct cso_context *cso = st->cso_context; 194 195 /* Setup vertex and geometry shaders */ 196 if (!st->pbo.vs) { 197 st->pbo.vs = st_pbo_create_vs(st); 198 if (!st->pbo.vs) 199 return false; 200 } 201 202 if (addr->depth != 1 && st->pbo.use_gs && !st->pbo.gs) { 203 st->pbo.gs = st_pbo_create_gs(st); 204 if (!st->pbo.gs) 205 return false; 206 } 207 208 cso_set_vertex_shader_handle(cso, st->pbo.vs); 209 210 cso_set_geometry_shader_handle(cso, addr->depth != 1 ? st->pbo.gs : NULL); 211 212 cso_set_tessctrl_shader_handle(cso, NULL); 213 214 cso_set_tesseval_shader_handle(cso, NULL); 215 216 /* Upload vertices */ 217 { 218 struct pipe_vertex_buffer vbo; 219 struct pipe_vertex_element velem; 220 221 float x0 = (float) addr->xoffset / surface_width * 2.0f - 1.0f; 222 float y0 = (float) addr->yoffset / surface_height * 2.0f - 1.0f; 223 float x1 = (float) (addr->xoffset + addr->width) / surface_width * 2.0f - 1.0f; 224 float y1 = (float) (addr->yoffset + addr->height) / surface_height * 2.0f - 1.0f; 225 226 float *verts = NULL; 227 228 vbo.user_buffer = NULL; 229 vbo.buffer = NULL; 230 vbo.stride = 2 * sizeof(float); 231 232 u_upload_alloc(st->uploader, 0, 8 * sizeof(float), 4, 233 &vbo.buffer_offset, &vbo.buffer, (void **) &verts); 234 if (!verts) 235 return false; 236 237 verts[0] = x0; 238 verts[1] = y0; 239 verts[2] = x0; 240 verts[3] = y1; 241 verts[4] = x1; 242 verts[5] = y0; 243 verts[6] = x1; 244 verts[7] = y1; 245 246 u_upload_unmap(st->uploader); 247 248 velem.src_offset = 0; 249 velem.instance_divisor = 0; 250 velem.vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso); 251 velem.src_format = PIPE_FORMAT_R32G32_FLOAT; 252 253 cso_set_vertex_elements(cso, 1, &velem); 254 255 cso_set_vertex_buffers(cso, velem.vertex_buffer_index, 1, &vbo); 256 257 pipe_resource_reference(&vbo.buffer, NULL); 258 } 259 260 /* Upload constants */ 261 { 262 struct pipe_constant_buffer cb; 263 264 if (st->constbuf_uploader) { 265 cb.buffer = NULL; 266 cb.user_buffer = NULL; 267 u_upload_data(st->constbuf_uploader, 0, sizeof(addr->constants), 268 st->ctx->Const.UniformBufferOffsetAlignment, 269 &addr->constants, &cb.buffer_offset, &cb.buffer); 270 if (!cb.buffer) 271 return false; 272 273 u_upload_unmap(st->constbuf_uploader); 274 } else { 275 cb.buffer = NULL; 276 cb.user_buffer = &addr->constants; 277 cb.buffer_offset = 0; 278 } 279 cb.buffer_size = sizeof(addr->constants); 280 281 cso_set_constant_buffer(cso, PIPE_SHADER_FRAGMENT, 0, &cb); 282 283 pipe_resource_reference(&cb.buffer, NULL); 284 } 285 286 /* Rasterizer state */ 287 cso_set_rasterizer(cso, &st->pbo.raster); 288 289 /* Disable stream output */ 290 cso_set_stream_outputs(cso, 0, NULL, 0); 291 292 if (addr->depth == 1) { 293 cso_draw_arrays(cso, PIPE_PRIM_TRIANGLE_STRIP, 0, 4); 294 } else { 295 cso_draw_arrays_instanced(cso, PIPE_PRIM_TRIANGLE_STRIP, 296 0, 4, 0, addr->depth); 297 } 298 299 return true; 300 } 301 302 void * 303 st_pbo_create_vs(struct st_context *st) 304 { 305 struct ureg_program *ureg; 306 struct ureg_src in_pos; 307 struct ureg_src in_instanceid; 308 struct ureg_dst out_pos; 309 struct ureg_dst out_layer; 310 311 ureg = ureg_create(PIPE_SHADER_VERTEX); 312 if (!ureg) 313 return NULL; 314 315 in_pos = ureg_DECL_vs_input(ureg, TGSI_SEMANTIC_POSITION); 316 317 out_pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 318 319 if (st->pbo.layers) { 320 in_instanceid = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_INSTANCEID, 0); 321 322 if (!st->pbo.use_gs) 323 out_layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0); 324 } 325 326 /* out_pos = in_pos */ 327 ureg_MOV(ureg, out_pos, in_pos); 328 329 if (st->pbo.layers) { 330 if (st->pbo.use_gs) { 331 /* out_pos.z = i2f(gl_InstanceID) */ 332 ureg_I2F(ureg, ureg_writemask(out_pos, TGSI_WRITEMASK_Z), 333 ureg_scalar(in_instanceid, TGSI_SWIZZLE_X)); 334 } else { 335 /* out_layer = gl_InstanceID */ 336 ureg_MOV(ureg, out_layer, in_instanceid); 337 } 338 } 339 340 ureg_END(ureg); 341 342 return ureg_create_shader_and_destroy(ureg, st->pipe); 343 } 344 345 void * 346 st_pbo_create_gs(struct st_context *st) 347 { 348 static const int zero = 0; 349 struct ureg_program *ureg; 350 struct ureg_dst out_pos; 351 struct ureg_dst out_layer; 352 struct ureg_src in_pos; 353 struct ureg_src imm; 354 unsigned i; 355 356 ureg = ureg_create(PIPE_SHADER_GEOMETRY); 357 if (!ureg) 358 return NULL; 359 360 ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_TRIANGLES); 361 ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_TRIANGLE_STRIP); 362 ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 3); 363 364 out_pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 365 out_layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0); 366 367 in_pos = ureg_DECL_input(ureg, TGSI_SEMANTIC_POSITION, 0, 0, 1); 368 369 imm = ureg_DECL_immediate_int(ureg, &zero, 1); 370 371 for (i = 0; i < 3; ++i) { 372 struct ureg_src in_pos_vertex = ureg_src_dimension(in_pos, i); 373 374 /* out_pos = in_pos[i] */ 375 ureg_MOV(ureg, out_pos, in_pos_vertex); 376 377 /* out_layer.x = f2i(in_pos[i].z) */ 378 ureg_F2I(ureg, ureg_writemask(out_layer, TGSI_WRITEMASK_X), 379 ureg_scalar(in_pos_vertex, TGSI_SWIZZLE_Z)); 380 381 ureg_EMIT(ureg, ureg_scalar(imm, TGSI_SWIZZLE_X)); 382 } 383 384 ureg_END(ureg); 385 386 return ureg_create_shader_and_destroy(ureg, st->pipe); 387 } 388 389 static void 390 build_conversion(struct ureg_program *ureg, const struct ureg_dst *temp, 391 enum st_pbo_conversion conversion) 392 { 393 switch (conversion) { 394 case ST_PBO_CONVERT_SINT_TO_UINT: 395 ureg_IMAX(ureg, *temp, ureg_src(*temp), ureg_imm1i(ureg, 0)); 396 break; 397 case ST_PBO_CONVERT_UINT_TO_SINT: 398 ureg_UMIN(ureg, *temp, ureg_src(*temp), ureg_imm1u(ureg, (1u << 31) - 1)); 399 break; 400 default: 401 /* no-op */ 402 break; 403 } 404 } 405 406 static void * 407 create_fs(struct st_context *st, bool download, enum pipe_texture_target target, 408 enum st_pbo_conversion conversion) 409 { 410 struct pipe_context *pipe = st->pipe; 411 struct pipe_screen *screen = pipe->screen; 412 struct ureg_program *ureg; 413 bool have_layer; 414 struct ureg_dst out; 415 struct ureg_src sampler; 416 struct ureg_src pos; 417 struct ureg_src layer; 418 struct ureg_src const0; 419 struct ureg_src const1; 420 struct ureg_dst temp0; 421 422 have_layer = 423 st->pbo.layers && 424 (!download || target == PIPE_TEXTURE_1D_ARRAY 425 || target == PIPE_TEXTURE_2D_ARRAY 426 || target == PIPE_TEXTURE_3D 427 || target == PIPE_TEXTURE_CUBE 428 || target == PIPE_TEXTURE_CUBE_ARRAY); 429 430 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 431 if (!ureg) 432 return NULL; 433 434 if (!download) { 435 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 436 } else { 437 struct ureg_src image; 438 439 /* writeonly images do not require an explicitly given format. */ 440 image = ureg_DECL_image(ureg, 0, TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE, 441 true, false); 442 out = ureg_dst(image); 443 } 444 445 sampler = ureg_DECL_sampler(ureg, 0); 446 if (screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL)) { 447 pos = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_POSITION, 0); 448 } else { 449 pos = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0, 450 TGSI_INTERPOLATE_LINEAR); 451 } 452 if (have_layer) { 453 layer = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_LAYER, 0, 454 TGSI_INTERPOLATE_CONSTANT); 455 } 456 const0 = ureg_DECL_constant(ureg, 0); 457 const1 = ureg_DECL_constant(ureg, 1); 458 temp0 = ureg_DECL_temporary(ureg); 459 460 /* Note: const0 = [ -xoffset + skip_pixels, -yoffset, stride, image_height ] */ 461 462 /* temp0.xy = f2i(temp0.xy) */ 463 ureg_F2I(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), 464 ureg_swizzle(pos, 465 TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, 466 TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y)); 467 468 /* temp0.xy = temp0.xy + const0.xy */ 469 ureg_UADD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), 470 ureg_swizzle(ureg_src(temp0), 471 TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, 472 TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y), 473 ureg_swizzle(const0, 474 TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, 475 TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y)); 476 477 /* temp0.x = const0.z * temp0.y + temp0.x */ 478 ureg_UMAD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_X), 479 ureg_scalar(const0, TGSI_SWIZZLE_Z), 480 ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_Y), 481 ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X)); 482 483 if (have_layer) { 484 /* temp0.x = const0.w * layer + temp0.x */ 485 ureg_UMAD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_X), 486 ureg_scalar(const0, TGSI_SWIZZLE_W), 487 ureg_scalar(layer, TGSI_SWIZZLE_X), 488 ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X)); 489 } 490 491 /* temp0.w = 0 */ 492 ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_W), ureg_imm1u(ureg, 0)); 493 494 if (download) { 495 struct ureg_dst temp1; 496 struct ureg_src op[2]; 497 498 temp1 = ureg_DECL_temporary(ureg); 499 500 /* temp1.xy = pos.xy */ 501 ureg_F2I(ureg, ureg_writemask(temp1, TGSI_WRITEMASK_XY), pos); 502 503 /* temp1.zw = 0 */ 504 ureg_MOV(ureg, ureg_writemask(temp1, TGSI_WRITEMASK_ZW), ureg_imm1u(ureg, 0)); 505 506 if (have_layer) { 507 struct ureg_dst temp1_layer = 508 ureg_writemask(temp1, target == PIPE_TEXTURE_1D_ARRAY ? TGSI_WRITEMASK_Y 509 : TGSI_WRITEMASK_Z); 510 511 /* temp1.y/z = layer */ 512 ureg_MOV(ureg, temp1_layer, ureg_scalar(layer, TGSI_SWIZZLE_X)); 513 514 if (target == PIPE_TEXTURE_3D) { 515 /* temp1.z += layer_offset */ 516 ureg_UADD(ureg, temp1_layer, 517 ureg_scalar(ureg_src(temp1), TGSI_SWIZZLE_Z), 518 ureg_scalar(const1, TGSI_SWIZZLE_X)); 519 } 520 } 521 522 /* temp1 = txf(sampler, temp1) */ 523 ureg_TXF(ureg, temp1, util_pipe_tex_to_tgsi_tex(target, 1), 524 ureg_src(temp1), sampler); 525 526 build_conversion(ureg, &temp1, conversion); 527 528 /* store(out, temp0, temp1) */ 529 op[0] = ureg_src(temp0); 530 op[1] = ureg_src(temp1); 531 ureg_memory_insn(ureg, TGSI_OPCODE_STORE, &out, 1, op, 2, 0, 532 TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE); 533 534 ureg_release_temporary(ureg, temp1); 535 } else { 536 /* out = txf(sampler, temp0.x) */ 537 ureg_TXF(ureg, temp0, TGSI_TEXTURE_BUFFER, ureg_src(temp0), sampler); 538 539 build_conversion(ureg, &temp0, conversion); 540 541 ureg_MOV(ureg, out, ureg_src(temp0)); 542 } 543 544 ureg_release_temporary(ureg, temp0); 545 546 ureg_END(ureg); 547 548 return ureg_create_shader_and_destroy(ureg, pipe); 549 } 550 551 static enum st_pbo_conversion 552 get_pbo_conversion(enum pipe_format src_format, enum pipe_format dst_format) 553 { 554 if (util_format_is_pure_uint(src_format)) { 555 if (util_format_is_pure_sint(dst_format)) 556 return ST_PBO_CONVERT_UINT_TO_SINT; 557 } else if (util_format_is_pure_sint(src_format)) { 558 if (util_format_is_pure_uint(dst_format)) 559 return ST_PBO_CONVERT_SINT_TO_UINT; 560 } 561 562 return ST_PBO_CONVERT_NONE; 563 } 564 565 void * 566 st_pbo_get_upload_fs(struct st_context *st, 567 enum pipe_format src_format, 568 enum pipe_format dst_format) 569 { 570 STATIC_ASSERT(ARRAY_SIZE(st->pbo.upload_fs) == ST_NUM_PBO_CONVERSIONS); 571 572 enum st_pbo_conversion conversion = get_pbo_conversion(src_format, dst_format); 573 574 if (!st->pbo.upload_fs[conversion]) 575 st->pbo.upload_fs[conversion] = create_fs(st, false, 0, conversion); 576 577 return st->pbo.upload_fs[conversion]; 578 } 579 580 void * 581 st_pbo_get_download_fs(struct st_context *st, enum pipe_texture_target target, 582 enum pipe_format src_format, 583 enum pipe_format dst_format) 584 { 585 STATIC_ASSERT(ARRAY_SIZE(st->pbo.download_fs) == ST_NUM_PBO_CONVERSIONS); 586 assert(target < PIPE_MAX_TEXTURE_TYPES); 587 588 enum st_pbo_conversion conversion = get_pbo_conversion(src_format, dst_format); 589 590 if (!st->pbo.download_fs[conversion][target]) 591 st->pbo.download_fs[conversion][target] = create_fs(st, true, target, conversion); 592 593 return st->pbo.download_fs[conversion][target]; 594 } 595 596 void 597 st_init_pbo_helpers(struct st_context *st) 598 { 599 struct pipe_context *pipe = st->pipe; 600 struct pipe_screen *screen = pipe->screen; 601 602 st->pbo.upload_enabled = 603 screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS) && 604 screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT) >= 1 && 605 screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS); 606 if (!st->pbo.upload_enabled) 607 return; 608 609 st->pbo.download_enabled = 610 st->pbo.upload_enabled && 611 screen->get_param(screen, PIPE_CAP_SAMPLER_VIEW_TARGET) && 612 screen->get_param(screen, PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT) && 613 screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, 614 PIPE_SHADER_CAP_MAX_SHADER_IMAGES) >= 1; 615 616 st->pbo.rgba_only = 617 screen->get_param(screen, PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY); 618 619 if (screen->get_param(screen, PIPE_CAP_TGSI_INSTANCEID)) { 620 if (screen->get_param(screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT)) { 621 st->pbo.layers = true; 622 } else if (screen->get_param(screen, PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES) >= 3) { 623 st->pbo.layers = true; 624 st->pbo.use_gs = true; 625 } 626 } 627 628 /* Blend state */ 629 memset(&st->pbo.upload_blend, 0, sizeof(struct pipe_blend_state)); 630 st->pbo.upload_blend.rt[0].colormask = PIPE_MASK_RGBA; 631 632 /* Rasterizer state */ 633 memset(&st->pbo.raster, 0, sizeof(struct pipe_rasterizer_state)); 634 st->pbo.raster.half_pixel_center = 1; 635 } 636 637 void 638 st_destroy_pbo_helpers(struct st_context *st) 639 { 640 unsigned i; 641 642 for (i = 0; i < ARRAY_SIZE(st->pbo.upload_fs); ++i) { 643 if (st->pbo.upload_fs[i]) { 644 cso_delete_fragment_shader(st->cso_context, st->pbo.upload_fs[i]); 645 st->pbo.upload_fs[i] = NULL; 646 } 647 } 648 649 for (i = 0; i < ARRAY_SIZE(st->pbo.download_fs); ++i) { 650 for (unsigned j = 0; j < ARRAY_SIZE(st->pbo.download_fs[0]); ++j) { 651 if (st->pbo.download_fs[i][j]) { 652 cso_delete_fragment_shader(st->cso_context, st->pbo.download_fs[i][j]); 653 st->pbo.download_fs[i][j] = NULL; 654 } 655 } 656 } 657 658 if (st->pbo.gs) { 659 cso_delete_geometry_shader(st->cso_context, st->pbo.gs); 660 st->pbo.gs = NULL; 661 } 662 663 if (st->pbo.vs) { 664 cso_delete_vertex_shader(st->cso_context, st->pbo.vs); 665 st->pbo.vs = NULL; 666 } 667 } 668