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