DynamicImage2DHLSL.cpp (31502B)
1 // 2 // Copyright 2019 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // DynamicImage2DHLSL.cpp: Implementation for link and run-time HLSL generation 7 // 8 9 #include "libANGLE/renderer/d3d/DynamicImage2DHLSL.h" 10 11 #include "common/string_utils.h" 12 #include "libANGLE/renderer/d3d/ProgramD3D.h" 13 #include "libANGLE/renderer/d3d/ShaderD3D.h" 14 15 using namespace gl; 16 17 namespace rx 18 { 19 20 namespace 21 { 22 23 enum Image2DHLSLGroup 24 { 25 IMAGE2D_R_FLOAT4, 26 IMAGE2D_MIN = IMAGE2D_R_FLOAT4, 27 IMAGE2D_R_UNORM, 28 IMAGE2D_R_SNORM, 29 IMAGE2D_R_UINT4, 30 IMAGE2D_R_INT4, 31 IMAGE2D_W_FLOAT4, 32 IMAGE2D_W_UNORM, 33 IMAGE2D_W_SNORM, 34 IMAGE2D_W_UINT4, 35 IMAGE2D_W_INT4, 36 IMAGE2D_UNKNOWN, 37 IMAGE2D_MAX = IMAGE2D_UNKNOWN 38 }; 39 40 enum Image2DMethod 41 { 42 IMAGE2DSIZE, 43 IMAGE2DLOAD, 44 IMAGE2DSTORE 45 }; 46 47 Image2DHLSLGroup image2DHLSLGroup(const sh::ShaderVariable &uniform) 48 { 49 GLenum format = uniform.imageUnitFormat; 50 bool readonly = uniform.readonly; 51 switch (uniform.type) 52 { 53 case GL_IMAGE_2D: 54 { 55 switch (format) 56 { 57 case GL_RGBA32F: 58 case GL_RGBA16F: 59 case GL_R32F: 60 return readonly ? IMAGE2D_R_FLOAT4 : IMAGE2D_W_FLOAT4; 61 case GL_RGBA8: 62 return readonly ? IMAGE2D_R_UNORM : IMAGE2D_W_UNORM; 63 case GL_RGBA8_SNORM: 64 return readonly ? IMAGE2D_R_SNORM : IMAGE2D_W_SNORM; 65 default: 66 UNREACHABLE(); 67 return IMAGE2D_UNKNOWN; 68 } 69 } 70 case GL_INT_IMAGE_2D: 71 { 72 switch (format) 73 { 74 case GL_RGBA32I: 75 case GL_RGBA16I: 76 case GL_RGBA8I: 77 case GL_R32I: 78 return readonly ? IMAGE2D_R_INT4 : IMAGE2D_W_INT4; 79 default: 80 UNREACHABLE(); 81 return IMAGE2D_UNKNOWN; 82 } 83 } 84 case GL_UNSIGNED_INT_IMAGE_2D: 85 { 86 switch (format) 87 { 88 case GL_RGBA32UI: 89 case GL_RGBA16UI: 90 case GL_RGBA8UI: 91 case GL_R32UI: 92 return readonly ? IMAGE2D_R_UINT4 : IMAGE2D_W_UINT4; 93 default: 94 UNREACHABLE(); 95 return IMAGE2D_UNKNOWN; 96 } 97 } 98 default: 99 UNREACHABLE(); 100 return IMAGE2D_UNKNOWN; 101 } 102 } 103 104 std::string Image2DHLSLGroupSuffix(Image2DHLSLGroup group) 105 { 106 switch (group) 107 { 108 case IMAGE2D_R_FLOAT4: 109 return "2D"; 110 case IMAGE2D_R_UNORM: 111 return "2D_unorm_float4_"; 112 case IMAGE2D_R_SNORM: 113 return "2D_snorm_float4_"; 114 case IMAGE2D_R_UINT4: 115 return "2D_uint4_"; 116 case IMAGE2D_R_INT4: 117 return "2D_int4_"; 118 case IMAGE2D_W_FLOAT4: 119 return "RW2D_float4_"; 120 case IMAGE2D_W_UNORM: 121 return "RW2D_unorm_float4_"; 122 case IMAGE2D_W_SNORM: 123 return "RW2D_snorm_float4_"; 124 case IMAGE2D_W_UINT4: 125 return "RW2D_uint4_"; 126 case IMAGE2D_W_INT4: 127 return "RW2D_int4_"; 128 default: 129 UNREACHABLE(); 130 } 131 132 return "<unknown group type>"; 133 } 134 135 std::string Image2DHLSLTextureString(Image2DHLSLGroup group, 136 gl::TextureType type, 137 bool rasterOrdered) 138 { 139 std::string textureString; 140 switch (group) 141 { 142 case IMAGE2D_R_FLOAT4: 143 case IMAGE2D_R_UNORM: 144 case IMAGE2D_R_SNORM: 145 case IMAGE2D_R_UINT4: 146 case IMAGE2D_R_INT4: 147 break; 148 case IMAGE2D_W_FLOAT4: 149 case IMAGE2D_W_UNORM: 150 case IMAGE2D_W_SNORM: 151 case IMAGE2D_W_UINT4: 152 case IMAGE2D_W_INT4: 153 textureString += rasterOrdered ? "RasterizerOrdered" : "RW"; 154 break; 155 default: 156 UNREACHABLE(); 157 } 158 159 textureString += "Texture"; 160 161 switch (type) 162 { 163 case gl::TextureType::_2D: 164 textureString += "2D"; 165 break; 166 case gl::TextureType::_3D: 167 textureString += "3D"; 168 break; 169 case gl::TextureType::_2DArray: 170 textureString += "2DArray"; 171 break; 172 default: 173 UNREACHABLE(); 174 } 175 176 switch (group) 177 { 178 case IMAGE2D_R_FLOAT4: 179 case IMAGE2D_W_FLOAT4: 180 textureString += "<float4>"; 181 break; 182 case IMAGE2D_R_UNORM: 183 case IMAGE2D_W_UNORM: 184 textureString += "<unorm float4>"; 185 break; 186 case IMAGE2D_R_SNORM: 187 case IMAGE2D_W_SNORM: 188 textureString += "<snorm float4>"; 189 break; 190 case IMAGE2D_R_UINT4: 191 case IMAGE2D_W_UINT4: 192 textureString += "<uint4>"; 193 break; 194 case IMAGE2D_R_INT4: 195 case IMAGE2D_W_INT4: 196 textureString += "<int4>"; 197 break; 198 default: 199 UNREACHABLE(); 200 } 201 202 return textureString; 203 } 204 205 std::string Image2DHLSLGroupOffsetPrefix(Image2DHLSLGroup group) 206 { 207 switch (group) 208 { 209 case IMAGE2D_R_FLOAT4: 210 case IMAGE2D_R_UNORM: 211 case IMAGE2D_R_SNORM: 212 case IMAGE2D_R_UINT4: 213 case IMAGE2D_R_INT4: 214 return "readonlyImageIndexOffset"; 215 case IMAGE2D_W_FLOAT4: 216 case IMAGE2D_W_UNORM: 217 case IMAGE2D_W_SNORM: 218 case IMAGE2D_W_UINT4: 219 case IMAGE2D_W_INT4: 220 return "imageIndexOffset"; 221 default: 222 UNREACHABLE(); 223 } 224 225 return "<unknown group type>"; 226 } 227 228 std::string Image2DHLSLGroupDeclarationPrefix(Image2DHLSLGroup group) 229 { 230 switch (group) 231 { 232 case IMAGE2D_R_FLOAT4: 233 case IMAGE2D_R_UNORM: 234 case IMAGE2D_R_SNORM: 235 case IMAGE2D_R_UINT4: 236 case IMAGE2D_R_INT4: 237 return "readonlyImages"; 238 case IMAGE2D_W_FLOAT4: 239 case IMAGE2D_W_UNORM: 240 case IMAGE2D_W_SNORM: 241 case IMAGE2D_W_UINT4: 242 case IMAGE2D_W_INT4: 243 return "images"; 244 default: 245 UNREACHABLE(); 246 } 247 248 return "<unknown group type>"; 249 } 250 251 std::string Image2DHLSLGroupRegisterSuffix(Image2DHLSLGroup group) 252 { 253 switch (group) 254 { 255 case IMAGE2D_R_FLOAT4: 256 case IMAGE2D_R_UNORM: 257 case IMAGE2D_R_SNORM: 258 case IMAGE2D_R_UINT4: 259 case IMAGE2D_R_INT4: 260 return "t"; 261 case IMAGE2D_W_FLOAT4: 262 case IMAGE2D_W_UNORM: 263 case IMAGE2D_W_SNORM: 264 case IMAGE2D_W_UINT4: 265 case IMAGE2D_W_INT4: 266 return "u"; 267 default: 268 UNREACHABLE(); 269 } 270 271 return "<unknown group type>"; 272 } 273 274 std::string Image2DHLSLGroupFunctionName(Image2DHLSLGroup group, Image2DMethod method) 275 { 276 std::string name = "gl_image"; 277 name += Image2DHLSLGroupSuffix(group); 278 switch (method) 279 { 280 case IMAGE2DSIZE: 281 name += "Size"; 282 break; 283 case IMAGE2DLOAD: 284 name += "Load"; 285 break; 286 case IMAGE2DSTORE: 287 name += "Store"; 288 break; 289 default: 290 UNREACHABLE(); 291 } 292 293 return name; 294 } 295 296 std::string getImage2DGroupReturnType(Image2DHLSLGroup group, Image2DMethod method) 297 { 298 switch (method) 299 { 300 case IMAGE2DSIZE: 301 return "int2"; 302 case IMAGE2DLOAD: 303 switch (group) 304 { 305 case IMAGE2D_R_FLOAT4: 306 case IMAGE2D_R_UNORM: 307 case IMAGE2D_R_SNORM: 308 case IMAGE2D_W_FLOAT4: 309 case IMAGE2D_W_UNORM: 310 case IMAGE2D_W_SNORM: 311 return "float4"; 312 case IMAGE2D_R_UINT4: 313 case IMAGE2D_W_UINT4: 314 return "uint4"; 315 case IMAGE2D_R_INT4: 316 case IMAGE2D_W_INT4: 317 return "int4"; 318 default: 319 UNREACHABLE(); 320 return "unknown group type"; 321 } 322 case IMAGE2DSTORE: 323 return "void"; 324 default: 325 UNREACHABLE(); 326 return "unknown image method"; 327 } 328 } 329 330 std::string getImageMetadata(Image2DHLSLGroup group) 331 { 332 switch (group) 333 { 334 case IMAGE2D_R_FLOAT4: 335 case IMAGE2D_R_UNORM: 336 case IMAGE2D_R_SNORM: 337 case IMAGE2D_R_UINT4: 338 case IMAGE2D_R_INT4: 339 return "readonlyImageMetadata[imageIndex - readonlyImageIndexStart]"; 340 case IMAGE2D_W_FLOAT4: 341 case IMAGE2D_W_UNORM: 342 case IMAGE2D_W_SNORM: 343 case IMAGE2D_W_UINT4: 344 case IMAGE2D_W_INT4: 345 return "imageMetadata[imageIndex - imageIndexStart]"; 346 default: 347 UNREACHABLE(); 348 return "unknown image method"; 349 } 350 } 351 352 void OutputImage2DFunctionArgumentList(std::ostringstream &out, 353 Image2DHLSLGroup group, 354 Image2DMethod method) 355 { 356 out << "uint imageIndex"; 357 358 if (method == IMAGE2DLOAD || method == IMAGE2DSTORE) 359 { 360 out << ", int2 p"; 361 if (method == IMAGE2DSTORE) 362 { 363 switch (group) 364 { 365 case IMAGE2D_R_FLOAT4: 366 case IMAGE2D_R_UNORM: 367 case IMAGE2D_R_SNORM: 368 case IMAGE2D_W_FLOAT4: 369 case IMAGE2D_W_UNORM: 370 case IMAGE2D_W_SNORM: 371 out << ", float4 data"; 372 break; 373 case IMAGE2D_R_UINT4: 374 case IMAGE2D_W_UINT4: 375 out << ", uint4 data"; 376 break; 377 case IMAGE2D_R_INT4: 378 case IMAGE2D_W_INT4: 379 out << ", int4 data"; 380 break; 381 default: 382 UNREACHABLE(); 383 } 384 } 385 } 386 } 387 388 void OutputImage2DSizeFunction(std::ostringstream &out, 389 Image2DHLSLGroup textureGroup, 390 unsigned int totalCount, 391 unsigned int texture2DCount, 392 unsigned int texture3DCount, 393 unsigned int texture2DArrayCount, 394 const std::string &offsetStr, 395 const std::string &declarationStr) 396 { 397 out << getImage2DGroupReturnType(textureGroup, IMAGE2DSIZE) << " " 398 << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE) << "("; 399 OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSIZE); 400 out << ")\n" 401 "{\n"; 402 out << " uint width, height;\n"; 403 404 if (texture2DCount > 0) 405 { 406 if (texture2DCount == totalCount) 407 { 408 out << " const uint index = imageIndex - " << offsetStr << "2D;\n"; 409 out << " " << declarationStr << "2D[index].GetDimensions(width, height);\n"; 410 } 411 else 412 { 413 out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr 414 << "2D + " << texture2DCount << ")\n"; 415 out << " {\n"; 416 out << " const uint index = imageIndex - " << offsetStr << "2D;\n"; 417 out << " " << declarationStr << "2D[index].GetDimensions(width, height);\n"; 418 out << " }\n"; 419 } 420 } 421 422 if (texture3DCount > 0) 423 { 424 if (texture3DCount == totalCount) 425 { 426 out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; 427 out << " uint depth;\n"; 428 out << " " << declarationStr << "3D[index].GetDimensions(width, height, depth);\n"; 429 } 430 else 431 { 432 if (texture2DArrayCount == 0) 433 { 434 out << " else\n"; 435 } 436 else 437 { 438 if (texture2DCount == 0) 439 { 440 out << " if "; 441 } 442 else 443 { 444 out << " else if"; 445 } 446 out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr 447 << "3D + " << texture3DCount << ")\n"; 448 } 449 out << " {\n"; 450 out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; 451 out << " uint depth;\n"; 452 out << " " << declarationStr 453 << "3D[index].GetDimensions(width, height, depth);\n"; 454 out << " }\n"; 455 } 456 } 457 458 if (texture2DArrayCount > 0) 459 { 460 if (texture2DArrayCount == totalCount) 461 { 462 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; 463 out << " uint depth;\n"; 464 out << " " << declarationStr 465 << "2DArray[index].GetDimensions(width, height, depth);\n"; 466 } 467 else 468 { 469 out << " else\n"; 470 out << " {\n"; 471 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; 472 out << " uint depth;\n"; 473 out << " " << declarationStr 474 << "2DArray[index].GetDimensions(width, height, depth);\n"; 475 out << " }\n"; 476 } 477 } 478 out << " return int2(width, height);\n"; 479 480 out << "}\n"; 481 } 482 483 void OutputImage2DLoadFunction(std::ostringstream &out, 484 Image2DHLSLGroup textureGroup, 485 unsigned int totalCount, 486 unsigned int texture2DCount, 487 unsigned int texture3DCount, 488 unsigned int texture2DArrayCount, 489 const std::string &offsetStr, 490 const std::string &declarationStr) 491 { 492 out << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " " 493 << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DLOAD) << "("; 494 OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DLOAD); 495 out << ")\n" 496 "{\n"; 497 498 out << " " << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " result;\n"; 499 500 if (texture2DCount > 0) 501 { 502 if (texture2DCount == totalCount) 503 { 504 out << " const uint index = imageIndex - " << offsetStr << "2D;\n"; 505 out << " result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n"; 506 } 507 else 508 { 509 out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr 510 << "2D + " << texture2DCount << ")\n"; 511 out << " {\n"; 512 out << " const uint index = imageIndex - " << offsetStr << "2D;\n"; 513 out << " result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n"; 514 out << " }\n"; 515 } 516 } 517 518 if (texture3DCount > 0) 519 { 520 if (texture3DCount == totalCount) 521 { 522 out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; 523 out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, " 524 << getImageMetadata(textureGroup) << ".layer)];\n"; 525 } 526 else 527 { 528 if (texture2DArrayCount == 0) 529 { 530 out << " else\n"; 531 } 532 else 533 { 534 if (texture2DCount == 0) 535 { 536 out << " if "; 537 } 538 else 539 { 540 out << " else if"; 541 } 542 out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr 543 << "3D + " << texture3DCount << ")\n"; 544 } 545 out << " {\n"; 546 out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; 547 out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, " 548 << getImageMetadata(textureGroup) << ".layer)];\n"; 549 out << " }\n"; 550 } 551 } 552 553 if (texture2DArrayCount > 0) 554 { 555 if (texture2DArrayCount == totalCount) 556 { 557 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; 558 out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, " 559 << getImageMetadata(textureGroup) << ".layer)];\n"; 560 } 561 else 562 { 563 out << " else\n"; 564 out << " {\n"; 565 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; 566 out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, " 567 << getImageMetadata(textureGroup) << ".layer)];\n"; 568 out << " }\n"; 569 } 570 } 571 572 out << " return result;\n"; 573 out << "}\n"; 574 } 575 576 void OutputImage2DStoreFunction(std::ostringstream &out, 577 Image2DHLSLGroup textureGroup, 578 unsigned int totalCount, 579 unsigned int texture2DCount, 580 unsigned int texture3DCount, 581 unsigned int texture2DArrayCount, 582 const std::string &offsetStr, 583 const std::string &declarationStr) 584 { 585 out << getImage2DGroupReturnType(textureGroup, IMAGE2DSTORE) << " " 586 << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSTORE) << "("; 587 OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSTORE); 588 out << ")\n" 589 "{\n"; 590 591 if (texture2DCount > 0) 592 { 593 if (texture2DCount == totalCount) 594 { 595 out << " const uint index = imageIndex - " << offsetStr << "2D;\n"; 596 out << " " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n"; 597 } 598 else 599 { 600 out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr 601 << "2D + " << texture2DCount << ")\n"; 602 out << " {\n"; 603 out << " const uint index = imageIndex - " << offsetStr << "2D;\n"; 604 out << " " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n"; 605 out << " }\n"; 606 } 607 } 608 609 if (texture3DCount > 0) 610 { 611 if (texture3DCount == totalCount) 612 { 613 out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; 614 out << " " << declarationStr << "3D[index][uint3(p.x, p.y, " 615 << getImageMetadata(textureGroup) << ".layer)] = data;\n"; 616 } 617 else 618 { 619 if (texture2DArrayCount == 0) 620 { 621 out << " else\n"; 622 } 623 else 624 { 625 if (texture2DCount == 0) 626 { 627 out << " if "; 628 } 629 else 630 { 631 out << " else if"; 632 } 633 out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr 634 << "3D + " << texture3DCount << ")\n"; 635 } 636 out << " {\n"; 637 out << " const uint index = imageIndex - " << offsetStr << "3D;\n"; 638 out << " " << declarationStr << "3D[index][uint3(p.x, p.y, " 639 << getImageMetadata(textureGroup) << ".layer)] = data;\n"; 640 out << " }\n"; 641 } 642 } 643 644 if (texture2DArrayCount > 0) 645 { 646 if (texture2DArrayCount == totalCount) 647 { 648 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; 649 out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, " 650 << getImageMetadata(textureGroup) << ".layer)] = data;\n"; 651 } 652 else 653 { 654 out << " else\n"; 655 out << " {\n"; 656 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n"; 657 out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, " 658 << getImageMetadata(textureGroup) << ".layer)] = data;\n"; 659 out << " }\n"; 660 } 661 } 662 663 out << "}\n"; 664 } 665 666 unsigned int *GetImage2DRegisterIndex(Image2DHLSLGroup textureGroup, 667 unsigned int *groupTextureRegisterIndex, 668 unsigned int *groupRWTextureRegisterIndex) 669 { 670 switch (textureGroup) 671 { 672 case IMAGE2D_R_FLOAT4: 673 case IMAGE2D_R_UNORM: 674 case IMAGE2D_R_SNORM: 675 case IMAGE2D_R_UINT4: 676 case IMAGE2D_R_INT4: 677 return groupTextureRegisterIndex; 678 case IMAGE2D_W_FLOAT4: 679 case IMAGE2D_W_UNORM: 680 case IMAGE2D_W_SNORM: 681 case IMAGE2D_W_UINT4: 682 case IMAGE2D_W_INT4: 683 return groupRWTextureRegisterIndex; 684 default: 685 UNREACHABLE(); 686 return nullptr; 687 } 688 } 689 690 void OutputHLSLImage2DUniformGroup(ProgramD3D &programD3D, 691 const gl::ProgramState &programData, 692 gl::ShaderType shaderType, 693 std::ostringstream &out, 694 const Image2DHLSLGroup textureGroup, 695 const std::vector<sh::ShaderVariable> &group, 696 const gl::ImageUnitTextureTypeMap &image2DBindLayout, 697 unsigned int baseUAVRegister, 698 unsigned int *groupTextureRegisterIndex, 699 unsigned int *groupRWTextureRegisterIndex, 700 unsigned int *image2DTexture3D, 701 unsigned int *image2DTexture2DArray, 702 unsigned int *image2DTexture2D) 703 { 704 if (group.empty()) 705 { 706 return; 707 } 708 709 unsigned int texture2DCount = 0, texture3DCount = 0, texture2DArrayCount = 0; 710 bool texture2DRasterOrdered = false, texture3DRasterOrdered = false, 711 texture2DArrayRasterOrdered = false; 712 for (const sh::ShaderVariable &uniform : group) 713 { 714 if (!programD3D.hasNamedUniform(uniform.name)) 715 { 716 continue; 717 } 718 for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++) 719 { 720 switch (image2DBindLayout.at(uniform.binding + index)) 721 { 722 case gl::TextureType::_2D: 723 texture2DCount++; 724 texture2DRasterOrdered |= uniform.rasterOrdered; 725 break; 726 case gl::TextureType::_3D: 727 texture3DCount++; 728 texture3DRasterOrdered |= uniform.rasterOrdered; 729 break; 730 case gl::TextureType::_2DArray: 731 case gl::TextureType::CubeMap: 732 texture2DArrayCount++; 733 texture2DArrayRasterOrdered |= uniform.rasterOrdered; 734 break; 735 default: 736 UNREACHABLE(); 737 } 738 } 739 } 740 741 unsigned int totalCount = texture2DCount + texture3DCount + texture2DArrayCount; 742 unsigned int *image2DRegisterIndex = GetImage2DRegisterIndex( 743 textureGroup, groupTextureRegisterIndex, groupRWTextureRegisterIndex); 744 unsigned int texture2DRegisterIndex = *image2DRegisterIndex; 745 unsigned int texture3DRegisterIndex = texture2DRegisterIndex + texture2DCount; 746 unsigned int texture2DArrayRegisterIndex = texture3DRegisterIndex + texture3DCount; 747 *image2DRegisterIndex += totalCount; 748 749 std::string offsetStr = 750 Image2DHLSLGroupOffsetPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup); 751 std::string declarationStr = 752 Image2DHLSLGroupDeclarationPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup); 753 std::string registerStr = Image2DHLSLGroupRegisterSuffix(textureGroup); 754 if (texture2DCount > 0) 755 { 756 out << "static const uint " << offsetStr << "2D = " << texture2DRegisterIndex << ";\n"; 757 out << "uniform " 758 << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2D, texture2DRasterOrdered) 759 << " " << declarationStr << "2D[" << texture2DCount << "]" 760 << " : register(" << registerStr << baseUAVRegister + texture2DRegisterIndex << ");\n"; 761 } 762 if (texture3DCount > 0) 763 { 764 out << "static const uint " << offsetStr << "3D = " << texture3DRegisterIndex << ";\n"; 765 out << "uniform " 766 << Image2DHLSLTextureString(textureGroup, gl::TextureType::_3D, texture3DRasterOrdered) 767 << " " << declarationStr << "3D[" << texture3DCount << "]" 768 << " : register(" << registerStr << baseUAVRegister + texture3DRegisterIndex << ");\n"; 769 } 770 if (texture2DArrayCount > 0) 771 { 772 out << "static const uint " << offsetStr << "2DArray = " << texture2DArrayRegisterIndex 773 << ";\n"; 774 out << "uniform " 775 << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2DArray, 776 texture2DArrayRasterOrdered) 777 << " " << declarationStr << "2DArray[" << texture2DArrayCount << "]" 778 << " : register(" << registerStr << baseUAVRegister + texture2DArrayRegisterIndex 779 << ");\n"; 780 } 781 for (const sh::ShaderVariable &uniform : group) 782 { 783 if (!programD3D.hasNamedUniform(uniform.name)) 784 { 785 continue; 786 } 787 788 out << "static const uint " << DecorateVariable(uniform.name) 789 << ArrayIndexString(uniform.arraySizes) << " = {"; 790 for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++) 791 { 792 if (index > 0) 793 { 794 out << ", "; 795 } 796 switch (image2DBindLayout.at(uniform.binding + index)) 797 { 798 case gl::TextureType::_2D: 799 { 800 out << texture2DRegisterIndex; 801 programD3D.assignImage2DRegisters(shaderType, texture2DRegisterIndex, 802 uniform.binding + index, uniform.readonly); 803 texture2DRegisterIndex++; 804 break; 805 } 806 case gl::TextureType::_3D: 807 { 808 out << texture3DRegisterIndex; 809 programD3D.assignImage2DRegisters(shaderType, texture3DRegisterIndex, 810 uniform.binding + index, uniform.readonly); 811 texture3DRegisterIndex++; 812 break; 813 } 814 case gl::TextureType::_2DArray: 815 case gl::TextureType::CubeMap: 816 { 817 out << texture2DArrayRegisterIndex; 818 programD3D.assignImage2DRegisters(shaderType, texture2DArrayRegisterIndex, 819 uniform.binding + index, uniform.readonly); 820 texture2DArrayRegisterIndex++; 821 break; 822 } 823 default: 824 UNREACHABLE(); 825 } 826 } 827 out << "};\n"; 828 } 829 830 gl::Shader *shaderGL = programData.getAttachedShader(shaderType); 831 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shaderGL); 832 833 if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE))) 834 { 835 OutputImage2DSizeFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount, 836 texture2DArrayCount, offsetStr, declarationStr); 837 } 838 if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DLOAD))) 839 { 840 OutputImage2DLoadFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount, 841 texture2DArrayCount, offsetStr, declarationStr); 842 } 843 if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSTORE))) 844 { 845 OutputImage2DStoreFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount, 846 texture2DArrayCount, offsetStr, declarationStr); 847 } 848 } 849 850 // kImage2DFunctionString must be the same as outputHLSL. 851 constexpr const char kImage2DFunctionString[] = "// @@ IMAGE2D DECLARATION FUNCTION STRING @@"; 852 } // anonymous namespace 853 854 std::string GenerateShaderForImage2DBindSignature( 855 ProgramD3D &programD3D, 856 const gl::ProgramState &programData, 857 gl::ShaderType shaderType, 858 const std::string &shaderHLSL, 859 std::vector<sh::ShaderVariable> &image2DUniforms, 860 const gl::ImageUnitTextureTypeMap &image2DBindLayout, 861 unsigned int baseUAVRegister) 862 { 863 std::vector<std::vector<sh::ShaderVariable>> groupedImage2DUniforms(IMAGE2D_MAX + 1); 864 unsigned int image2DTexture3DCount = 0, image2DTexture2DArrayCount = 0; 865 for (sh::ShaderVariable &image2D : image2DUniforms) 866 { 867 for (unsigned int index = 0; index < image2D.getArraySizeProduct(); index++) 868 { 869 // Any image variable declared without a binding qualifier is initially bound to unit 870 // zero. 871 if (image2D.binding == -1) 872 { 873 image2D.binding = 0; 874 } 875 switch (image2DBindLayout.at(image2D.binding + index)) 876 { 877 case gl::TextureType::_2D: 878 break; 879 case gl::TextureType::_3D: 880 image2DTexture3DCount++; 881 break; 882 case gl::TextureType::_2DArray: 883 case gl::TextureType::CubeMap: 884 image2DTexture2DArrayCount++; 885 break; 886 default: 887 UNREACHABLE(); 888 } 889 } 890 Image2DHLSLGroup group = image2DHLSLGroup(image2D); 891 groupedImage2DUniforms[group].push_back(image2D); 892 } 893 894 gl::Shader *shaderGL = programData.getAttachedShader(shaderType); 895 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shaderGL); 896 unsigned int groupTextureRegisterIndex = shaderD3D->getReadonlyImage2DRegisterIndex(); 897 unsigned int groupRWTextureRegisterIndex = shaderD3D->getImage2DRegisterIndex(); 898 unsigned int image2DTexture3DIndex = 0; 899 unsigned int image2DTexture2DArrayIndex = image2DTexture3DCount; 900 unsigned int image2DTexture2DIndex = image2DTexture3DCount + image2DTexture2DArrayCount; 901 std::ostringstream out; 902 903 for (int groupId = IMAGE2D_MIN; groupId < IMAGE2D_MAX; ++groupId) 904 { 905 OutputHLSLImage2DUniformGroup( 906 programD3D, programData, shaderType, out, Image2DHLSLGroup(groupId), 907 groupedImage2DUniforms[groupId], image2DBindLayout, baseUAVRegister, 908 &groupTextureRegisterIndex, &groupRWTextureRegisterIndex, &image2DTexture3DIndex, 909 &image2DTexture2DArrayIndex, &image2DTexture2DIndex); 910 } 911 912 std::string result = shaderHLSL; 913 bool success = angle::ReplaceSubstring(&result, kImage2DFunctionString, out.str()); 914 ASSERT(success); 915 916 return result; 917 } 918 919 } // namespace rx