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,bool getDimensionsIgnoresBaseLevel)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 bool getDimensionsIgnoresBaseLevel)
395 {
396 out << getImage2DGroupReturnType(textureGroup, IMAGE2DSIZE) << " "
397 << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE) << "(";
398 OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSIZE);
399 out << ")\n"
400 "{\n";
401 out << " uint width, height;\n";
402
403 if (texture2DCount > 0)
404 {
405 if (texture2DCount == totalCount)
406 {
407 out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
408 if (getDimensionsIgnoresBaseLevel)
409 {
410 out << " uint levelCount;\n";
411 out << " const uint level = " << getImageMetadata(textureGroup) << ".level;\n";
412 out << " " << declarationStr
413 << "2D[index].GetDimensions(level, width, height, levelCount);\n";
414 }
415 else
416 {
417 out << " " << declarationStr << "2D[index].GetDimensions(width, height);\n";
418 }
419 }
420 else
421 {
422 out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
423 << "2D + " << texture2DCount << ")\n";
424 out << " {\n";
425 out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
426 out << " " << declarationStr << "2D[index].GetDimensions(width, height);\n";
427 out << " }\n";
428 }
429 }
430
431 if (texture3DCount > 0)
432 {
433 if (texture3DCount == totalCount)
434 {
435 out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
436 out << " uint depth;\n";
437 out << " " << declarationStr << "3D[index].GetDimensions(width, height, depth);\n";
438 }
439 else
440 {
441 if (texture2DArrayCount == 0)
442 {
443 out << " else\n";
444 }
445 else
446 {
447 if (texture2DCount == 0)
448 {
449 out << " if ";
450 }
451 else
452 {
453 out << " else if";
454 }
455 out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
456 << "3D + " << texture3DCount << ")\n";
457 }
458 out << " {\n";
459 out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
460 out << " uint depth;\n";
461 out << " " << declarationStr
462 << "3D[index].GetDimensions(width, height, depth);\n";
463 out << " }\n";
464 }
465 }
466
467 if (texture2DArrayCount > 0)
468 {
469 if (texture2DArrayCount == totalCount)
470 {
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 }
476 else
477 {
478 out << " else\n";
479 out << " {\n";
480 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
481 out << " uint depth;\n";
482 out << " " << declarationStr
483 << "2DArray[index].GetDimensions(width, height, depth);\n";
484 out << " }\n";
485 }
486 }
487 out << " return int2(width, height);\n";
488
489 out << "}\n";
490 }
491
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)492 void OutputImage2DLoadFunction(std::ostringstream &out,
493 Image2DHLSLGroup textureGroup,
494 unsigned int totalCount,
495 unsigned int texture2DCount,
496 unsigned int texture3DCount,
497 unsigned int texture2DArrayCount,
498 const std::string &offsetStr,
499 const std::string &declarationStr)
500 {
501 out << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " "
502 << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DLOAD) << "(";
503 OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DLOAD);
504 out << ")\n"
505 "{\n";
506
507 out << " " << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " result;\n";
508
509 if (texture2DCount > 0)
510 {
511 if (texture2DCount == totalCount)
512 {
513 out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
514 out << " result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n";
515 }
516 else
517 {
518 out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
519 << "2D + " << texture2DCount << ")\n";
520 out << " {\n";
521 out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
522 out << " result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n";
523 out << " }\n";
524 }
525 }
526
527 if (texture3DCount > 0)
528 {
529 if (texture3DCount == totalCount)
530 {
531 out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
532 out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, "
533 << getImageMetadata(textureGroup) << ".layer)];\n";
534 }
535 else
536 {
537 if (texture2DArrayCount == 0)
538 {
539 out << " else\n";
540 }
541 else
542 {
543 if (texture2DCount == 0)
544 {
545 out << " if ";
546 }
547 else
548 {
549 out << " else if";
550 }
551 out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
552 << "3D + " << texture3DCount << ")\n";
553 }
554 out << " {\n";
555 out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
556 out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, "
557 << getImageMetadata(textureGroup) << ".layer)];\n";
558 out << " }\n";
559 }
560 }
561
562 if (texture2DArrayCount > 0)
563 {
564 if (texture2DArrayCount == totalCount)
565 {
566 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
567 out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
568 << getImageMetadata(textureGroup) << ".layer)];\n";
569 }
570 else
571 {
572 out << " else\n";
573 out << " {\n";
574 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
575 out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
576 << getImageMetadata(textureGroup) << ".layer)];\n";
577 out << " }\n";
578 }
579 }
580
581 out << " return result;\n";
582 out << "}\n";
583 }
584
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)585 void OutputImage2DStoreFunction(std::ostringstream &out,
586 Image2DHLSLGroup textureGroup,
587 unsigned int totalCount,
588 unsigned int texture2DCount,
589 unsigned int texture3DCount,
590 unsigned int texture2DArrayCount,
591 const std::string &offsetStr,
592 const std::string &declarationStr)
593 {
594 out << getImage2DGroupReturnType(textureGroup, IMAGE2DSTORE) << " "
595 << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSTORE) << "(";
596 OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSTORE);
597 out << ")\n"
598 "{\n";
599
600 if (texture2DCount > 0)
601 {
602 if (texture2DCount == totalCount)
603 {
604 out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
605 out << " " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n";
606 }
607 else
608 {
609 out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
610 << "2D + " << texture2DCount << ")\n";
611 out << " {\n";
612 out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
613 out << " " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n";
614 out << " }\n";
615 }
616 }
617
618 if (texture3DCount > 0)
619 {
620 if (texture3DCount == totalCount)
621 {
622 out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
623 out << " " << declarationStr << "3D[index][uint3(p.x, p.y, "
624 << getImageMetadata(textureGroup) << ".layer)] = data;\n";
625 }
626 else
627 {
628 if (texture2DArrayCount == 0)
629 {
630 out << " else\n";
631 }
632 else
633 {
634 if (texture2DCount == 0)
635 {
636 out << " if ";
637 }
638 else
639 {
640 out << " else if";
641 }
642 out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
643 << "3D + " << texture3DCount << ")\n";
644 }
645 out << " {\n";
646 out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
647 out << " " << declarationStr << "3D[index][uint3(p.x, p.y, "
648 << getImageMetadata(textureGroup) << ".layer)] = data;\n";
649 out << " }\n";
650 }
651 }
652
653 if (texture2DArrayCount > 0)
654 {
655 if (texture2DArrayCount == totalCount)
656 {
657 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
658 out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
659 << getImageMetadata(textureGroup) << ".layer)] = data;\n";
660 }
661 else
662 {
663 out << " else\n";
664 out << " {\n";
665 out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
666 out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
667 << getImageMetadata(textureGroup) << ".layer)] = data;\n";
668 out << " }\n";
669 }
670 }
671
672 out << "}\n";
673 }
674
GetImage2DRegisterIndex(Image2DHLSLGroup textureGroup,unsigned int * groupTextureRegisterIndex,unsigned int * groupRWTextureRegisterIndex)675 unsigned int *GetImage2DRegisterIndex(Image2DHLSLGroup textureGroup,
676 unsigned int *groupTextureRegisterIndex,
677 unsigned int *groupRWTextureRegisterIndex)
678 {
679 switch (textureGroup)
680 {
681 case IMAGE2D_R_FLOAT4:
682 case IMAGE2D_R_UNORM:
683 case IMAGE2D_R_SNORM:
684 case IMAGE2D_R_UINT4:
685 case IMAGE2D_R_INT4:
686 return groupTextureRegisterIndex;
687 case IMAGE2D_W_FLOAT4:
688 case IMAGE2D_W_UNORM:
689 case IMAGE2D_W_SNORM:
690 case IMAGE2D_W_UINT4:
691 case IMAGE2D_W_INT4:
692 return groupRWTextureRegisterIndex;
693 default:
694 UNREACHABLE();
695 return nullptr;
696 }
697 }
698
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)699 void OutputHLSLImage2DUniformGroup(ProgramD3D &programD3D,
700 const gl::ProgramState &programData,
701 gl::ShaderType shaderType,
702 std::ostringstream &out,
703 const Image2DHLSLGroup textureGroup,
704 const std::vector<sh::ShaderVariable> &group,
705 const gl::ImageUnitTextureTypeMap &image2DBindLayout,
706 unsigned int *groupTextureRegisterIndex,
707 unsigned int *groupRWTextureRegisterIndex,
708 unsigned int *image2DTexture3D,
709 unsigned int *image2DTexture2DArray,
710 unsigned int *image2DTexture2D)
711 {
712 if (group.empty())
713 {
714 return;
715 }
716
717 unsigned int texture2DCount = 0, texture3DCount = 0, texture2DArrayCount = 0;
718 for (const sh::ShaderVariable &uniform : group)
719 {
720 if (!programD3D.hasNamedUniform(uniform.name))
721 {
722 continue;
723 }
724 for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++)
725 {
726 switch (image2DBindLayout.at(uniform.binding + index))
727 {
728 case gl::TextureType::_2D:
729 texture2DCount++;
730 break;
731 case gl::TextureType::_3D:
732 texture3DCount++;
733 break;
734 case gl::TextureType::_2DArray:
735 case gl::TextureType::CubeMap:
736 texture2DArrayCount++;
737 break;
738 default:
739 UNREACHABLE();
740 }
741 }
742 }
743
744 unsigned int totalCount = texture2DCount + texture3DCount + texture2DArrayCount;
745 unsigned int *image2DRegisterIndex = GetImage2DRegisterIndex(
746 textureGroup, groupTextureRegisterIndex, groupRWTextureRegisterIndex);
747 unsigned int texture2DRegisterIndex = *image2DRegisterIndex;
748 unsigned int texture3DRegisterIndex = texture2DRegisterIndex + texture2DCount;
749 unsigned int texture2DArrayRegisterIndex = texture3DRegisterIndex + texture3DCount;
750 *image2DRegisterIndex += totalCount;
751
752 std::string offsetStr =
753 Image2DHLSLGroupOffsetPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup);
754 std::string declarationStr =
755 Image2DHLSLGroupDeclarationPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup);
756 std::string registerStr = Image2DHLSLGroupRegisterSuffix(textureGroup);
757 if (texture2DCount > 0)
758 {
759 out << "static const uint " << offsetStr << "2D = " << texture2DRegisterIndex << ";\n";
760 out << "uniform " << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2D) << " "
761 << declarationStr << "2D[" << texture2DCount << "]"
762 << " : register(" << registerStr << texture2DRegisterIndex << ");\n";
763 }
764 if (texture3DCount > 0)
765 {
766 out << "static const uint " << offsetStr << "3D = " << texture3DRegisterIndex << ";\n";
767 out << "uniform " << Image2DHLSLTextureString(textureGroup, gl::TextureType::_3D) << " "
768 << declarationStr << "3D[" << texture3DCount << "]"
769 << " : register(" << registerStr << texture3DRegisterIndex << ");\n";
770 }
771 if (texture2DArrayCount > 0)
772 {
773 out << "static const uint " << offsetStr << "2DArray = " << texture2DArrayRegisterIndex
774 << ";\n";
775 out << "uniform " << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2DArray)
776 << " " << declarationStr << "2DArray[" << texture2DArrayCount << "]"
777 << " : register(" << registerStr << texture2DArrayRegisterIndex << ");\n";
778 }
779 for (const sh::ShaderVariable &uniform : group)
780 {
781 if (!programD3D.hasNamedUniform(uniform.name))
782 {
783 continue;
784 }
785
786 out << "static const uint " << DecorateVariable(uniform.name)
787 << ArrayIndexString(uniform.arraySizes) << " = {";
788 for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++)
789 {
790 if (index > 0)
791 {
792 out << ", ";
793 }
794 switch (image2DBindLayout.at(uniform.binding + index))
795 {
796 case gl::TextureType::_2D:
797 {
798 out << texture2DRegisterIndex;
799 programD3D.assignImage2DRegisters(texture2DRegisterIndex,
800 uniform.binding + index, uniform.readonly);
801 texture2DRegisterIndex++;
802 break;
803 }
804 case gl::TextureType::_3D:
805 {
806 out << texture3DRegisterIndex;
807 programD3D.assignImage2DRegisters(texture3DRegisterIndex,
808 uniform.binding + index, uniform.readonly);
809 texture3DRegisterIndex++;
810 break;
811 }
812 case gl::TextureType::_2DArray:
813 case gl::TextureType::CubeMap:
814 {
815 out << texture2DArrayRegisterIndex;
816 programD3D.assignImage2DRegisters(texture2DArrayRegisterIndex,
817 uniform.binding + index, uniform.readonly);
818 texture2DArrayRegisterIndex++;
819 break;
820 }
821 default:
822 UNREACHABLE();
823 }
824 }
825 out << "};\n";
826 }
827
828 gl::Shader *shaderGL = programData.getAttachedShader(shaderType);
829 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shaderGL);
830 const bool getDimensionsIgnoresBaseLevel = programD3D.usesGetDimensionsIgnoresBaseLevel();
831
832 if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE)))
833 {
834 OutputImage2DSizeFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
835 texture2DArrayCount, offsetStr, declarationStr,
836 getDimensionsIgnoresBaseLevel);
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(const d3d::Context * context,ProgramD3D & programD3D,const gl::ProgramState & programData,gl::ShaderType shaderType,std::vector<sh::ShaderVariable> & image2DUniforms,const gl::ImageUnitTextureTypeMap & image2DBindLayout)854 std::string generateShaderForImage2DBindSignature(
855 const d3d::Context *context,
856 ProgramD3D &programD3D,
857 const gl::ProgramState &programData,
858 gl::ShaderType shaderType,
859 std::vector<sh::ShaderVariable> &image2DUniforms,
860 const gl::ImageUnitTextureTypeMap &image2DBindLayout)
861 {
862 std::vector<std::vector<sh::ShaderVariable>> groupedImage2DUniforms(IMAGE2D_MAX + 1);
863 unsigned int image2DTexture2DCount = 0, image2DTexture3DCount = 0,
864 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 image2DTexture2DCount++;
879 break;
880 case gl::TextureType::_3D:
881 image2DTexture3DCount++;
882 break;
883 case gl::TextureType::_2DArray:
884 case gl::TextureType::CubeMap:
885 image2DTexture2DArrayCount++;
886 break;
887 default:
888 UNREACHABLE();
889 }
890 }
891 Image2DHLSLGroup group = image2DHLSLGroup(image2D);
892 groupedImage2DUniforms[group].push_back(image2D);
893 }
894
895 gl::Shader *shaderGL = programData.getAttachedShader(shaderType);
896 const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shaderGL);
897 unsigned int groupTextureRegisterIndex = shaderD3D->getReadonlyImage2DRegisterIndex();
898 unsigned int groupRWTextureRegisterIndex = shaderD3D->getImage2DRegisterIndex();
899 unsigned int image2DTexture3DIndex = 0;
900 unsigned int image2DTexture2DArrayIndex = image2DTexture3DCount;
901 unsigned int image2DTexture2DIndex = image2DTexture3DCount + image2DTexture2DArrayCount;
902 std::ostringstream out;
903
904 for (int groupId = IMAGE2D_MIN; groupId < IMAGE2D_MAX; ++groupId)
905 {
906 OutputHLSLImage2DUniformGroup(programD3D, programData, shaderType, out,
907 Image2DHLSLGroup(groupId), groupedImage2DUniforms[groupId],
908 image2DBindLayout, &groupTextureRegisterIndex,
909 &groupRWTextureRegisterIndex, &image2DTexture3DIndex,
910 &image2DTexture2DArrayIndex, &image2DTexture2DIndex);
911 }
912
913 std::string shaderHLSL(programData.getAttachedShader(shaderType)->getTranslatedSource());
914 bool success = angle::ReplaceSubstring(&shaderHLSL, kImage2DFunctionString, out.str());
915 ASSERT(success);
916
917 return shaderHLSL;
918 }
919
920 } // namespace rx
921