1 //
2 // Copyright 2020 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
7 #include "compiler/translator/tree_ops/msl/IntroduceVertexIndexID.h"
8 #include "compiler/translator/IntermRebuild.h"
9 #include "compiler/translator/StaticType.h"
10 #include "compiler/translator/msl/AstHelpers.h"
11 #include "compiler/translator/tree_util/BuiltIn.h"
12 using namespace sh;
13
14 ////////////////////////////////////////////////////////////////////////////////
15
16 namespace
17 {
18
19 constexpr const TVariable kgl_VertexIDMetal(BuiltInId::gl_VertexID,
20 ImmutableString("vertexIDMetal"),
21 SymbolType::AngleInternal,
22 TExtension::UNDEFINED,
23 StaticType::Get<EbtUInt, EbpHigh, EvqVertexID, 1, 1>());
24
25 constexpr const TVariable kgl_instanceIdMetal(
26 BuiltInId::gl_InstanceID,
27 ImmutableString("instanceIdMod"),
28 SymbolType::AngleInternal,
29 TExtension::UNDEFINED,
30 StaticType::Get<EbtUInt, EbpHigh, EvqInstanceID, 1, 1>());
31
32 constexpr const TVariable kgl_baseInstanceMetal(
33 BuiltInId::gl_BaseInstance,
34 ImmutableString("baseInstance"),
35 SymbolType::AngleInternal,
36 TExtension::UNDEFINED,
37 StaticType::Get<EbtUInt, EbpHigh, EvqInstanceID, 1, 1>());
38
39 class Rewriter : public TIntermRebuild
40 {
41 public:
Rewriter(TCompiler & compiler)42 Rewriter(TCompiler &compiler) : TIntermRebuild(compiler, true, true) {}
43
44 private:
visitFunctionDefinitionPre(TIntermFunctionDefinition & node)45 PreResult visitFunctionDefinitionPre(TIntermFunctionDefinition &node) override
46 {
47 if (node.getFunction()->isMain())
48 {
49 const TFunction *mainFunction = node.getFunction();
50 bool needsVertexId = true;
51 bool needsInstanceId = true;
52 std::vector<const TVariable *> mVariablesToIntroduce;
53 for (size_t i = 0; i < mainFunction->getParamCount(); ++i)
54 {
55 const TVariable *param = mainFunction->getParam(i);
56 Name instanceIDName =
57 Pipeline{Pipeline::Type::InstanceId, nullptr}.getStructInstanceName(
58 Pipeline::Variant::Modified);
59 if (Name(*param) == instanceIDName)
60 {
61 needsInstanceId = false;
62 }
63 else if (param->getType().getQualifier() == TQualifier::EvqVertexID)
64 {
65 needsVertexId = false;
66 }
67 }
68 if (needsInstanceId)
69 {
70 // Ensure these variables are present because they are required for XFB emulation.
71 mVariablesToIntroduce.push_back(&kgl_instanceIdMetal);
72 mVariablesToIntroduce.push_back(&kgl_baseInstanceMetal);
73 }
74 if (needsVertexId)
75 {
76 mVariablesToIntroduce.push_back(&kgl_VertexIDMetal);
77 }
78 const TFunction &newFunction = CloneFunctionAndAppendParams(
79 mSymbolTable, nullptr, *node.getFunction(), mVariablesToIntroduce);
80 TIntermFunctionPrototype *newProto = new TIntermFunctionPrototype(&newFunction);
81 return new TIntermFunctionDefinition(newProto, node.getBody());
82 }
83 return node;
84 }
85 };
86
87 } // anonymous namespace
88
89 ////////////////////////////////////////////////////////////////////////////////
90
IntroduceVertexAndInstanceIndex(TCompiler & compiler,TIntermBlock & root)91 bool sh::IntroduceVertexAndInstanceIndex(TCompiler &compiler, TIntermBlock &root)
92 {
93 if (!Rewriter(compiler).rebuildRoot(root))
94 {
95 return false;
96 }
97 return true;
98 }
99