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