LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - UniformHLSL.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 214 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2014 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             : // UniformHLSL.cpp:
       7             : //   Methods for GLSL to HLSL translation for uniforms and interface blocks.
       8             : //
       9             : 
      10             : #include "compiler/translator/UniformHLSL.h"
      11             : 
      12             : #include "common/utilities.h"
      13             : #include "compiler/translator/StructureHLSL.h"
      14             : #include "compiler/translator/UtilsHLSL.h"
      15             : #include "compiler/translator/blocklayoutHLSL.h"
      16             : #include "compiler/translator/util.h"
      17             : 
      18             : namespace sh
      19             : {
      20             : 
      21           0 : static const char *UniformRegisterPrefix(const TType &type)
      22             : {
      23           0 :     if (IsSampler(type.getBasicType()))
      24             :     {
      25           0 :         return "s";
      26             :     }
      27             :     else
      28             :     {
      29           0 :         return "c";
      30             :     }
      31             : }
      32             : 
      33           0 : static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
      34             : {
      35           0 :     const TType &fieldType = *field.type();
      36           0 :     const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
      37           0 :     ASSERT(matrixPacking != EmpUnspecified);
      38           0 :     TStructure *structure = fieldType.getStruct();
      39             : 
      40           0 :     if (fieldType.isMatrix())
      41             :     {
      42             :         // Use HLSL row-major packing for GLSL column-major matrices
      43           0 :         const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
      44           0 :         return matrixPackString + " " + TypeString(fieldType);
      45             :     }
      46           0 :     else if (structure)
      47             :     {
      48             :         // Use HLSL row-major packing for GLSL column-major matrices
      49             :         return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor,
      50           0 :             blockStorage == EbsStd140);
      51             :     }
      52             :     else
      53             :     {
      54           0 :         return TypeString(fieldType);
      55             :     }
      56             : }
      57             : 
      58           0 : static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
      59             : {
      60           0 :     return DecoratePrivate(interfaceBlock.name()) + "_type";
      61             : }
      62             : 
      63           0 : UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms)
      64             :     : mUniformRegister(0),
      65             :       mInterfaceBlockRegister(0),
      66             :       mSamplerRegister(0),
      67             :       mStructureHLSL(structureHLSL),
      68             :       mOutputType(outputType),
      69           0 :       mUniforms(uniforms)
      70           0 : {}
      71             : 
      72           0 : void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
      73             : {
      74           0 :     mUniformRegister = registerCount;
      75           0 : }
      76             : 
      77           0 : void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount)
      78             : {
      79           0 :     mInterfaceBlockRegister = registerCount;
      80           0 : }
      81             : 
      82           0 : const Uniform *UniformHLSL::findUniformByName(const TString &name) const
      83             : {
      84           0 :     for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
      85             :     {
      86           0 :         if (mUniforms[uniformIndex].name == name.c_str())
      87             :         {
      88           0 :             return &mUniforms[uniformIndex];
      89             :         }
      90             :     }
      91             : 
      92           0 :     return nullptr;
      93             : }
      94             : 
      95           0 : unsigned int UniformHLSL::assignUniformRegister(const TType &type,
      96             :                                                 const TString &name,
      97             :                                                 unsigned int *outRegisterCount)
      98             : {
      99           0 :     unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
     100             : 
     101           0 :     const Uniform *uniform = findUniformByName(name);
     102           0 :     ASSERT(uniform);
     103             : 
     104           0 :     mUniformRegisterMap[uniform->name] = registerIndex;
     105             : 
     106           0 :     unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
     107             : 
     108           0 :     if (gl::IsSamplerType(uniform->type))
     109             :     {
     110           0 :         mSamplerRegister += registerCount;
     111             :     }
     112             :     else
     113             :     {
     114           0 :         mUniformRegister += registerCount;
     115             :     }
     116           0 :     if (outRegisterCount)
     117             :     {
     118           0 :         *outRegisterCount = registerCount;
     119             :     }
     120           0 :     return registerIndex;
     121             : }
     122             : 
     123           0 : unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type,
     124             :                                                                const TString &name,
     125             :                                                                unsigned int *outRegisterCount)
     126             : {
     127             :     // Sampler that is a field of a uniform structure.
     128           0 :     ASSERT(IsSampler(type.getBasicType()));
     129           0 :     unsigned int registerIndex = mSamplerRegister;
     130           0 :     mUniformRegisterMap[std::string(name.c_str())] = registerIndex;
     131           0 :     unsigned int registerCount                     = type.isArray() ? type.getArraySize() : 1u;
     132           0 :     mSamplerRegister += registerCount;
     133           0 :     if (outRegisterCount)
     134             :     {
     135           0 :         *outRegisterCount = registerCount;
     136             :     }
     137           0 :     return registerIndex;
     138             : }
     139             : 
     140           0 : void UniformHLSL::outputHLSLSamplerUniformGroup(
     141             :     TInfoSinkBase &out,
     142             :     const HLSLTextureSamplerGroup textureGroup,
     143             :     const TVector<const TIntermSymbol *> &group,
     144             :     const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames,
     145             :     unsigned int *groupTextureRegisterIndex)
     146             : {
     147           0 :     if (group.empty())
     148             :     {
     149           0 :         return;
     150             :     }
     151           0 :     unsigned int groupRegisterCount = 0;
     152           0 :     for (const TIntermSymbol *uniform : group)
     153             :     {
     154           0 :         const TType &type   = uniform->getType();
     155           0 :         const TString &name = uniform->getSymbol();
     156             :         unsigned int registerCount;
     157             : 
     158             :         // The uniform might be just a regular sampler or one extracted from a struct.
     159           0 :         unsigned int samplerArrayIndex = 0u;
     160           0 :         const Uniform *uniformByName = findUniformByName(name);
     161           0 :         if (uniformByName)
     162             :         {
     163           0 :             samplerArrayIndex = assignUniformRegister(type, name, &registerCount);
     164             :         }
     165             :         else
     166             :         {
     167           0 :             ASSERT(samplerInStructSymbolsToAPINames.find(uniform) !=
     168           0 :                    samplerInStructSymbolsToAPINames.end());
     169           0 :             samplerArrayIndex = assignSamplerInStructUniformRegister(
     170           0 :                 type, samplerInStructSymbolsToAPINames.at(uniform), &registerCount);
     171             :         }
     172           0 :         groupRegisterCount += registerCount;
     173             : 
     174           0 :         if (type.isArray())
     175             :         {
     176           0 :             out << "static const uint " << DecorateIfNeeded(uniform->getName()) << ArrayString(type)
     177           0 :                 << " = {";
     178           0 :             for (unsigned int i = 0u; i < type.getArraySize(); ++i)
     179             :             {
     180           0 :                 if (i > 0u)
     181           0 :                     out << ", ";
     182           0 :                 out << (samplerArrayIndex + i);
     183             :             }
     184           0 :             out << "};\n";
     185             :         }
     186             :         else
     187             :         {
     188           0 :             out << "static const uint " << DecorateIfNeeded(uniform->getName()) << " = "
     189           0 :                 << samplerArrayIndex << ";\n";
     190             :         }
     191             :     }
     192           0 :     TString suffix = TextureGroupSuffix(textureGroup);
     193             :     // Since HLSL_TEXTURE_2D is the first group, it has a fixed offset of zero.
     194           0 :     if (textureGroup != HLSL_TEXTURE_2D)
     195             :     {
     196           0 :         out << "static const uint textureIndexOffset" << suffix << " = "
     197           0 :             << (*groupTextureRegisterIndex) << ";\n";
     198           0 :         out << "static const uint samplerIndexOffset" << suffix << " = "
     199           0 :             << (*groupTextureRegisterIndex) << ";\n";
     200             :     }
     201           0 :     out << "uniform " << TextureString(textureGroup) << " textures" << suffix << "["
     202           0 :         << groupRegisterCount << "]"
     203           0 :         << " : register(t" << (*groupTextureRegisterIndex) << ");\n";
     204           0 :     out << "uniform " << SamplerString(textureGroup) << " samplers" << suffix << "["
     205           0 :         << groupRegisterCount << "]"
     206           0 :         << " : register(s" << (*groupTextureRegisterIndex) << ");\n";
     207           0 :     *groupTextureRegisterIndex += groupRegisterCount;
     208             : }
     209             : 
     210           0 : void UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
     211             :                                              const TType &type,
     212             :                                              const TName &name,
     213             :                                              const unsigned int registerIndex)
     214             : {
     215           0 :     out << "uniform " << SamplerString(type.getBasicType()) << " sampler_"
     216           0 :         << DecorateUniform(name, type) << ArrayString(type) << " : register(s" << str(registerIndex)
     217           0 :         << ");\n";
     218           0 :     out << "uniform " << TextureString(type.getBasicType()) << " texture_"
     219           0 :         << DecorateUniform(name, type) << ArrayString(type) << " : register(t" << str(registerIndex)
     220           0 :         << ");\n";
     221           0 : }
     222             : 
     223           0 : void UniformHLSL::outputUniform(TInfoSinkBase &out,
     224             :                                 const TType &type,
     225             :                                 const TName &name,
     226             :                                 const unsigned int registerIndex)
     227             : {
     228           0 :     const TStructure *structure = type.getStruct();
     229             :     // If this is a nameless struct, we need to use its full definition, rather than its (empty)
     230             :     // name.
     231             :     // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for
     232             :     // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers
     233             :     // are permitted.
     234           0 :     const TString &typeName = ((structure && !structure->name().empty())
     235           0 :                                    ? QualifiedStructNameString(*structure, false, false)
     236           0 :                                    : TypeString(type));
     237             : 
     238             :     const TString &registerString =
     239           0 :         TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";
     240             : 
     241           0 :     out << "uniform " << typeName << " ";
     242             : 
     243           0 :     out << DecorateUniform(name, type);
     244             : 
     245           0 :     out << ArrayString(type) << " : " << registerString << ";\n";
     246           0 : }
     247             : 
     248           0 : void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
     249             :                                  ShShaderOutput outputType,
     250             :                                  const ReferencedSymbols &referencedUniforms)
     251             : {
     252           0 :     if (!referencedUniforms.empty())
     253             :     {
     254           0 :         out << "// Uniforms\n\n";
     255             :     }
     256             :     // In the case of HLSL 4, sampler uniforms need to be grouped by type before the code is
     257             :     // written. They are grouped based on the combination of the HLSL texture type and
     258             :     // HLSL sampler type, enumerated in HLSLTextureSamplerGroup.
     259           0 :     TVector<TVector<const TIntermSymbol *>> groupedSamplerUniforms(HLSL_TEXTURE_MAX + 1);
     260           0 :     TMap<const TIntermSymbol *, TString> samplerInStructSymbolsToAPINames;
     261           0 :     for (auto &uniformIt : referencedUniforms)
     262             :     {
     263             :         // Output regular uniforms. Group sampler uniforms by type.
     264           0 :         const TIntermSymbol &uniform = *uniformIt.second;
     265           0 :         const TType &type            = uniform.getType();
     266           0 :         const TName &name            = uniform.getName();
     267             : 
     268           0 :         if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType()))
     269             :         {
     270           0 :             HLSLTextureSamplerGroup group = TextureGroup(type.getBasicType());
     271           0 :             groupedSamplerUniforms[group].push_back(&uniform);
     272             :         }
     273           0 :         else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType()))
     274             :         {
     275           0 :             unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
     276           0 :             outputHLSL4_0_FL9_3Sampler(out, type, name, registerIndex);
     277             :         }
     278             :         else
     279             :         {
     280           0 :             if (type.isStructureContainingSamplers())
     281             :             {
     282           0 :                 TVector<TIntermSymbol *> samplerSymbols;
     283           0 :                 TMap<TIntermSymbol *, TString> symbolsToAPINames;
     284           0 :                 unsigned int arrayOfStructsSize = type.isArray() ? type.getArraySize() : 0u;
     285           0 :                 type.createSamplerSymbols("angle_" + name.getString(), name.getString(),
     286           0 :                                           arrayOfStructsSize, &samplerSymbols, &symbolsToAPINames);
     287           0 :                 for (TIntermSymbol *sampler : samplerSymbols)
     288             :                 {
     289           0 :                     const TType &samplerType = sampler->getType();
     290             : 
     291             :                     // Will use angle_ prefix instead of regular prefix.
     292           0 :                     sampler->setInternal(true);
     293           0 :                     const TName &samplerName = sampler->getName();
     294             : 
     295           0 :                     if (outputType == SH_HLSL_4_1_OUTPUT)
     296             :                     {
     297           0 :                         HLSLTextureSamplerGroup group = TextureGroup(samplerType.getBasicType());
     298           0 :                         groupedSamplerUniforms[group].push_back(sampler);
     299           0 :                         samplerInStructSymbolsToAPINames[sampler] = symbolsToAPINames[sampler];
     300             :                     }
     301           0 :                     else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
     302             :                     {
     303             :                         unsigned int registerIndex = assignSamplerInStructUniformRegister(
     304           0 :                             samplerType, symbolsToAPINames[sampler], nullptr);
     305           0 :                         outputHLSL4_0_FL9_3Sampler(out, samplerType, samplerName, registerIndex);
     306             :                     }
     307             :                     else
     308             :                     {
     309           0 :                         ASSERT(outputType == SH_HLSL_3_0_OUTPUT);
     310             :                         unsigned int registerIndex = assignSamplerInStructUniformRegister(
     311           0 :                             samplerType, symbolsToAPINames[sampler], nullptr);
     312           0 :                         outputUniform(out, samplerType, samplerName, registerIndex);
     313             :                     }
     314             :                 }
     315             :             }
     316           0 :             unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
     317           0 :             outputUniform(out, type, name, registerIndex);
     318             :         }
     319             :     }
     320             : 
     321           0 :     if (outputType == SH_HLSL_4_1_OUTPUT)
     322             :     {
     323           0 :         unsigned int groupTextureRegisterIndex = 0;
     324             :         // TEXTURE_2D is special, index offset is assumed to be 0 and omitted in that case.
     325             :         ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D);
     326           0 :         for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId)
     327             :         {
     328           0 :             outputHLSLSamplerUniformGroup(
     329           0 :                 out, HLSLTextureSamplerGroup(groupId), groupedSamplerUniforms[groupId],
     330           0 :                 samplerInStructSymbolsToAPINames, &groupTextureRegisterIndex);
     331             :         }
     332             :     }
     333           0 : }
     334             : 
     335           0 : void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg)
     336             : {
     337             :     // If mSamplerRegister is 0 the shader doesn't use any textures.
     338           0 :     if (mSamplerRegister > 0)
     339             :     {
     340             :         out << "    struct SamplerMetadata\n"
     341             :                "    {\n"
     342             :                "        int baseLevel;\n"
     343             :                "        int internalFormatBits;\n"
     344             :                "        int wrapModes;\n"
     345             :                "        int padding;\n"
     346             :                "    };\n"
     347           0 :                "    SamplerMetadata samplerMetadata["
     348           0 :             << mSamplerRegister << "] : packoffset(" << reg << ");\n";
     349             :     }
     350           0 : }
     351             : 
     352           0 : TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
     353             : {
     354           0 :     TString interfaceBlocks;
     355             : 
     356           0 :     for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
     357           0 :          interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
     358             :     {
     359           0 :         const TType &nodeType = interfaceBlockIt->second->getType();
     360           0 :         const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
     361             : 
     362           0 :         unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
     363           0 :         unsigned int activeRegister = mInterfaceBlockRegister;
     364             : 
     365           0 :         mInterfaceBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
     366           0 :         mInterfaceBlockRegister += std::max(1u, arraySize);
     367             : 
     368             :         // FIXME: interface block field names
     369             : 
     370           0 :         if (interfaceBlock.hasInstanceName())
     371             :         {
     372           0 :             interfaceBlocks += interfaceBlockStructString(interfaceBlock);
     373             :         }
     374             : 
     375           0 :         if (arraySize > 0)
     376             :         {
     377           0 :             for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
     378             :             {
     379           0 :                 interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex);
     380             :             }
     381             :         }
     382             :         else
     383             :         {
     384           0 :             interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX);
     385             :         }
     386             :     }
     387             : 
     388           0 :     return (interfaceBlocks.empty() ? "" : ("// Interface Blocks\n\n" + interfaceBlocks));
     389             : }
     390             : 
     391           0 : TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex)
     392             : {
     393           0 :     const TString &arrayIndexString =  (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
     394           0 :     const TString &blockName = interfaceBlock.name() + arrayIndexString;
     395           0 :     TString hlsl;
     396             : 
     397           0 :     hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
     398           0 :             "{\n";
     399             : 
     400           0 :     if (interfaceBlock.hasInstanceName())
     401             :     {
     402           0 :         hlsl += "    " + InterfaceBlockStructName(interfaceBlock) + " " +
     403           0 :                 interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
     404             :     }
     405             :     else
     406             :     {
     407           0 :         const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
     408           0 :         hlsl += interfaceBlockMembersString(interfaceBlock, blockStorage);
     409             :     }
     410             : 
     411           0 :     hlsl += "};\n\n";
     412             : 
     413           0 :     return hlsl;
     414             : }
     415             : 
     416           0 : TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex)
     417             : {
     418           0 :     if (!interfaceBlock.hasInstanceName())
     419             :     {
     420           0 :         return "";
     421             :     }
     422           0 :     else if (interfaceBlock.isArray())
     423             :     {
     424           0 :         return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
     425             :     }
     426             :     else
     427             :     {
     428           0 :         return Decorate(interfaceBlock.instanceName());
     429             :     }
     430             : }
     431             : 
     432           0 : TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage)
     433             : {
     434           0 :     TString hlsl;
     435             : 
     436           0 :     Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper();
     437             : 
     438           0 :     for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
     439             :     {
     440           0 :         const TField &field = *interfaceBlock.fields()[typeIndex];
     441           0 :         const TType &fieldType = *field.type();
     442             : 
     443           0 :         if (blockStorage == EbsStd140)
     444             :         {
     445             :             // 2 and 3 component vector types in some cases need pre-padding
     446           0 :             hlsl += padHelper.prePaddingString(fieldType);
     447             :         }
     448             : 
     449           0 :         hlsl += "    " + InterfaceBlockFieldTypeString(field, blockStorage) +
     450           0 :                 " " + Decorate(field.name()) + ArrayString(fieldType) + ";\n";
     451             : 
     452             :         // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
     453           0 :         if (blockStorage == EbsStd140)
     454             :         {
     455           0 :             const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
     456           0 :             hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
     457             :         }
     458             :     }
     459             : 
     460           0 :     return hlsl;
     461             : }
     462             : 
     463           0 : TString UniformHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
     464             : {
     465           0 :     const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
     466             : 
     467           0 :     return "struct " + InterfaceBlockStructName(interfaceBlock) + "\n"
     468           0 :            "{\n" +
     469           0 :            interfaceBlockMembersString(interfaceBlock, blockStorage) +
     470           0 :            "};\n\n";
     471             : }
     472             : 
     473             : }

Generated by: LCOV version 1.13