| // | |
| // Copyright 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 |