xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2014 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 // DynamicHLSL.cpp: Implementation for link and run-time HLSL generation
7 //
8 
9 #include "libANGLE/renderer/d3d/DynamicHLSL.h"
10 
11 #include "common/string_utils.h"
12 #include "common/utilities.h"
13 #include "compiler/translator/hlsl/blocklayoutHLSL.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/Program.h"
16 #include "libANGLE/Shader.h"
17 #include "libANGLE/VaryingPacking.h"
18 #include "libANGLE/formatutils.h"
19 #include "libANGLE/renderer/d3d/ProgramD3D.h"
20 #include "libANGLE/renderer/d3d/ProgramExecutableD3D.h"
21 #include "libANGLE/renderer/d3d/RendererD3D.h"
22 #include "libANGLE/renderer/d3d/ShaderD3D.h"
23 
24 using namespace gl;
25 
26 namespace rx
27 {
28 
29 namespace
30 {
31 
32 // kShaderStorageDeclarationString must be the same as outputHLSL.
33 constexpr const char kShaderStorageDeclarationString[] =
34     "// @@ SHADER STORAGE DECLARATION STRING @@";
35 
HLSLComponentTypeString(GLenum componentType)36 const char *HLSLComponentTypeString(GLenum componentType)
37 {
38     switch (componentType)
39     {
40         case GL_UNSIGNED_INT:
41             return "uint";
42         case GL_INT:
43             return "int";
44         case GL_UNSIGNED_NORMALIZED:
45         case GL_SIGNED_NORMALIZED:
46         case GL_FLOAT:
47             return "float";
48         default:
49             UNREACHABLE();
50             return "not-component-type";
51     }
52 }
53 
HLSLComponentTypeString(std::ostringstream & ostream,GLenum componentType,int componentCount)54 void HLSLComponentTypeString(std::ostringstream &ostream, GLenum componentType, int componentCount)
55 {
56     ostream << HLSLComponentTypeString(componentType);
57     if (componentCount > 1)
58     {
59         ostream << componentCount;
60     }
61 }
62 
HLSLMatrixTypeString(GLenum type)63 const char *HLSLMatrixTypeString(GLenum type)
64 {
65     switch (type)
66     {
67         case GL_FLOAT_MAT2:
68             return "float2x2";
69         case GL_FLOAT_MAT3:
70             return "float3x3";
71         case GL_FLOAT_MAT4:
72             return "float4x4";
73         case GL_FLOAT_MAT2x3:
74             return "float2x3";
75         case GL_FLOAT_MAT3x2:
76             return "float3x2";
77         case GL_FLOAT_MAT2x4:
78             return "float2x4";
79         case GL_FLOAT_MAT4x2:
80             return "float4x2";
81         case GL_FLOAT_MAT3x4:
82             return "float3x4";
83         case GL_FLOAT_MAT4x3:
84             return "float4x3";
85         default:
86             UNREACHABLE();
87             return "not-matrix-type";
88     }
89 }
90 
HLSLTypeString(std::ostringstream & ostream,GLenum type)91 void HLSLTypeString(std::ostringstream &ostream, GLenum type)
92 {
93     if (gl::IsMatrixType(type))
94     {
95         ostream << HLSLMatrixTypeString(type);
96         return;
97     }
98 
99     HLSLComponentTypeString(ostream, gl::VariableComponentType(type),
100                             gl::VariableComponentCount(type));
101 }
102 
FindOutputAtLocation(const std::vector<PixelShaderOutputVariable> & outputVariables,unsigned int location,size_t index=0)103 const PixelShaderOutputVariable *FindOutputAtLocation(
104     const std::vector<PixelShaderOutputVariable> &outputVariables,
105     unsigned int location,
106     size_t index = 0)
107 {
108     for (auto &outputVar : outputVariables)
109     {
110         if (outputVar.outputLocation == location && outputVar.outputIndex == index)
111         {
112             return &outputVar;
113         }
114     }
115 
116     return nullptr;
117 }
118 
WriteArrayString(std::ostringstream & strstr,unsigned int i)119 void WriteArrayString(std::ostringstream &strstr, unsigned int i)
120 {
121     static_assert(GL_INVALID_INDEX == UINT_MAX,
122                   "GL_INVALID_INDEX must be equal to the max unsigned int.");
123     if (i == UINT_MAX)
124     {
125         return;
126     }
127 
128     strstr << "[";
129     strstr << i;
130     strstr << "]";
131 }
132 
ReplaceShaderStorageDeclaration(const std::vector<ShaderStorageBlock> & shaderStorageBlocks,std::string * hlsl,size_t baseUAVRegister,gl::ShaderType shaderType)133 bool ReplaceShaderStorageDeclaration(const std::vector<ShaderStorageBlock> &shaderStorageBlocks,
134                                      std::string *hlsl,
135                                      size_t baseUAVRegister,
136                                      gl::ShaderType shaderType)
137 {
138     std::string ssboHeader;
139     std::ostringstream out(ssboHeader);
140     for (const ShaderStorageBlock &ssbo : shaderStorageBlocks)
141     {
142         size_t uavRegister = baseUAVRegister + ssbo.registerIndex;
143         std::string name   = ssbo.name;
144         if (ssbo.arraySize > 0)
145         {
146             for (unsigned int arrayIndex = 0; arrayIndex < ssbo.arraySize; arrayIndex++)
147             {
148                 out << "RWByteAddressBuffer ";
149                 out << "dx_" << name << "_" << arrayIndex << ": register(u";
150                 out << uavRegister + arrayIndex << ");\n";
151             }
152         }
153         else
154         {
155             out << "RWByteAddressBuffer ";
156             out << "_" << name << ": register(u" << uavRegister << ");\n";
157         }
158     }
159     if (out.str().empty())
160     {
161         return true;
162     }
163     return angle::ReplaceSubstring(hlsl, kShaderStorageDeclarationString, out.str());
164 }
165 
166 constexpr const char *VERTEX_ATTRIBUTE_STUB_STRING      = "@@ VERTEX ATTRIBUTES @@";
167 constexpr const char *VERTEX_OUTPUT_STUB_STRING         = "@@ VERTEX OUTPUT @@";
168 constexpr const char *PIXEL_OUTPUT_STUB_STRING          = "@@ PIXEL OUTPUT @@";
169 constexpr const char *PIXEL_MAIN_PARAMETERS_STUB_STRING = "@@ PIXEL MAIN PARAMETERS @@";
170 constexpr const char *MAIN_PROLOGUE_STUB_STRING         = "@@ MAIN PROLOGUE @@";
171 }  // anonymous namespace
172 
173 // BuiltinInfo implementation
174 
175 BuiltinInfo::BuiltinInfo()  = default;
176 BuiltinInfo::~BuiltinInfo() = default;
177 
178 // DynamicHLSL implementation
179 
180 // static
GenerateVertexShaderForInputLayout(RendererD3D * renderer,const std::string & sourceShader,const InputLayout & inputLayout,const std::vector<gl::ProgramInput> & shaderAttributes,const std::vector<rx::ShaderStorageBlock> & shaderStorageBlocks,size_t baseUAVRegister)181 std::string DynamicHLSL::GenerateVertexShaderForInputLayout(
182     RendererD3D *renderer,
183     const std::string &sourceShader,
184     const InputLayout &inputLayout,
185     const std::vector<gl::ProgramInput> &shaderAttributes,
186     const std::vector<rx::ShaderStorageBlock> &shaderStorageBlocks,
187     size_t baseUAVRegister)
188 {
189     std::ostringstream structStream;
190     std::ostringstream initStream;
191 
192     structStream << "struct VS_INPUT\n"
193                     "{\n";
194 
195     int semanticIndex       = 0;
196     unsigned int inputIndex = 0;
197 
198     for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex)
199     {
200         const gl::ProgramInput &shaderAttribute = shaderAttributes[attributeIndex];
201         if (!shaderAttribute.name.empty())
202         {
203             ASSERT(inputIndex < MAX_VERTEX_ATTRIBS);
204             angle::FormatID vertexFormatID =
205                 inputIndex < inputLayout.size() ? inputLayout[inputIndex] : angle::FormatID::NONE;
206 
207             // HLSL code for input structure
208             if (IsMatrixType(shaderAttribute.getType()))
209             {
210                 // Matrix types are always transposed
211                 structStream << "    "
212                              << HLSLMatrixTypeString(
213                                     TransposeMatrixType(shaderAttribute.getType()));
214             }
215             else
216             {
217                 if (shaderAttribute.name == "gl_InstanceID" ||
218                     shaderAttribute.name == "gl_VertexID")
219                 {
220                     // The input types of the instance ID and vertex ID in HLSL (uint) differs from
221                     // the ones in ESSL (int).
222                     structStream << " uint";
223                 }
224                 else
225                 {
226                     GLenum componentType = renderer->getVertexComponentType(vertexFormatID);
227 
228                     structStream << "    ";
229                     HLSLComponentTypeString(structStream, componentType,
230                                             VariableComponentCount(shaderAttribute.getType()));
231                 }
232             }
233 
234             structStream << " " << DecorateVariable(shaderAttribute.name) << " : ";
235 
236             if (shaderAttribute.name == "gl_InstanceID")
237             {
238                 structStream << "SV_InstanceID";
239             }
240             else if (shaderAttribute.name == "gl_VertexID")
241             {
242                 structStream << "SV_VertexID";
243             }
244             else
245             {
246                 structStream << "TEXCOORD" << semanticIndex;
247                 semanticIndex += VariableRegisterCount(shaderAttribute.getType());
248             }
249 
250             structStream << ";\n";
251 
252             // HLSL code for initialization
253             initStream << "    " << DecorateVariable(shaderAttribute.name) << " = ";
254 
255             // Mismatched vertex attribute to vertex input may result in an undefined
256             // data reinterpretation (eg for pure integer->float, float->pure integer)
257             // TODO: issue warning with gl debug info extension, when supported
258             if (IsMatrixType(shaderAttribute.getType()) ||
259                 (renderer->getVertexConversionType(vertexFormatID) & VERTEX_CONVERT_GPU) != 0)
260             {
261                 GenerateAttributeConversionHLSL(vertexFormatID, shaderAttribute, initStream);
262             }
263             else
264             {
265                 initStream << "input." << DecorateVariable(shaderAttribute.name);
266             }
267 
268             if (shaderAttribute.name == "gl_VertexID")
269             {
270                 // dx_VertexID contains the firstVertex offset
271                 initStream << " + dx_VertexID";
272             }
273 
274             initStream << ";\n";
275 
276             inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.getType()));
277         }
278     }
279 
280     structStream << "};\n"
281                     "\n"
282                     "void initAttributes(VS_INPUT input)\n"
283                     "{\n"
284                  << initStream.str() << "}\n";
285 
286     std::string vertexHLSL(sourceShader);
287 
288     bool success =
289         angle::ReplaceSubstring(&vertexHLSL, VERTEX_ATTRIBUTE_STUB_STRING, structStream.str());
290     ASSERT(success);
291 
292     success = ReplaceShaderStorageDeclaration(shaderStorageBlocks, &vertexHLSL, baseUAVRegister,
293                                               gl::ShaderType::Vertex);
294     ASSERT(success);
295 
296     return vertexHLSL;
297 }
298 
299 // static
GeneratePixelShaderForOutputSignature(RendererD3D * renderer,const std::string & sourceShader,const std::vector<PixelShaderOutputVariable> & outputVariables,FragDepthUsage fragDepthUsage,bool usesSampleMask,const std::vector<GLenum> & outputLayout,const std::vector<ShaderStorageBlock> & shaderStorageBlocks,size_t baseUAVRegister)300 std::string DynamicHLSL::GeneratePixelShaderForOutputSignature(
301     RendererD3D *renderer,
302     const std::string &sourceShader,
303     const std::vector<PixelShaderOutputVariable> &outputVariables,
304     FragDepthUsage fragDepthUsage,
305     bool usesSampleMask,
306     const std::vector<GLenum> &outputLayout,
307     const std::vector<ShaderStorageBlock> &shaderStorageBlocks,
308     size_t baseUAVRegister)
309 {
310     const int shaderModel      = renderer->getMajorShaderModel();
311     std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR";
312     std::string depthSemantic  = [shaderModel, fragDepthUsage]() {
313         if (shaderModel < 4)
314         {
315             return "DEPTH";
316         }
317         switch (fragDepthUsage)
318         {
319             case FragDepthUsage::Less:
320                 return "SV_DepthLessEqual";
321             case FragDepthUsage::Greater:
322                 return "SV_DepthGreaterEqual";
323             default:
324                 return "SV_Depth";
325         }
326     }();
327 
328     std::ostringstream declarationStream;
329     std::ostringstream copyStream;
330 
331     declarationStream << "struct PS_OUTPUT\n"
332                          "{\n";
333 
334     size_t numOutputs = outputLayout.size();
335 
336     // Workaround for HLSL 3.x: We can't do a depth/stencil only render, the runtime will complain.
337     if (numOutputs == 0 && (shaderModel == 3 || !renderer->getShaderModelSuffix().empty()))
338     {
339         numOutputs = 1u;
340     }
341     const PixelShaderOutputVariable defaultOutput(GL_FLOAT_VEC4, "unused", "float4(0, 0, 0, 1)", 0,
342                                                   0);
343     size_t outputIndex = 0;
344 
345     for (size_t layoutIndex = 0; layoutIndex < numOutputs; ++layoutIndex)
346     {
347         GLenum binding = outputLayout.empty() ? GL_COLOR_ATTACHMENT0 : outputLayout[layoutIndex];
348 
349         if (binding != GL_NONE)
350         {
351             unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
352             outputIndex =
353                 layoutIndex > 0 && binding == outputLayout[layoutIndex - 1] ? outputIndex + 1 : 0;
354 
355             const PixelShaderOutputVariable *outputVariable =
356                 outputLayout.empty() ? &defaultOutput
357                                      : FindOutputAtLocation(outputVariables, location, outputIndex);
358 
359             // OpenGL ES 3.0 spec $4.2.1
360             // If [...] not all user-defined output variables are written, the values of fragment
361             // colors corresponding to unwritten variables are similarly undefined.
362             if (outputVariable)
363             {
364                 declarationStream << "    ";
365                 HLSLTypeString(declarationStream, outputVariable->type);
366                 declarationStream << " " << outputVariable->name << " : " << targetSemantic
367                                   << static_cast<int>(layoutIndex) << ";\n";
368 
369                 copyStream << "    output." << outputVariable->name << " = "
370                            << outputVariable->source << ";\n";
371             }
372         }
373     }
374 
375     if (fragDepthUsage != FragDepthUsage::Unused)
376     {
377         declarationStream << "    float gl_Depth : " << depthSemantic << ";\n";
378         copyStream << "    output.gl_Depth = gl_Depth; \n";
379     }
380 
381     if (usesSampleMask)
382     {
383         declarationStream << "    uint sampleMask : SV_Coverage;\n";
384         // Ignore gl_SampleMask[0] value when rendering to a single-sampled framebuffer
385         copyStream << "    output.sampleMask = (dx_Misc & 1) ? gl_SampleMask[0] : 0xFFFFFFFFu;\n";
386     }
387 
388     declarationStream << "};\n"
389                          "\n"
390                          "PS_OUTPUT generateOutput()\n"
391                          "{\n"
392                          "    PS_OUTPUT output;\n"
393                       << copyStream.str()
394                       << "    return output;\n"
395                          "}\n";
396 
397     std::string pixelHLSL(sourceShader);
398 
399     bool success =
400         angle::ReplaceSubstring(&pixelHLSL, PIXEL_OUTPUT_STUB_STRING, declarationStream.str());
401     ASSERT(success);
402 
403     success = ReplaceShaderStorageDeclaration(shaderStorageBlocks, &pixelHLSL, baseUAVRegister,
404                                               gl::ShaderType::Fragment);
405     ASSERT(success);
406 
407     return pixelHLSL;
408 }
409 
410 // static
GenerateShaderForImage2DBindSignature(ProgramExecutableD3D & executableD3D,gl::ShaderType shaderType,const SharedCompiledShaderStateD3D & shaderData,const std::string & shaderHLSL,std::vector<sh::ShaderVariable> & image2DUniforms,const gl::ImageUnitTextureTypeMap & image2DBindLayout,unsigned int baseUAVRegister)411 std::string DynamicHLSL::GenerateShaderForImage2DBindSignature(
412     ProgramExecutableD3D &executableD3D,
413     gl::ShaderType shaderType,
414     const SharedCompiledShaderStateD3D &shaderData,
415     const std::string &shaderHLSL,
416     std::vector<sh::ShaderVariable> &image2DUniforms,
417     const gl::ImageUnitTextureTypeMap &image2DBindLayout,
418     unsigned int baseUAVRegister)
419 {
420     if (image2DUniforms.empty())
421     {
422         return shaderHLSL;
423     }
424 
425     return GenerateShaderForImage2DBindSignatureImpl(executableD3D, shaderType, shaderData,
426                                                      shaderHLSL, image2DUniforms, image2DBindLayout,
427                                                      baseUAVRegister);
428 }
429 
430 // static
GenerateVaryingLinkHLSL(RendererD3D * renderer,const VaryingPacking & varyingPacking,const BuiltinInfo & builtins,bool programUsesPointSize,std::ostringstream & hlslStream)431 void DynamicHLSL::GenerateVaryingLinkHLSL(RendererD3D *renderer,
432                                           const VaryingPacking &varyingPacking,
433                                           const BuiltinInfo &builtins,
434                                           bool programUsesPointSize,
435                                           std::ostringstream &hlslStream)
436 {
437     ASSERT(builtins.dxPosition.enabled);
438     hlslStream << "{\n";
439     hlslStream << "    float4 dx_Position : " << builtins.dxPosition.str() << ";\n";
440 
441     if (builtins.glPosition.enabled)
442     {
443         hlslStream << "    float4 gl_Position : " << builtins.glPosition.str() << ";\n";
444     }
445 
446     if (builtins.glClipDistance.enabled)
447     {
448         ASSERT(builtins.glClipDistance.indexOrSize > 0 && builtins.glClipDistance.indexOrSize < 9);
449         for (unsigned int i = 0; i < (builtins.glClipDistance.indexOrSize + 3) >> 2; i++)
450         {
451             unsigned int size = std::min(builtins.glClipDistance.indexOrSize - 4u * i, 4u);
452             hlslStream << "    float" << ((size == 1) ? "" : Str(size)) << " gl_ClipDistance" << i
453                        << " : " << builtins.glClipDistance.str() << i << ";\n";
454         }
455     }
456 
457     if (builtins.glCullDistance.enabled)
458     {
459         ASSERT(builtins.glCullDistance.indexOrSize > 0 && builtins.glCullDistance.indexOrSize < 9);
460         for (unsigned int i = 0; i < (builtins.glCullDistance.indexOrSize + 3) >> 2; i++)
461         {
462             unsigned int size = std::min(builtins.glCullDistance.indexOrSize - 4u * i, 4u);
463             hlslStream << "    float" << ((size == 1) ? "" : Str(size)) << " gl_CullDistance" << i
464                        << " : " << builtins.glCullDistance.str() << i << ";\n";
465         }
466     }
467 
468     if (builtins.glFragCoord.enabled)
469     {
470         hlslStream << "    float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
471     }
472 
473     if (builtins.glPointCoord.enabled)
474     {
475         hlslStream << "    float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
476     }
477 
478     if (builtins.glPointSize.enabled)
479     {
480         hlslStream << "    float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
481     }
482 
483     if (builtins.glViewIDOVR.enabled)
484     {
485         hlslStream << "    nointerpolation uint gl_ViewID_OVR : " << builtins.glViewIDOVR.str()
486                    << ";\n";
487     }
488 
489     std::string varyingSemantic =
490         GetVaryingSemantic(renderer->getMajorShaderModel(), programUsesPointSize);
491 
492     const auto &registerInfos = varyingPacking.getRegisterList();
493     for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
494     {
495         const PackedVaryingRegister &registerInfo = registerInfos[registerIndex];
496         const auto &varying                       = registerInfo.packedVarying->varying();
497         ASSERT(!varying.isStruct());
498 
499         // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
500         // registers being used.
501         // For example, if there are N registers, and we have N vec3 varyings and 1 float
502         // varying, then D3D will pack them into N registers.
503         // If the float varying has the 'nointerpolation' modifier on it then we would need
504         // N + 1 registers, and D3D compilation will fail.
505 
506         switch (registerInfo.packedVarying->interpolation)
507         {
508             case sh::INTERPOLATION_SMOOTH:
509                 hlslStream << "    ";
510                 break;
511             case sh::INTERPOLATION_FLAT:
512                 hlslStream << "    nointerpolation ";
513                 break;
514             case sh::INTERPOLATION_NOPERSPECTIVE:
515                 hlslStream << "    noperspective ";
516                 break;
517             case sh::INTERPOLATION_CENTROID:
518                 hlslStream << "    centroid ";
519                 break;
520             case sh::INTERPOLATION_SAMPLE:
521                 hlslStream << "    sample ";
522                 break;
523             case sh::INTERPOLATION_NOPERSPECTIVE_CENTROID:
524                 hlslStream << "    noperspective centroid ";
525                 break;
526             case sh::INTERPOLATION_NOPERSPECTIVE_SAMPLE:
527                 hlslStream << "    noperspective sample ";
528                 break;
529             default:
530                 UNREACHABLE();
531         }
532 
533         GLenum transposedType = gl::TransposeMatrixType(varying.type);
534         GLenum componentType  = gl::VariableComponentType(transposedType);
535         int columnCount       = gl::VariableColumnCount(transposedType);
536         HLSLComponentTypeString(hlslStream, componentType, columnCount);
537         hlslStream << " v" << registerIndex << " : " << varyingSemantic << registerIndex << ";\n";
538     }
539 
540     // Note that the following outputs need to be declared after the others. They are not included
541     // in pixel shader inputs even when they are in vertex/geometry shader outputs, and the pixel
542     // shader input struct must be a prefix of the vertex/geometry shader output struct.
543 
544     if (builtins.glLayer.enabled)
545     {
546         hlslStream << "    nointerpolation uint gl_Layer : " << builtins.glLayer.str() << ";\n";
547     }
548 
549     hlslStream << "};\n";
550 }
551 
552 // static
GenerateShaderLinkHLSL(RendererD3D * renderer,const gl::Caps & caps,const gl::ShaderMap<gl::SharedCompiledShaderState> & shaderData,const gl::ShaderMap<SharedCompiledShaderStateD3D> & shaderDataD3D,const ProgramD3DMetadata & programMetadata,const VaryingPacking & varyingPacking,const BuiltinVaryingsD3D & builtinsD3D,gl::ShaderMap<std::string> * shaderHLSL)553 void DynamicHLSL::GenerateShaderLinkHLSL(
554     RendererD3D *renderer,
555     const gl::Caps &caps,
556     const gl::ShaderMap<gl::SharedCompiledShaderState> &shaderData,
557     const gl::ShaderMap<SharedCompiledShaderStateD3D> &shaderDataD3D,
558     const ProgramD3DMetadata &programMetadata,
559     const VaryingPacking &varyingPacking,
560     const BuiltinVaryingsD3D &builtinsD3D,
561     gl::ShaderMap<std::string> *shaderHLSL)
562 {
563     ASSERT(shaderHLSL);
564     ASSERT((*shaderHLSL)[gl::ShaderType::Vertex].empty() &&
565            (*shaderHLSL)[gl::ShaderType::Fragment].empty());
566 
567     const gl::SharedCompiledShaderState &vertexShader   = shaderData[ShaderType::Vertex];
568     const gl::SharedCompiledShaderState &fragmentShader = shaderData[ShaderType::Fragment];
569     const int shaderModel                               = renderer->getMajorShaderModel();
570 
571     const SharedCompiledShaderStateD3D &fragmentShaderD3D = shaderDataD3D[ShaderType::Fragment];
572 
573     // usesViewScale() isn't supported in the D3D9 renderer
574     ASSERT(shaderModel >= 4 || !programMetadata.usesViewScale());
575 
576     // Validation done in the compiler
577     ASSERT(!fragmentShaderD3D || !fragmentShaderD3D->usesFragColor ||
578            !fragmentShaderD3D->usesFragData);
579 
580     std::ostringstream vertexStream;
581     vertexStream << "struct VS_OUTPUT\n";
582     const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex];
583     GenerateVaryingLinkHLSL(renderer, varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(),
584                             vertexStream);
585 
586     std::ostringstream vertexGenerateOutput;
587     vertexGenerateOutput << "VS_OUTPUT generateOutput(VS_INPUT input)\n"
588                          << "{\n"
589                          << "    VS_OUTPUT output;\n";
590 
591     if (vertexBuiltins.glPosition.enabled)
592     {
593         vertexGenerateOutput << "    output.gl_Position = gl_Position;\n";
594     }
595 
596     if (vertexBuiltins.glClipDistance.enabled)
597     {
598         ASSERT(vertexBuiltins.glClipDistance.indexOrSize > 0 &&
599                vertexBuiltins.glClipDistance.indexOrSize < 9);
600         vertexGenerateOutput << "    output.gl_ClipDistance0 = (clipDistancesEnabled & ";
601         switch (vertexBuiltins.glClipDistance.indexOrSize)
602         {
603             case 1:
604                 vertexGenerateOutput << "1) ? (float)gl_ClipDistance : 0;\n";
605                 break;
606             case 2:
607                 vertexGenerateOutput << "int2(1, 2)) ? (float2)gl_ClipDistance : 0;\n";
608                 break;
609             case 3:
610                 vertexGenerateOutput << "int3(1, 2, 4)) ? (float3)gl_ClipDistance : 0;\n";
611                 break;
612             default:
613                 vertexGenerateOutput << "int4(1, 2, 4, 8)) ? (float4)gl_ClipDistance : 0;\n";
614                 break;
615         }
616         if (vertexBuiltins.glClipDistance.indexOrSize > 4)
617         {
618             vertexGenerateOutput << "    output.gl_ClipDistance1 = (clipDistancesEnabled & ";
619             switch (vertexBuiltins.glClipDistance.indexOrSize)
620             {
621                 case 5:
622                     vertexGenerateOutput << "16) ? gl_ClipDistance[4] : 0;\n";
623                     break;
624                 case 6:
625                     vertexGenerateOutput << "int2(16, 32)) ? "
626                                             "((float2[3])gl_ClipDistance)[2] : 0;\n";
627                     break;
628                 case 7:
629                     vertexGenerateOutput << "int3(16, 32, 64)) ? float3(gl_ClipDistance[4], "
630                                             "gl_ClipDistance[5], gl_ClipDistance[6]) : 0;\n";
631                     break;
632                 case 8:
633                     vertexGenerateOutput << "int4(16, 32, 64, 128)) ? "
634                                             "((float4[2])gl_ClipDistance)[1] : 0;\n";
635                     break;
636             }
637         }
638     }
639 
640     if (vertexBuiltins.glCullDistance.enabled)
641     {
642         ASSERT(vertexBuiltins.glCullDistance.indexOrSize > 0 &&
643                vertexBuiltins.glCullDistance.indexOrSize < 9);
644         vertexGenerateOutput << "    output.gl_CullDistance0 = ";
645         switch (vertexBuiltins.glCullDistance.indexOrSize)
646         {
647             case 1:
648                 vertexGenerateOutput << "(float)gl_CullDistance;\n";
649                 break;
650             case 2:
651                 vertexGenerateOutput << "(float2)gl_CullDistance;\n";
652                 break;
653             case 3:
654                 vertexGenerateOutput << "(float3)gl_CullDistance;\n";
655                 break;
656             default:
657                 vertexGenerateOutput << "(float4)gl_CullDistance;\n";
658                 break;
659         }
660         if (vertexBuiltins.glCullDistance.indexOrSize > 4)
661         {
662             vertexGenerateOutput << "    output.gl_CullDistance1 = ";
663             switch (vertexBuiltins.glCullDistance.indexOrSize)
664             {
665                 case 5:
666                     vertexGenerateOutput << "gl_CullDistance[4];\n";
667                     break;
668                 case 6:
669                     vertexGenerateOutput << "((float2[3])gl_CullDistance)[2];\n";
670                     break;
671                 case 7:
672                     vertexGenerateOutput << "float3(gl_CullDistance[4], "
673                                             "gl_CullDistance[5], gl_CullDistance[6]);\n";
674                     break;
675                 case 8:
676                     vertexGenerateOutput << "((float4[2])gl_CullDistance)[1];\n";
677                     break;
678             }
679         }
680     }
681 
682     if (vertexBuiltins.glViewIDOVR.enabled)
683     {
684         vertexGenerateOutput << "    output.gl_ViewID_OVR = ViewID_OVR;\n";
685     }
686     if (programMetadata.hasMultiviewEnabled() && programMetadata.canSelectViewInVertexShader())
687     {
688         ASSERT(vertexBuiltins.glLayer.enabled);
689         vertexGenerateOutput << "    output.gl_Layer = ViewID_OVR;\n";
690     }
691 
692     // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
693     if (shaderModel >= 4 && renderer->getShaderModelSuffix() == "")
694     {
695         vertexGenerateOutput << "    output.dx_Position.x = gl_Position.x;\n";
696 
697         if (programMetadata.usesViewScale())
698         {
699             // This code assumes that dx_ViewScale.y = -1.0f when rendering to texture, and +1.0f
700             // when rendering to the default framebuffer. No other values are valid.
701             vertexGenerateOutput << "    output.dx_Position.y = dx_ViewScale.y * gl_Position.y;\n";
702         }
703         else
704         {
705             vertexGenerateOutput
706                 << "    output.dx_Position.y = clipControlOrigin * gl_Position.y;\n";
707         }
708 
709         vertexGenerateOutput
710             << "    if (clipControlZeroToOne)\n"
711             << "    {\n"
712             << "        output.dx_Position.z = gl_Position.z;\n"
713             << "    } else {\n"
714             << "        output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
715             << "    }\n";
716 
717         vertexGenerateOutput << "    output.dx_Position.w = gl_Position.w;\n";
718     }
719     else
720     {
721         vertexGenerateOutput << "    output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + "
722                                 "dx_ViewAdjust.x * gl_Position.w;\n";
723 
724         // If usesViewScale() is true and we're using the D3D11 renderer via Feature Level 9_*,
725         // then we need to multiply the gl_Position.y by the viewScale.
726         // usesViewScale() isn't supported when using the D3D9 renderer.
727         if (programMetadata.usesViewScale() &&
728             (shaderModel >= 4 && renderer->getShaderModelSuffix() != ""))
729         {
730             vertexGenerateOutput << "    output.dx_Position.y = dx_ViewScale.y * (gl_Position.y * "
731                                     "dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n";
732         }
733         else
734         {
735             vertexGenerateOutput << "    output.dx_Position.y = clipControlOrigin * (gl_Position.y "
736                                     "* dx_ViewAdjust.w + "
737                                     "dx_ViewAdjust.y * gl_Position.w);\n";
738         }
739 
740         vertexGenerateOutput
741             << "    if (clipControlZeroToOne)\n"
742             << "    {\n"
743             << "        output.dx_Position.z = gl_Position.z;\n"
744             << "    } else {\n"
745             << "        output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
746             << "    }\n";
747 
748         vertexGenerateOutput << "    output.dx_Position.w = gl_Position.w;\n";
749     }
750 
751     // We don't need to output gl_PointSize if we use are emulating point sprites via instancing.
752     if (vertexBuiltins.glPointSize.enabled)
753     {
754         vertexGenerateOutput << "    output.gl_PointSize = gl_PointSize;\n";
755     }
756 
757     if (vertexBuiltins.glFragCoord.enabled)
758     {
759         vertexGenerateOutput << "    output.gl_FragCoord = gl_Position;\n";
760     }
761 
762     const auto &registerInfos = varyingPacking.getRegisterList();
763     for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
764     {
765         const PackedVaryingRegister &registerInfo = registerInfos[registerIndex];
766         const auto &packedVarying                 = *registerInfo.packedVarying;
767         const auto &varying                       = *packedVarying.frontVarying.varying;
768         ASSERT(!varying.isStruct());
769 
770         vertexGenerateOutput << "    output.v" << registerIndex << " = ";
771 
772         if (packedVarying.isStructField())
773         {
774             vertexGenerateOutput << DecorateVariable(packedVarying.frontVarying.parentStructName)
775                                  << ".";
776         }
777 
778         vertexGenerateOutput << DecorateVariable(varying.name);
779 
780         if (varying.isArray())
781         {
782             WriteArrayString(vertexGenerateOutput, registerInfo.varyingArrayIndex);
783         }
784 
785         if (VariableRowCount(varying.type) > 1)
786         {
787             WriteArrayString(vertexGenerateOutput, registerInfo.varyingRowIndex);
788         }
789 
790         vertexGenerateOutput << ";\n";
791     }
792 
793     // Renderers that enable instanced pointsprite emulation require the vertex shader output member
794     // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same
795     // default value used in the generated pixel shader.
796     if (programMetadata.usesInsertedPointCoordValue())
797     {
798         vertexGenerateOutput << "\n"
799                                 "    output.gl_PointCoord = float2(0.5, 0.5);\n";
800     }
801 
802     vertexGenerateOutput << "\n"
803                             "    return output;\n"
804                             "}";
805 
806     if (vertexShader)
807     {
808         std::string vertexSource = vertexShader->translatedSource;
809         angle::ReplaceSubstring(&vertexSource, std::string(MAIN_PROLOGUE_STUB_STRING),
810                                 "    initAttributes(input);\n");
811         angle::ReplaceSubstring(&vertexSource, std::string(VERTEX_OUTPUT_STUB_STRING),
812                                 vertexGenerateOutput.str());
813         vertexStream << vertexSource;
814     }
815 
816     const auto &pixelBuiltins = builtinsD3D[gl::ShaderType::Fragment];
817 
818     std::ostringstream pixelStream;
819     pixelStream << "struct PS_INPUT\n";
820     GenerateVaryingLinkHLSL(renderer, varyingPacking, pixelBuiltins, builtinsD3D.usesPointSize(),
821                             pixelStream);
822     pixelStream << "\n";
823 
824     std::ostringstream pixelPrologue;
825     if (fragmentShaderD3D && fragmentShaderD3D->usesViewID)
826     {
827         ASSERT(pixelBuiltins.glViewIDOVR.enabled);
828         pixelPrologue << "    ViewID_OVR = input.gl_ViewID_OVR;\n";
829     }
830 
831     if (pixelBuiltins.glFragCoord.enabled)
832     {
833         pixelPrologue << "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
834 
835         // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader.
836         // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using
837         // dx_ViewCoords.
838         // DComp usually gives us an offset at (0, 0), but this is not always the case. It is
839         // valid for DComp to give us an offset into the texture atlas. In that scenario, we
840         // need to offset gl_FragCoord using dx_FragCoordOffset to point to the correct location
841         // of the pixel.
842         if (shaderModel >= 4 && renderer->getShaderModelSuffix() == "")
843         {
844             pixelPrologue << "    gl_FragCoord.x = input.dx_Position.x - dx_FragCoordOffset.x;\n"
845                           << "    gl_FragCoord.y = input.dx_Position.y - dx_FragCoordOffset.y;\n";
846         }
847         else if (shaderModel == 3)
848         {
849             pixelPrologue
850                 << "    gl_FragCoord.x = input.dx_Position.x + 0.5 - dx_FragCoordOffset.x;\n"
851                 << "    gl_FragCoord.y = input.dx_Position.y + 0.5 - dx_FragCoordOffset.y;\n";
852         }
853         else
854         {
855             // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See
856             // Renderer::setViewport()
857             pixelPrologue
858                 << "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + "
859                    "dx_ViewCoords.z - dx_FragCoordOffset.x;\n"
860                 << "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + "
861                    "dx_ViewCoords.w - dx_FragCoordOffset.y;\n";
862         }
863 
864         if (programMetadata.usesViewScale())
865         {
866             // For Feature Level 9_3 and below, we need to correct gl_FragCoord.y to account
867             // for dx_ViewScale. On Feature Level 10_0+, gl_FragCoord.y is calculated above using
868             // dx_ViewCoords and is always correct irrespective of dx_ViewScale's value.
869             // NOTE: usesViewScale() can only be true on D3D11 (i.e. Shader Model 4.0+).
870             if (shaderModel >= 4 && renderer->getShaderModelSuffix() == "")
871             {
872                 // Some assumptions:
873                 //  - dx_ViewScale.y = -1.0f when rendering to texture
874                 //  - dx_ViewScale.y = +1.0f when rendering to the default framebuffer
875                 //  - gl_FragCoord.y has been set correctly above.
876                 //
877                 // When rendering to the backbuffer, the code inverts gl_FragCoord's y coordinate.
878                 // This involves subtracting the y coordinate from the height of the area being
879                 // rendered to.
880                 //
881                 // First we calculate the height of the area being rendered to:
882                 //    render_area_height = (2.0f / (1.0f - input.gl_FragCoord.y * rhw)) *
883                 //    gl_FragCoord.y
884                 //
885                 // Note that when we're rendering to default FB, we want our output to be
886                 // equivalent to:
887                 //    "gl_FragCoord.y = render_area_height - gl_FragCoord.y"
888                 //
889                 // When we're rendering to a texture, we want our output to be equivalent to:
890                 //    "gl_FragCoord.y = gl_FragCoord.y;"
891                 //
892                 // If we set scale_factor = ((1.0f + dx_ViewScale.y) / 2.0f), then notice that
893                 //  - When rendering to default FB: scale_factor = 1.0f
894                 //  - When rendering to texture:    scale_factor = 0.0f
895                 //
896                 // Therefore, we can get our desired output by setting:
897                 //    "gl_FragCoord.y = scale_factor * render_area_height - dx_ViewScale.y *
898                 //    gl_FragCoord.y"
899                 //
900                 // Simplifying, this becomes:
901                 pixelPrologue
902                     << "    gl_FragCoord.y = (1.0f + dx_ViewScale.y) * gl_FragCoord.y /"
903                        "(1.0f - input.gl_FragCoord.y * rhw)  - dx_ViewScale.y * gl_FragCoord.y;\n";
904             }
905         }
906 
907         if (shaderModel >= 4 && renderer->getShaderModelSuffix() == "")
908         {
909             pixelPrologue << "    gl_FragCoord.z = input.dx_Position.z;\n";
910         }
911         else
912         {
913             pixelPrologue
914                 << "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + "
915                    "dx_DepthFront.y;\n";
916         }
917         pixelPrologue << "    gl_FragCoord.w = rhw;\n";
918     }
919 
920     if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3)
921     {
922         pixelPrologue << "    gl_PointCoord.x = input.gl_PointCoord.x;\n"
923                       << "    gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
924     }
925 
926     if (fragmentShaderD3D && fragmentShaderD3D->usesFrontFacing)
927     {
928         if (shaderModel <= 3)
929         {
930             pixelPrologue << "    gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
931         }
932         else
933         {
934             pixelPrologue << "    gl_FrontFacing = isFrontFace;\n";
935         }
936     }
937 
938     bool declareSampleID = false;
939     if (fragmentShaderD3D && fragmentShaderD3D->usesSampleID)
940     {
941         declareSampleID = true;
942         pixelPrologue << "    gl_SampleID = sampleID;\n";
943     }
944 
945     if (fragmentShaderD3D && fragmentShaderD3D->usesSamplePosition)
946     {
947         declareSampleID = true;
948         pixelPrologue << "    gl_SamplePosition = GetRenderTargetSamplePosition(sampleID) + 0.5;\n";
949     }
950 
951     if (fragmentShaderD3D && fragmentShaderD3D->clipDistanceSize)
952     {
953         ASSERT(vertexBuiltins.glClipDistance.indexOrSize > 0 &&
954                vertexBuiltins.glClipDistance.indexOrSize < 9);
955         switch (pixelBuiltins.glClipDistance.indexOrSize)
956         {
957             case 1:
958                 pixelPrologue << "    (float)gl_ClipDistance = input.gl_ClipDistance0;\n";
959                 break;
960             case 2:
961                 pixelPrologue << "    (float2)gl_ClipDistance = input.gl_ClipDistance0;\n";
962                 break;
963             case 3:
964                 pixelPrologue << "    (float3)gl_ClipDistance = input.gl_ClipDistance0;\n";
965                 break;
966             default:
967                 pixelPrologue << "    (float4)gl_ClipDistance = input.gl_ClipDistance0;\n";
968                 break;
969         }
970         switch (pixelBuiltins.glClipDistance.indexOrSize)
971         {
972             case 5:
973                 pixelPrologue << "    gl_ClipDistance[4] = input.gl_ClipDistance1;\n";
974                 break;
975             case 6:
976                 pixelPrologue << "    ((float2[3])gl_ClipDistance)[2] = input.gl_ClipDistance1;\n";
977                 break;
978             case 7:
979                 pixelPrologue << "    gl_ClipDistance[4] = input.gl_ClipDistance1.x;\n";
980                 pixelPrologue << "    gl_ClipDistance[5] = input.gl_ClipDistance1.y;\n";
981                 pixelPrologue << "    gl_ClipDistance[6] = input.gl_ClipDistance1.z;\n";
982                 break;
983             case 8:
984                 pixelPrologue << "    ((float4[2])gl_ClipDistance)[1] = input.gl_ClipDistance1;\n";
985                 break;
986         }
987     }
988 
989     if (fragmentShaderD3D && fragmentShaderD3D->cullDistanceSize)
990     {
991         ASSERT(vertexBuiltins.glCullDistance.indexOrSize > 0 &&
992                vertexBuiltins.glCullDistance.indexOrSize < 9);
993         switch (pixelBuiltins.glCullDistance.indexOrSize)
994         {
995             case 1:
996                 pixelPrologue << "    (float)gl_CullDistance = input.gl_CullDistance0;\n";
997                 break;
998             case 2:
999                 pixelPrologue << "    (float2)gl_CullDistance = input.gl_CullDistance0;\n";
1000                 break;
1001             case 3:
1002                 pixelPrologue << "    (float3)gl_CullDistance = input.gl_CullDistance0;\n";
1003                 break;
1004             default:
1005                 pixelPrologue << "    (float4)gl_CullDistance = input.gl_CullDistance0;\n";
1006                 break;
1007         }
1008         switch (pixelBuiltins.glCullDistance.indexOrSize)
1009         {
1010             case 5:
1011                 pixelPrologue << "    gl_CullDistance[4] = input.gl_CullDistance1;\n";
1012                 break;
1013             case 6:
1014                 pixelPrologue << "    ((float2[3])gl_CullDistance)[2] = input.gl_CullDistance1;\n";
1015                 break;
1016             case 7:
1017                 pixelPrologue << "    gl_CullDistance[4] = input.gl_CullDistance1.x;\n";
1018                 pixelPrologue << "    gl_CullDistance[5] = input.gl_CullDistance1.y;\n";
1019                 pixelPrologue << "    gl_CullDistance[6] = input.gl_CullDistance1.z;\n";
1020                 break;
1021             case 8:
1022                 pixelPrologue << "    ((float4[2])gl_CullDistance)[1] = input.gl_CullDistance1;\n";
1023                 break;
1024         }
1025     }
1026 
1027     bool usesSampleInterpolation = false;
1028     for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
1029     {
1030         const PackedVaryingRegister &registerInfo = registerInfos[registerIndex];
1031         const auto &packedVarying                 = *registerInfo.packedVarying;
1032 
1033         // Don't reference VS-only transform feedback varyings in the PS.
1034         if (packedVarying.vertexOnly())
1035         {
1036             continue;
1037         }
1038 
1039         const auto &varying = *packedVarying.backVarying.varying;
1040         ASSERT(!varying.isBuiltIn() && !varying.isStruct());
1041 
1042         // Note that we're relying on that the active flag is set according to usage in the fragment
1043         // shader.
1044         if (!varying.active)
1045         {
1046             continue;
1047         }
1048 
1049         if (packedVarying.interpolation == sh::InterpolationType::INTERPOLATION_SAMPLE ||
1050             packedVarying.interpolation ==
1051                 sh::InterpolationType::INTERPOLATION_NOPERSPECTIVE_SAMPLE)
1052         {
1053             usesSampleInterpolation = true;
1054         }
1055 
1056         pixelPrologue << "    ";
1057 
1058         if (packedVarying.isStructField())
1059         {
1060             pixelPrologue << DecorateVariable(packedVarying.backVarying.parentStructName) << ".";
1061         }
1062 
1063         pixelPrologue << DecorateVariable(varying.name);
1064 
1065         if (varying.isArray())
1066         {
1067             WriteArrayString(pixelPrologue, registerInfo.varyingArrayIndex);
1068         }
1069 
1070         GLenum transposedType = TransposeMatrixType(varying.type);
1071         if (VariableRowCount(transposedType) > 1)
1072         {
1073             WriteArrayString(pixelPrologue, registerInfo.varyingRowIndex);
1074         }
1075 
1076         pixelPrologue << " = input.v" << registerIndex;
1077 
1078         switch (VariableColumnCount(transposedType))
1079         {
1080             case 1:
1081                 pixelPrologue << ".x";
1082                 break;
1083             case 2:
1084                 pixelPrologue << ".xy";
1085                 break;
1086             case 3:
1087                 pixelPrologue << ".xyz";
1088                 break;
1089             case 4:
1090                 break;
1091             default:
1092                 UNREACHABLE();
1093         }
1094         pixelPrologue << ";\n";
1095     }
1096 
1097     if (fragmentShaderD3D && fragmentShaderD3D->usesSampleMaskIn)
1098     {
1099         // When per-sample shading is active due to the use of a fragment input qualified
1100         // by sample or due to the use of the gl_SampleID or gl_SamplePosition variables,
1101         // only the bit for the current sample is set in gl_SampleMaskIn.
1102         declareSampleID = declareSampleID || usesSampleInterpolation;
1103         pixelPrologue << "    gl_SampleMaskIn[0] = "
1104                       << (declareSampleID ? "1 << sampleID" : "sampleMaskIn") << ";\n";
1105     }
1106 
1107     if (fragmentShader)
1108     {
1109         std::string pixelSource = fragmentShader->translatedSource;
1110 
1111         std::ostringstream pixelMainParametersStream;
1112         pixelMainParametersStream << "PS_INPUT input";
1113 
1114         if (fragmentShaderD3D->usesFrontFacing)
1115         {
1116             pixelMainParametersStream << (shaderModel >= 4 ? ", bool isFrontFace : SV_IsFrontFace"
1117                                                            : ", float vFace : VFACE");
1118         }
1119 
1120         if (declareSampleID)
1121         {
1122             pixelMainParametersStream << ", uint sampleID : SV_SampleIndex";
1123         }
1124         else if (fragmentShaderD3D->usesSampleMaskIn)
1125         {
1126             pixelMainParametersStream << ", uint sampleMaskIn : SV_Coverage";
1127         }
1128 
1129         angle::ReplaceSubstring(&pixelSource, std::string(PIXEL_MAIN_PARAMETERS_STUB_STRING),
1130                                 pixelMainParametersStream.str());
1131 
1132         angle::ReplaceSubstring(&pixelSource, std::string(MAIN_PROLOGUE_STUB_STRING),
1133                                 pixelPrologue.str());
1134         pixelStream << pixelSource;
1135     }
1136 
1137     (*shaderHLSL)[gl::ShaderType::Vertex]   = vertexStream.str();
1138     (*shaderHLSL)[gl::ShaderType::Fragment] = pixelStream.str();
1139 }
1140 
1141 // static
GenerateGeometryShaderPreamble(RendererD3D * renderer,const VaryingPacking & varyingPacking,const BuiltinVaryingsD3D & builtinsD3D,const bool hasMultiviewEnabled,const bool selectViewInVS)1142 std::string DynamicHLSL::GenerateGeometryShaderPreamble(RendererD3D *renderer,
1143                                                         const VaryingPacking &varyingPacking,
1144                                                         const BuiltinVaryingsD3D &builtinsD3D,
1145                                                         const bool hasMultiviewEnabled,
1146                                                         const bool selectViewInVS)
1147 {
1148     ASSERT(renderer->getMajorShaderModel() >= 4);
1149 
1150     std::ostringstream preambleStream;
1151 
1152     const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex];
1153 
1154     preambleStream << "struct GS_INPUT\n";
1155     GenerateVaryingLinkHLSL(renderer, varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(),
1156                             preambleStream);
1157     preambleStream << "\n"
1158                       "struct GS_OUTPUT\n";
1159     GenerateVaryingLinkHLSL(renderer, varyingPacking, builtinsD3D[gl::ShaderType::Geometry],
1160                             builtinsD3D.usesPointSize(), preambleStream);
1161     preambleStream
1162         << "\n"
1163         << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n"
1164         << "{\n"
1165         << "    output.gl_Position = input.gl_Position;\n";
1166 
1167     if (vertexBuiltins.glPointSize.enabled)
1168     {
1169         preambleStream << "    output.gl_PointSize = input.gl_PointSize;\n";
1170     }
1171 
1172     if (hasMultiviewEnabled)
1173     {
1174         preambleStream << "    output.gl_ViewID_OVR = input.gl_ViewID_OVR;\n";
1175         if (selectViewInVS)
1176         {
1177             ASSERT(builtinsD3D[gl::ShaderType::Geometry].glLayer.enabled);
1178 
1179             // If the view is already selected in the VS, then we just pass gl_Layer to the output.
1180             preambleStream << "    output.gl_Layer = input.gl_Layer;\n";
1181         }
1182     }
1183 
1184     const auto &registerInfos = varyingPacking.getRegisterList();
1185     for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
1186     {
1187         const PackedVaryingRegister &varyingRegister = registerInfos[registerIndex];
1188         preambleStream << "    output.v" << registerIndex << " = ";
1189         if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT)
1190         {
1191             preambleStream << "flat";
1192         }
1193         preambleStream << "input.v" << registerIndex << "; \n";
1194     }
1195 
1196     if (vertexBuiltins.glFragCoord.enabled)
1197     {
1198         preambleStream << "    output.gl_FragCoord = input.gl_FragCoord;\n";
1199     }
1200 
1201     // Only write the dx_Position if we aren't using point sprites
1202     preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n"
1203                    << "    output.dx_Position = input.dx_Position;\n"
1204                    << "#endif  // ANGLE_POINT_SPRITE_SHADER\n"
1205                    << "}\n";
1206 
1207     if (hasMultiviewEnabled && !selectViewInVS)
1208     {
1209         ASSERT(builtinsD3D[gl::ShaderType::Geometry].glLayer.enabled);
1210 
1211         preambleStream << "\n"
1212                        << "void selectView(inout GS_OUTPUT output, GS_INPUT input)\n"
1213                        << "{\n"
1214                        << "    output.gl_Layer = input.gl_ViewID_OVR;\n"
1215                        << "}\n";
1216     }
1217 
1218     return preambleStream.str();
1219 }
1220 
1221 // static
GenerateGeometryShaderHLSL(RendererD3D * renderer,const gl::Caps & caps,gl::PrimitiveMode primitiveType,const bool useViewScale,const bool hasMultiviewEnabled,const bool selectViewInVS,const bool pointSpriteEmulation,const std::string & preambleString)1222 std::string DynamicHLSL::GenerateGeometryShaderHLSL(RendererD3D *renderer,
1223                                                     const gl::Caps &caps,
1224                                                     gl::PrimitiveMode primitiveType,
1225                                                     const bool useViewScale,
1226                                                     const bool hasMultiviewEnabled,
1227                                                     const bool selectViewInVS,
1228                                                     const bool pointSpriteEmulation,
1229                                                     const std::string &preambleString)
1230 {
1231     ASSERT(renderer->getMajorShaderModel() >= 4);
1232 
1233     std::stringstream shaderStream;
1234 
1235     const bool pointSprites = (primitiveType == gl::PrimitiveMode::Points) && pointSpriteEmulation;
1236     const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos;
1237 
1238     const char *inputPT  = nullptr;
1239     const char *outputPT = nullptr;
1240     int inputSize        = 0;
1241     int maxVertexOutput  = 0;
1242 
1243     switch (primitiveType)
1244     {
1245         case gl::PrimitiveMode::Points:
1246             inputPT   = "point";
1247             inputSize = 1;
1248 
1249             if (pointSprites)
1250             {
1251                 outputPT        = "Triangle";
1252                 maxVertexOutput = 4;
1253             }
1254             else
1255             {
1256                 outputPT        = "Point";
1257                 maxVertexOutput = 1;
1258             }
1259 
1260             break;
1261 
1262         case gl::PrimitiveMode::Lines:
1263         case gl::PrimitiveMode::LineStrip:
1264         case gl::PrimitiveMode::LineLoop:
1265             inputPT         = "line";
1266             outputPT        = "Line";
1267             inputSize       = 2;
1268             maxVertexOutput = 2;
1269             break;
1270 
1271         case gl::PrimitiveMode::Triangles:
1272         case gl::PrimitiveMode::TriangleStrip:
1273         case gl::PrimitiveMode::TriangleFan:
1274             inputPT         = "triangle";
1275             outputPT        = "Triangle";
1276             inputSize       = 3;
1277             maxVertexOutput = 3;
1278             break;
1279 
1280         default:
1281             UNREACHABLE();
1282             break;
1283     }
1284 
1285     if (pointSprites || hasMultiviewEnabled)
1286     {
1287         shaderStream << "cbuffer DriverConstants : register(b0)\n"
1288                         "{\n";
1289 
1290         if (pointSprites)
1291         {
1292             shaderStream << "    float4 dx_ViewCoords : packoffset(c1);\n";
1293             if (useViewScale)
1294             {
1295                 shaderStream << "    float2 dx_ViewScale : packoffset(c3.z);\n";
1296             }
1297         }
1298 
1299         shaderStream << "};\n\n";
1300     }
1301 
1302     if (pointSprites)
1303     {
1304         shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
1305                         "\n"
1306                         "static float2 pointSpriteCorners[] = \n"
1307                         "{\n"
1308                         "    float2( 0.5f, -0.5f),\n"
1309                         "    float2( 0.5f,  0.5f),\n"
1310                         "    float2(-0.5f, -0.5f),\n"
1311                         "    float2(-0.5f,  0.5f)\n"
1312                         "};\n"
1313                         "\n"
1314                         "static float2 pointSpriteTexcoords[] = \n"
1315                         "{\n"
1316                         "    float2(1.0f, 1.0f),\n"
1317                         "    float2(1.0f, 0.0f),\n"
1318                         "    float2(0.0f, 1.0f),\n"
1319                         "    float2(0.0f, 0.0f)\n"
1320                         "};\n"
1321                         "\n"
1322                         "static float minPointSize = "
1323                      << static_cast<int>(caps.minAliasedPointSize)
1324                      << ".0f;\n"
1325                         "static float maxPointSize = "
1326                      << static_cast<int>(caps.maxAliasedPointSize) << ".0f;\n"
1327                      << "\n";
1328     }
1329 
1330     shaderStream << preambleString << "\n"
1331                  << "[maxvertexcount(" << maxVertexOutput << ")]\n"
1332                  << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], ";
1333 
1334     if (primitiveType == gl::PrimitiveMode::TriangleStrip)
1335     {
1336         shaderStream << "uint primitiveID : SV_PrimitiveID, ";
1337     }
1338 
1339     shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n"
1340                  << "{\n"
1341                  << "    GS_OUTPUT output = (GS_OUTPUT)0;\n";
1342 
1343     if (primitiveType == gl::PrimitiveMode::TriangleStrip)
1344     {
1345         shaderStream << "    uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n";
1346     }
1347     else
1348     {
1349         shaderStream << "    uint lastVertexIndex = " << (inputSize - 1) << ";\n";
1350     }
1351 
1352     for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex)
1353     {
1354         shaderStream << "    copyVertex(output, input[" << vertexIndex
1355                      << "], input[lastVertexIndex]);\n";
1356         if (hasMultiviewEnabled && !selectViewInVS)
1357         {
1358             shaderStream << "   selectView(output, input[" << vertexIndex << "]);\n";
1359         }
1360         if (!pointSprites)
1361         {
1362             ASSERT(inputSize == maxVertexOutput);
1363             shaderStream << "    outStream.Append(output);\n";
1364         }
1365     }
1366 
1367     if (pointSprites)
1368     {
1369         shaderStream << "\n"
1370                         "    float4 dx_Position = input[0].dx_Position;\n"
1371                         "    float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, "
1372                         "maxPointSize);\n"
1373                         "    float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / "
1374                         "dx_ViewCoords.y) * dx_Position.w;\n";
1375 
1376         for (int corner = 0; corner < 4; corner++)
1377         {
1378             if (useViewScale)
1379             {
1380                 shaderStream << "    \n"
1381                                 "    output.dx_Position = dx_Position + float4(1.0f, "
1382                                 "-dx_ViewScale.y, 1.0f, 1.0f)"
1383                                 "        * float4(pointSpriteCorners["
1384                              << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
1385             }
1386             else
1387             {
1388                 shaderStream << "\n"
1389                                 "    output.dx_Position = dx_Position + float4(pointSpriteCorners["
1390                              << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
1391             }
1392 
1393             if (usesPointCoord)
1394             {
1395                 shaderStream << "    output.gl_PointCoord = pointSpriteTexcoords[" << corner
1396                              << "];\n";
1397             }
1398 
1399             shaderStream << "    outStream.Append(output);\n";
1400         }
1401     }
1402 
1403     shaderStream << "    \n"
1404                     "    outStream.RestartStrip();\n"
1405                     "}\n";
1406 
1407     return shaderStream.str();
1408 }
1409 
1410 // static
GenerateAttributeConversionHLSL(angle::FormatID vertexFormatID,const gl::ProgramInput & shaderAttrib,std::ostringstream & outStream)1411 void DynamicHLSL::GenerateAttributeConversionHLSL(angle::FormatID vertexFormatID,
1412                                                   const gl::ProgramInput &shaderAttrib,
1413                                                   std::ostringstream &outStream)
1414 {
1415     // Matrix
1416     if (IsMatrixType(shaderAttrib.getType()))
1417     {
1418         outStream << "transpose(input." << DecorateVariable(shaderAttrib.name) << ")";
1419         return;
1420     }
1421 
1422     GLenum shaderComponentType           = VariableComponentType(shaderAttrib.getType());
1423     int shaderComponentCount             = VariableComponentCount(shaderAttrib.getType());
1424     const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromID(vertexFormatID);
1425 
1426     // Perform integer to float conversion (if necessary)
1427     if (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT)
1428     {
1429         // TODO: normalization for 32-bit integer formats
1430         ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger);
1431         outStream << "float" << shaderComponentCount << "(input."
1432                   << DecorateVariable(shaderAttrib.name) << ")";
1433         return;
1434     }
1435 
1436     // No conversion necessary
1437     outStream << "input." << DecorateVariable(shaderAttrib.name);
1438 }
1439 
1440 // static
GetPixelShaderOutputKey(RendererD3D * renderer,const gl::Caps & caps,const gl::Version & clientVersion,const gl::ProgramExecutable & executable,const ProgramD3DMetadata & metadata,std::vector<PixelShaderOutputVariable> * outPixelShaderKey)1441 void DynamicHLSL::GetPixelShaderOutputKey(RendererD3D *renderer,
1442                                           const gl::Caps &caps,
1443                                           const gl::Version &clientVersion,
1444                                           const gl::ProgramExecutable &executable,
1445                                           const ProgramD3DMetadata &metadata,
1446                                           std::vector<PixelShaderOutputVariable> *outPixelShaderKey)
1447 {
1448     // Two cases when writing to gl_FragColor and using ESSL 1.0:
1449     // - with a 3.0 context, the output color is copied to channel 0
1450     // - with a 2.0 context, the output color is broadcast to all channels
1451     bool broadcast                      = metadata.usesBroadcast(clientVersion);
1452     const unsigned int numRenderTargets = (broadcast || metadata.usesMultipleFragmentOuts()
1453                                                ? static_cast<unsigned int>(caps.maxDrawBuffers)
1454                                                : 1);
1455 
1456     if (!metadata.usesCustomOutVars())
1457     {
1458         for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets;
1459              renderTargetIndex++)
1460         {
1461             PixelShaderOutputVariable outputKeyVariable;
1462             outputKeyVariable.type = GL_FLOAT_VEC4;
1463             outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
1464             outputKeyVariable.source =
1465                 broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
1466             outputKeyVariable.outputLocation = renderTargetIndex;
1467 
1468             outPixelShaderKey->push_back(outputKeyVariable);
1469         }
1470 
1471         if (metadata.usesSecondaryColor())
1472         {
1473             for (unsigned int secondaryIndex = 0; secondaryIndex < caps.maxDualSourceDrawBuffers;
1474                  secondaryIndex++)
1475             {
1476                 PixelShaderOutputVariable outputKeyVariable;
1477                 outputKeyVariable.type           = GL_FLOAT_VEC4;
1478                 outputKeyVariable.name           = "gl_SecondaryColor" + Str(secondaryIndex);
1479                 outputKeyVariable.source         = "gl_SecondaryColor[" + Str(secondaryIndex) + "]";
1480                 outputKeyVariable.outputLocation = secondaryIndex;
1481                 outputKeyVariable.outputIndex    = 1;
1482 
1483                 outPixelShaderKey->push_back(outputKeyVariable);
1484             }
1485         }
1486     }
1487     else
1488     {
1489         const gl::SharedCompiledShaderState &fragmentShader = metadata.getFragmentShader();
1490 
1491         if (!fragmentShader)
1492         {
1493             return;
1494         }
1495 
1496         const auto &shaderOutputVars = fragmentShader->activeOutputVariables;
1497 
1498         for (size_t outputLocationIndex = 0u;
1499              outputLocationIndex < executable.getOutputLocations().size(); ++outputLocationIndex)
1500         {
1501             const VariableLocation &outputLocation =
1502                 executable.getOutputLocations().at(outputLocationIndex);
1503             if (!outputLocation.used())
1504             {
1505                 continue;
1506             }
1507             const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
1508             const std::string &variableName          = "out_" + outputVariable.name;
1509 
1510             // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6.
1511             const std::string &elementString =
1512                 (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : "");
1513 
1514             ASSERT(outputVariable.active);
1515 
1516             PixelShaderOutputVariable outputKeyVariable;
1517             outputKeyVariable.type = outputVariable.type;
1518             outputKeyVariable.name = variableName + elementString;
1519             outputKeyVariable.source =
1520                 variableName +
1521                 (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : "");
1522             outputKeyVariable.outputLocation = outputLocationIndex;
1523 
1524             outPixelShaderKey->push_back(outputKeyVariable);
1525         }
1526 
1527         // Now generate any secondary outputs...
1528         for (size_t outputLocationIndex = 0u;
1529              outputLocationIndex < executable.getSecondaryOutputLocations().size();
1530              ++outputLocationIndex)
1531         {
1532             const VariableLocation &outputLocation =
1533                 executable.getSecondaryOutputLocations().at(outputLocationIndex);
1534             if (!outputLocation.used())
1535             {
1536                 continue;
1537             }
1538             const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
1539             const std::string &variableName          = "out_" + outputVariable.name;
1540 
1541             // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6.
1542             const std::string &elementString =
1543                 (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : "");
1544 
1545             ASSERT(outputVariable.active);
1546 
1547             PixelShaderOutputVariable outputKeyVariable;
1548             outputKeyVariable.type = outputVariable.type;
1549             outputKeyVariable.name = variableName + elementString;
1550             outputKeyVariable.source =
1551                 variableName +
1552                 (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : "");
1553             outputKeyVariable.outputLocation = outputLocationIndex;
1554             outputKeyVariable.outputIndex    = 1;
1555 
1556             outPixelShaderKey->push_back(outputKeyVariable);
1557         }
1558     }
1559 }
1560 
1561 // BuiltinVarying Implementation.
BuiltinVarying()1562 BuiltinVarying::BuiltinVarying() : enabled(false), indexOrSize(0), systemValue(false) {}
1563 
str() const1564 std::string BuiltinVarying::str() const
1565 {
1566     return (systemValue ? semantic : (semantic + Str(indexOrSize)));
1567 }
1568 
enableSystem(const std::string & systemValueSemantic)1569 void BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
1570 {
1571     enabled     = true;
1572     semantic    = systemValueSemantic;
1573     systemValue = true;
1574 }
1575 
enableSystem(const std::string & systemValueSemantic,unsigned int sizeVal)1576 void BuiltinVarying::enableSystem(const std::string &systemValueSemantic, unsigned int sizeVal)
1577 {
1578     enabled     = true;
1579     semantic    = systemValueSemantic;
1580     systemValue = true;
1581     indexOrSize = sizeVal;
1582 }
1583 
enable(const std::string & semanticVal,unsigned int indexVal)1584 void BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
1585 {
1586     enabled     = true;
1587     semantic    = semanticVal;
1588     indexOrSize = indexVal;
1589 }
1590 
1591 // BuiltinVaryingsD3D Implementation.
BuiltinVaryingsD3D(const ProgramD3DMetadata & metadata,const VaryingPacking & packing)1592 BuiltinVaryingsD3D::BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata,
1593                                        const VaryingPacking &packing)
1594 {
1595     updateBuiltins(gl::ShaderType::Vertex, metadata, packing);
1596     updateBuiltins(gl::ShaderType::Fragment, metadata, packing);
1597     int shaderModel = metadata.getRendererMajorShaderModel();
1598     if (shaderModel >= 4)
1599     {
1600         updateBuiltins(gl::ShaderType::Geometry, metadata, packing);
1601     }
1602     // In shader model >= 4, some builtins need to be the same in vertex and pixel shaders - input
1603     // struct needs to be a prefix of output struct.
1604     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPosition.enabled ==
1605                                   mBuiltinInfo[gl::ShaderType::Fragment].glPosition.enabled);
1606     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glFragCoord.enabled ==
1607                                   mBuiltinInfo[gl::ShaderType::Fragment].glFragCoord.enabled);
1608     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPointCoord.enabled ==
1609                                   mBuiltinInfo[gl::ShaderType::Fragment].glPointCoord.enabled);
1610     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPointSize.enabled ==
1611                                   mBuiltinInfo[gl::ShaderType::Fragment].glPointSize.enabled);
1612     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glViewIDOVR.enabled ==
1613                                   mBuiltinInfo[gl::ShaderType::Fragment].glViewIDOVR.enabled);
1614 }
1615 
1616 BuiltinVaryingsD3D::~BuiltinVaryingsD3D() = default;
1617 
updateBuiltins(gl::ShaderType shaderType,const ProgramD3DMetadata & metadata,const VaryingPacking & packing)1618 void BuiltinVaryingsD3D::updateBuiltins(gl::ShaderType shaderType,
1619                                         const ProgramD3DMetadata &metadata,
1620                                         const VaryingPacking &packing)
1621 {
1622     const std::string &userSemantic = GetVaryingSemantic(metadata.getRendererMajorShaderModel(),
1623                                                          metadata.usesSystemValuePointSize());
1624 
1625     // Note that when enabling builtins only for specific shader stages in shader model >= 4, the
1626     // code needs to ensure that the input struct of the shader stage is a prefix of the output
1627     // struct of the previous stage.
1628 
1629     unsigned int reservedSemanticIndex = packing.getMaxSemanticIndex();
1630 
1631     BuiltinInfo *builtins = &mBuiltinInfo[shaderType];
1632 
1633     if (metadata.getRendererMajorShaderModel() >= 4)
1634     {
1635         builtins->dxPosition.enableSystem("SV_Position");
1636     }
1637     else if (shaderType == gl::ShaderType::Fragment)
1638     {
1639         builtins->dxPosition.enableSystem("VPOS");
1640     }
1641     else
1642     {
1643         builtins->dxPosition.enableSystem("POSITION");
1644     }
1645 
1646     if (metadata.usesTransformFeedbackGLPosition())
1647     {
1648         builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
1649     }
1650 
1651     if (metadata.getClipDistanceArraySize())
1652     {
1653         builtins->glClipDistance.enableSystem("SV_ClipDistance",
1654                                               metadata.getClipDistanceArraySize());
1655     }
1656 
1657     if (metadata.getCullDistanceArraySize())
1658     {
1659         builtins->glCullDistance.enableSystem("SV_CullDistance",
1660                                               metadata.getCullDistanceArraySize());
1661     }
1662 
1663     if (metadata.usesFragCoord())
1664     {
1665         builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
1666     }
1667 
1668     if (shaderType == gl::ShaderType::Vertex ? metadata.addsPointCoordToVertexShader()
1669                                              : metadata.usesPointCoord())
1670     {
1671         // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
1672         // In D3D11 we manually compute gl_PointCoord in the GS.
1673         if (metadata.getRendererMajorShaderModel() >= 4)
1674         {
1675             builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
1676         }
1677         else
1678         {
1679             builtins->glPointCoord.enable("TEXCOORD", 0);
1680         }
1681     }
1682 
1683     if (metadata.hasMultiviewEnabled())
1684     {
1685         // Although it is possible to compute gl_ViewID_OVR from the value of
1686         // SV_RenderTargetArrayIndex, it is easier and cleaner to always pass it as a varying.
1687         builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++);
1688 
1689         if ((shaderType == gl::ShaderType::Vertex && metadata.canSelectViewInVertexShader()) ||
1690             shaderType == gl::ShaderType::Geometry)
1691         {
1692             builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex");
1693         }
1694     }
1695 
1696     // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
1697     if (metadata.usesSystemValuePointSize() &&
1698         (shaderType != gl::ShaderType::Fragment || metadata.getRendererMajorShaderModel() >= 4))
1699     {
1700         builtins->glPointSize.enableSystem("PSIZE");
1701     }
1702 }
1703 
1704 }  // namespace rx
1705