• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,FragDepthUsage fragDepthUsage,bool programUsesPointSize,std::ostringstream & hlslStream)431 void DynamicHLSL::GenerateVaryingLinkHLSL(RendererD3D *renderer,
432                                           const VaryingPacking &varyingPacking,
433                                           const BuiltinInfo &builtins,
434                                           FragDepthUsage fragDepthUsage,
435                                           bool programUsesPointSize,
436                                           std::ostringstream &hlslStream)
437 {
438     ASSERT(builtins.dxPosition.enabled);
439     hlslStream << "{\n";
440     hlslStream << "    ";
441     if (fragDepthUsage == FragDepthUsage::Greater || fragDepthUsage == FragDepthUsage::Less)
442     {
443         // When conservative depth output is used and the pixel shader runs at pixel-frequency,
444         // input position must use centroid interpolation to avoid HLSL compilation errors.
445         // NOTE: Accuracy can be improved by using sample interpolation here,
446         // when a shader already runs at sample-frequency.
447         hlslStream << "centroid ";
448     }
449     hlslStream << "float4 dx_Position : " << builtins.dxPosition.str() << ";\n";
450 
451     if (builtins.glPosition.enabled)
452     {
453         hlslStream << "    float4 gl_Position : " << builtins.glPosition.str() << ";\n";
454     }
455 
456     if (builtins.glClipDistance.enabled)
457     {
458         ASSERT(builtins.glClipDistance.indexOrSize > 0 && builtins.glClipDistance.indexOrSize < 9);
459         for (unsigned int i = 0; i < (builtins.glClipDistance.indexOrSize + 3) >> 2; i++)
460         {
461             unsigned int size = std::min(builtins.glClipDistance.indexOrSize - 4u * i, 4u);
462             hlslStream << "    float" << ((size == 1) ? "" : Str(size)) << " gl_ClipDistance" << i
463                        << " : " << builtins.glClipDistance.str() << i << ";\n";
464         }
465     }
466 
467     if (builtins.glCullDistance.enabled)
468     {
469         ASSERT(builtins.glCullDistance.indexOrSize > 0 && builtins.glCullDistance.indexOrSize < 9);
470         for (unsigned int i = 0; i < (builtins.glCullDistance.indexOrSize + 3) >> 2; i++)
471         {
472             unsigned int size = std::min(builtins.glCullDistance.indexOrSize - 4u * i, 4u);
473             hlslStream << "    float" << ((size == 1) ? "" : Str(size)) << " gl_CullDistance" << i
474                        << " : " << builtins.glCullDistance.str() << i << ";\n";
475         }
476     }
477 
478     if (builtins.glFragCoord.enabled)
479     {
480         hlslStream << "    float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
481     }
482 
483     if (builtins.glPointCoord.enabled)
484     {
485         hlslStream << "    float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
486     }
487 
488     if (builtins.glPointSize.enabled)
489     {
490         hlslStream << "    float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
491     }
492 
493     if (builtins.glViewIDOVR.enabled)
494     {
495         hlslStream << "    nointerpolation uint gl_ViewID_OVR : " << builtins.glViewIDOVR.str()
496                    << ";\n";
497     }
498 
499     std::string varyingSemantic =
500         GetVaryingSemantic(renderer->getMajorShaderModel(), programUsesPointSize);
501 
502     const auto &registerInfos = varyingPacking.getRegisterList();
503     for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
504     {
505         const PackedVaryingRegister &registerInfo = registerInfos[registerIndex];
506         const auto &varying                       = registerInfo.packedVarying->varying();
507         ASSERT(!varying.isStruct());
508 
509         // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
510         // registers being used.
511         // For example, if there are N registers, and we have N vec3 varyings and 1 float
512         // varying, then D3D will pack them into N registers.
513         // If the float varying has the 'nointerpolation' modifier on it then we would need
514         // N + 1 registers, and D3D compilation will fail.
515 
516         switch (registerInfo.packedVarying->interpolation)
517         {
518             case sh::INTERPOLATION_SMOOTH:
519                 hlslStream << "    ";
520                 break;
521             case sh::INTERPOLATION_FLAT:
522                 hlslStream << "    nointerpolation ";
523                 break;
524             case sh::INTERPOLATION_NOPERSPECTIVE:
525                 hlslStream << "    noperspective ";
526                 break;
527             case sh::INTERPOLATION_CENTROID:
528                 hlslStream << "    centroid ";
529                 break;
530             case sh::INTERPOLATION_SAMPLE:
531                 hlslStream << "    sample ";
532                 break;
533             case sh::INTERPOLATION_NOPERSPECTIVE_CENTROID:
534                 hlslStream << "    noperspective centroid ";
535                 break;
536             case sh::INTERPOLATION_NOPERSPECTIVE_SAMPLE:
537                 hlslStream << "    noperspective sample ";
538                 break;
539             default:
540                 UNREACHABLE();
541         }
542 
543         GLenum transposedType = gl::TransposeMatrixType(varying.type);
544         GLenum componentType  = gl::VariableComponentType(transposedType);
545         int columnCount       = gl::VariableColumnCount(transposedType);
546         HLSLComponentTypeString(hlslStream, componentType, columnCount);
547         hlslStream << " v" << registerIndex << " : " << varyingSemantic << registerIndex << ";\n";
548     }
549 
550     // Note that the following outputs need to be declared after the others. They are not included
551     // in pixel shader inputs even when they are in vertex/geometry shader outputs, and the pixel
552     // shader input struct must be a prefix of the vertex/geometry shader output struct.
553 
554     if (builtins.glLayer.enabled)
555     {
556         hlslStream << "    nointerpolation uint gl_Layer : " << builtins.glLayer.str() << ";\n";
557     }
558 
559     hlslStream << "};\n";
560 }
561 
562 // 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)563 void DynamicHLSL::GenerateShaderLinkHLSL(
564     RendererD3D *renderer,
565     const gl::Caps &caps,
566     const gl::ShaderMap<gl::SharedCompiledShaderState> &shaderData,
567     const gl::ShaderMap<SharedCompiledShaderStateD3D> &shaderDataD3D,
568     const ProgramD3DMetadata &programMetadata,
569     const VaryingPacking &varyingPacking,
570     const BuiltinVaryingsD3D &builtinsD3D,
571     gl::ShaderMap<std::string> *shaderHLSL)
572 {
573     ASSERT(shaderHLSL);
574     ASSERT((*shaderHLSL)[gl::ShaderType::Vertex].empty() &&
575            (*shaderHLSL)[gl::ShaderType::Fragment].empty());
576 
577     const gl::SharedCompiledShaderState &vertexShader   = shaderData[ShaderType::Vertex];
578     const gl::SharedCompiledShaderState &fragmentShader = shaderData[ShaderType::Fragment];
579     const int shaderModel                               = renderer->getMajorShaderModel();
580 
581     const SharedCompiledShaderStateD3D &fragmentShaderD3D = shaderDataD3D[ShaderType::Fragment];
582 
583     // usesViewScale() isn't supported in the D3D9 renderer
584     ASSERT(shaderModel >= 4 || !programMetadata.usesViewScale());
585 
586     // Validation done in the compiler
587     ASSERT(!fragmentShaderD3D || !fragmentShaderD3D->usesFragColor ||
588            !fragmentShaderD3D->usesFragData);
589 
590     std::ostringstream vertexStream;
591     vertexStream << "struct VS_OUTPUT\n";
592     const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex];
593     GenerateVaryingLinkHLSL(renderer, varyingPacking, vertexBuiltins, FragDepthUsage::Unused,
594                             builtinsD3D.usesPointSize(), vertexStream);
595 
596     std::ostringstream vertexGenerateOutput;
597     vertexGenerateOutput << "VS_OUTPUT generateOutput(VS_INPUT input)\n"
598                          << "{\n"
599                          << "    VS_OUTPUT output;\n";
600 
601     if (vertexBuiltins.glPosition.enabled)
602     {
603         vertexGenerateOutput << "    output.gl_Position = gl_Position;\n";
604     }
605 
606     if (vertexBuiltins.glClipDistance.enabled)
607     {
608         ASSERT(vertexBuiltins.glClipDistance.indexOrSize > 0 &&
609                vertexBuiltins.glClipDistance.indexOrSize < 9);
610         vertexGenerateOutput << "    output.gl_ClipDistance0 = (clipDistancesEnabled & ";
611         switch (vertexBuiltins.glClipDistance.indexOrSize)
612         {
613             case 1:
614                 vertexGenerateOutput << "1) ? (float)gl_ClipDistance : 0;\n";
615                 break;
616             case 2:
617                 vertexGenerateOutput << "int2(1, 2)) ? (float2)gl_ClipDistance : 0;\n";
618                 break;
619             case 3:
620                 vertexGenerateOutput << "int3(1, 2, 4)) ? (float3)gl_ClipDistance : 0;\n";
621                 break;
622             default:
623                 vertexGenerateOutput << "int4(1, 2, 4, 8)) ? (float4)gl_ClipDistance : 0;\n";
624                 break;
625         }
626         if (vertexBuiltins.glClipDistance.indexOrSize > 4)
627         {
628             vertexGenerateOutput << "    output.gl_ClipDistance1 = (clipDistancesEnabled & ";
629             switch (vertexBuiltins.glClipDistance.indexOrSize)
630             {
631                 case 5:
632                     vertexGenerateOutput << "16) ? gl_ClipDistance[4] : 0;\n";
633                     break;
634                 case 6:
635                     vertexGenerateOutput << "int2(16, 32)) ? "
636                                             "((float2[3])gl_ClipDistance)[2] : 0;\n";
637                     break;
638                 case 7:
639                     vertexGenerateOutput << "int3(16, 32, 64)) ? float3(gl_ClipDistance[4], "
640                                             "gl_ClipDistance[5], gl_ClipDistance[6]) : 0;\n";
641                     break;
642                 case 8:
643                     vertexGenerateOutput << "int4(16, 32, 64, 128)) ? "
644                                             "((float4[2])gl_ClipDistance)[1] : 0;\n";
645                     break;
646             }
647         }
648     }
649 
650     if (vertexBuiltins.glCullDistance.enabled)
651     {
652         ASSERT(vertexBuiltins.glCullDistance.indexOrSize > 0 &&
653                vertexBuiltins.glCullDistance.indexOrSize < 9);
654         vertexGenerateOutput << "    output.gl_CullDistance0 = ";
655         switch (vertexBuiltins.glCullDistance.indexOrSize)
656         {
657             case 1:
658                 vertexGenerateOutput << "(float)gl_CullDistance;\n";
659                 break;
660             case 2:
661                 vertexGenerateOutput << "(float2)gl_CullDistance;\n";
662                 break;
663             case 3:
664                 vertexGenerateOutput << "(float3)gl_CullDistance;\n";
665                 break;
666             default:
667                 vertexGenerateOutput << "(float4)gl_CullDistance;\n";
668                 break;
669         }
670         if (vertexBuiltins.glCullDistance.indexOrSize > 4)
671         {
672             vertexGenerateOutput << "    output.gl_CullDistance1 = ";
673             switch (vertexBuiltins.glCullDistance.indexOrSize)
674             {
675                 case 5:
676                     vertexGenerateOutput << "gl_CullDistance[4];\n";
677                     break;
678                 case 6:
679                     vertexGenerateOutput << "((float2[3])gl_CullDistance)[2];\n";
680                     break;
681                 case 7:
682                     vertexGenerateOutput << "float3(gl_CullDistance[4], "
683                                             "gl_CullDistance[5], gl_CullDistance[6]);\n";
684                     break;
685                 case 8:
686                     vertexGenerateOutput << "((float4[2])gl_CullDistance)[1];\n";
687                     break;
688             }
689         }
690     }
691 
692     if (vertexBuiltins.glViewIDOVR.enabled)
693     {
694         vertexGenerateOutput << "    output.gl_ViewID_OVR = ViewID_OVR;\n";
695     }
696     if (programMetadata.hasMultiviewEnabled() && programMetadata.canSelectViewInVertexShader())
697     {
698         ASSERT(vertexBuiltins.glLayer.enabled);
699         vertexGenerateOutput << "    output.gl_Layer = ViewID_OVR;\n";
700     }
701 
702     // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
703     if (shaderModel >= 4 && renderer->getShaderModelSuffix() == "")
704     {
705         vertexGenerateOutput << "    output.dx_Position.x = gl_Position.x;\n";
706 
707         if (programMetadata.usesViewScale())
708         {
709             // This code assumes that dx_ViewScale.y = -1.0f when rendering to texture, and +1.0f
710             // when rendering to the default framebuffer. No other values are valid.
711             vertexGenerateOutput << "    output.dx_Position.y = dx_ViewScale.y * gl_Position.y;\n";
712         }
713         else
714         {
715             vertexGenerateOutput
716                 << "    output.dx_Position.y = clipControlOrigin * gl_Position.y;\n";
717         }
718 
719         vertexGenerateOutput
720             << "    if (clipControlZeroToOne)\n"
721             << "    {\n"
722             << "        output.dx_Position.z = gl_Position.z;\n"
723             << "    } else {\n"
724             << "        output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
725             << "    }\n";
726 
727         vertexGenerateOutput << "    output.dx_Position.w = gl_Position.w;\n";
728     }
729     else
730     {
731         vertexGenerateOutput << "    output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + "
732                                 "dx_ViewAdjust.x * gl_Position.w;\n";
733 
734         // If usesViewScale() is true and we're using the D3D11 renderer via Feature Level 9_*,
735         // then we need to multiply the gl_Position.y by the viewScale.
736         // usesViewScale() isn't supported when using the D3D9 renderer.
737         if (programMetadata.usesViewScale() &&
738             (shaderModel >= 4 && renderer->getShaderModelSuffix() != ""))
739         {
740             vertexGenerateOutput << "    output.dx_Position.y = dx_ViewScale.y * (gl_Position.y * "
741                                     "dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n";
742         }
743         else
744         {
745             vertexGenerateOutput << "    output.dx_Position.y = clipControlOrigin * (gl_Position.y "
746                                     "* dx_ViewAdjust.w + "
747                                     "dx_ViewAdjust.y * gl_Position.w);\n";
748         }
749 
750         vertexGenerateOutput
751             << "    if (clipControlZeroToOne)\n"
752             << "    {\n"
753             << "        output.dx_Position.z = gl_Position.z;\n"
754             << "    } else {\n"
755             << "        output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
756             << "    }\n";
757 
758         vertexGenerateOutput << "    output.dx_Position.w = gl_Position.w;\n";
759     }
760 
761     // We don't need to output gl_PointSize if we use are emulating point sprites via instancing.
762     if (vertexBuiltins.glPointSize.enabled)
763     {
764         vertexGenerateOutput << "    output.gl_PointSize = gl_PointSize;\n";
765     }
766 
767     if (vertexBuiltins.glFragCoord.enabled)
768     {
769         vertexGenerateOutput << "    output.gl_FragCoord = gl_Position;\n";
770     }
771 
772     const auto &registerInfos = varyingPacking.getRegisterList();
773     for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
774     {
775         const PackedVaryingRegister &registerInfo = registerInfos[registerIndex];
776         const auto &packedVarying                 = *registerInfo.packedVarying;
777         const auto &varying                       = *packedVarying.frontVarying.varying;
778         ASSERT(!varying.isStruct());
779 
780         vertexGenerateOutput << "    output.v" << registerIndex << " = ";
781 
782         if (packedVarying.isStructField())
783         {
784             vertexGenerateOutput << DecorateVariable(packedVarying.frontVarying.parentStructName)
785                                  << ".";
786         }
787 
788         vertexGenerateOutput << DecorateVariable(varying.name);
789 
790         if (varying.isArray())
791         {
792             WriteArrayString(vertexGenerateOutput, registerInfo.varyingArrayIndex);
793         }
794 
795         if (VariableRowCount(varying.type) > 1)
796         {
797             WriteArrayString(vertexGenerateOutput, registerInfo.varyingRowIndex);
798         }
799 
800         vertexGenerateOutput << ";\n";
801     }
802 
803     // Renderers that enable instanced pointsprite emulation require the vertex shader output member
804     // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same
805     // default value used in the generated pixel shader.
806     if (programMetadata.usesInsertedPointCoordValue())
807     {
808         vertexGenerateOutput << "\n"
809                                 "    output.gl_PointCoord = float2(0.5, 0.5);\n";
810     }
811 
812     vertexGenerateOutput << "\n"
813                             "    return output;\n"
814                             "}";
815 
816     if (vertexShader)
817     {
818         std::string vertexSource = vertexShader->translatedSource;
819         angle::ReplaceSubstring(&vertexSource, std::string(MAIN_PROLOGUE_STUB_STRING),
820                                 "    initAttributes(input);\n");
821         angle::ReplaceSubstring(&vertexSource, std::string(VERTEX_OUTPUT_STUB_STRING),
822                                 vertexGenerateOutput.str());
823         vertexStream << vertexSource;
824     }
825 
826     const auto &pixelBuiltins = builtinsD3D[gl::ShaderType::Fragment];
827 
828     std::ostringstream pixelStream;
829     pixelStream << "struct PS_INPUT\n";
830     GenerateVaryingLinkHLSL(renderer, varyingPacking, pixelBuiltins,
831                             programMetadata.getFragDepthUsage(), builtinsD3D.usesPointSize(),
832                             pixelStream);
833     pixelStream << "\n";
834 
835     std::ostringstream pixelPrologue;
836     if (fragmentShaderD3D && fragmentShaderD3D->usesViewID)
837     {
838         ASSERT(pixelBuiltins.glViewIDOVR.enabled);
839         pixelPrologue << "    ViewID_OVR = input.gl_ViewID_OVR;\n";
840     }
841 
842     if (pixelBuiltins.glFragCoord.enabled)
843     {
844         pixelPrologue << "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
845 
846         // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader.
847         // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using
848         // dx_ViewCoords.
849         // DComp usually gives us an offset at (0, 0), but this is not always the case. It is
850         // valid for DComp to give us an offset into the texture atlas. In that scenario, we
851         // need to offset gl_FragCoord using dx_FragCoordOffset to point to the correct location
852         // of the pixel.
853         if (shaderModel >= 4 && renderer->getShaderModelSuffix() == "")
854         {
855             pixelPrologue << "    gl_FragCoord.x = input.dx_Position.x - dx_FragCoordOffset.x;\n"
856                           << "    gl_FragCoord.y = input.dx_Position.y - dx_FragCoordOffset.y;\n";
857         }
858         else if (shaderModel == 3)
859         {
860             pixelPrologue
861                 << "    gl_FragCoord.x = input.dx_Position.x + 0.5 - dx_FragCoordOffset.x;\n"
862                 << "    gl_FragCoord.y = input.dx_Position.y + 0.5 - dx_FragCoordOffset.y;\n";
863         }
864         else
865         {
866             // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See
867             // Renderer::setViewport()
868             pixelPrologue
869                 << "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + "
870                    "dx_ViewCoords.z - dx_FragCoordOffset.x;\n"
871                 << "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + "
872                    "dx_ViewCoords.w - dx_FragCoordOffset.y;\n";
873         }
874 
875         if (programMetadata.usesViewScale())
876         {
877             // For Feature Level 9_3 and below, we need to correct gl_FragCoord.y to account
878             // for dx_ViewScale. On Feature Level 10_0+, gl_FragCoord.y is calculated above using
879             // dx_ViewCoords and is always correct irrespective of dx_ViewScale's value.
880             // NOTE: usesViewScale() can only be true on D3D11 (i.e. Shader Model 4.0+).
881             if (shaderModel >= 4 && renderer->getShaderModelSuffix() == "")
882             {
883                 // Some assumptions:
884                 //  - dx_ViewScale.y = -1.0f when rendering to texture
885                 //  - dx_ViewScale.y = +1.0f when rendering to the default framebuffer
886                 //  - gl_FragCoord.y has been set correctly above.
887                 //
888                 // When rendering to the backbuffer, the code inverts gl_FragCoord's y coordinate.
889                 // This involves subtracting the y coordinate from the height of the area being
890                 // rendered to.
891                 //
892                 // First we calculate the height of the area being rendered to:
893                 //    render_area_height = (2.0f / (1.0f - input.gl_FragCoord.y * rhw)) *
894                 //    gl_FragCoord.y
895                 //
896                 // Note that when we're rendering to default FB, we want our output to be
897                 // equivalent to:
898                 //    "gl_FragCoord.y = render_area_height - gl_FragCoord.y"
899                 //
900                 // When we're rendering to a texture, we want our output to be equivalent to:
901                 //    "gl_FragCoord.y = gl_FragCoord.y;"
902                 //
903                 // If we set scale_factor = ((1.0f + dx_ViewScale.y) / 2.0f), then notice that
904                 //  - When rendering to default FB: scale_factor = 1.0f
905                 //  - When rendering to texture:    scale_factor = 0.0f
906                 //
907                 // Therefore, we can get our desired output by setting:
908                 //    "gl_FragCoord.y = scale_factor * render_area_height - dx_ViewScale.y *
909                 //    gl_FragCoord.y"
910                 //
911                 // Simplifying, this becomes:
912                 pixelPrologue
913                     << "    gl_FragCoord.y = (1.0f + dx_ViewScale.y) * gl_FragCoord.y /"
914                        "(1.0f - input.gl_FragCoord.y * rhw)  - dx_ViewScale.y * gl_FragCoord.y;\n";
915             }
916         }
917 
918         if (shaderModel >= 4 && renderer->getShaderModelSuffix() == "")
919         {
920             pixelPrologue << "    gl_FragCoord.z = input.dx_Position.z;\n";
921         }
922         else
923         {
924             pixelPrologue
925                 << "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + "
926                    "dx_DepthFront.y;\n";
927         }
928         pixelPrologue << "    gl_FragCoord.w = rhw;\n";
929     }
930 
931     if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3)
932     {
933         pixelPrologue << "    gl_PointCoord.x = input.gl_PointCoord.x;\n"
934                       << "    gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
935     }
936 
937     if (fragmentShaderD3D && fragmentShaderD3D->usesFrontFacing)
938     {
939         if (shaderModel <= 3)
940         {
941             pixelPrologue << "    gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
942         }
943         else
944         {
945             pixelPrologue << "    gl_FrontFacing = isFrontFace;\n";
946         }
947     }
948 
949     bool declareSampleID = false;
950     if (fragmentShaderD3D && fragmentShaderD3D->usesSampleID)
951     {
952         declareSampleID = true;
953         pixelPrologue << "    gl_SampleID = sampleID;\n";
954     }
955 
956     if (fragmentShaderD3D && fragmentShaderD3D->usesSamplePosition)
957     {
958         declareSampleID = true;
959         pixelPrologue << "    gl_SamplePosition = GetRenderTargetSamplePosition(sampleID) + 0.5;\n";
960     }
961 
962     if (fragmentShaderD3D && fragmentShaderD3D->clipDistanceSize)
963     {
964         ASSERT(vertexBuiltins.glClipDistance.indexOrSize > 0 &&
965                vertexBuiltins.glClipDistance.indexOrSize < 9);
966         switch (pixelBuiltins.glClipDistance.indexOrSize)
967         {
968             case 1:
969                 pixelPrologue << "    (float)gl_ClipDistance = input.gl_ClipDistance0;\n";
970                 break;
971             case 2:
972                 pixelPrologue << "    (float2)gl_ClipDistance = input.gl_ClipDistance0;\n";
973                 break;
974             case 3:
975                 pixelPrologue << "    (float3)gl_ClipDistance = input.gl_ClipDistance0;\n";
976                 break;
977             default:
978                 pixelPrologue << "    (float4)gl_ClipDistance = input.gl_ClipDistance0;\n";
979                 break;
980         }
981         switch (pixelBuiltins.glClipDistance.indexOrSize)
982         {
983             case 5:
984                 pixelPrologue << "    gl_ClipDistance[4] = input.gl_ClipDistance1;\n";
985                 break;
986             case 6:
987                 pixelPrologue << "    ((float2[3])gl_ClipDistance)[2] = input.gl_ClipDistance1;\n";
988                 break;
989             case 7:
990                 pixelPrologue << "    gl_ClipDistance[4] = input.gl_ClipDistance1.x;\n";
991                 pixelPrologue << "    gl_ClipDistance[5] = input.gl_ClipDistance1.y;\n";
992                 pixelPrologue << "    gl_ClipDistance[6] = input.gl_ClipDistance1.z;\n";
993                 break;
994             case 8:
995                 pixelPrologue << "    ((float4[2])gl_ClipDistance)[1] = input.gl_ClipDistance1;\n";
996                 break;
997         }
998     }
999 
1000     if (fragmentShaderD3D && fragmentShaderD3D->cullDistanceSize)
1001     {
1002         ASSERT(vertexBuiltins.glCullDistance.indexOrSize > 0 &&
1003                vertexBuiltins.glCullDistance.indexOrSize < 9);
1004         switch (pixelBuiltins.glCullDistance.indexOrSize)
1005         {
1006             case 1:
1007                 pixelPrologue << "    (float)gl_CullDistance = input.gl_CullDistance0;\n";
1008                 break;
1009             case 2:
1010                 pixelPrologue << "    (float2)gl_CullDistance = input.gl_CullDistance0;\n";
1011                 break;
1012             case 3:
1013                 pixelPrologue << "    (float3)gl_CullDistance = input.gl_CullDistance0;\n";
1014                 break;
1015             default:
1016                 pixelPrologue << "    (float4)gl_CullDistance = input.gl_CullDistance0;\n";
1017                 break;
1018         }
1019         switch (pixelBuiltins.glCullDistance.indexOrSize)
1020         {
1021             case 5:
1022                 pixelPrologue << "    gl_CullDistance[4] = input.gl_CullDistance1;\n";
1023                 break;
1024             case 6:
1025                 pixelPrologue << "    ((float2[3])gl_CullDistance)[2] = input.gl_CullDistance1;\n";
1026                 break;
1027             case 7:
1028                 pixelPrologue << "    gl_CullDistance[4] = input.gl_CullDistance1.x;\n";
1029                 pixelPrologue << "    gl_CullDistance[5] = input.gl_CullDistance1.y;\n";
1030                 pixelPrologue << "    gl_CullDistance[6] = input.gl_CullDistance1.z;\n";
1031                 break;
1032             case 8:
1033                 pixelPrologue << "    ((float4[2])gl_CullDistance)[1] = input.gl_CullDistance1;\n";
1034                 break;
1035         }
1036     }
1037 
1038     bool usesSampleInterpolation = false;
1039     for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
1040     {
1041         const PackedVaryingRegister &registerInfo = registerInfos[registerIndex];
1042         const auto &packedVarying                 = *registerInfo.packedVarying;
1043 
1044         // Don't reference VS-only transform feedback varyings in the PS.
1045         if (packedVarying.vertexOnly())
1046         {
1047             continue;
1048         }
1049 
1050         const auto &varying = *packedVarying.backVarying.varying;
1051         ASSERT(!varying.isBuiltIn() && !varying.isStruct());
1052 
1053         // Note that we're relying on that the active flag is set according to usage in the fragment
1054         // shader.
1055         if (!varying.active)
1056         {
1057             continue;
1058         }
1059 
1060         if (packedVarying.interpolation == sh::InterpolationType::INTERPOLATION_SAMPLE ||
1061             packedVarying.interpolation ==
1062                 sh::InterpolationType::INTERPOLATION_NOPERSPECTIVE_SAMPLE)
1063         {
1064             usesSampleInterpolation = true;
1065         }
1066 
1067         pixelPrologue << "    ";
1068 
1069         if (packedVarying.isStructField())
1070         {
1071             pixelPrologue << DecorateVariable(packedVarying.backVarying.parentStructName) << ".";
1072         }
1073 
1074         pixelPrologue << DecorateVariable(varying.name);
1075 
1076         if (varying.isArray())
1077         {
1078             WriteArrayString(pixelPrologue, registerInfo.varyingArrayIndex);
1079         }
1080 
1081         GLenum transposedType = TransposeMatrixType(varying.type);
1082         if (VariableRowCount(transposedType) > 1)
1083         {
1084             WriteArrayString(pixelPrologue, registerInfo.varyingRowIndex);
1085         }
1086 
1087         pixelPrologue << " = input.v" << registerIndex;
1088 
1089         switch (VariableColumnCount(transposedType))
1090         {
1091             case 1:
1092                 pixelPrologue << ".x";
1093                 break;
1094             case 2:
1095                 pixelPrologue << ".xy";
1096                 break;
1097             case 3:
1098                 pixelPrologue << ".xyz";
1099                 break;
1100             case 4:
1101                 break;
1102             default:
1103                 UNREACHABLE();
1104         }
1105         pixelPrologue << ";\n";
1106     }
1107 
1108     if (fragmentShaderD3D && fragmentShaderD3D->usesSampleMaskIn)
1109     {
1110         // When per-sample shading is active due to the use of a fragment input qualified
1111         // by sample or due to the use of the gl_SampleID or gl_SamplePosition variables,
1112         // only the bit for the current sample is set in gl_SampleMaskIn.
1113         declareSampleID = declareSampleID || usesSampleInterpolation;
1114         pixelPrologue << "    gl_SampleMaskIn[0] = "
1115                       << (declareSampleID ? "1 << sampleID" : "sampleMaskIn") << ";\n";
1116     }
1117 
1118     if (fragmentShader)
1119     {
1120         std::string pixelSource = fragmentShader->translatedSource;
1121 
1122         std::ostringstream pixelMainParametersStream;
1123         pixelMainParametersStream << "PS_INPUT input";
1124 
1125         if (fragmentShaderD3D->usesFrontFacing)
1126         {
1127             pixelMainParametersStream << (shaderModel >= 4 ? ", bool isFrontFace : SV_IsFrontFace"
1128                                                            : ", float vFace : VFACE");
1129         }
1130 
1131         if (declareSampleID)
1132         {
1133             pixelMainParametersStream << ", uint sampleID : SV_SampleIndex";
1134         }
1135         else if (fragmentShaderD3D->usesSampleMaskIn)
1136         {
1137             pixelMainParametersStream << ", uint sampleMaskIn : SV_Coverage";
1138         }
1139 
1140         angle::ReplaceSubstring(&pixelSource, std::string(PIXEL_MAIN_PARAMETERS_STUB_STRING),
1141                                 pixelMainParametersStream.str());
1142 
1143         angle::ReplaceSubstring(&pixelSource, std::string(MAIN_PROLOGUE_STUB_STRING),
1144                                 pixelPrologue.str());
1145         pixelStream << pixelSource;
1146     }
1147 
1148     (*shaderHLSL)[gl::ShaderType::Vertex]   = vertexStream.str();
1149     (*shaderHLSL)[gl::ShaderType::Fragment] = pixelStream.str();
1150 }
1151 
1152 // static
GenerateGeometryShaderPreamble(RendererD3D * renderer,const VaryingPacking & varyingPacking,const BuiltinVaryingsD3D & builtinsD3D,const bool hasMultiviewEnabled,const bool selectViewInVS)1153 std::string DynamicHLSL::GenerateGeometryShaderPreamble(RendererD3D *renderer,
1154                                                         const VaryingPacking &varyingPacking,
1155                                                         const BuiltinVaryingsD3D &builtinsD3D,
1156                                                         const bool hasMultiviewEnabled,
1157                                                         const bool selectViewInVS)
1158 {
1159     ASSERT(renderer->getMajorShaderModel() >= 4);
1160 
1161     std::ostringstream preambleStream;
1162 
1163     const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex];
1164 
1165     preambleStream << "struct GS_INPUT\n";
1166     GenerateVaryingLinkHLSL(renderer, varyingPacking, vertexBuiltins, FragDepthUsage::Unused,
1167                             builtinsD3D.usesPointSize(), preambleStream);
1168     preambleStream << "\n"
1169                       "struct GS_OUTPUT\n";
1170     GenerateVaryingLinkHLSL(renderer, varyingPacking, builtinsD3D[gl::ShaderType::Geometry],
1171                             FragDepthUsage::Unused, builtinsD3D.usesPointSize(), preambleStream);
1172     preambleStream
1173         << "\n"
1174         << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n"
1175         << "{\n"
1176         << "    output.gl_Position = input.gl_Position;\n";
1177 
1178     if (vertexBuiltins.glPointSize.enabled)
1179     {
1180         preambleStream << "    output.gl_PointSize = input.gl_PointSize;\n";
1181     }
1182 
1183     if (hasMultiviewEnabled)
1184     {
1185         preambleStream << "    output.gl_ViewID_OVR = input.gl_ViewID_OVR;\n";
1186         if (selectViewInVS)
1187         {
1188             ASSERT(builtinsD3D[gl::ShaderType::Geometry].glLayer.enabled);
1189 
1190             // If the view is already selected in the VS, then we just pass gl_Layer to the output.
1191             preambleStream << "    output.gl_Layer = input.gl_Layer;\n";
1192         }
1193     }
1194 
1195     const auto &registerInfos = varyingPacking.getRegisterList();
1196     for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
1197     {
1198         const PackedVaryingRegister &varyingRegister = registerInfos[registerIndex];
1199         preambleStream << "    output.v" << registerIndex << " = ";
1200         if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT)
1201         {
1202             preambleStream << "flat";
1203         }
1204         preambleStream << "input.v" << registerIndex << "; \n";
1205     }
1206 
1207     if (vertexBuiltins.glFragCoord.enabled)
1208     {
1209         preambleStream << "    output.gl_FragCoord = input.gl_FragCoord;\n";
1210     }
1211 
1212     // Only write the dx_Position if we aren't using point sprites
1213     preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n"
1214                    << "    output.dx_Position = input.dx_Position;\n"
1215                    << "#endif  // ANGLE_POINT_SPRITE_SHADER\n"
1216                    << "}\n";
1217 
1218     if (hasMultiviewEnabled && !selectViewInVS)
1219     {
1220         ASSERT(builtinsD3D[gl::ShaderType::Geometry].glLayer.enabled);
1221 
1222         preambleStream << "\n"
1223                        << "void selectView(inout GS_OUTPUT output, GS_INPUT input)\n"
1224                        << "{\n"
1225                        << "    output.gl_Layer = input.gl_ViewID_OVR;\n"
1226                        << "}\n";
1227     }
1228 
1229     return preambleStream.str();
1230 }
1231 
1232 // 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)1233 std::string DynamicHLSL::GenerateGeometryShaderHLSL(RendererD3D *renderer,
1234                                                     const gl::Caps &caps,
1235                                                     gl::PrimitiveMode primitiveType,
1236                                                     const bool useViewScale,
1237                                                     const bool hasMultiviewEnabled,
1238                                                     const bool selectViewInVS,
1239                                                     const bool pointSpriteEmulation,
1240                                                     const std::string &preambleString)
1241 {
1242     ASSERT(renderer->getMajorShaderModel() >= 4);
1243 
1244     std::stringstream shaderStream;
1245 
1246     const bool pointSprites = (primitiveType == gl::PrimitiveMode::Points) && pointSpriteEmulation;
1247     const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos;
1248 
1249     const char *inputPT  = nullptr;
1250     const char *outputPT = nullptr;
1251     int inputSize        = 0;
1252     int maxVertexOutput  = 0;
1253 
1254     switch (primitiveType)
1255     {
1256         case gl::PrimitiveMode::Points:
1257             inputPT   = "point";
1258             inputSize = 1;
1259 
1260             if (pointSprites)
1261             {
1262                 outputPT        = "Triangle";
1263                 maxVertexOutput = 4;
1264             }
1265             else
1266             {
1267                 outputPT        = "Point";
1268                 maxVertexOutput = 1;
1269             }
1270 
1271             break;
1272 
1273         case gl::PrimitiveMode::Lines:
1274         case gl::PrimitiveMode::LineStrip:
1275         case gl::PrimitiveMode::LineLoop:
1276             inputPT         = "line";
1277             outputPT        = "Line";
1278             inputSize       = 2;
1279             maxVertexOutput = 2;
1280             break;
1281 
1282         case gl::PrimitiveMode::Triangles:
1283         case gl::PrimitiveMode::TriangleStrip:
1284         case gl::PrimitiveMode::TriangleFan:
1285             inputPT         = "triangle";
1286             outputPT        = "Triangle";
1287             inputSize       = 3;
1288             maxVertexOutput = 3;
1289             break;
1290 
1291         default:
1292             UNREACHABLE();
1293             break;
1294     }
1295 
1296     if (pointSprites || hasMultiviewEnabled)
1297     {
1298         shaderStream << "cbuffer DriverConstants : register(b0)\n"
1299                         "{\n";
1300 
1301         if (pointSprites)
1302         {
1303             shaderStream << "    float4 dx_ViewCoords : packoffset(c1);\n";
1304             if (useViewScale)
1305             {
1306                 shaderStream << "    float2 dx_ViewScale : packoffset(c3.z);\n";
1307             }
1308         }
1309 
1310         shaderStream << "};\n\n";
1311     }
1312 
1313     if (pointSprites)
1314     {
1315         shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
1316                         "\n"
1317                         "static float2 pointSpriteCorners[] = \n"
1318                         "{\n"
1319                         "    float2( 0.5f, -0.5f),\n"
1320                         "    float2( 0.5f,  0.5f),\n"
1321                         "    float2(-0.5f, -0.5f),\n"
1322                         "    float2(-0.5f,  0.5f)\n"
1323                         "};\n"
1324                         "\n"
1325                         "static float2 pointSpriteTexcoords[] = \n"
1326                         "{\n"
1327                         "    float2(1.0f, 1.0f),\n"
1328                         "    float2(1.0f, 0.0f),\n"
1329                         "    float2(0.0f, 1.0f),\n"
1330                         "    float2(0.0f, 0.0f)\n"
1331                         "};\n"
1332                         "\n"
1333                         "static float minPointSize = "
1334                      << static_cast<int>(caps.minAliasedPointSize)
1335                      << ".0f;\n"
1336                         "static float maxPointSize = "
1337                      << static_cast<int>(caps.maxAliasedPointSize) << ".0f;\n"
1338                      << "\n";
1339     }
1340 
1341     shaderStream << preambleString << "\n"
1342                  << "[maxvertexcount(" << maxVertexOutput << ")]\n"
1343                  << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], ";
1344 
1345     if (primitiveType == gl::PrimitiveMode::TriangleStrip)
1346     {
1347         shaderStream << "uint primitiveID : SV_PrimitiveID, ";
1348     }
1349 
1350     shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n"
1351                  << "{\n"
1352                  << "    GS_OUTPUT output = (GS_OUTPUT)0;\n";
1353 
1354     if (primitiveType == gl::PrimitiveMode::TriangleStrip)
1355     {
1356         shaderStream << "    uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n";
1357     }
1358     else
1359     {
1360         shaderStream << "    uint lastVertexIndex = " << (inputSize - 1) << ";\n";
1361     }
1362 
1363     for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex)
1364     {
1365         shaderStream << "    copyVertex(output, input[" << vertexIndex
1366                      << "], input[lastVertexIndex]);\n";
1367         if (hasMultiviewEnabled && !selectViewInVS)
1368         {
1369             shaderStream << "   selectView(output, input[" << vertexIndex << "]);\n";
1370         }
1371         if (!pointSprites)
1372         {
1373             ASSERT(inputSize == maxVertexOutput);
1374             shaderStream << "    outStream.Append(output);\n";
1375         }
1376     }
1377 
1378     if (pointSprites)
1379     {
1380         shaderStream << "\n"
1381                         "    float4 dx_Position = input[0].dx_Position;\n"
1382                         "    float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, "
1383                         "maxPointSize);\n"
1384                         "    float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / "
1385                         "dx_ViewCoords.y) * dx_Position.w;\n";
1386 
1387         for (int corner = 0; corner < 4; corner++)
1388         {
1389             if (useViewScale)
1390             {
1391                 shaderStream << "    \n"
1392                                 "    output.dx_Position = dx_Position + float4(1.0f, "
1393                                 "-dx_ViewScale.y, 1.0f, 1.0f)"
1394                                 "        * float4(pointSpriteCorners["
1395                              << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
1396             }
1397             else
1398             {
1399                 shaderStream << "\n"
1400                                 "    output.dx_Position = dx_Position + float4(pointSpriteCorners["
1401                              << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
1402             }
1403 
1404             if (usesPointCoord)
1405             {
1406                 shaderStream << "    output.gl_PointCoord = pointSpriteTexcoords[" << corner
1407                              << "];\n";
1408             }
1409 
1410             shaderStream << "    outStream.Append(output);\n";
1411         }
1412     }
1413 
1414     shaderStream << "    \n"
1415                     "    outStream.RestartStrip();\n"
1416                     "}\n";
1417 
1418     return shaderStream.str();
1419 }
1420 
1421 // static
GenerateAttributeConversionHLSL(angle::FormatID vertexFormatID,const gl::ProgramInput & shaderAttrib,std::ostringstream & outStream)1422 void DynamicHLSL::GenerateAttributeConversionHLSL(angle::FormatID vertexFormatID,
1423                                                   const gl::ProgramInput &shaderAttrib,
1424                                                   std::ostringstream &outStream)
1425 {
1426     // Matrix
1427     if (IsMatrixType(shaderAttrib.getType()))
1428     {
1429         outStream << "transpose(input." << DecorateVariable(shaderAttrib.name) << ")";
1430         return;
1431     }
1432 
1433     GLenum shaderComponentType           = VariableComponentType(shaderAttrib.getType());
1434     int shaderComponentCount             = VariableComponentCount(shaderAttrib.getType());
1435     const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromID(vertexFormatID);
1436 
1437     // Perform integer to float conversion (if necessary)
1438     if (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT)
1439     {
1440         // TODO: normalization for 32-bit integer formats
1441         ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger);
1442         outStream << "float" << shaderComponentCount << "(input."
1443                   << DecorateVariable(shaderAttrib.name) << ")";
1444         return;
1445     }
1446 
1447     // No conversion necessary
1448     outStream << "input." << DecorateVariable(shaderAttrib.name);
1449 }
1450 
1451 // static
GetPixelShaderOutputKey(RendererD3D * renderer,const gl::Caps & caps,const gl::Version & clientVersion,const gl::ProgramExecutable & executable,const ProgramD3DMetadata & metadata,std::vector<PixelShaderOutputVariable> * outPixelShaderKey)1452 void DynamicHLSL::GetPixelShaderOutputKey(RendererD3D *renderer,
1453                                           const gl::Caps &caps,
1454                                           const gl::Version &clientVersion,
1455                                           const gl::ProgramExecutable &executable,
1456                                           const ProgramD3DMetadata &metadata,
1457                                           std::vector<PixelShaderOutputVariable> *outPixelShaderKey)
1458 {
1459     // Two cases when writing to gl_FragColor and using ESSL 1.0:
1460     // - with a 3.0 context, the output color is copied to channel 0
1461     // - with a 2.0 context, the output color is broadcast to all channels
1462     bool broadcast                      = metadata.usesBroadcast(clientVersion);
1463     const unsigned int numRenderTargets = (broadcast || metadata.usesMultipleFragmentOuts()
1464                                                ? static_cast<unsigned int>(caps.maxDrawBuffers)
1465                                                : 1);
1466 
1467     if (!metadata.usesCustomOutVars())
1468     {
1469         for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets;
1470              renderTargetIndex++)
1471         {
1472             PixelShaderOutputVariable outputKeyVariable;
1473             outputKeyVariable.type = GL_FLOAT_VEC4;
1474             outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
1475             outputKeyVariable.source =
1476                 broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
1477             outputKeyVariable.outputLocation = renderTargetIndex;
1478 
1479             outPixelShaderKey->push_back(outputKeyVariable);
1480         }
1481 
1482         if (metadata.usesSecondaryColor())
1483         {
1484             for (unsigned int secondaryIndex = 0; secondaryIndex < caps.maxDualSourceDrawBuffers;
1485                  secondaryIndex++)
1486             {
1487                 PixelShaderOutputVariable outputKeyVariable;
1488                 outputKeyVariable.type           = GL_FLOAT_VEC4;
1489                 outputKeyVariable.name           = "gl_SecondaryColor" + Str(secondaryIndex);
1490                 outputKeyVariable.source         = "gl_SecondaryColor[" + Str(secondaryIndex) + "]";
1491                 outputKeyVariable.outputLocation = secondaryIndex;
1492                 outputKeyVariable.outputIndex    = 1;
1493 
1494                 outPixelShaderKey->push_back(outputKeyVariable);
1495             }
1496         }
1497     }
1498     else
1499     {
1500         const gl::SharedCompiledShaderState &fragmentShader = metadata.getFragmentShader();
1501 
1502         if (!fragmentShader)
1503         {
1504             return;
1505         }
1506 
1507         const auto &shaderOutputVars = fragmentShader->activeOutputVariables;
1508 
1509         for (size_t outputLocationIndex = 0u;
1510              outputLocationIndex < executable.getOutputLocations().size(); ++outputLocationIndex)
1511         {
1512             const VariableLocation &outputLocation =
1513                 executable.getOutputLocations().at(outputLocationIndex);
1514             if (!outputLocation.used())
1515             {
1516                 continue;
1517             }
1518             const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
1519             const std::string &variableName          = "out_" + outputVariable.name;
1520 
1521             // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6.
1522             const std::string &elementString =
1523                 (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : "");
1524 
1525             ASSERT(outputVariable.active);
1526 
1527             PixelShaderOutputVariable outputKeyVariable;
1528             outputKeyVariable.type = outputVariable.type;
1529             outputKeyVariable.name = variableName + elementString;
1530             outputKeyVariable.source =
1531                 variableName +
1532                 (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : "");
1533             outputKeyVariable.outputLocation = outputLocationIndex;
1534 
1535             outPixelShaderKey->push_back(outputKeyVariable);
1536         }
1537 
1538         // Now generate any secondary outputs...
1539         for (size_t outputLocationIndex = 0u;
1540              outputLocationIndex < executable.getSecondaryOutputLocations().size();
1541              ++outputLocationIndex)
1542         {
1543             const VariableLocation &outputLocation =
1544                 executable.getSecondaryOutputLocations().at(outputLocationIndex);
1545             if (!outputLocation.used())
1546             {
1547                 continue;
1548             }
1549             const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
1550             const std::string &variableName          = "out_" + outputVariable.name;
1551 
1552             // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6.
1553             const std::string &elementString =
1554                 (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : "");
1555 
1556             ASSERT(outputVariable.active);
1557 
1558             PixelShaderOutputVariable outputKeyVariable;
1559             outputKeyVariable.type = outputVariable.type;
1560             outputKeyVariable.name = variableName + elementString;
1561             outputKeyVariable.source =
1562                 variableName +
1563                 (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : "");
1564             outputKeyVariable.outputLocation = outputLocationIndex;
1565             outputKeyVariable.outputIndex    = 1;
1566 
1567             outPixelShaderKey->push_back(outputKeyVariable);
1568         }
1569     }
1570 }
1571 
1572 // BuiltinVarying Implementation.
BuiltinVarying()1573 BuiltinVarying::BuiltinVarying() : enabled(false), indexOrSize(0), systemValue(false) {}
1574 
str() const1575 std::string BuiltinVarying::str() const
1576 {
1577     return (systemValue ? semantic : (semantic + Str(indexOrSize)));
1578 }
1579 
enableSystem(const std::string & systemValueSemantic)1580 void BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
1581 {
1582     enabled     = true;
1583     semantic    = systemValueSemantic;
1584     systemValue = true;
1585 }
1586 
enableSystem(const std::string & systemValueSemantic,unsigned int sizeVal)1587 void BuiltinVarying::enableSystem(const std::string &systemValueSemantic, unsigned int sizeVal)
1588 {
1589     enabled     = true;
1590     semantic    = systemValueSemantic;
1591     systemValue = true;
1592     indexOrSize = sizeVal;
1593 }
1594 
enable(const std::string & semanticVal,unsigned int indexVal)1595 void BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
1596 {
1597     enabled     = true;
1598     semantic    = semanticVal;
1599     indexOrSize = indexVal;
1600 }
1601 
1602 // BuiltinVaryingsD3D Implementation.
BuiltinVaryingsD3D(const ProgramD3DMetadata & metadata,const VaryingPacking & packing)1603 BuiltinVaryingsD3D::BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata,
1604                                        const VaryingPacking &packing)
1605 {
1606     updateBuiltins(gl::ShaderType::Vertex, metadata, packing);
1607     updateBuiltins(gl::ShaderType::Fragment, metadata, packing);
1608     int shaderModel = metadata.getRendererMajorShaderModel();
1609     if (shaderModel >= 4)
1610     {
1611         updateBuiltins(gl::ShaderType::Geometry, metadata, packing);
1612     }
1613     // In shader model >= 4, some builtins need to be the same in vertex and pixel shaders - input
1614     // struct needs to be a prefix of output struct.
1615     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPosition.enabled ==
1616                                   mBuiltinInfo[gl::ShaderType::Fragment].glPosition.enabled);
1617     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glFragCoord.enabled ==
1618                                   mBuiltinInfo[gl::ShaderType::Fragment].glFragCoord.enabled);
1619     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPointCoord.enabled ==
1620                                   mBuiltinInfo[gl::ShaderType::Fragment].glPointCoord.enabled);
1621     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPointSize.enabled ==
1622                                   mBuiltinInfo[gl::ShaderType::Fragment].glPointSize.enabled);
1623     ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glViewIDOVR.enabled ==
1624                                   mBuiltinInfo[gl::ShaderType::Fragment].glViewIDOVR.enabled);
1625 }
1626 
1627 BuiltinVaryingsD3D::~BuiltinVaryingsD3D() = default;
1628 
updateBuiltins(gl::ShaderType shaderType,const ProgramD3DMetadata & metadata,const VaryingPacking & packing)1629 void BuiltinVaryingsD3D::updateBuiltins(gl::ShaderType shaderType,
1630                                         const ProgramD3DMetadata &metadata,
1631                                         const VaryingPacking &packing)
1632 {
1633     const std::string &userSemantic = GetVaryingSemantic(metadata.getRendererMajorShaderModel(),
1634                                                          metadata.usesSystemValuePointSize());
1635 
1636     // Note that when enabling builtins only for specific shader stages in shader model >= 4, the
1637     // code needs to ensure that the input struct of the shader stage is a prefix of the output
1638     // struct of the previous stage.
1639 
1640     unsigned int reservedSemanticIndex = packing.getMaxSemanticIndex();
1641 
1642     BuiltinInfo *builtins = &mBuiltinInfo[shaderType];
1643 
1644     if (metadata.getRendererMajorShaderModel() >= 4)
1645     {
1646         builtins->dxPosition.enableSystem("SV_Position");
1647     }
1648     else if (shaderType == gl::ShaderType::Fragment)
1649     {
1650         builtins->dxPosition.enableSystem("VPOS");
1651     }
1652     else
1653     {
1654         builtins->dxPosition.enableSystem("POSITION");
1655     }
1656 
1657     if (metadata.usesTransformFeedbackGLPosition())
1658     {
1659         builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
1660     }
1661 
1662     if (metadata.getClipDistanceArraySize())
1663     {
1664         builtins->glClipDistance.enableSystem("SV_ClipDistance",
1665                                               metadata.getClipDistanceArraySize());
1666     }
1667 
1668     if (metadata.getCullDistanceArraySize())
1669     {
1670         builtins->glCullDistance.enableSystem("SV_CullDistance",
1671                                               metadata.getCullDistanceArraySize());
1672     }
1673 
1674     if (metadata.usesFragCoord())
1675     {
1676         builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
1677     }
1678 
1679     if (shaderType == gl::ShaderType::Vertex ? metadata.addsPointCoordToVertexShader()
1680                                              : metadata.usesPointCoord())
1681     {
1682         // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
1683         // In D3D11 we manually compute gl_PointCoord in the GS.
1684         if (metadata.getRendererMajorShaderModel() >= 4)
1685         {
1686             builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
1687         }
1688         else
1689         {
1690             builtins->glPointCoord.enable("TEXCOORD", 0);
1691         }
1692     }
1693 
1694     if (metadata.hasMultiviewEnabled())
1695     {
1696         // Although it is possible to compute gl_ViewID_OVR from the value of
1697         // SV_RenderTargetArrayIndex, it is easier and cleaner to always pass it as a varying.
1698         builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++);
1699 
1700         if ((shaderType == gl::ShaderType::Vertex && metadata.canSelectViewInVertexShader()) ||
1701             shaderType == gl::ShaderType::Geometry)
1702         {
1703             builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex");
1704         }
1705     }
1706 
1707     // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
1708     if (metadata.usesSystemValuePointSize() &&
1709         (shaderType != gl::ShaderType::Fragment || metadata.getRendererMajorShaderModel() >= 4))
1710     {
1711         builtins->glPointSize.enableSystem("PSIZE");
1712     }
1713 }
1714 
1715 }  // namespace rx
1716