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