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 19namespace sh 20{ 21struct ShaderVariable; 22struct InterfaceBlockField; 23struct Uniform; 24struct Varying; 25struct InterfaceBlock; 26 27struct 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 47class 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 76class 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 94class 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). 122unsigned int HLSLVariableRegisterCount(const Varying &variable); 123unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); 124 125} 126 127#endif // COMMON_BLOCKLAYOUT_H_ 128