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