xref: /aosp_15_r20/external/angle/src/compiler/translator/tree_ops/msl/GuardFragDepthWrite.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2022 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 // GuardFragDepthWrite: Guards use of frag depth behind the function constant
7 // ANGLEDepthWriteEnabled to ensure it is only used when a valid depth buffer
8 // is bound.
9 
10 #include "compiler/translator/tree_ops/msl/GuardFragDepthWrite.h"
11 #include "compiler/translator/IntermRebuild.h"
12 #include "compiler/translator/msl/AstHelpers.h"
13 #include "compiler/translator/tree_util/BuiltIn.h"
14 
15 using namespace sh;
16 
17 ////////////////////////////////////////////////////////////////////////////////
18 
19 namespace
20 {
21 
22 class Rewriter : public TIntermRebuild
23 {
24   public:
Rewriter(TCompiler & compiler)25     Rewriter(TCompiler &compiler) : TIntermRebuild(compiler, false, true) {}
26 
visitBinaryPost(TIntermBinary & node)27     PostResult visitBinaryPost(TIntermBinary &node) override
28     {
29         if (TIntermSymbol *leftSymbolNode = node.getLeft()->getAsSymbolNode())
30         {
31             if (leftSymbolNode->getType().getQualifier() == TQualifier::EvqFragDepth)
32             {
33                 // This transformation leaves the tree in an inconsistent state by using a variable
34                 // that's defined in text, outside of the knowledge of the AST.
35                 // FIXME(jcunningham): remove once function constants (specconst) are implemented
36                 // with the metal translator.
37                 mCompiler.disableValidateVariableReferences();
38 
39                 TSymbolTable *symbolTable = &mCompiler.getSymbolTable();
40 
41                 // Create kDepthWriteEnabled variable reference.
42                 TType *boolType = new TType(EbtBool);
43                 boolType->setQualifier(EvqConst);
44                 TVariable *depthWriteEnabledVar = new TVariable(
45                     symbolTable, sh::ImmutableString(sh::mtl::kDepthWriteEnabledConstName),
46                     boolType, SymbolType::AngleInternal);
47 
48                 TIntermBlock *innerif = new TIntermBlock;
49                 innerif->appendStatement(&node);
50 
51                 TIntermSymbol *depthWriteEnabled = new TIntermSymbol(depthWriteEnabledVar);
52                 TIntermIfElse *ifCall = new TIntermIfElse(depthWriteEnabled, innerif, nullptr);
53                 return ifCall;
54             }
55         }
56 
57         return node;
58     }
59 };
60 
61 }  // anonymous namespace
62 
63 ////////////////////////////////////////////////////////////////////////////////
64 
GuardFragDepthWrite(TCompiler & compiler,TIntermBlock & root)65 bool sh::GuardFragDepthWrite(TCompiler &compiler, TIntermBlock &root)
66 {
67     Rewriter rewriter(compiler);
68     if (!rewriter.rebuildRoot(root))
69     {
70         return false;
71     }
72     return true;
73 }
74