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