Edit

kc3-lang/angle/src/compiler/translator/AtomicCounterFunctionHLSL.cpp

Branch :

  • Show log

    Commit

  • Author : Enrico Galli
    Date : 2018-12-13 14:07:52
    Hash : ee7ffd9e
    Message : ES31: Enabling skipped deqp atomic counter tests on D3D11 Enabling deqp tests previously skipped due to lack of atomic counters. Fixing bug found in translator found by new tests. * Switching atomicCounterDecrement from pre to post decrement * Added 4 byte alignment check to atomic_uint offset * Added workaround for NVIDIA D3D bug * Added globallycoherent to atomic counters Bug: angleproject:1729 Change-Id: If62ea003826fbe2df0834b905ff3ad7b76328399 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1480867 Commit-Queue: Enrico Galli <enrico.galli@intel.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>

  • src/compiler/translator/AtomicCounterFunctionHLSL.cpp
  • //
    // 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