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