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 ®isterInfos = varyingPacking.getRegisterList();
507 for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
508 {
509 const PackedVaryingRegister ®isterInfo = 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 ®isterInfos = varyingPacking.getRegisterList();
791 for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
792 {
793 const PackedVaryingRegister ®isterInfo = 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 ®isterInfo = 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 ®isterInfos = 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