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 */ 34 static uint32_t 35 get_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 */ 56 static inline bool 57 has_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 */ 70 static inline bool 71 has_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 */ 81 static inline bool 82 bounds_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 */ 98 static inline bool 99 has_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 146 static bool 147 get_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 186 static void 187 fill_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 */ 202 static void 203 sp_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; 293 fail_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 */ 304 static void 305 sp_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 */ 380 static void 381 handle_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 unsigned 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 */ 497 static void 498 handle_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 unsigned 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 */ 611 static void 612 handle_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 unsigned 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 */ 649 static void 650 sp_tgsi_op(const struct tgsi_image *image, 651 const struct tgsi_image_params *params, 652 unsigned 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; 729 fail_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 737 static void 738 sp_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 790 struct sp_tgsi_image * 791 sp_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