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