blob: 63fe0265456ff65fdf525dada43f3256e07a005b [file] [log] [blame]
Brandon Jones4a22f4b2018-10-23 14:36:47 -07001//
2// Copyright (c) 2018 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// AtomicCounterFunctionHLSL: Class for writing implementation of atomic counter functions into HLSL
7// output.
8//
9
10#include "compiler/translator/AtomicCounterFunctionHLSL.h"
11
12#include "compiler/translator/ImmutableStringBuilder.h"
13#include "compiler/translator/InfoSink.h"
14#include "compiler/translator/IntermNode.h"
15
16namespace sh
17{
18
19namespace
20{
21constexpr ImmutableString kAtomicCounter("atomicCounter");
22constexpr ImmutableString kAtomicCounterIncrement("atomicCounterIncrement");
23constexpr ImmutableString kAtomicCounterDecrement("atomicCounterDecrement");
24constexpr ImmutableString kAtomicCounterBaseName("_acbase_");
25} // namespace
26
27ImmutableString AtomicCounterFunctionHLSL::useAtomicCounterFunction(const ImmutableString &name)
28{
29 // The largest string that will be create created is "_acbase_increment" or "_acbase_decrement"
30 ImmutableStringBuilder hlslFunctionNameSB(kAtomicCounterBaseName.length() +
31 strlen("increment"));
32 hlslFunctionNameSB << kAtomicCounterBaseName;
33
34 AtomicCounterFunction atomicMethod;
35 if (kAtomicCounter == name)
36 {
37 atomicMethod = AtomicCounterFunction::LOAD;
38 hlslFunctionNameSB << "load";
39 }
40 else if (kAtomicCounterIncrement == name)
41 {
42 atomicMethod = AtomicCounterFunction::INCREMENT;
43 hlslFunctionNameSB << "increment";
44 }
45 else if (kAtomicCounterDecrement == name)
46 {
47 atomicMethod = AtomicCounterFunction::DECREMENT;
48 hlslFunctionNameSB << "decrement";
49 }
50 else
51 {
52 atomicMethod = AtomicCounterFunction::INVALID;
53 UNREACHABLE();
54 }
55
56 ImmutableString hlslFunctionName(hlslFunctionNameSB);
57 mAtomicCounterFunctions[hlslFunctionName] = atomicMethod;
58
59 return hlslFunctionName;
60}
61
62void AtomicCounterFunctionHLSL::atomicCounterFunctionHeader(TInfoSinkBase &out)
63{
64 for (auto &atomicFunction : mAtomicCounterFunctions)
65 {
66 out << "uint " << atomicFunction.first
67 << "(in RWByteAddressBuffer counter, int address)\n"
68 "{\n";
69 switch (atomicFunction.second)
70 {
71 case AtomicCounterFunction::INCREMENT:
72 case AtomicCounterFunction::DECREMENT:
73 out << " uint ret;\n"
74 " counter.InterlockedAdd(address, ";
75 if (atomicFunction.second == AtomicCounterFunction::DECREMENT)
76 {
77 out << "0u - ";
78 }
79 out << "1u, ret);\n"
80 << " return ret;\n";
81 break;
82 case AtomicCounterFunction::LOAD:
83 out << " return counter.Load(address);\n";
84 break;
85 default:
86 UNREACHABLE();
87 break;
88 }
89 out << "}\n\n";
90 }
91}
92
93ImmutableString getAtomicCounterNameForBinding(int binding)
94{
95 std::stringstream counterName;
96 counterName << kAtomicCounterBaseName << binding;
97 return ImmutableString(counterName.str());
98}
99
100} // namespace sh