LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - StructureHLSL.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 243 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 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             : // StructureHLSL.cpp:
       7             : //   Definitions of methods for HLSL translation of GLSL structures.
       8             : //
       9             : 
      10             : #include "compiler/translator/StructureHLSL.h"
      11             : #include "common/utilities.h"
      12             : #include "compiler/translator/OutputHLSL.h"
      13             : #include "compiler/translator/Types.h"
      14             : #include "compiler/translator/util.h"
      15             : #include "compiler/translator/UtilsHLSL.h"
      16             : 
      17             : namespace sh
      18             : {
      19             : 
      20           0 : Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &structElementIndexes,
      21           0 :                                          unsigned *uniqueCounter)
      22             :     : mPaddingCounter(uniqueCounter),
      23             :       mElementIndex(0),
      24           0 :       mStructElementIndexes(&structElementIndexes)
      25           0 : {}
      26             : 
      27           0 : Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other)
      28           0 :     : mPaddingCounter(other.mPaddingCounter),
      29           0 :       mElementIndex(other.mElementIndex),
      30           0 :       mStructElementIndexes(other.mStructElementIndexes)
      31           0 : {}
      32             : 
      33           0 : Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other)
      34             : {
      35           0 :     mPaddingCounter = other.mPaddingCounter;
      36           0 :     mElementIndex = other.mElementIndex;
      37           0 :     mStructElementIndexes = other.mStructElementIndexes;
      38           0 :     return *this;
      39             : }
      40             : 
      41           0 : TString Std140PaddingHelper::next()
      42             : {
      43           0 :     unsigned value = (*mPaddingCounter)++;
      44           0 :     return str(value);
      45             : }
      46             : 
      47           0 : int Std140PaddingHelper::prePadding(const TType &type)
      48             : {
      49           0 :     if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
      50             :     {
      51             :         // no padding needed, HLSL will align the field to a new register
      52           0 :         mElementIndex = 0;
      53           0 :         return 0;
      54             :     }
      55             : 
      56           0 :     const GLenum glType = GLVariableType(type);
      57           0 :     const int numComponents = gl::VariableComponentCount(glType);
      58             : 
      59           0 :     if (numComponents >= 4)
      60             :     {
      61             :         // no padding needed, HLSL will align the field to a new register
      62           0 :         mElementIndex = 0;
      63           0 :         return 0;
      64             :     }
      65             : 
      66           0 :     if (mElementIndex + numComponents > 4)
      67             :     {
      68             :         // no padding needed, HLSL will align the field to a new register
      69           0 :         mElementIndex = numComponents;
      70           0 :         return 0;
      71             :     }
      72             : 
      73           0 :     const int alignment = numComponents == 3 ? 4 : numComponents;
      74           0 :     const int paddingOffset = (mElementIndex % alignment);
      75           0 :     const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0);
      76             : 
      77           0 :     mElementIndex += paddingCount;
      78           0 :     mElementIndex += numComponents;
      79           0 :     mElementIndex %= 4;
      80             : 
      81           0 :     return paddingCount;
      82             : }
      83             : 
      84           0 : TString Std140PaddingHelper::prePaddingString(const TType &type)
      85             : {
      86           0 :     int paddingCount = prePadding(type);
      87             : 
      88           0 :     TString padding;
      89             : 
      90           0 :     for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++)
      91             :     {
      92           0 :         padding += "    float pad_" + next() + ";\n";
      93             :     }
      94             : 
      95           0 :     return padding;
      96             : }
      97             : 
      98           0 : TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRowMajorPacking)
      99             : {
     100           0 :     if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct)
     101             :     {
     102           0 :         return "";
     103             :     }
     104             : 
     105           0 :     int numComponents = 0;
     106           0 :     TStructure *structure = type.getStruct();
     107             : 
     108           0 :     if (type.isMatrix())
     109             :     {
     110             :         // This method can also be called from structureString, which does not use layout qualifiers.
     111             :         // Thus, use the method parameter for determining the matrix packing.
     112             :         //
     113             :         // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we
     114             :         // wish to always transpose GL matrices to play well with HLSL's matrix array indexing.
     115             :         //
     116           0 :         const bool isRowMajorMatrix = !useHLSLRowMajorPacking;
     117           0 :         const GLenum glType = GLVariableType(type);
     118           0 :         numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
     119             :     }
     120           0 :     else if (structure)
     121             :     {
     122             :         const TString &structName = QualifiedStructNameString(*structure,
     123           0 :                                                               useHLSLRowMajorPacking, true);
     124           0 :         numComponents = mStructElementIndexes->find(structName)->second;
     125             : 
     126           0 :         if (numComponents == 0)
     127             :         {
     128           0 :             return "";
     129             :         }
     130             :     }
     131             :     else
     132             :     {
     133           0 :         const GLenum glType = GLVariableType(type);
     134           0 :         numComponents = gl::VariableComponentCount(glType);
     135             :     }
     136             : 
     137           0 :     TString padding;
     138           0 :     for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++)
     139             :     {
     140           0 :         padding += "    float pad_" + next() + ";\n";
     141             :     }
     142           0 :     return padding;
     143             : }
     144             : 
     145           0 : StructureHLSL::StructureHLSL()
     146           0 :     : mUniquePaddingCounter(0)
     147           0 : {}
     148             : 
     149           0 : Std140PaddingHelper StructureHLSL::getPaddingHelper()
     150             : {
     151           0 :     return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter);
     152             : }
     153             : 
     154           0 : TString StructureHLSL::defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing)
     155             : {
     156           0 :     if (useStd140Packing)
     157             :     {
     158           0 :         Std140PaddingHelper padHelper = getPaddingHelper();
     159           0 :         return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper);
     160             :     }
     161             :     else
     162             :     {
     163           0 :         return define(structure, useHLSLRowMajorPacking, useStd140Packing, NULL);
     164             :     }
     165             : }
     166             : 
     167           0 : TString StructureHLSL::defineNameless(const TStructure &structure)
     168             : {
     169           0 :     return define(structure, false, false, NULL);
     170             : }
     171             : 
     172           0 : TString StructureHLSL::define(const TStructure &structure, bool useHLSLRowMajorPacking,
     173             :                               bool useStd140Packing, Std140PaddingHelper *padHelper)
     174             : {
     175           0 :     const TFieldList &fields = structure.fields();
     176           0 :     const bool isNameless = (structure.name() == "");
     177             :     const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking,
     178           0 :                                                           useStd140Packing);
     179           0 :     const TString declareString = (isNameless ? "struct" : "struct " + structName);
     180             : 
     181           0 :     TString string;
     182           0 :     string += declareString + "\n"
     183           0 :               "{\n";
     184             : 
     185           0 :     for (const TField *field : fields)
     186             :     {
     187           0 :         const TType &fieldType = *field->type();
     188           0 :         if (!IsSampler(fieldType.getBasicType()))
     189             :         {
     190           0 :             const TStructure *fieldStruct = fieldType.getStruct();
     191             :             const TString &fieldTypeString =
     192             :                 fieldStruct ? QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking,
     193             :                                                         useStd140Packing)
     194           0 :                             : TypeString(fieldType);
     195             : 
     196           0 :             if (padHelper)
     197             :             {
     198           0 :                 string += padHelper->prePaddingString(fieldType);
     199             :             }
     200             : 
     201           0 :             string += "    " + fieldTypeString + " " + DecorateField(field->name(), structure) +
     202           0 :                       ArrayString(fieldType) + ";\n";
     203             : 
     204           0 :             if (padHelper)
     205             :             {
     206           0 :                 string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking);
     207             :             }
     208             :         }
     209             :     }
     210             : 
     211             :     // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable
     212           0 :     string += (isNameless ? "} " : "};\n");
     213             : 
     214           0 :     return string;
     215             : }
     216             : 
     217           0 : TString StructureHLSL::addConstructor(const TType &type,
     218             :                                       const TString &name,
     219             :                                       const TIntermSequence *parameters)
     220             : {
     221           0 :     if (name == "")
     222             :     {
     223           0 :         return TString();  // Nameless structures don't have constructors
     224             :     }
     225             : 
     226           0 :     if (type.getStruct() && mStructNames.find(name) != mStructNames.end())
     227             :     {
     228           0 :         return TString(name);  // Already added
     229             :     }
     230             : 
     231           0 :     TType ctorType = type;
     232           0 :     ctorType.clearArrayness();
     233           0 :     ctorType.setPrecision(EbpHigh);
     234           0 :     ctorType.setQualifier(EvqTemporary);
     235             : 
     236             :     typedef std::vector<TType> ParameterArray;
     237           0 :     ParameterArray ctorParameters;
     238             : 
     239           0 :     TString constructorFunctionName;
     240             : 
     241           0 :     const TStructure* structure = type.getStruct();
     242           0 :     if (structure)
     243             :     {
     244           0 :         mStructNames.insert(name);
     245             : 
     246             :         // Add element index
     247           0 :         storeStd140ElementIndex(*structure, false);
     248           0 :         storeStd140ElementIndex(*structure, true);
     249             : 
     250           0 :         const TString &structString = defineQualified(*structure, false, false);
     251             : 
     252           0 :         if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == mStructDeclarations.end())
     253             :         {
     254             :             // Add row-major packed struct for interface blocks
     255           0 :             TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
     256           0 :                 defineQualified(*structure, true, false) +
     257           0 :                 "#pragma pack_matrix(column_major)\n";
     258             : 
     259           0 :             TString std140String = defineQualified(*structure, false, true);
     260           0 :             TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
     261           0 :                 defineQualified(*structure, true, true) +
     262           0 :                 "#pragma pack_matrix(column_major)\n";
     263             : 
     264           0 :             mStructDeclarations.push_back(structString);
     265           0 :             mStructDeclarations.push_back(rowMajorString);
     266           0 :             mStructDeclarations.push_back(std140String);
     267           0 :             mStructDeclarations.push_back(std140RowMajorString);
     268             :         }
     269             : 
     270           0 :         const TFieldList &fields = structure->fields();
     271           0 :         for (const TField *field : fields)
     272             :         {
     273           0 :             const TType *fieldType = field->type();
     274           0 :             if (!IsSampler(fieldType->getBasicType()))
     275             :             {
     276           0 :                 ctorParameters.push_back(*fieldType);
     277             :             }
     278             :         }
     279           0 :         constructorFunctionName = TString(name);
     280             :     }
     281           0 :     else if (parameters)
     282             :     {
     283           0 :         for (auto parameter : *parameters)
     284             :         {
     285           0 :             const TType &paramType = parameter->getAsTyped()->getType();
     286           0 :             ctorParameters.push_back(paramType);
     287             :         }
     288           0 :         constructorFunctionName = TString(name) + DisambiguateFunctionName(parameters);
     289             :     }
     290           0 :     else UNREACHABLE();
     291             : 
     292           0 :     TString constructor;
     293             : 
     294           0 :     if (ctorType.getStruct())
     295             :     {
     296           0 :         constructor += name + " " + name + "_ctor(";
     297             :     }
     298             :     else   // Built-in type
     299             :     {
     300           0 :         constructor += TypeString(ctorType) + " " + constructorFunctionName + "(";
     301             :     }
     302             : 
     303           0 :     for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
     304             :     {
     305           0 :         const TType &paramType = ctorParameters[parameter];
     306             : 
     307           0 :         constructor += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType);
     308             : 
     309           0 :         if (parameter < ctorParameters.size() - 1)
     310             :         {
     311           0 :             constructor += ", ";
     312             :         }
     313             :     }
     314             : 
     315             :     constructor += ")\n"
     316           0 :                    "{\n";
     317             : 
     318           0 :     if (ctorType.getStruct())
     319             :     {
     320           0 :         constructor += "    " + name + " structure";
     321           0 :         if (ctorParameters.empty())
     322             :         {
     323           0 :             constructor += ";\n";
     324             :         }
     325             :         else
     326             :         {
     327           0 :             constructor += " = { ";
     328             :         }
     329             :     }
     330             :     else
     331             :     {
     332           0 :         constructor += "    return " + TypeString(ctorType) + "(";
     333             :     }
     334             : 
     335           0 :     if (ctorType.isMatrix() && ctorParameters.size() == 1)
     336             :     {
     337           0 :         int rows = ctorType.getRows();
     338           0 :         int cols = ctorType.getCols();
     339           0 :         const TType &parameter = ctorParameters[0];
     340             : 
     341           0 :         if (parameter.isScalar())
     342             :         {
     343           0 :             for (int col = 0; col < cols; col++)
     344             :             {
     345           0 :                 for (int row = 0; row < rows; row++)
     346             :                 {
     347           0 :                     constructor += TString((row == col) ? "x0" : "0.0");
     348             : 
     349           0 :                     if (row < rows - 1 || col < cols - 1)
     350             :                     {
     351           0 :                         constructor += ", ";
     352             :                     }
     353             :                 }
     354             :             }
     355             :         }
     356           0 :         else if (parameter.isMatrix())
     357             :         {
     358           0 :             for (int col = 0; col < cols; col++)
     359             :             {
     360           0 :                 for (int row = 0; row < rows; row++)
     361             :                 {
     362           0 :                     if (row < parameter.getRows() && col < parameter.getCols())
     363             :                     {
     364           0 :                         constructor += TString("x0") + "[" + str(col) + "][" + str(row) + "]";
     365             :                     }
     366             :                     else
     367             :                     {
     368           0 :                         constructor += TString((row == col) ? "1.0" : "0.0");
     369             :                     }
     370             : 
     371           0 :                     if (row < rows - 1 || col < cols - 1)
     372             :                     {
     373           0 :                         constructor += ", ";
     374             :                     }
     375             :                 }
     376             :             }
     377             :         }
     378             :         else
     379             :         {
     380           0 :             ASSERT(rows == 2 && cols == 2 && parameter.isVector() && parameter.getNominalSize() == 4);
     381             : 
     382           0 :             constructor += "x0";
     383             :         }
     384             :     }
     385             :     else
     386             :     {
     387           0 :         size_t remainingComponents = 0;
     388           0 :         if (ctorType.getStruct())
     389             :         {
     390           0 :             remainingComponents = ctorParameters.size();
     391             :         }
     392             :         else
     393             :         {
     394           0 :             remainingComponents = ctorType.getObjectSize();
     395             :         }
     396           0 :         size_t parameterIndex = 0;
     397             : 
     398           0 :         while (remainingComponents > 0)
     399             :         {
     400           0 :             const TType &parameter = ctorParameters[parameterIndex];
     401           0 :             const size_t parameterSize = parameter.getObjectSize();
     402           0 :             bool moreParameters = parameterIndex + 1 < ctorParameters.size();
     403             : 
     404           0 :             constructor += "x" + str(parameterIndex);
     405             : 
     406           0 :             if (ctorType.getStruct())
     407             :             {
     408           0 :                 ASSERT(remainingComponents == 1 || moreParameters);
     409             : 
     410           0 :                 --remainingComponents;
     411             :             }
     412           0 :             else if (parameter.isScalar())
     413             :             {
     414           0 :                 remainingComponents -= parameter.getObjectSize();
     415             :             }
     416           0 :             else if (parameter.isVector())
     417             :             {
     418           0 :                 if (remainingComponents == parameterSize || moreParameters)
     419             :                 {
     420           0 :                     ASSERT(parameterSize <= remainingComponents);
     421           0 :                     remainingComponents -= parameterSize;
     422             :                 }
     423           0 :                 else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
     424             :                 {
     425           0 :                     switch (remainingComponents)
     426             :                     {
     427           0 :                       case 1: constructor += ".x";    break;
     428           0 :                       case 2: constructor += ".xy";   break;
     429           0 :                       case 3: constructor += ".xyz";  break;
     430           0 :                       case 4: constructor += ".xyzw"; break;
     431           0 :                       default: UNREACHABLE();
     432             :                     }
     433             : 
     434           0 :                     remainingComponents = 0;
     435             :                 }
     436           0 :                 else UNREACHABLE();
     437             :             }
     438           0 :             else if (parameter.isMatrix())
     439             :             {
     440           0 :                 int column = 0;
     441           0 :                 while (remainingComponents > 0 && column < parameter.getCols())
     442             :                 {
     443           0 :                     constructor += "[" + str(column) + "]";
     444             : 
     445           0 :                     if (remainingComponents < static_cast<size_t>(parameter.getRows()))
     446             :                     {
     447           0 :                         switch (remainingComponents)
     448             :                         {
     449           0 :                           case 1:  constructor += ".x";    break;
     450           0 :                           case 2:  constructor += ".xy";   break;
     451           0 :                           case 3:  constructor += ".xyz";  break;
     452           0 :                           default: UNREACHABLE();
     453             :                         }
     454             : 
     455           0 :                         remainingComponents = 0;
     456             :                     }
     457             :                     else
     458             :                     {
     459           0 :                         remainingComponents -= parameter.getRows();
     460             : 
     461           0 :                         if (remainingComponents > 0)
     462             :                         {
     463           0 :                             constructor += ", x" + str(parameterIndex);
     464             :                         }
     465             :                     }
     466             : 
     467           0 :                     column++;
     468             :                 }
     469             :             }
     470           0 :             else UNREACHABLE();
     471             : 
     472           0 :             if (moreParameters)
     473             :             {
     474           0 :                 parameterIndex++;
     475             :             }
     476             : 
     477           0 :             if (remainingComponents)
     478             :             {
     479           0 :                 constructor += ", ";
     480             :             }
     481             :         }
     482             :     }
     483             : 
     484           0 :     if (ctorType.getStruct())
     485             :     {
     486           0 :         if (!ctorParameters.empty())
     487             :         {
     488           0 :             constructor += "};\n";
     489             :         }
     490             :         constructor +=
     491             :             "    return structure;\n"
     492           0 :             "}\n";
     493             :     }
     494             :     else
     495             :     {
     496             :         constructor += ");\n"
     497           0 :                        "}\n";
     498             :     }
     499             : 
     500           0 :     mConstructors.insert(constructor);
     501             : 
     502           0 :     return constructorFunctionName;
     503             : }
     504             : 
     505           0 : std::string StructureHLSL::structsHeader() const
     506             : {
     507           0 :     TInfoSinkBase out;
     508             : 
     509           0 :     for (size_t structIndex = 0; structIndex < mStructDeclarations.size(); structIndex++)
     510             :     {
     511           0 :         out << mStructDeclarations[structIndex];
     512             :     }
     513             : 
     514           0 :     for (Constructors::const_iterator constructor = mConstructors.begin();
     515           0 :          constructor != mConstructors.end();
     516             :          constructor++)
     517             :     {
     518           0 :         out << *constructor;
     519             :     }
     520             : 
     521           0 :     return out.str();
     522             : }
     523             : 
     524           0 : void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking)
     525             : {
     526           0 :     Std140PaddingHelper padHelper = getPaddingHelper();
     527           0 :     const TFieldList &fields = structure.fields();
     528             : 
     529           0 :     for (unsigned int i = 0; i < fields.size(); i++)
     530             :     {
     531           0 :         padHelper.prePadding(*fields[i]->type());
     532             :     }
     533             : 
     534             :     // Add remaining element index to the global map, for use with nested structs in standard layouts
     535           0 :     const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, true);
     536           0 :     mStd140StructElementIndexes[structName] = padHelper.elementIndex();
     537           0 : }
     538             : 
     539             : }

Generated by: LCOV version 1.13