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/format/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 compatible 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 uint32_t sdata[4]; 266 util_format_read_4(params->format, 267 sdata, 0, 268 data_ptr, stride, 269 s_coord, t_coord, 1, 1); 270 for (c = 0; c < 4; c++) 271 ((uint32_t *)rgba[c])[j] = sdata[c]; 272 } 273 return; 274fail_write_all_zero: 275 for (j = 0; j < TGSI_QUAD_SIZE; j++) { 276 for (c = 0; c < 4; c++) 277 rgba[c][j] = 0; 278 } 279 return; 280} 281 282/* 283 * Implement the image STORE operation. 284 */ 285static void 286sp_tgsi_store(const struct tgsi_image *image, 287 const struct tgsi_image_params *params, 288 const int s[TGSI_QUAD_SIZE], 289 const int t[TGSI_QUAD_SIZE], 290 const int r[TGSI_QUAD_SIZE], 291 const int sample[TGSI_QUAD_SIZE], 292 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 293{ 294 struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image; 295 struct pipe_image_view *iview; 296 struct softpipe_resource *spr; 297 unsigned width, height, depth; 298 unsigned stride; 299 char *data_ptr; 300 int j, c; 301 unsigned offset = 0; 302 unsigned pformat = params->format; 303 304 if (params->unit >= PIPE_MAX_SHADER_IMAGES) 305 return; 306 iview = &sp_img->sp_iview[params->unit]; 307 spr = (struct softpipe_resource *)iview->resource; 308 if (!spr) 309 return; 310 if (!has_compat_target(spr->base.target, params->tgsi_tex_instr)) 311 return; 312 313 if (params->format == PIPE_FORMAT_NONE) 314 pformat = spr->base.format; 315 316 if (!get_dimensions(iview, spr, params->tgsi_tex_instr, 317 pformat, &width, &height, &depth)) 318 return; 319 320 stride = util_format_get_stride(pformat, width); 321 322 for (j = 0; j < TGSI_QUAD_SIZE; j++) { 323 int s_coord, t_coord, r_coord; 324 325 if (!(params->execmask & (1 << j))) 326 continue; 327 328 fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord); 329 if (!bounds_check(width, height, depth, 330 s_coord, t_coord, r_coord)) 331 continue; 332 333 offset = get_image_offset(spr, iview, pformat, r_coord); 334 data_ptr = (char *)spr->data + offset; 335 336 uint32_t sdata[4]; 337 for (c = 0; c < 4; c++) 338 sdata[c] = ((uint32_t *)rgba[c])[j]; 339 util_format_write_4(pformat, sdata, 0, data_ptr, stride, 340 s_coord, t_coord, 1, 1); 341 } 342} 343 344/* 345 * Implement atomic operations on unsigned integers. 346 */ 347static void 348handle_op_uint(const struct pipe_image_view *iview, 349 const struct tgsi_image_params *params, 350 bool just_read, 351 char *data_ptr, 352 uint qi, 353 unsigned stride, 354 enum tgsi_opcode opcode, 355 int s, 356 int t, 357 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE], 358 float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 359{ 360 uint c; 361 int nc = util_format_get_nr_components(params->format); 362 unsigned sdata[4]; 363 364 util_format_read_4(params->format, 365 sdata, 0, 366 data_ptr, stride, 367 s, t, 1, 1); 368 369 if (just_read) { 370 for (c = 0; c < nc; c++) { 371 ((uint32_t *)rgba[c])[qi] = sdata[c]; 372 } 373 return; 374 } 375 switch (opcode) { 376 case TGSI_OPCODE_ATOMUADD: 377 for (c = 0; c < nc; c++) { 378 unsigned temp = sdata[c]; 379 sdata[c] += ((uint32_t *)rgba[c])[qi]; 380 ((uint32_t *)rgba[c])[qi] = temp; 381 } 382 break; 383 case TGSI_OPCODE_ATOMXCHG: 384 for (c = 0; c < nc; c++) { 385 unsigned temp = sdata[c]; 386 sdata[c] = ((uint32_t *)rgba[c])[qi]; 387 ((uint32_t *)rgba[c])[qi] = temp; 388 } 389 break; 390 case TGSI_OPCODE_ATOMCAS: 391 for (c = 0; c < nc; c++) { 392 unsigned dst_x = sdata[c]; 393 unsigned cmp_x = ((uint32_t *)rgba[c])[qi]; 394 unsigned src_x = ((uint32_t *)rgba2[c])[qi]; 395 unsigned temp = sdata[c]; 396 sdata[c] = (dst_x == cmp_x) ? src_x : dst_x; 397 ((uint32_t *)rgba[c])[qi] = temp; 398 } 399 break; 400 case TGSI_OPCODE_ATOMAND: 401 for (c = 0; c < nc; c++) { 402 unsigned temp = sdata[c]; 403 sdata[c] &= ((uint32_t *)rgba[c])[qi]; 404 ((uint32_t *)rgba[c])[qi] = temp; 405 } 406 break; 407 case TGSI_OPCODE_ATOMOR: 408 for (c = 0; c < nc; c++) { 409 unsigned temp = sdata[c]; 410 sdata[c] |= ((uint32_t *)rgba[c])[qi]; 411 ((uint32_t *)rgba[c])[qi] = temp; 412 } 413 break; 414 case TGSI_OPCODE_ATOMXOR: 415 for (c = 0; c < nc; c++) { 416 unsigned temp = sdata[c]; 417 sdata[c] ^= ((uint32_t *)rgba[c])[qi]; 418 ((uint32_t *)rgba[c])[qi] = temp; 419 } 420 break; 421 case TGSI_OPCODE_ATOMUMIN: 422 for (c = 0; c < nc; c++) { 423 unsigned dst_x = sdata[c]; 424 unsigned src_x = ((uint32_t *)rgba[c])[qi]; 425 sdata[c] = MIN2(dst_x, src_x); 426 ((uint32_t *)rgba[c])[qi] = dst_x; 427 } 428 break; 429 case TGSI_OPCODE_ATOMUMAX: 430 for (c = 0; c < nc; c++) { 431 unsigned dst_x = sdata[c]; 432 unsigned src_x = ((uint32_t *)rgba[c])[qi]; 433 sdata[c] = MAX2(dst_x, src_x); 434 ((uint32_t *)rgba[c])[qi] = dst_x; 435 } 436 break; 437 case TGSI_OPCODE_ATOMIMIN: 438 for (c = 0; c < nc; c++) { 439 int dst_x = sdata[c]; 440 int src_x = ((uint32_t *)rgba[c])[qi]; 441 sdata[c] = MIN2(dst_x, src_x); 442 ((uint32_t *)rgba[c])[qi] = dst_x; 443 } 444 break; 445 case TGSI_OPCODE_ATOMIMAX: 446 for (c = 0; c < nc; c++) { 447 int dst_x = sdata[c]; 448 int src_x = ((uint32_t *)rgba[c])[qi]; 449 sdata[c] = MAX2(dst_x, src_x); 450 ((uint32_t *)rgba[c])[qi] = dst_x; 451 } 452 break; 453 default: 454 assert(!"Unexpected TGSI opcode in sp_tgsi_op"); 455 break; 456 } 457 util_format_write_4(params->format, sdata, 0, data_ptr, stride, 458 s, t, 1, 1); 459} 460 461/* 462 * Implement atomic operations on signed integers. 463 */ 464static void 465handle_op_int(const struct pipe_image_view *iview, 466 const struct tgsi_image_params *params, 467 bool just_read, 468 char *data_ptr, 469 uint qi, 470 unsigned stride, 471 enum tgsi_opcode opcode, 472 int s, 473 int t, 474 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE], 475 float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 476{ 477 uint c; 478 int nc = util_format_get_nr_components(params->format); 479 int sdata[4]; 480 util_format_read_4(params->format, 481 sdata, 0, 482 data_ptr, stride, 483 s, t, 1, 1); 484 485 if (just_read) { 486 for (c = 0; c < nc; c++) { 487 ((int32_t *)rgba[c])[qi] = sdata[c]; 488 } 489 return; 490 } 491 switch (opcode) { 492 case TGSI_OPCODE_ATOMUADD: 493 for (c = 0; c < nc; c++) { 494 int temp = sdata[c]; 495 sdata[c] += ((int32_t *)rgba[c])[qi]; 496 ((int32_t *)rgba[c])[qi] = temp; 497 } 498 break; 499 case TGSI_OPCODE_ATOMXCHG: 500 for (c = 0; c < nc; c++) { 501 int temp = sdata[c]; 502 sdata[c] = ((int32_t *)rgba[c])[qi]; 503 ((int32_t *)rgba[c])[qi] = temp; 504 } 505 break; 506 case TGSI_OPCODE_ATOMCAS: 507 for (c = 0; c < nc; c++) { 508 int dst_x = sdata[c]; 509 int cmp_x = ((int32_t *)rgba[c])[qi]; 510 int src_x = ((int32_t *)rgba2[c])[qi]; 511 int temp = sdata[c]; 512 sdata[c] = (dst_x == cmp_x) ? src_x : dst_x; 513 ((int32_t *)rgba[c])[qi] = temp; 514 } 515 break; 516 case TGSI_OPCODE_ATOMAND: 517 for (c = 0; c < nc; c++) { 518 int temp = sdata[c]; 519 sdata[c] &= ((int32_t *)rgba[c])[qi]; 520 ((int32_t *)rgba[c])[qi] = temp; 521 } 522 break; 523 case TGSI_OPCODE_ATOMOR: 524 for (c = 0; c < nc; c++) { 525 int temp = sdata[c]; 526 sdata[c] |= ((int32_t *)rgba[c])[qi]; 527 ((int32_t *)rgba[c])[qi] = temp; 528 } 529 break; 530 case TGSI_OPCODE_ATOMXOR: 531 for (c = 0; c < nc; c++) { 532 int temp = sdata[c]; 533 sdata[c] ^= ((int32_t *)rgba[c])[qi]; 534 ((int32_t *)rgba[c])[qi] = temp; 535 } 536 break; 537 case TGSI_OPCODE_ATOMUMIN: 538 for (c = 0; c < nc; c++) { 539 int dst_x = sdata[c]; 540 int src_x = ((int32_t *)rgba[c])[qi]; 541 sdata[c] = MIN2(dst_x, src_x); 542 ((int32_t *)rgba[c])[qi] = dst_x; 543 } 544 break; 545 case TGSI_OPCODE_ATOMUMAX: 546 for (c = 0; c < nc; c++) { 547 int dst_x = sdata[c]; 548 int src_x = ((int32_t *)rgba[c])[qi]; 549 sdata[c] = MAX2(dst_x, src_x); 550 ((int32_t *)rgba[c])[qi] = dst_x; 551 } 552 break; 553 case TGSI_OPCODE_ATOMIMIN: 554 for (c = 0; c < nc; c++) { 555 int dst_x = sdata[c]; 556 int src_x = ((int32_t *)rgba[c])[qi]; 557 sdata[c] = MIN2(dst_x, src_x); 558 ((int32_t *)rgba[c])[qi] = dst_x; 559 } 560 break; 561 case TGSI_OPCODE_ATOMIMAX: 562 for (c = 0; c < nc; c++) { 563 int dst_x = sdata[c]; 564 int src_x = ((int32_t *)rgba[c])[qi]; 565 sdata[c] = MAX2(dst_x, src_x); 566 ((int32_t *)rgba[c])[qi] = dst_x; 567 } 568 break; 569 default: 570 assert(!"Unexpected TGSI opcode in sp_tgsi_op"); 571 break; 572 } 573 util_format_write_4(params->format, sdata, 0, data_ptr, stride, 574 s, t, 1, 1); 575} 576 577/* GLES OES_shader_image_atomic.txt allows XCHG on R32F */ 578static void 579handle_op_r32f_xchg(const struct pipe_image_view *iview, 580 const struct tgsi_image_params *params, 581 bool just_read, 582 char *data_ptr, 583 uint qi, 584 unsigned stride, 585 enum tgsi_opcode opcode, 586 int s, 587 int t, 588 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 589{ 590 float sdata[4]; 591 uint c; 592 int nc = 1; 593 util_format_read_4(params->format, 594 sdata, 0, 595 data_ptr, stride, 596 s, t, 1, 1); 597 if (just_read) { 598 for (c = 0; c < nc; c++) { 599 ((int32_t *)rgba[c])[qi] = sdata[c]; 600 } 601 return; 602 } 603 604 for (c = 0; c < nc; c++) { 605 int temp = sdata[c]; 606 sdata[c] = ((float *)rgba[c])[qi]; 607 ((float *)rgba[c])[qi] = temp; 608 } 609 util_format_write_4(params->format, sdata, 0, data_ptr, stride, 610 s, t, 1, 1); 611} 612 613/* 614 * Implement atomic image operations. 615 */ 616static void 617sp_tgsi_op(const struct tgsi_image *image, 618 const struct tgsi_image_params *params, 619 enum tgsi_opcode opcode, 620 const int s[TGSI_QUAD_SIZE], 621 const int t[TGSI_QUAD_SIZE], 622 const int r[TGSI_QUAD_SIZE], 623 const int sample[TGSI_QUAD_SIZE], 624 float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE], 625 float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]) 626{ 627 struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image; 628 struct pipe_image_view *iview; 629 struct softpipe_resource *spr; 630 unsigned width, height, depth; 631 unsigned stride; 632 int j, c; 633 unsigned offset; 634 char *data_ptr; 635 636 if (params->unit >= PIPE_MAX_SHADER_IMAGES) 637 return; 638 iview = &sp_img->sp_iview[params->unit]; 639 spr = (struct softpipe_resource *)iview->resource; 640 if (!spr) 641 goto fail_write_all_zero; 642 if (!has_compat_target(spr->base.target, params->tgsi_tex_instr)) 643 goto fail_write_all_zero; 644 645 if (!get_dimensions(iview, spr, params->tgsi_tex_instr, 646 params->format, &width, &height, &depth)) 647 goto fail_write_all_zero; 648 649 stride = util_format_get_stride(spr->base.format, width); 650 651 for (j = 0; j < TGSI_QUAD_SIZE; j++) { 652 int s_coord, t_coord, r_coord; 653 bool just_read = false; 654 655 fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord); 656 if (!bounds_check(width, height, depth, 657 s_coord, t_coord, r_coord)) { 658 int nc = util_format_get_nr_components(params->format); 659 int ival = util_format_is_pure_integer(params->format); 660 int c; 661 for (c = 0; c < 4; c++) { 662 rgba[c][j] = 0; 663 if (c == 3 && nc < 4) { 664 if (ival) 665 ((int32_t *)rgba[c])[j] = 1; 666 else 667 rgba[c][j] = 1.0; 668 } 669 } 670 continue; 671 } 672 673 /* just readback the value for atomic if execmask isn't set */ 674 if (!(params->execmask & (1 << j))) { 675 just_read = true; 676 } 677 678 offset = get_image_offset(spr, iview, params->format, r_coord); 679 data_ptr = (char *)spr->data + offset; 680 681 /* we should see atomic operations on r32 formats */ 682 if (util_format_is_pure_uint(params->format)) 683 handle_op_uint(iview, params, just_read, data_ptr, j, stride, 684 opcode, s_coord, t_coord, rgba, rgba2); 685 else if (util_format_is_pure_sint(params->format)) 686 handle_op_int(iview, params, just_read, data_ptr, j, stride, 687 opcode, s_coord, t_coord, rgba, rgba2); 688 else if (params->format == PIPE_FORMAT_R32_FLOAT && 689 opcode == TGSI_OPCODE_ATOMXCHG) 690 handle_op_r32f_xchg(iview, params, just_read, data_ptr, j, stride, 691 opcode, s_coord, t_coord, rgba); 692 else 693 assert(0); 694 } 695 return; 696fail_write_all_zero: 697 for (j = 0; j < TGSI_QUAD_SIZE; j++) { 698 for (c = 0; c < 4; c++) 699 rgba[c][j] = 0; 700 } 701 return; 702} 703 704static void 705sp_tgsi_get_dims(const struct tgsi_image *image, 706 const struct tgsi_image_params *params, 707 int dims[4]) 708{ 709 struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image; 710 struct pipe_image_view *iview; 711 struct softpipe_resource *spr; 712 int level; 713 714 if (params->unit >= PIPE_MAX_SHADER_IMAGES) 715 return; 716 iview = &sp_img->sp_iview[params->unit]; 717 spr = (struct softpipe_resource *)iview->resource; 718 if (!spr) 719 return; 720 721 if (params->tgsi_tex_instr == TGSI_TEXTURE_BUFFER) { 722 dims[0] = iview->u.buf.size / util_format_get_blocksize(iview->format); 723 dims[1] = dims[2] = dims[3] = 0; 724 return; 725 } 726 727 level = iview->u.tex.level; 728 dims[0] = u_minify(spr->base.width0, level); 729 switch (params->tgsi_tex_instr) { 730 case TGSI_TEXTURE_1D_ARRAY: 731 dims[1] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1; 732 FALLTHROUGH; 733 case TGSI_TEXTURE_1D: 734 return; 735 case TGSI_TEXTURE_2D_ARRAY: 736 dims[2] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1; 737 FALLTHROUGH; 738 case TGSI_TEXTURE_2D: 739 case TGSI_TEXTURE_CUBE: 740 case TGSI_TEXTURE_RECT: 741 dims[1] = u_minify(spr->base.height0, level); 742 return; 743 case TGSI_TEXTURE_3D: 744 dims[1] = u_minify(spr->base.height0, level); 745 dims[2] = u_minify(spr->base.depth0, level); 746 return; 747 case TGSI_TEXTURE_CUBE_ARRAY: 748 dims[1] = u_minify(spr->base.height0, level); 749 dims[2] = (iview->u.tex.last_layer - iview->u.tex.first_layer + 1) / 6; 750 break; 751 default: 752 assert(!"unexpected texture target in sp_get_dims()"); 753 return; 754 } 755} 756 757struct sp_tgsi_image * 758sp_create_tgsi_image(void) 759{ 760 struct sp_tgsi_image *img = CALLOC_STRUCT(sp_tgsi_image); 761 if (!img) 762 return NULL; 763 764 img->base.load = sp_tgsi_load; 765 img->base.store = sp_tgsi_store; 766 img->base.op = sp_tgsi_op; 767 img->base.get_dims = sp_tgsi_get_dims; 768 return img; 769}; 770