Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / common / blocklayout.cpp
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.cpp:
7 //   Implementation for block layout classes and methods.
8 //
9
10 #include "common/blocklayout.h"
11 #include "common/mathutil.h"
12 #include "common/utilities.h"
13
14 namespace sh
15 {
16
17 BlockLayoutEncoder::BlockLayoutEncoder()
18     : mCurrentOffset(0)
19 {
20 }
21
22 BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
23 {
24     int arrayStride;
25     int matrixStride;
26
27     getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
28
29     const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
30
31     advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
32
33     return memberInfo;
34 }
35
36 void BlockLayoutEncoder::nextRegister()
37 {
38     mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
39 }
40
41 Std140BlockEncoder::Std140BlockEncoder()
42 {
43 }
44
45 void Std140BlockEncoder::enterAggregateType()
46 {
47     nextRegister();
48 }
49
50 void Std140BlockEncoder::exitAggregateType()
51 {
52     nextRegister();
53 }
54
55 void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
56 {
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);
59
60     size_t baseAlignment = 0;
61     int matrixStride = 0;
62     int arrayStride = 0;
63
64     if (gl::IsMatrixType(type))
65     {
66         baseAlignment = ComponentsPerRegister;
67         matrixStride = ComponentsPerRegister;
68
69         if (arraySize > 0)
70         {
71             const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
72             arrayStride = ComponentsPerRegister * numRegisters;
73         }
74     }
75     else if (arraySize > 0)
76     {
77         baseAlignment = ComponentsPerRegister;
78         arrayStride = ComponentsPerRegister;
79     }
80     else
81     {
82         const int numComponents = gl::VariableComponentCount(type);
83         baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
84     }
85
86     mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
87
88     *matrixStrideOut = matrixStride;
89     *arrayStrideOut = arrayStride;
90 }
91
92 void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
93 {
94     if (arraySize > 0)
95     {
96         mCurrentOffset += arrayStride * arraySize;
97     }
98     else if (gl::IsMatrixType(type))
99     {
100         ASSERT(matrixStride == ComponentsPerRegister);
101         const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
102         mCurrentOffset += ComponentsPerRegister * numRegisters;
103     }
104     else
105     {
106         mCurrentOffset += gl::VariableComponentCount(type);
107     }
108 }
109
110 HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy)
111     : mEncoderStrategy(strategy)
112 {
113 }
114
115 void HLSLBlockEncoder::enterAggregateType()
116 {
117     nextRegister();
118 }
119
120 void HLSLBlockEncoder::exitAggregateType()
121 {
122 }
123
124 void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
125 {
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);
128
129     int matrixStride = 0;
130     int arrayStride = 0;
131
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
134     // register
135     if (!isPacked() ||
136         gl::IsMatrixType(type) ||
137         arraySize > 0)
138     {
139         nextRegister();
140     }
141
142     if (gl::IsMatrixType(type))
143     {
144         matrixStride = ComponentsPerRegister;
145
146         if (arraySize > 0)
147         {
148             const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
149             arrayStride = ComponentsPerRegister * numRegisters;
150         }
151     }
152     else if (arraySize > 0)
153     {
154         arrayStride = ComponentsPerRegister;
155     }
156     else if (isPacked())
157     {
158         int numComponents = gl::VariableComponentCount(type);
159         if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
160         {
161             nextRegister();
162         }
163     }
164
165     *matrixStrideOut = matrixStride;
166     *arrayStrideOut = arrayStride;
167 }
168
169 void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
170 {
171     if (arraySize > 0)
172     {
173         mCurrentOffset += arrayStride * (arraySize - 1);
174     }
175
176     if (gl::IsMatrixType(type))
177     {
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;
183     }
184     else if (isPacked())
185     {
186         mCurrentOffset += gl::VariableComponentCount(type);
187     }
188     else
189     {
190         mCurrentOffset += ComponentsPerRegister;
191     }
192 }
193
194 void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
195 {
196     mCurrentOffset += (numRegisters * ComponentsPerRegister);
197 }
198
199 HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
200 {
201     switch (outputType)
202     {
203       case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
204       case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
205       default: UNREACHABLE(); return ENCODE_PACKED;
206     }
207 }
208
209 template <class ShaderVarType>
210 void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
211 {
212     if (variable.isStruct())
213     {
214         for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
215         {
216             encoder->enterAggregateType();
217
218             for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
219             {
220                 HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
221             }
222
223             encoder->exitAggregateType();
224         }
225     }
226     else
227     {
228         // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
229         encoder->encodeType(variable.type, variable.arraySize, false);
230     }
231 }
232
233 unsigned int HLSLVariableRegisterCount(const Varying &variable)
234 {
235     HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
236     HLSLVariableRegisterCount(variable, &encoder);
237
238     const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
239     return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
240 }
241
242 unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
243 {
244     HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
245     HLSLVariableRegisterCount(variable, &encoder);
246
247     const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
248     return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
249 }
250
251 }