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