Home | History | Annotate | Download | only in common
      1 //
      2 // Copyright (c) 2013-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 // blocklayout.h:
      7 //   Methods and classes related to uniform layout and packing in GLSL and HLSL.
      8 //
      9 
     10 #ifndef COMMON_BLOCKLAYOUT_H_
     11 #define COMMON_BLOCKLAYOUT_H_
     12 
     13 #include <cstddef>
     14 #include <vector>
     15 
     16 #include "angle_gl.h"
     17 #include <GLSLANG/ShaderLang.h>
     18 
     19 namespace sh
     20 {
     21 struct ShaderVariable;
     22 struct InterfaceBlockField;
     23 struct Uniform;
     24 struct Varying;
     25 struct InterfaceBlock;
     26 
     27 struct BlockMemberInfo
     28 {
     29     BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
     30         : offset(offset),
     31           arrayStride(arrayStride),
     32           matrixStride(matrixStride),
     33           isRowMajorMatrix(isRowMajorMatrix)
     34     {}
     35 
     36     static BlockMemberInfo getDefaultBlockInfo()
     37     {
     38         return BlockMemberInfo(-1, -1, -1, false);
     39     }
     40 
     41     int offset;
     42     int arrayStride;
     43     int matrixStride;
     44     bool isRowMajorMatrix;
     45 };
     46 
     47 class BlockLayoutEncoder
     48 {
     49   public:
     50     BlockLayoutEncoder();
     51 
     52     BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
     53 
     54     size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
     55     size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; }
     56     size_t getCurrentElement() const { return mCurrentOffset % ComponentsPerRegister; }
     57 
     58     virtual void enterAggregateType() = 0;
     59     virtual void exitAggregateType() = 0;
     60 
     61     static const size_t BytesPerComponent = 4u;
     62     static const unsigned int ComponentsPerRegister = 4u;
     63 
     64   protected:
     65     size_t mCurrentOffset;
     66 
     67     void nextRegister();
     68 
     69     virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0;
     70     virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0;
     71 };
     72 
     73 // Block layout according to the std140 block layout
     74 // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
     75 
     76 class Std140BlockEncoder : public BlockLayoutEncoder
     77 {
     78   public:
     79     Std140BlockEncoder();
     80 
     81     virtual void enterAggregateType();
     82     virtual void exitAggregateType();
     83 
     84   protected:
     85     virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut);
     86     virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
     87 };
     88 
     89 // Block layout packed according to the D3D9 or default D3D10+ register packing rules
     90 // See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
     91 // The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED
     92 // for everything else (D3D10+ constant blocks and all attributes/varyings).
     93 
     94 class HLSLBlockEncoder : public BlockLayoutEncoder
     95 {
     96   public:
     97     enum HLSLBlockEncoderStrategy
     98     {
     99         ENCODE_PACKED,
    100         ENCODE_LOOSE
    101     };
    102 
    103     HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy);
    104 
    105     virtual void enterAggregateType();
    106     virtual void exitAggregateType();
    107     void skipRegisters(unsigned int numRegisters);
    108 
    109     bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
    110 
    111     static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType);
    112 
    113   protected:
    114     virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut);
    115     virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
    116 
    117     HLSLBlockEncoderStrategy mEncoderStrategy;
    118 };
    119 
    120 // This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder
    121 // class to count the number of used registers in a struct (which are individually packed according to the same rules).
    122 unsigned int HLSLVariableRegisterCount(const Varying &variable);
    123 unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType);
    124 
    125 }
    126 
    127 #endif // COMMON_BLOCKLAYOUT_H_
    128