blob: f7c9b8f42cf7a3a48204c2ec1eced81a77fe2606 [file] [log] [blame]
Jamie Madill834e8b72014-04-11 13:33:58 -04001//
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/shadervars.h"
12#include "common/mathutil.h"
13#include "common/utilities.h"
14
15namespace gl
16{
17
18BlockLayoutEncoder::BlockLayoutEncoder(std::vector<BlockMemberInfo> *blockInfoOut)
19 : mCurrentOffset(0),
20 mBlockInfoOut(blockInfoOut)
21{
22}
23
24void BlockLayoutEncoder::encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields)
25{
26 for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
27 {
28 const InterfaceBlockField &variable = fields[fieldIndex];
29
30 if (variable.fields.size() > 0)
31 {
32 const unsigned int elementCount = std::max(1u, variable.arraySize);
33
34 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
35 {
36 enterAggregateType();
37 encodeInterfaceBlockFields(variable.fields);
38 exitAggregateType();
39 }
40 }
41 else
42 {
43 encodeInterfaceBlockField(variable);
44 }
45 }
46}
47
48void BlockLayoutEncoder::encodeInterfaceBlockField(const InterfaceBlockField &field)
49{
50 int arrayStride;
51 int matrixStride;
52
53 ASSERT(field.fields.empty());
54 getBlockLayoutInfo(field.type, field.arraySize, field.isRowMajorMatrix, &arrayStride, &matrixStride);
55
56 const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, field.isRowMajorMatrix);
57
58 if (mBlockInfoOut)
59 {
60 mBlockInfoOut->push_back(memberInfo);
61 }
62
63 advanceOffset(field.type, field.arraySize, field.isRowMajorMatrix, arrayStride, matrixStride);
64}
65
66void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
67{
68 int arrayStride;
69 int matrixStride;
70
71 getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
72
73 const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
74
75 if (mBlockInfoOut)
76 {
77 mBlockInfoOut->push_back(memberInfo);
78 }
79
80 advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
81}
82
83void BlockLayoutEncoder::nextRegister()
84{
85 mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
86}
87
88Std140BlockEncoder::Std140BlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut)
89 : BlockLayoutEncoder(blockInfoOut)
90{
91}
92
93void Std140BlockEncoder::enterAggregateType()
94{
95 nextRegister();
96}
97
98void Std140BlockEncoder::exitAggregateType()
99{
100 nextRegister();
101}
102
103void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
104{
105 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
106 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(type)) == BytesPerComponent);
107
108 size_t baseAlignment = 0;
109 int matrixStride = 0;
110 int arrayStride = 0;
111
112 if (gl::IsMatrixType(type))
113 {
114 baseAlignment = ComponentsPerRegister;
115 matrixStride = ComponentsPerRegister;
116
117 if (arraySize > 0)
118 {
119 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
120 arrayStride = ComponentsPerRegister * numRegisters;
121 }
122 }
123 else if (arraySize > 0)
124 {
125 baseAlignment = ComponentsPerRegister;
126 arrayStride = ComponentsPerRegister;
127 }
128 else
129 {
130 const int numComponents = gl::UniformComponentCount(type);
131 baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
132 }
133
134 mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
135
136 *matrixStrideOut = matrixStride;
137 *arrayStrideOut = arrayStride;
138}
139
140void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
141{
142 if (arraySize > 0)
143 {
144 mCurrentOffset += arrayStride * arraySize;
145 }
146 else if (gl::IsMatrixType(type))
147 {
148 ASSERT(matrixStride == ComponentsPerRegister);
149 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
150 mCurrentOffset += ComponentsPerRegister * numRegisters;
151 }
152 else
153 {
154 mCurrentOffset += gl::UniformComponentCount(type);
155 }
156}
157
158HLSLBlockEncoder::HLSLBlockEncoder(std::vector<BlockMemberInfo> *blockInfoOut)
159 : BlockLayoutEncoder(blockInfoOut)
160{
161}
162
163void HLSLBlockEncoder::enterAggregateType()
164{
165 nextRegister();
166}
167
168void HLSLBlockEncoder::exitAggregateType()
169{
170}
171
172void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
173{
174 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
175 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(type)) == BytesPerComponent);
176
177 int matrixStride = 0;
178 int arrayStride = 0;
179
180 if (gl::IsMatrixType(type))
181 {
182 nextRegister();
183 matrixStride = ComponentsPerRegister;
184
185 if (arraySize > 0)
186 {
187 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
188 arrayStride = ComponentsPerRegister * numRegisters;
189 }
190 }
191 else if (arraySize > 0)
192 {
193 nextRegister();
194 arrayStride = ComponentsPerRegister;
195 }
196 else
197 {
198 int numComponents = gl::UniformComponentCount(type);
199 if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
200 {
201 nextRegister();
202 }
203 }
204
205 *matrixStrideOut = matrixStride;
206 *arrayStrideOut = arrayStride;
207}
208
209void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
210{
211 if (arraySize > 0)
212 {
213 mCurrentOffset += arrayStride * (arraySize - 1);
214 }
215
216 if (gl::IsMatrixType(type))
217 {
218 ASSERT(matrixStride == ComponentsPerRegister);
219 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
220 const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
221 mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
222 mCurrentOffset += numComponents;
223 }
224 else
225 {
226 mCurrentOffset += gl::UniformComponentCount(type);
227 }
228}
229
Jamie Madillc600c8c2014-05-16 11:22:21 -0400230void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
231{
232 mCurrentOffset += (numRegisters * ComponentsPerRegister);
233}
234
Jamie Madill834e8b72014-04-11 13:33:58 -0400235void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *variable, HLSLBlockEncoder *encoder, const std::vector<gl::BlockMemberInfo> &blockInfo)
236{
237 // because this method computes offsets (element indexes) instead of any total sizes,
238 // we can ignore the array size of the variable
239
240 if (variable->isStruct())
241 {
242 encoder->enterAggregateType();
243
Jamie Madillc600c8c2014-05-16 11:22:21 -0400244 variable->registerIndex = baseRegisterIndex;
245
Jamie Madill834e8b72014-04-11 13:33:58 -0400246 for (size_t fieldIndex = 0; fieldIndex < variable->fields.size(); fieldIndex++)
247 {
248 HLSLVariableGetRegisterInfo(baseRegisterIndex, &variable->fields[fieldIndex], encoder, blockInfo);
249 }
250
Jamie Madillc600c8c2014-05-16 11:22:21 -0400251 // Since the above loop only encodes one element of an array, ensure we don't lose track of the
252 // current register offset
253 if (variable->isArray())
254 {
255 unsigned int structRegisterCount = (HLSLVariableRegisterCount(*variable) / variable->arraySize);
256 encoder->skipRegisters(structRegisterCount * (variable->arraySize - 1));
257 }
258
Jamie Madill834e8b72014-04-11 13:33:58 -0400259 encoder->exitAggregateType();
260 }
261 else
262 {
263 encoder->encodeType(variable->type, variable->arraySize, false);
264
265 const size_t registerBytes = (encoder->BytesPerComponent * encoder->ComponentsPerRegister);
266 variable->registerIndex = baseRegisterIndex + (blockInfo.back().offset / registerBytes);
267 variable->elementIndex = (blockInfo.back().offset % registerBytes) / sizeof(float);
268 }
269}
270
271void HLSLVariableGetRegisterInfo(unsigned int baseRegisterIndex, gl::Uniform *variable)
272{
273 std::vector<BlockMemberInfo> blockInfo;
274 HLSLBlockEncoder encoder(&blockInfo);
275 HLSLVariableGetRegisterInfo(baseRegisterIndex, variable, &encoder, blockInfo);
276}
277
278template <class ShaderVarType>
279void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
280{
281 if (variable.isStruct())
282 {
283 for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
284 {
285 encoder->enterAggregateType();
286
287 for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
288 {
289 HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
290 }
291
292 encoder->exitAggregateType();
293 }
294 }
295 else
296 {
297 // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
298 encoder->encodeType(variable.type, variable.arraySize, false);
299 }
300}
301
302unsigned int HLSLVariableRegisterCount(const Varying &variable)
303{
304 HLSLBlockEncoder encoder(NULL);
305 HLSLVariableRegisterCount(variable, &encoder);
306
307 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
308 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
309}
310
311unsigned int HLSLVariableRegisterCount(const Uniform &variable)
312{
313 HLSLBlockEncoder encoder(NULL);
314 HLSLVariableRegisterCount(variable, &encoder);
315
316 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
317 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
318}
319
320}