tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ShaderStorageBlockFunctionHLSL.cpp (16060B)


      1 //
      2 // Copyright 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 // ShaderStorageBlockFunctionHLSL: Wrapper functions for RWByteAddressBuffer Load/Store functions.
      7 //
      8 
      9 #include "compiler/translator/ShaderStorageBlockFunctionHLSL.h"
     10 
     11 #include "common/utilities.h"
     12 #include "compiler/translator/UtilsHLSL.h"
     13 #include "compiler/translator/blocklayout.h"
     14 #include "compiler/translator/blocklayoutHLSL.h"
     15 #include "compiler/translator/util.h"
     16 
     17 namespace sh
     18 {
     19 
     20 // static
     21 void ShaderStorageBlockFunctionHLSL::OutputSSBOLoadFunctionBody(
     22    TInfoSinkBase &out,
     23    const ShaderStorageBlockFunction &ssboFunction)
     24 {
     25    const char *convertString;
     26    switch (ssboFunction.type.getBasicType())
     27    {
     28        case EbtFloat:
     29            convertString = "asfloat(";
     30            break;
     31        case EbtInt:
     32            convertString = "asint(";
     33            break;
     34        case EbtUInt:
     35            convertString = "asuint(";
     36            break;
     37        case EbtBool:
     38            convertString = "asint(";
     39            break;
     40        default:
     41            UNREACHABLE();
     42            return;
     43    }
     44 
     45    size_t bytesPerComponent =
     46        gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type)));
     47    out << "    " << ssboFunction.typeString << " result";
     48    if (ssboFunction.type.isScalar())
     49    {
     50        size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent;
     51        out << " = " << convertString << "buffer.Load(loc + " << offset << "));\n ";
     52    }
     53    else if (ssboFunction.type.isVector())
     54    {
     55        if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle)
     56        {
     57            size_t componentStride = bytesPerComponent;
     58            if (ssboFunction.rowMajor)
     59            {
     60                componentStride = ssboFunction.matrixStride;
     61            }
     62 
     63            out << " = {";
     64            for (const int offset : ssboFunction.swizzleOffsets)
     65            {
     66                size_t offsetInBytes = offset * componentStride;
     67                out << convertString << "buffer.Load(loc + " << offsetInBytes << ")),";
     68            }
     69            out << "};\n";
     70        }
     71        else
     72        {
     73            out << " = " << convertString << "buffer.Load"
     74                << static_cast<uint32_t>(ssboFunction.type.getNominalSize()) << "(loc));\n";
     75        }
     76    }
     77    else if (ssboFunction.type.isMatrix())
     78    {
     79        if (ssboFunction.rowMajor)
     80        {
     81            out << ";";
     82            out << "    float" << static_cast<uint32_t>(ssboFunction.type.getRows()) << "x"
     83                << static_cast<uint32_t>(ssboFunction.type.getCols()) << " tmp_ = {";
     84            for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++)
     85            {
     86                out << "asfloat(buffer.Load" << static_cast<uint32_t>(ssboFunction.type.getCols())
     87                    << "(loc + " << rowIndex * ssboFunction.matrixStride << ")), ";
     88            }
     89            out << "};\n";
     90            out << "    result = transpose(tmp_);\n";
     91        }
     92        else
     93        {
     94            out << " = {";
     95            for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++)
     96            {
     97                out << "asfloat(buffer.Load" << static_cast<uint32_t>(ssboFunction.type.getRows())
     98                    << "(loc + " << columnIndex * ssboFunction.matrixStride << ")), ";
     99            }
    100            out << "};\n";
    101        }
    102    }
    103    else
    104    {
    105        // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951
    106        out << ";\n";
    107    }
    108 
    109    out << "    return result;\n";
    110    return;
    111 }
    112 
    113 // static
    114 void ShaderStorageBlockFunctionHLSL::OutputSSBOStoreFunctionBody(
    115    TInfoSinkBase &out,
    116    const ShaderStorageBlockFunction &ssboFunction)
    117 {
    118    size_t bytesPerComponent =
    119        gl::VariableComponentSize(gl::VariableComponentType(GLVariableType(ssboFunction.type)));
    120    if (ssboFunction.type.isScalar())
    121    {
    122        size_t offset = ssboFunction.swizzleOffsets[0] * bytesPerComponent;
    123        if (ssboFunction.type.getBasicType() == EbtBool)
    124        {
    125            out << "    buffer.Store(loc + " << offset << ", uint(value));\n";
    126        }
    127        else
    128        {
    129            out << "    buffer.Store(loc + " << offset << ", asuint(value));\n";
    130        }
    131    }
    132    else if (ssboFunction.type.isVector())
    133    {
    134        out << "    uint" << static_cast<uint32_t>(ssboFunction.type.getNominalSize())
    135            << " _value;\n";
    136        if (ssboFunction.type.getBasicType() == EbtBool)
    137        {
    138            out << "    _value = uint" << static_cast<uint32_t>(ssboFunction.type.getNominalSize())
    139                << "(value);\n";
    140        }
    141        else
    142        {
    143            out << "    _value = asuint(value);\n";
    144        }
    145 
    146        if (ssboFunction.rowMajor || !ssboFunction.isDefaultSwizzle)
    147        {
    148            size_t componentStride = bytesPerComponent;
    149            if (ssboFunction.rowMajor)
    150            {
    151                componentStride = ssboFunction.matrixStride;
    152            }
    153            const TVector<int> &swizzleOffsets = ssboFunction.swizzleOffsets;
    154            for (int index = 0; index < static_cast<int>(swizzleOffsets.size()); index++)
    155            {
    156                size_t offsetInBytes = swizzleOffsets[index] * componentStride;
    157                out << "buffer.Store(loc + " << offsetInBytes << ", _value[" << index << "]);\n";
    158            }
    159        }
    160        else
    161        {
    162            out << "    buffer.Store" << static_cast<uint32_t>(ssboFunction.type.getNominalSize())
    163                << "(loc, _value);\n";
    164        }
    165    }
    166    else if (ssboFunction.type.isMatrix())
    167    {
    168        if (ssboFunction.rowMajor)
    169        {
    170            out << "    float" << static_cast<uint32_t>(ssboFunction.type.getRows()) << "x"
    171                << static_cast<uint32_t>(ssboFunction.type.getCols())
    172                << " tmp_ = transpose(value);\n";
    173            for (uint8_t rowIndex = 0; rowIndex < ssboFunction.type.getRows(); rowIndex++)
    174            {
    175                out << "    buffer.Store" << static_cast<uint32_t>(ssboFunction.type.getCols())
    176                    << "(loc + " << rowIndex * ssboFunction.matrixStride << ", asuint(tmp_["
    177                    << static_cast<uint32_t>(rowIndex) << "]));\n";
    178            }
    179        }
    180        else
    181        {
    182            for (uint8_t columnIndex = 0; columnIndex < ssboFunction.type.getCols(); columnIndex++)
    183            {
    184                out << "    buffer.Store" << static_cast<uint32_t>(ssboFunction.type.getRows())
    185                    << "(loc + " << columnIndex * ssboFunction.matrixStride << ", asuint(value["
    186                    << static_cast<uint32_t>(columnIndex) << "]));\n";
    187            }
    188        }
    189    }
    190    else
    191    {
    192        // TODO(jiajia.qin@intel.com): Process all possible return types. http://anglebug.com/1951
    193    }
    194 }
    195 
    196 // static
    197 void ShaderStorageBlockFunctionHLSL::OutputSSBOLengthFunctionBody(TInfoSinkBase &out,
    198                                                                  int unsizedArrayStride)
    199 {
    200    out << "    uint dim = 0;\n";
    201    out << "    buffer.GetDimensions(dim);\n";
    202    out << "    return int((dim - loc)/uint(" << unsizedArrayStride << "));\n";
    203 }
    204 
    205 // static
    206 void ShaderStorageBlockFunctionHLSL::OutputSSBOAtomicMemoryFunctionBody(
    207    TInfoSinkBase &out,
    208    const ShaderStorageBlockFunction &ssboFunction)
    209 {
    210    out << "    " << ssboFunction.typeString << " original_value;\n";
    211    switch (ssboFunction.method)
    212    {
    213        case SSBOMethod::ATOMIC_ADD:
    214            out << "    buffer.InterlockedAdd(loc, value, original_value);\n";
    215            break;
    216        case SSBOMethod::ATOMIC_MIN:
    217            out << "    buffer.InterlockedMin(loc, value, original_value);\n";
    218            break;
    219        case SSBOMethod::ATOMIC_MAX:
    220            out << "    buffer.InterlockedMax(loc, value, original_value);\n";
    221            break;
    222        case SSBOMethod::ATOMIC_AND:
    223            out << "    buffer.InterlockedAnd(loc, value, original_value);\n";
    224            break;
    225        case SSBOMethod::ATOMIC_OR:
    226            out << "    buffer.InterlockedOr(loc, value, original_value);\n";
    227            break;
    228        case SSBOMethod::ATOMIC_XOR:
    229            out << "    buffer.InterlockedXor(loc, value, original_value);\n";
    230            break;
    231        case SSBOMethod::ATOMIC_EXCHANGE:
    232            out << "    buffer.InterlockedExchange(loc, value, original_value);\n";
    233            break;
    234        case SSBOMethod::ATOMIC_COMPSWAP:
    235            out << "    buffer.InterlockedCompareExchange(loc, compare_value, value, "
    236                   "original_value);\n";
    237            break;
    238        default:
    239            UNREACHABLE();
    240    }
    241    out << "    return original_value;\n";
    242 }
    243 
    244 bool ShaderStorageBlockFunctionHLSL::ShaderStorageBlockFunction::operator<(
    245    const ShaderStorageBlockFunction &rhs) const
    246 {
    247    return functionName < rhs.functionName;
    248 }
    249 
    250 TString ShaderStorageBlockFunctionHLSL::registerShaderStorageBlockFunction(
    251    const TType &type,
    252    SSBOMethod method,
    253    TLayoutBlockStorage storage,
    254    bool rowMajor,
    255    int matrixStride,
    256    int unsizedArrayStride,
    257    TIntermSwizzle *swizzleNode)
    258 {
    259    ShaderStorageBlockFunction ssboFunction;
    260    ssboFunction.typeString = TypeString(type);
    261    ssboFunction.method     = method;
    262    switch (method)
    263    {
    264        case SSBOMethod::LOAD:
    265            ssboFunction.functionName = "_Load_";
    266            break;
    267        case SSBOMethod::STORE:
    268            ssboFunction.functionName = "_Store_";
    269            break;
    270        case SSBOMethod::LENGTH:
    271            ssboFunction.unsizedArrayStride = unsizedArrayStride;
    272            ssboFunction.functionName       = "_Length_" + str(unsizedArrayStride);
    273            mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    274            return ssboFunction.functionName;
    275        case SSBOMethod::ATOMIC_ADD:
    276            ssboFunction.functionName = "_ssbo_atomicAdd_" + ssboFunction.typeString;
    277            mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    278            return ssboFunction.functionName;
    279        case SSBOMethod::ATOMIC_MIN:
    280            ssboFunction.functionName = "_ssbo_atomicMin_" + ssboFunction.typeString;
    281            mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    282            return ssboFunction.functionName;
    283        case SSBOMethod::ATOMIC_MAX:
    284            ssboFunction.functionName = "_ssbo_atomicMax_" + ssboFunction.typeString;
    285            mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    286            return ssboFunction.functionName;
    287        case SSBOMethod::ATOMIC_AND:
    288            ssboFunction.functionName = "_ssbo_atomicAnd_" + ssboFunction.typeString;
    289            mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    290            return ssboFunction.functionName;
    291        case SSBOMethod::ATOMIC_OR:
    292            ssboFunction.functionName = "_ssbo_atomicOr_" + ssboFunction.typeString;
    293            mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    294            return ssboFunction.functionName;
    295        case SSBOMethod::ATOMIC_XOR:
    296            ssboFunction.functionName = "_ssbo_atomicXor_" + ssboFunction.typeString;
    297            mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    298            return ssboFunction.functionName;
    299        case SSBOMethod::ATOMIC_EXCHANGE:
    300            ssboFunction.functionName = "_ssbo_atomicExchange_" + ssboFunction.typeString;
    301            mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    302            return ssboFunction.functionName;
    303        case SSBOMethod::ATOMIC_COMPSWAP:
    304            ssboFunction.functionName = "_ssbo_atomicCompSwap_" + ssboFunction.typeString;
    305            mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    306            return ssboFunction.functionName;
    307        default:
    308            UNREACHABLE();
    309    }
    310 
    311    ssboFunction.functionName += ssboFunction.typeString;
    312    ssboFunction.type = type;
    313    if (swizzleNode != nullptr)
    314    {
    315        ssboFunction.swizzleOffsets   = swizzleNode->getSwizzleOffsets();
    316        ssboFunction.isDefaultSwizzle = false;
    317    }
    318    else
    319    {
    320        if (ssboFunction.type.getNominalSize() > 1)
    321        {
    322            for (uint8_t index = 0; index < ssboFunction.type.getNominalSize(); index++)
    323            {
    324                ssboFunction.swizzleOffsets.push_back(index);
    325            }
    326        }
    327        else
    328        {
    329            ssboFunction.swizzleOffsets.push_back(0);
    330        }
    331 
    332        ssboFunction.isDefaultSwizzle = true;
    333    }
    334    ssboFunction.rowMajor     = rowMajor;
    335    ssboFunction.matrixStride = matrixStride;
    336    ssboFunction.functionName += "_" + TString(getBlockStorageString(storage));
    337 
    338    if (rowMajor)
    339    {
    340        ssboFunction.functionName += "_rm_";
    341    }
    342    else
    343    {
    344        ssboFunction.functionName += "_cm_";
    345    }
    346 
    347    for (const int offset : ssboFunction.swizzleOffsets)
    348    {
    349        switch (offset)
    350        {
    351            case 0:
    352                ssboFunction.functionName += "x";
    353                break;
    354            case 1:
    355                ssboFunction.functionName += "y";
    356                break;
    357            case 2:
    358                ssboFunction.functionName += "z";
    359                break;
    360            case 3:
    361                ssboFunction.functionName += "w";
    362                break;
    363            default:
    364                UNREACHABLE();
    365        }
    366    }
    367 
    368    mRegisteredShaderStorageBlockFunctions.insert(ssboFunction);
    369    return ssboFunction.functionName;
    370 }
    371 
    372 void ShaderStorageBlockFunctionHLSL::shaderStorageBlockFunctionHeader(TInfoSinkBase &out)
    373 {
    374    for (const ShaderStorageBlockFunction &ssboFunction : mRegisteredShaderStorageBlockFunctions)
    375    {
    376        switch (ssboFunction.method)
    377        {
    378            case SSBOMethod::LOAD:
    379            {
    380                // Function header
    381                out << ssboFunction.typeString << " " << ssboFunction.functionName
    382                    << "(RWByteAddressBuffer buffer, uint loc)\n";
    383                out << "{\n";
    384                OutputSSBOLoadFunctionBody(out, ssboFunction);
    385                break;
    386            }
    387            case SSBOMethod::STORE:
    388            {
    389                // Function header
    390                out << "void " << ssboFunction.functionName
    391                    << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString
    392                    << " value)\n";
    393                out << "{\n";
    394                OutputSSBOStoreFunctionBody(out, ssboFunction);
    395                break;
    396            }
    397            case SSBOMethod::LENGTH:
    398            {
    399                out << "int " << ssboFunction.functionName
    400                    << "(RWByteAddressBuffer buffer, uint loc)\n";
    401                out << "{\n";
    402                OutputSSBOLengthFunctionBody(out, ssboFunction.unsizedArrayStride);
    403                break;
    404            }
    405            case SSBOMethod::ATOMIC_ADD:
    406            case SSBOMethod::ATOMIC_MIN:
    407            case SSBOMethod::ATOMIC_MAX:
    408            case SSBOMethod::ATOMIC_AND:
    409            case SSBOMethod::ATOMIC_OR:
    410            case SSBOMethod::ATOMIC_XOR:
    411            case SSBOMethod::ATOMIC_EXCHANGE:
    412            {
    413                out << ssboFunction.typeString << " " << ssboFunction.functionName
    414                    << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString
    415                    << " value)\n";
    416                out << "{\n";
    417 
    418                OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction);
    419                break;
    420            }
    421            case SSBOMethod::ATOMIC_COMPSWAP:
    422            {
    423                out << ssboFunction.typeString << " " << ssboFunction.functionName
    424                    << "(RWByteAddressBuffer buffer, uint loc, " << ssboFunction.typeString
    425                    << " compare_value, " << ssboFunction.typeString << " value)\n";
    426                out << "{\n";
    427                OutputSSBOAtomicMemoryFunctionBody(out, ssboFunction);
    428                break;
    429            }
    430            default:
    431                UNREACHABLE();
    432        }
    433 
    434        out << "}\n"
    435               "\n";
    436    }
    437 }
    438 
    439 }  // namespace sh