Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2019-02-01 14:16:32
    Hash : c09ae15c
    Message : Enable -Wextra-semi and -Wextra-semi-stmt. This will prevent users from accidentally making semicolon errors in the future. Bug: chromium:926235 Change-Id: I79a6fa376fb1ad8f0fcf1b65b1f572a035d1f4e9 Reviewed-on: https://chromium-review.googlesource.com/c/1446493 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Nico Weber <thakis@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>

  • src/compiler/translator/ShaderStorageBlockFunctionHLSL.cpp
  • //
    // 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.
    //
    // ShaderStorageBlockFunctionHLSL: Wrapper functions for RWByteAddressBuffer Load/Store functions.
    //
    
    #include "compiler/translator/ShaderStorageBlockFunctionHLSL.h"
    
    #include "common/utilities.h"
    #include "compiler/translator/UtilsHLSL.h"
    #include "compiler/translator/blocklayout.h"
    #include "compiler/translator/blocklayoutHLSL.h"
    #include "compiler/translator/util.h"
    
    namespace sh
    {
    
    // static
    void ShaderStorageBlockFunctionHLSL::OutputSSBOLoadFunctionBody(
        TInfoSinkBase &out,
        const ShaderStorageBlockFunction &ssboFunction)
    {
        const char *convertString;
        switch (ssboFunction.type.getBasicType())
        {
            case EbtFloat:
                convertString = "asfloat(";
                break;
            case EbtInt:
                convertString = "asint(";
                break;
            case EbtUInt:
                convertString = "asuint(";
                break;
            case EbtBool:
                convertString = "asint(";
                break;
            default:
                UNREACHABLE();
                return;
        }
    
        size_t bytesPerComponent =
            gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type)));
        out << "    " << ssboFunction.typeString << " result";
        if (ssboFunction.type.isScalar())
        {
            size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent;
            out << " = " << convertString << "buffer.Load(loc + " << offset << "));\n ";
        }
        else if (ssboFunction.type.isVector())
        {
            if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle)
            {
                size_t componentStride = bytesPerComponent;
                if (ssboFunction.rowMajor)
                {
                    componentStride = ssboFunction.matrixStride;
                }
    
                out << " = {";
                for (const int offset : ssboFunction.swizzleOffsets)
                {
                    size_t offsetInBytes = offset * componentStride;
                    out << convertString << "buffer.Load(loc + " << offsetInBytes << ")),";
                }
                out << "};\n";
            }
            else
            {
                out << " = " << convertString << "buffer.Load" << ssboFunction.type.getNominalSize()
                    << "(loc));\n";
            }
        }
        else if (ssboFunction.type.isMatrix())
        {
            if (ssboFunction.rowMajor)
            {
                out << ";";
                out << "    float" << ssboFunction.type.getRows() << "x" << ssboFunction.type.getCols()
                    << " tmp_ = {";
                for (int rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++)
                {
                    out << "asfloat(buffer.Load" << ssboFunction.type.getCols() << "(loc + "
                        << rowIndex * ssboFunction.matrixStride << ")), ";
                }
                out << "};\n";
                out << "    result = transpose(tmp_);\n";
            }
            else
            {
                out << " = {";
                for (int columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++)
                {
                    out << "asfloat(buffer.Load" << ssboFunction.type.getRows() << "(loc + "
                        << columnIndex * ssboFunction.matrixStride << ")), ";
                }
                out << "};\n";
            }
        }
        else
        {
            // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951
            out << ";\n";
        }
    
        out << "    return result;\n";
        return;
    }
    
    // static
    void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody(
        TInfoSinkBase &out,
        const ShaderStorageBlockFunction &ssboFunction)
    {
        size_t bytesPerComponent =
            gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type)));
        if (ssboFunction.type.isScalar())
        {
            size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent;
            if (ssboFunction.type.getBasicType() == EbtBool)
            {
                out << "    buffer.Store(loc + " << offset << ", uint(value));\n";
            }
            else
            {
                out << "    buffer.Store(loc + " << offset << ", asuint(value));\n";
            }
        }
        else if (ssboFunction.type.isVector())
        {
            out << "    uint" << ssboFunction.type.getNominalSize() << " _value;\n";
            if (ssboFunction.type.getBasicType() == EbtBool)
            {
                out << "    _value = uint" << ssboFunction.type.getNominalSize() << "(value);\n";
            }
            else
            {
                out << "    _value = asuint(value);\n";
            }
    
            if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle)
            {
                size_t componentStride = bytesPerComponent;
                if (ssboFunction.rowMajor)
                {
                    componentStride = ssboFunction.matrixStride;
                }
                const TVector<int> &swizzleOffsets = ssboFunction.swizzleOffsets;
                for (int index = 0; index < static_cast<int>(swizzleOffsets.size()); index++)
                {
                    size_t offsetInBytes = swizzleOffsets[index] * componentStride;
                    out << "buffer.Store(loc + " << offsetInBytes << ", _value[" << index << "]);\n";
                }
            }
            else
            {
                out << "    buffer.Store" << ssboFunction.type.getNominalSize() << "(loc, _value);\n";
            }
        }
        else if (ssboFunction.type.isMatrix())
        {
            if (ssboFunction.rowMajor)
            {
                out << "    float" << ssboFunction.type.getRows() << "x" << ssboFunction.type.getCols()
                    << " tmp_ = transpose(value);\n";
                for (int rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++)
                {
                    out << "    buffer.Store" << ssboFunction.type.getCols() << "(loc + "
                        << rowIndex * ssboFunction.matrixStride << ", asuint(tmp_[" << rowIndex
                        << "]));\n";
                }
            }
            else
            {
                for (int columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++)
                {
                    out << "    buffer.Store" << ssboFunction.type.getRows() << "(loc + "
                        << columnIndex * ssboFunction.matrixStride << ", asuint(value[" << columnIndex
                        << "]));\n";
                }
            }
        }
        else
        {
            // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951
        }
    }
    
    // static
    void ShaderStorageBlockFunctionHLSL::OutputSSBOLengthFunctionBody(TInfoSinkBase &out,
                                                                      int unsizedArrayStride)
    {
        out << "    uint dim = 0;\n";
        out << "    buffer.GetDimensions(dim);\n";
        out << "    return int((dim - loc)/uint(" << unsizedArrayStride << "));\n";
    }
    
    // static
    void ShaderStorageBlockFunctionHLSL::OutputSSBOAtomicMemoryFunctionBody(
        TInfoSinkBase &out,
        const ShaderStorageBlockFunction &ssboFunction)
    {
        out << "    " << ssboFunction.typeString << " original_value;\n";
        switch (ssboFunction.method)
        {
            case SSBOMethod::ATOMIC_ADD:
                out << "    buffer.InterlockedAdd(loc, value, original_value);\n";
                break;
            case SSBOMethod::ATOMIC_MIN:
                out << "    buffer.InterlockedMin(loc, value, original_value);\n";
                break;
            case SSBOMethod::ATOMIC_MAX:
                out << "    buffer.InterlockedMax(loc, value, original_value);\n";
                break;
            case SSBOMethod::ATOMIC_AND:
                out << "    buffer.InterlockedAnd(loc, value, original_value);\n";
                break;
            case SSBOMethod::ATOMIC_OR:
                out << "    buffer.InterlockedOr(loc, value, original_value);\n";
                break;
            case SSBOMethod::ATOMIC_XOR:
                out << "    buffer.InterlockedXor(loc, value, original_value);\n";
                break;
            case SSBOMethod::ATOMIC_EXCHANGE:
                out << "    buffer.InterlockedExchange(loc, value, original_value);\n";
                break;
            case SSBOMethod::ATOMIC_COMPSWAP:
                out << "    buffer.InterlockedCompareExchange(loc, compare_value, value, "
                       "original_value);\n";
                break;
            default:
                UNREACHABLE();
        }
        out << "    return original_value;\n";
    }
    
    bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<(
        const ShaderStorageBlockFunction &rhs) const
    {
        return functionName < rhs.functionName;
    }
    
    TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction(
        const TType &type,
        SSBOMethod method,
        TLayoutBlockStorage storage,
        bool rowMajor,
        int matrixStride,
        int unsizedArrayStride,
        TIntermSwizzle *swizzleNode)
    {
        ShaderStorageBlockFunction ssboFunction;
        ssboFunction.typeString = TypeString(type);
        ssboFunction.method     = method;
        switch (method)
        {
            case SSBOMethod::LOAD:
                ssboFunction.functionName = "_Load_";
                break;
            case SSBOMethod::STORE:
                ssboFunction.functionName = "_Store_";
                break;
            case SSBOMethod::LENGTH:
                ssboFunction.unsizedArrayStride = unsizedArrayStride;
                ssboFunction.functionName       = "_Length_" + str(unsizedArrayStride);
                mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
                return ssboFunction.functionName;
            case SSBOMethod::ATOMIC_ADD:
                ssboFunction.functionName = "_ssbo_atomicAdd_" + ssboFunction.typeString;
                mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
                return ssboFunction.functionName;
            case SSBOMethod::ATOMIC_MIN:
                ssboFunction.functionName = "_ssbo_atomicMin_" + ssboFunction.typeString;
                mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
                return ssboFunction.functionName;
            case SSBOMethod::ATOMIC_MAX:
                ssboFunction.functionName = "_ssbo_atomicMax_" + ssboFunction.typeString;
                mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
                return ssboFunction.functionName;
            case SSBOMethod::ATOMIC_AND:
                ssboFunction.functionName = "_ssbo_atomicAnd_" + ssboFunction.typeString;
                mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
                return ssboFunction.functionName;
            case SSBOMethod::ATOMIC_OR:
                ssboFunction.functionName = "_ssbo_atomicOr_" + ssboFunction.typeString;
                mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
                return ssboFunction.functionName;
            case SSBOMethod::ATOMIC_XOR:
                ssboFunction.functionName = "_ssbo_atomicXor_" + ssboFunction.typeString;
                mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
                return ssboFunction.functionName;
            case SSBOMethod::ATOMIC_EXCHANGE:
                ssboFunction.functionName = "_ssbo_atomicExchange_" + ssboFunction.typeString;
                mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
                return ssboFunction.functionName;
            case SSBOMethod::ATOMIC_COMPSWAP:
                ssboFunction.functionName = "_ssbo_atomicCompSwap_" + ssboFunction.typeString;
                mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
                return ssboFunction.functionName;
            default:
                UNREACHABLE();
        }
    
        ssboFunction.functionName += ssboFunction.typeString;
        ssboFunction.type = type;
        if (swizzleNode != nullptr)
        {
            ssboFunction.swizzleOffsets   = swizzleNode->getSwizzleOffsets();
            ssboFunction.isDefaultSwizzle = false;
        }
        else
        {
            if (ssboFunction.type.getNominalSize() > 1)
            {
                for (int index = 0; index < ssboFunction.type.getNominalSize(); index++)
                {
                    ssboFunction.swizzleOffsets.push_back(index);
                }
            }
            else
            {
                ssboFunction.swizzleOffsets.push_back(0);
            }
    
            ssboFunction.isDefaultSwizzle = true;
        }
        ssboFunction.rowMajor     = rowMajor;
        ssboFunction.matrixStride = matrixStride;
        ssboFunction.functionName += "_" + TString(getBlockStorageString(storage));
    
        if (rowMajor)
        {
            ssboFunction.functionName += "_rm_";
        }
        else
        {
            ssboFunction.functionName += "_cm_";
        }
    
        for (const int offset : ssboFunction.swizzleOffsets)
        {
            switch (offset)
            {
                case 0:
                    ssboFunction.functionName += "x";
                    break;
                case 1:
                    ssboFunction.functionName += "y";
                    break;
                case 2:
                    ssboFunction.functionName += "z";
                    break;
                case 3:
                    ssboFunction.functionName += "w";
                    break;
                default:
                    UNREACHABLE();
            }
        }
    
        mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
        return ssboFunction.functionName;
    }
    
    void ShaderStorageBlockFunctionHLSL::shaderStorageBlockFunctionHeader(TInfoSinkBase &out)
    {
        for (const ShaderStorageBlockFunction &ssboFunction : mRegisteredShaderStorageBlockFunctions)
        {
            switch (ssboFunction.method)
            {
                case SSBOMethod::LOAD:
                {
                    // Function header
                    out << ssboFunction.typeString << " " << ssboFunction.functionName
                        << "(RWByteAddressBuffer buffer, uint loc)\n";
                    out << "{\n";
                    OutputSSBOLoadFunctionBody(out, ssboFunction);
                    break;
                }
                case SSBOMethod::STORE:
                {
                    // Function header
                    out << "void " << ssboFunction.functionName
                        << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString
                        << " value)\n";
                    out << "{\n";
                    OutputSSBOStoreFunctionBody(out, ssboFunction);
                    break;
                }
                case SSBOMethod::LENGTH:
                {
                    out << "int " << ssboFunction.functionName
                        << "(RWByteAddressBuffer buffer, uint loc)\n";
                    out << "{\n";
                    OutputSSBOLengthFunctionBody(out, ssboFunction.unsizedArrayStride);
                    break;
                }
                case SSBOMethod::ATOMIC_ADD:
                case SSBOMethod::ATOMIC_MIN:
                case SSBOMethod::ATOMIC_MAX:
                case SSBOMethod::ATOMIC_AND:
                case SSBOMethod::ATOMIC_OR:
                case SSBOMethod::ATOMIC_XOR:
                case SSBOMethod::ATOMIC_EXCHANGE:
                {
                    out << ssboFunction.typeString << " " << ssboFunction.functionName
                        << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString
                        << " value)\n";
                    out << "{\n";
    
                    OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction);
                    break;
                }
                case SSBOMethod::ATOMIC_COMPSWAP:
                {
                    out << ssboFunction.typeString << " " << ssboFunction.functionName
                        << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString
                        << " compare_value, " << ssboFunction.typeString << " value)\n";
                    out << "{\n";
                    OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction);
                    break;
                }
                default:
                    UNREACHABLE();
            }
    
            out << "}\n"
                   "\n";
        }
    }
    
    }  // namespace sh