• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
image2DHLSLGroup(const sh::ShaderVariable & uniform)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 
Image2DHLSLGroupSuffix(Image2DHLSLGroup group)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 
Image2DHLSLTextureString(Image2DHLSLGroup group,gl::TextureType type,bool rasterOrdered)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 
Image2DHLSLGroupOffsetPrefix(Image2DHLSLGroup group)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 
Image2DHLSLGroupDeclarationPrefix(Image2DHLSLGroup group)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 
Image2DHLSLGroupRegisterSuffix(Image2DHLSLGroup group)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 
Image2DHLSLGroupFunctionName(Image2DHLSLGroup group,Image2DMethod method)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 
getImage2DGroupReturnType(Image2DHLSLGroup group,Image2DMethod method)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 
getImageMetadata(Image2DHLSLGroup group)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 
OutputImage2DFunctionArgumentList(std::ostringstream & out,Image2DHLSLGroup group,Image2DMethod method)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 
OutputImage2DSizeFunction(std::ostringstream & out,Image2DHLSLGroup textureGroup,unsigned int totalCount,unsigned int texture2DCount,unsigned int texture3DCount,unsigned int texture2DArrayCount,const std::string & offsetStr,const std::string & declarationStr)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 
OutputImage2DLoadFunction(std::ostringstream & out,Image2DHLSLGroup textureGroup,unsigned int totalCount,unsigned int texture2DCount,unsigned int texture3DCount,unsigned int texture2DArrayCount,const std::string & offsetStr,const std::string & declarationStr)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 
OutputImage2DStoreFunction(std::ostringstream & out,Image2DHLSLGroup textureGroup,unsigned int totalCount,unsigned int texture2DCount,unsigned int texture3DCount,unsigned int texture2DArrayCount,const std::string & offsetStr,const std::string & declarationStr)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 
GetImage2DRegisterIndex(Image2DHLSLGroup textureGroup,unsigned int * groupTextureRegisterIndex,unsigned int * groupRWTextureRegisterIndex)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 
OutputHLSLImage2DUniformGroup(ProgramD3D & programD3D,const gl::ProgramState & programData,gl::ShaderType shaderType,std::ostringstream & out,const Image2DHLSLGroup textureGroup,const std::vector<sh::ShaderVariable> & group,const gl::ImageUnitTextureTypeMap & image2DBindLayout,unsigned int baseUAVRegister,unsigned int * groupTextureRegisterIndex,unsigned int * groupRWTextureRegisterIndex,unsigned int * image2DTexture3D,unsigned int * image2DTexture2DArray,unsigned int * image2DTexture2D)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 
GenerateShaderForImage2DBindSignature(ProgramD3D & programD3D,const gl::ProgramState & programData,gl::ShaderType shaderType,const std::string & shaderHLSL,std::vector<sh::ShaderVariable> & image2DUniforms,const gl::ImageUnitTextureTypeMap & image2DBindLayout,unsigned int baseUAVRegister)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
920