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