diff options
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.cpp')
-rw-r--r-- | gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.cpp | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.cpp new file mode 100644 index 0000000000..52b8b878c3 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/AtomicCounterFunctionHLSL.cpp @@ -0,0 +1,112 @@ +// +// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// AtomicCounterFunctionHLSL: Class for writing implementation of atomic counter functions into HLSL +// output. +// + +#include "compiler/translator/AtomicCounterFunctionHLSL.h" + +#include "compiler/translator/Common.h" +#include "compiler/translator/ImmutableStringBuilder.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/IntermNode.h" + +namespace sh +{ + +namespace +{ +constexpr ImmutableString kAtomicCounter("atomicCounter"); +constexpr ImmutableString kAtomicCounterIncrement("atomicCounterIncrement"); +constexpr ImmutableString kAtomicCounterDecrement("atomicCounterDecrement"); +constexpr ImmutableString kAtomicCounterBaseName("_acbase_"); +} // namespace + +AtomicCounterFunctionHLSL::AtomicCounterFunctionHLSL(bool forceResolution) + : mForceResolution(forceResolution) +{} + +ImmutableString AtomicCounterFunctionHLSL::useAtomicCounterFunction(const ImmutableString &name) +{ + // The largest string that will be create created is "_acbase_increment" or "_acbase_decrement" + ImmutableStringBuilder hlslFunctionNameSB(kAtomicCounterBaseName.length() + + strlen("increment")); + hlslFunctionNameSB << kAtomicCounterBaseName; + + AtomicCounterFunction atomicMethod; + if (kAtomicCounter == name) + { + atomicMethod = AtomicCounterFunction::LOAD; + hlslFunctionNameSB << "load"; + } + else if (kAtomicCounterIncrement == name) + { + atomicMethod = AtomicCounterFunction::INCREMENT; + hlslFunctionNameSB << "increment"; + } + else if (kAtomicCounterDecrement == name) + { + atomicMethod = AtomicCounterFunction::DECREMENT; + hlslFunctionNameSB << "decrement"; + } + else + { + atomicMethod = AtomicCounterFunction::INVALID; + UNREACHABLE(); + } + + ImmutableString hlslFunctionName(hlslFunctionNameSB); + mAtomicCounterFunctions[hlslFunctionName] = atomicMethod; + + return hlslFunctionName; +} + +void AtomicCounterFunctionHLSL::atomicCounterFunctionHeader(TInfoSinkBase &out) +{ + for (auto &atomicFunction : mAtomicCounterFunctions) + { + out << "uint " << atomicFunction.first + << "(in RWByteAddressBuffer counter, int address)\n" + "{\n" + " uint ret;\n"; + + switch (atomicFunction.second) + { + case AtomicCounterFunction::INCREMENT: + out << " counter.InterlockedAdd(address, 1u, ret);\n"; + break; + case AtomicCounterFunction::DECREMENT: + out << " counter.InterlockedAdd(address, 0u - 1u, ret);\n" + " ret -= 1u;\n"; // atomicCounterDecrement is a post-decrement op + break; + case AtomicCounterFunction::LOAD: + out << " ret = counter.Load(address);\n"; + break; + default: + UNREACHABLE(); + break; + } + + if (mForceResolution && atomicFunction.second != AtomicCounterFunction::LOAD) + { + out << " if (ret == 0) {\n" + " ret = 0 - ret;\n" + " }\n"; + } + + out << " return ret;\n" + "}\n\n"; + } +} + +ImmutableString getAtomicCounterNameForBinding(int binding) +{ + std::stringstream counterName = sh::InitializeStream<std::stringstream>(); + counterName << kAtomicCounterBaseName << binding; + return ImmutableString(counterName.str()); +} + +} // namespace sh |