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