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.
7 // Implementation for block layout classes and methods.
10 #include "common/blocklayout.h"
11 #include "common/mathutil.h"
12 #include "common/utilities.h"
17 BlockLayoutEncoder::BlockLayoutEncoder()
22 BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
27 getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
29 const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
31 advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
36 void BlockLayoutEncoder::nextRegister()
38 mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
41 Std140BlockEncoder::Std140BlockEncoder()
45 void Std140BlockEncoder::enterAggregateType()
50 void Std140BlockEncoder::exitAggregateType()
55 void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
57 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
58 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
60 size_t baseAlignment = 0;
64 if (gl::IsMatrixType(type))
66 baseAlignment = ComponentsPerRegister;
67 matrixStride = ComponentsPerRegister;
71 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
72 arrayStride = ComponentsPerRegister * numRegisters;
75 else if (arraySize > 0)
77 baseAlignment = ComponentsPerRegister;
78 arrayStride = ComponentsPerRegister;
82 const int numComponents = gl::VariableComponentCount(type);
83 baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
86 mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
88 *matrixStrideOut = matrixStride;
89 *arrayStrideOut = arrayStride;
92 void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
96 mCurrentOffset += arrayStride * arraySize;
98 else if (gl::IsMatrixType(type))
100 ASSERT(matrixStride == ComponentsPerRegister);
101 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
102 mCurrentOffset += ComponentsPerRegister * numRegisters;
106 mCurrentOffset += gl::VariableComponentCount(type);
110 HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy)
111 : mEncoderStrategy(strategy)
115 void HLSLBlockEncoder::enterAggregateType()
120 void HLSLBlockEncoder::exitAggregateType()
124 void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
126 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
127 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
129 int matrixStride = 0;
132 // if variables are not to be packed, or we're about to
133 // pack a matrix or array, skip to the start of the next
136 gl::IsMatrixType(type) ||
142 if (gl::IsMatrixType(type))
144 matrixStride = ComponentsPerRegister;
148 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
149 arrayStride = ComponentsPerRegister * numRegisters;
152 else if (arraySize > 0)
154 arrayStride = ComponentsPerRegister;
158 int numComponents = gl::VariableComponentCount(type);
159 if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
165 *matrixStrideOut = matrixStride;
166 *arrayStrideOut = arrayStride;
169 void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
173 mCurrentOffset += arrayStride * (arraySize - 1);
176 if (gl::IsMatrixType(type))
178 ASSERT(matrixStride == ComponentsPerRegister);
179 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
180 const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
181 mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
182 mCurrentOffset += numComponents;
186 mCurrentOffset += gl::VariableComponentCount(type);
190 mCurrentOffset += ComponentsPerRegister;
194 void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
196 mCurrentOffset += (numRegisters * ComponentsPerRegister);
199 HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
203 case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
204 case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
205 default: UNREACHABLE(); return ENCODE_PACKED;
209 template <class ShaderVarType>
210 void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
212 if (variable.isStruct())
214 for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
216 encoder->enterAggregateType();
218 for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
220 HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
223 encoder->exitAggregateType();
228 // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
229 encoder->encodeType(variable.type, variable.arraySize, false);
233 unsigned int HLSLVariableRegisterCount(const Varying &variable)
235 HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
236 HLSLVariableRegisterCount(variable, &encoder);
238 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
239 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
242 unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
244 HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
245 HLSLVariableRegisterCount(variable, &encoder);
247 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
248 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);