1/* 2 * Copyright 2016 Red Hat. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#include "sp_context.h" 25#include "sp_image.h" 26#include "sp_texture.h" 27 28#include "util/u_format.h" 29 30/* 31 * Get the offset into the base image 32 * first element for a buffer or layer/level for texture. 33 */ 34static uint32_t 35get_image_offset(const struct softpipe_resource *spr, 36 const struct pipe_image_view *iview, 37 enum pipe_format format, unsigned r_coord) 38{ 39 int base_layer = 0; 40 41 if (spr->base.target == PIPE_BUFFER) 42 return iview->u.buf.offset; 43 44 if (spr->base.target == PIPE_TEXTURE_1D_ARRAY || 45 spr->base.target == PIPE_TEXTURE_2D_ARRAY || 46 spr->base.target == PIPE_TEXTURE_CUBE_ARRAY || 47 spr->base.target == PIPE_TEXTURE_CUBE || 48 spr->base.target == PIPE_TEXTURE_3D) 49 base_layer = r_coord + iview->u.tex.first_layer; 50 return softpipe_get_tex_image_offset(spr, iview->u.tex.level, base_layer); 51} 52 53/* 54 * Does this texture instruction have a layer or depth parameter. 55 */ 56static inline bool 57has_layer_or_depth(unsigned tgsi_tex_instr) 58{ 59 return (tgsi_tex_instr == TGSI_TEXTURE_3D || 60 tgsi_tex_instr == TGSI_TEXTURE_CUBE || 61 tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY || 62 tgsi_tex_instr == TGSI_TEXTURE_2D_ARRAY || 63 tgsi_tex_instr == TGSI_TEXTURE_CUBE_ARRAY || 64 tgsi_tex_instr == TGSI_TEXTURE_2D_ARRAY_MSAA); 65} 66 67/* 68 * Is this texture instruction a single non-array coordinate. 69 */ 70static inline bool 71has_1coord(unsigned tgsi_tex_instr) 72{ 73 return (tgsi_tex_instr == TGSI_TEXTURE_BUFFER || 74 tgsi_tex_instr == TGSI_TEXTURE_1D || 75 tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY); 76} 77 78/* 79 * check the bounds vs w/h/d 80 */ 81static inline bool 82bounds_check(int width, int height, int depth, 83 int s, int t, int r) 84{ 85 if (s < 0 || s >= width) 86 return false; 87 if (t < 0 || t >= height) 88 return false; 89 if (r < 0 || r >= depth) 90 return false; 91 return true; 92} 93 94/* 95 * Checks if the texture target compatible with the image resource 96 * pipe target. 97 */ 98static inline bool 99has_compat_target(unsigned pipe_target, unsigned tgsi_target) 100{ 101 switch (pipe_target) { 102 case PIPE_TEXTURE_1D: 103 if (tgsi_target == TGSI_TEXTURE_1D) 104 return true; 105 break; 106 case PIPE_TEXTURE_2D: 107 if (tgsi_target == TGSI_TEXTURE_2D) 108 return true; 109 break; 110 case PIPE_TEXTURE_RECT: 111 if (tgsi_target == TGSI_TEXTURE_RECT) 112 return true; 113 break; 114 case PIPE_TEXTURE_3D: 115 if (tgsi_target == TGSI_TEXTURE_3D || 116 tgsi_target == TGSI_TEXTURE_2D) 117 return true; 118 break; 119 case PIPE_TEXTURE_CUBE: 120 if (tgsi_target == TGSI_TEXTURE_CUBE || 121 tgsi_target == TGSI_TEXTURE_2D) 122 return true; 123 break; 124 case PIPE_TEXTURE_1D_ARRAY: 125 if (tgsi_target == TGSI_TEXTURE_1D || 126 tgsi_target == TGSI_TEXTURE_1D_ARRAY) 127 return true; 128 break; 129 case PIPE_TEXTURE_2D_ARRAY: 130 if (tgsi_target == TGSI_TEXTURE_2D || 131 tgsi_target == TGSI_TEXTURE_2D_ARRAY) 132 return true; 133 break; 134 case PIPE_TEXTURE_CUBE_ARRAY: 135 if (tgsi_target == TGSI_TEXTURE_CUBE || 136 tgsi_target == TGSI_TEXTURE_CUBE_ARRAY || 137 tgsi_target == TGSI_TEXTURE_2D) 138 return true; 139 break; 140 case PIPE_BUFFER: 141 return (tgsi_target == TGSI_TEXTURE_BUFFER); 142 } 143 return false; 144} 145 146static bool 147get_dimensions(const struct pipe_image_view *iview, 148 const struct softpipe_resource *spr, 149 unsigned tgsi_tex_instr, 150 enum pipe_format pformat, 151 unsigned *width, 152 unsigned *height, 153 unsigned *depth) 154{ 155 if (tgsi_tex_instr == TGSI_TEXTURE_BUFFER) { 156 *width = iview->u.buf.size / util_format_get_blocksize(pformat); 157 *height = 1; 158 *depth = 1; 159 /* 160 * Bounds check the buffer size from the view 161 * and the buffer size from the underlying buffer. 162 */ 163 if (util_format_get_stride(pformat, *width) > 164 util_format_get_stride(spr->base.format, spr->base.width0)) 165 return false; 166 } else { 167 unsigned level; 168 169 level = spr->base.target == PIPE_BUFFER ? 0 : iview->u.tex.level; 170 *width = u_minify(spr->base.width0, level); 171 *height = u_minify(spr->base.height0, level); 172 173 if (spr->base.target == PIPE_TEXTURE_3D) 174 *depth = u_minify(spr->base.depth0, level); 175 else 176 *depth = spr->base.array_size; 177 178 /* Make sure the resource and view have compatiable formats */ 179 if (util_format_get_blocksize(pformat) > 180 util_format_get_blocksize(spr->base.format)) 181 return false; 182 } 183 return true; 184} 185 186static void 187fill_coords(const struct tgsi_image_params *params, 188 unsigned index, 189 const int s[TGSI_QUAD_SIZE], 190 const int t[TGSI_QUAD_SIZE], 191 const int r[TGSI_QUAD_SIZE], 192 int *s_coord, int *t_coord, int *r_coord) 193{ 194 *s_coord = s[index]; 195 *t_coord = has_1coord(params->tgsi_tex_instr) ? 0 : t[index]; 196 *r_coord = has_layer_or_depth(params->tgsi_tex_instr) ? 197 (params->tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY ? t[index] : r[index]) : 0; 198} 199/* 200 * Implement the image LOAD operation. 201 */ 202static void 203sp_tgsi_load(const struct tgsi_image *image, 204 const struct tgsi_image_params *params, 205 const int s[TGSI_QUAD_SIZE], 206 const int t[TGSI_QUAD_SIZE], 207 const int r[TGSI_QUAD_SIZE], 208 const int sample[TGSI_QUAD_SIZE], 209 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 210{ 211 struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image; 212 struct pipe_image_view *iview; 213 struct softpipe_resource *spr; 214 unsigned width, height, depth; 215 unsigned stride; 216 int c, j; 217 char *data_ptr; 218 unsigned offset = 0; 219 220 if (params->unit >= PIPE_MAX_SHADER_IMAGES) 221 goto fail_write_all_zero; 222 iview = &sp_img->sp_iview[params->unit]; 223 spr = (struct softpipe_resource *)iview->resource; 224 if (!spr) 225 goto fail_write_all_zero; 226 227 if (!has_compat_target(spr->base.target, params->tgsi_tex_instr)) 228 goto fail_write_all_zero; 229 230 if (!get_dimensions(iview, spr, params->tgsi_tex_instr, 231 params->format, &width, &height, &depth)) 232 return; 233 234 stride = util_format_get_stride(params->format, width); 235 236 for (j = 0; j < TGSI_QUAD_SIZE; j++) { 237 int s_coord, t_coord, r_coord; 238 bool fill_zero = false; 239 240 if (!(params->execmask & (1 << j))) 241 fill_zero = true; 242 243 fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord); 244 if (!bounds_check(width, height, depth, 245 s_coord, t_coord, r_coord)) 246 fill_zero = true; 247 248 if (fill_zero) { 249 int nc = util_format_get_nr_components(params->format); 250 int ival = util_format_is_pure_integer(params->format); 251 for (c = 0; c < 4; c++) { 252 rgba[c][j] = 0; 253 if (c == 3 && nc < 4) { 254 if (ival) 255 ((int32_t *)rgba[c])[j] = 1; 256 else 257 rgba[c][j] = 1.0; 258 } 259 } 260 continue; 261 } 262 offset = get_image_offset(spr, iview, params->format, r_coord); 263 data_ptr = (char *)spr->data + offset; 264 265 if (util_format_is_pure_sint(params->format)) { 266 int32_t sdata[4]; 267 268 util_format_read_4i(params->format, 269 sdata, 0, 270 data_ptr, stride, 271 s_coord, t_coord, 1, 1); 272 for (c = 0; c < 4; c++) 273 ((int32_t *)rgba[c])[j] = sdata[c]; 274 } else if (util_format_is_pure_uint(params->format)) { 275 uint32_t sdata[4]; 276 util_format_read_4ui(params->format, 277 sdata, 0, 278 data_ptr, stride, 279 s_coord, t_coord, 1, 1); 280 for (c = 0; c < 4; c++) 281 ((uint32_t *)rgba[c])[j] = sdata[c]; 282 } else { 283 float sdata[4]; 284 util_format_read_4f(params->format, 285 sdata, 0, 286 data_ptr, stride, 287 s_coord, t_coord, 1, 1); 288 for (c = 0; c < 4; c++) 289 rgba[c][j] = sdata[c]; 290 } 291 } 292 return; 293fail_write_all_zero: 294 for (j = 0; j < TGSI_QUAD_SIZE; j++) { 295 for (c = 0; c < 4; c++) 296 rgba[c][j] = 0; 297 } 298 return; 299} 300 301/* 302 * Implement the image STORE operation. 303 */ 304static void 305sp_tgsi_store(const struct tgsi_image *image, 306 const struct tgsi_image_params *params, 307 const int s[TGSI_QUAD_SIZE], 308 const int t[TGSI_QUAD_SIZE], 309 const int r[TGSI_QUAD_SIZE], 310 const int sample[TGSI_QUAD_SIZE], 311 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 312{ 313 struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image; 314 struct pipe_image_view *iview; 315 struct softpipe_resource *spr; 316 unsigned width, height, depth; 317 unsigned stride; 318 char *data_ptr; 319 int j, c; 320 unsigned offset = 0; 321 unsigned pformat = params->format; 322 323 if (params->unit >= PIPE_MAX_SHADER_IMAGES) 324 return; 325 iview = &sp_img->sp_iview[params->unit]; 326 spr = (struct softpipe_resource *)iview->resource; 327 if (!spr) 328 return; 329 if (!has_compat_target(spr->base.target, params->tgsi_tex_instr)) 330 return; 331 332 if (params->format == PIPE_FORMAT_NONE) 333 pformat = spr->base.format; 334 335 if (!get_dimensions(iview, spr, params->tgsi_tex_instr, 336 pformat, &width, &height, &depth)) 337 return; 338 339 stride = util_format_get_stride(pformat, width); 340 341 for (j = 0; j < TGSI_QUAD_SIZE; j++) { 342 int s_coord, t_coord, r_coord; 343 344 if (!(params->execmask & (1 << j))) 345 continue; 346 347 fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord); 348 if (!bounds_check(width, height, depth, 349 s_coord, t_coord, r_coord)) 350 continue; 351 352 offset = get_image_offset(spr, iview, pformat, r_coord); 353 data_ptr = (char *)spr->data + offset; 354 355 if (util_format_is_pure_sint(pformat)) { 356 int32_t sdata[4]; 357 for (c = 0; c < 4; c++) 358 sdata[c] = ((int32_t *)rgba[c])[j]; 359 util_format_write_4i(pformat, sdata, 0, data_ptr, stride, 360 s_coord, t_coord, 1, 1); 361 } else if (util_format_is_pure_uint(pformat)) { 362 uint32_t sdata[4]; 363 for (c = 0; c < 4; c++) 364 sdata[c] = ((uint32_t *)rgba[c])[j]; 365 util_format_write_4ui(pformat, sdata, 0, data_ptr, stride, 366 s_coord, t_coord, 1, 1); 367 } else { 368 float sdata[4]; 369 for (c = 0; c < 4; c++) 370 sdata[c] = rgba[c][j]; 371 util_format_write_4f(pformat, sdata, 0, data_ptr, stride, 372 s_coord, t_coord, 1, 1); 373 } 374 } 375} 376 377/* 378 * Implement atomic operations on unsigned integers. 379 */ 380static void 381handle_op_uint(const struct pipe_image_view *iview, 382 const struct tgsi_image_params *params, 383 bool just_read, 384 char *data_ptr, 385 uint qi, 386 unsigned stride, 387 enum tgsi_opcode opcode, 388 int s, 389 int t, 390 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE], 391 float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 392{ 393 uint c; 394 int nc = util_format_get_nr_components(params->format); 395 unsigned sdata[4]; 396 397 util_format_read_4ui(params->format, 398 sdata, 0, 399 data_ptr, stride, 400 s, t, 1, 1); 401 402 if (just_read) { 403 for (c = 0; c < nc; c++) { 404 ((uint32_t *)rgba[c])[qi] = sdata[c]; 405 } 406 return; 407 } 408 switch (opcode) { 409 case TGSI_OPCODE_ATOMUADD: 410 for (c = 0; c < nc; c++) { 411 unsigned temp = sdata[c]; 412 sdata[c] += ((uint32_t *)rgba[c])[qi]; 413 ((uint32_t *)rgba[c])[qi] = temp; 414 } 415 break; 416 case TGSI_OPCODE_ATOMXCHG: 417 for (c = 0; c < nc; c++) { 418 unsigned temp = sdata[c]; 419 sdata[c] = ((uint32_t *)rgba[c])[qi]; 420 ((uint32_t *)rgba[c])[qi] = temp; 421 } 422 break; 423 case TGSI_OPCODE_ATOMCAS: 424 for (c = 0; c < nc; c++) { 425 unsigned dst_x = sdata[c]; 426 unsigned cmp_x = ((uint32_t *)rgba[c])[qi]; 427 unsigned src_x = ((uint32_t *)rgba2[c])[qi]; 428 unsigned temp = sdata[c]; 429 sdata[c] = (dst_x == cmp_x) ? src_x : dst_x; 430 ((uint32_t *)rgba[c])[qi] = temp; 431 } 432 break; 433 case TGSI_OPCODE_ATOMAND: 434 for (c = 0; c < nc; c++) { 435 unsigned temp = sdata[c]; 436 sdata[c] &= ((uint32_t *)rgba[c])[qi]; 437 ((uint32_t *)rgba[c])[qi] = temp; 438 } 439 break; 440 case TGSI_OPCODE_ATOMOR: 441 for (c = 0; c < nc; c++) { 442 unsigned temp = sdata[c]; 443 sdata[c] |= ((uint32_t *)rgba[c])[qi]; 444 ((uint32_t *)rgba[c])[qi] = temp; 445 } 446 break; 447 case TGSI_OPCODE_ATOMXOR: 448 for (c = 0; c < nc; c++) { 449 unsigned temp = sdata[c]; 450 sdata[c] ^= ((uint32_t *)rgba[c])[qi]; 451 ((uint32_t *)rgba[c])[qi] = temp; 452 } 453 break; 454 case TGSI_OPCODE_ATOMUMIN: 455 for (c = 0; c < nc; c++) { 456 unsigned dst_x = sdata[c]; 457 unsigned src_x = ((uint32_t *)rgba[c])[qi]; 458 sdata[c] = MIN2(dst_x, src_x); 459 ((uint32_t *)rgba[c])[qi] = dst_x; 460 } 461 break; 462 case TGSI_OPCODE_ATOMUMAX: 463 for (c = 0; c < nc; c++) { 464 unsigned dst_x = sdata[c]; 465 unsigned src_x = ((uint32_t *)rgba[c])[qi]; 466 sdata[c] = MAX2(dst_x, src_x); 467 ((uint32_t *)rgba[c])[qi] = dst_x; 468 } 469 break; 470 case TGSI_OPCODE_ATOMIMIN: 471 for (c = 0; c < nc; c++) { 472 int dst_x = sdata[c]; 473 int src_x = ((uint32_t *)rgba[c])[qi]; 474 sdata[c] = MIN2(dst_x, src_x); 475 ((uint32_t *)rgba[c])[qi] = dst_x; 476 } 477 break; 478 case TGSI_OPCODE_ATOMIMAX: 479 for (c = 0; c < nc; c++) { 480 int dst_x = sdata[c]; 481 int src_x = ((uint32_t *)rgba[c])[qi]; 482 sdata[c] = MAX2(dst_x, src_x); 483 ((uint32_t *)rgba[c])[qi] = dst_x; 484 } 485 break; 486 default: 487 assert(!"Unexpected TGSI opcode in sp_tgsi_op"); 488 break; 489 } 490 util_format_write_4ui(params->format, sdata, 0, data_ptr, stride, 491 s, t, 1, 1); 492} 493 494/* 495 * Implement atomic operations on signed integers. 496 */ 497static void 498handle_op_int(const struct pipe_image_view *iview, 499 const struct tgsi_image_params *params, 500 bool just_read, 501 char *data_ptr, 502 uint qi, 503 unsigned stride, 504 enum tgsi_opcode opcode, 505 int s, 506 int t, 507 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE], 508 float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 509{ 510 uint c; 511 int nc = util_format_get_nr_components(params->format); 512 int sdata[4]; 513 util_format_read_4i(params->format, 514 sdata, 0, 515 data_ptr, stride, 516 s, t, 1, 1); 517 518 if (just_read) { 519 for (c = 0; c < nc; c++) { 520 ((int32_t *)rgba[c])[qi] = sdata[c]; 521 } 522 return; 523 } 524 switch (opcode) { 525 case TGSI_OPCODE_ATOMUADD: 526 for (c = 0; c < nc; c++) { 527 int temp = sdata[c]; 528 sdata[c] += ((int32_t *)rgba[c])[qi]; 529 ((int32_t *)rgba[c])[qi] = temp; 530 } 531 break; 532 case TGSI_OPCODE_ATOMXCHG: 533 for (c = 0; c < nc; c++) { 534 int temp = sdata[c]; 535 sdata[c] = ((int32_t *)rgba[c])[qi]; 536 ((int32_t *)rgba[c])[qi] = temp; 537 } 538 break; 539 case TGSI_OPCODE_ATOMCAS: 540 for (c = 0; c < nc; c++) { 541 int dst_x = sdata[c]; 542 int cmp_x = ((int32_t *)rgba[c])[qi]; 543 int src_x = ((int32_t *)rgba2[c])[qi]; 544 int temp = sdata[c]; 545 sdata[c] = (dst_x == cmp_x) ? src_x : dst_x; 546 ((int32_t *)rgba[c])[qi] = temp; 547 } 548 break; 549 case TGSI_OPCODE_ATOMAND: 550 for (c = 0; c < nc; c++) { 551 int temp = sdata[c]; 552 sdata[c] &= ((int32_t *)rgba[c])[qi]; 553 ((int32_t *)rgba[c])[qi] = temp; 554 } 555 break; 556 case TGSI_OPCODE_ATOMOR: 557 for (c = 0; c < nc; c++) { 558 int temp = sdata[c]; 559 sdata[c] |= ((int32_t *)rgba[c])[qi]; 560 ((int32_t *)rgba[c])[qi] = temp; 561 } 562 break; 563 case TGSI_OPCODE_ATOMXOR: 564 for (c = 0; c < nc; c++) { 565 int temp = sdata[c]; 566 sdata[c] ^= ((int32_t *)rgba[c])[qi]; 567 ((int32_t *)rgba[c])[qi] = temp; 568 } 569 break; 570 case TGSI_OPCODE_ATOMUMIN: 571 for (c = 0; c < nc; c++) { 572 int dst_x = sdata[c]; 573 int src_x = ((int32_t *)rgba[c])[qi]; 574 sdata[c] = MIN2(dst_x, src_x); 575 ((int32_t *)rgba[c])[qi] = dst_x; 576 } 577 break; 578 case TGSI_OPCODE_ATOMUMAX: 579 for (c = 0; c < nc; c++) { 580 int dst_x = sdata[c]; 581 int src_x = ((int32_t *)rgba[c])[qi]; 582 sdata[c] = MAX2(dst_x, src_x); 583 ((int32_t *)rgba[c])[qi] = dst_x; 584 } 585 break; 586 case TGSI_OPCODE_ATOMIMIN: 587 for (c = 0; c < nc; c++) { 588 int dst_x = sdata[c]; 589 int src_x = ((int32_t *)rgba[c])[qi]; 590 sdata[c] = MIN2(dst_x, src_x); 591 ((int32_t *)rgba[c])[qi] = dst_x; 592 } 593 break; 594 case TGSI_OPCODE_ATOMIMAX: 595 for (c = 0; c < nc; c++) { 596 int dst_x = sdata[c]; 597 int src_x = ((int32_t *)rgba[c])[qi]; 598 sdata[c] = MAX2(dst_x, src_x); 599 ((int32_t *)rgba[c])[qi] = dst_x; 600 } 601 break; 602 default: 603 assert(!"Unexpected TGSI opcode in sp_tgsi_op"); 604 break; 605 } 606 util_format_write_4i(params->format, sdata, 0, data_ptr, stride, 607 s, t, 1, 1); 608} 609 610/* GLES OES_shader_image_atomic.txt allows XCHG on R32F */ 611static void 612handle_op_r32f_xchg(const struct pipe_image_view *iview, 613 const struct tgsi_image_params *params, 614 bool just_read, 615 char *data_ptr, 616 uint qi, 617 unsigned stride, 618 enum tgsi_opcode opcode, 619 int s, 620 int t, 621 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 622{ 623 float sdata[4]; 624 uint c; 625 int nc = 1; 626 util_format_read_4f(params->format, 627 sdata, 0, 628 data_ptr, stride, 629 s, t, 1, 1); 630 if (just_read) { 631 for (c = 0; c < nc; c++) { 632 ((int32_t *)rgba[c])[qi] = sdata[c]; 633 } 634 return; 635 } 636 637 for (c = 0; c < nc; c++) { 638 int temp = sdata[c]; 639 sdata[c] = ((float *)rgba[c])[qi]; 640 ((float *)rgba[c])[qi] = temp; 641 } 642 util_format_write_4f(params->format, sdata, 0, data_ptr, stride, 643 s, t, 1, 1); 644} 645 646/* 647 * Implement atomic image operations. 648 */ 649static void 650sp_tgsi_op(const struct tgsi_image *image, 651 const struct tgsi_image_params *params, 652 enum tgsi_opcode opcode, 653 const int s[TGSI_QUAD_SIZE], 654 const int t[TGSI_QUAD_SIZE], 655 const int r[TGSI_QUAD_SIZE], 656 const int sample[TGSI_QUAD_SIZE], 657 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE], 658 float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 659{ 660 struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image; 661 struct pipe_image_view *iview; 662 struct softpipe_resource *spr; 663 unsigned width, height, depth; 664 unsigned stride; 665 int j, c; 666 unsigned offset; 667 char *data_ptr; 668 669 if (params->unit >= PIPE_MAX_SHADER_IMAGES) 670 return; 671 iview = &sp_img->sp_iview[params->unit]; 672 spr = (struct softpipe_resource *)iview->resource; 673 if (!spr) 674 goto fail_write_all_zero; 675 if (!has_compat_target(spr->base.target, params->tgsi_tex_instr)) 676 goto fail_write_all_zero; 677 678 if (!get_dimensions(iview, spr, params->tgsi_tex_instr, 679 params->format, &width, &height, &depth)) 680 goto fail_write_all_zero; 681 682 stride = util_format_get_stride(spr->base.format, width); 683 684 for (j = 0; j < TGSI_QUAD_SIZE; j++) { 685 int s_coord, t_coord, r_coord; 686 bool just_read = false; 687 688 fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord); 689 if (!bounds_check(width, height, depth, 690 s_coord, t_coord, r_coord)) { 691 int nc = util_format_get_nr_components(params->format); 692 int ival = util_format_is_pure_integer(params->format); 693 int c; 694 for (c = 0; c < 4; c++) { 695 rgba[c][j] = 0; 696 if (c == 3 && nc < 4) { 697 if (ival) 698 ((int32_t *)rgba[c])[j] = 1; 699 else 700 rgba[c][j] = 1.0; 701 } 702 } 703 continue; 704 } 705 706 /* just readback the value for atomic if execmask isn't set */ 707 if (!(params->execmask & (1 << j))) { 708 just_read = true; 709 } 710 711 offset = get_image_offset(spr, iview, params->format, r_coord); 712 data_ptr = (char *)spr->data + offset; 713 714 /* we should see atomic operations on r32 formats */ 715 if (util_format_is_pure_uint(params->format)) 716 handle_op_uint(iview, params, just_read, data_ptr, j, stride, 717 opcode, s_coord, t_coord, rgba, rgba2); 718 else if (util_format_is_pure_sint(params->format)) 719 handle_op_int(iview, params, just_read, data_ptr, j, stride, 720 opcode, s_coord, t_coord, rgba, rgba2); 721 else if (params->format == PIPE_FORMAT_R32_FLOAT && 722 opcode == TGSI_OPCODE_ATOMXCHG) 723 handle_op_r32f_xchg(iview, params, just_read, data_ptr, j, stride, 724 opcode, s_coord, t_coord, rgba); 725 else 726 assert(0); 727 } 728 return; 729fail_write_all_zero: 730 for (j = 0; j < TGSI_QUAD_SIZE; j++) { 731 for (c = 0; c < 4; c++) 732 rgba[c][j] = 0; 733 } 734 return; 735} 736 737static void 738sp_tgsi_get_dims(const struct tgsi_image *image, 739 const struct tgsi_image_params *params, 740 int dims[4]) 741{ 742 struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image; 743 struct pipe_image_view *iview; 744 struct softpipe_resource *spr; 745 int level; 746 747 if (params->unit >= PIPE_MAX_SHADER_IMAGES) 748 return; 749 iview = &sp_img->sp_iview[params->unit]; 750 spr = (struct softpipe_resource *)iview->resource; 751 if (!spr) 752 return; 753 754 if (params->tgsi_tex_instr == TGSI_TEXTURE_BUFFER) { 755 dims[0] = iview->u.buf.size / util_format_get_blocksize(iview->format); 756 dims[1] = dims[2] = dims[3] = 0; 757 return; 758 } 759 760 level = iview->u.tex.level; 761 dims[0] = u_minify(spr->base.width0, level); 762 switch (params->tgsi_tex_instr) { 763 case TGSI_TEXTURE_1D_ARRAY: 764 dims[1] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1; 765 /* fallthrough */ 766 case TGSI_TEXTURE_1D: 767 return; 768 case TGSI_TEXTURE_2D_ARRAY: 769 dims[2] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1; 770 /* fallthrough */ 771 case TGSI_TEXTURE_2D: 772 case TGSI_TEXTURE_CUBE: 773 case TGSI_TEXTURE_RECT: 774 dims[1] = u_minify(spr->base.height0, level); 775 return; 776 case TGSI_TEXTURE_3D: 777 dims[1] = u_minify(spr->base.height0, level); 778 dims[2] = u_minify(spr->base.depth0, level); 779 return; 780 case TGSI_TEXTURE_CUBE_ARRAY: 781 dims[1] = u_minify(spr->base.height0, level); 782 dims[2] = (iview->u.tex.last_layer - iview->u.tex.first_layer + 1) / 6; 783 break; 784 default: 785 assert(!"unexpected texture target in sp_get_dims()"); 786 return; 787 } 788} 789 790struct sp_tgsi_image * 791sp_create_tgsi_image(void) 792{ 793 struct sp_tgsi_image *img = CALLOC_STRUCT(sp_tgsi_image); 794 if (!img) 795 return NULL; 796 797 img->base.load = sp_tgsi_load; 798 img->base.store = sp_tgsi_store; 799 img->base.op = sp_tgsi_op; 800 img->base.get_dims = sp_tgsi_get_dims; 801 return img; 802}; 803