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