blob: 7db6e980f1cb6268e61655882f6a507de85269a4 [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
Jamie Madillf2575982014-06-25 16:04:54 -040015namespace sh
Jamie Madill834e8b72014-04-11 13:33:58 -040016{
17
Jamie Madille04a5b72014-07-18 10:33:12 -040018BlockLayoutEncoder::BlockLayoutEncoder()
19 : mCurrentOffset(0)
Jamie Madill834e8b72014-04-11 13:33:58 -040020{
21}
22
23void BlockLayoutEncoder::encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields)
24{
25 for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
26 {
27 const InterfaceBlockField &variable = fields[fieldIndex];
28
29 if (variable.fields.size() > 0)
30 {
31 const unsigned int elementCount = std::max(1u, variable.arraySize);
32
33 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
34 {
35 enterAggregateType();
36 encodeInterfaceBlockFields(variable.fields);
37 exitAggregateType();
38 }
39 }
40 else
41 {
42 encodeInterfaceBlockField(variable);
43 }
44 }
45}
46
Jamie Madille04a5b72014-07-18 10:33:12 -040047BlockMemberInfo BlockLayoutEncoder::encodeInterfaceBlockField(const InterfaceBlockField &field)
Jamie Madill834e8b72014-04-11 13:33:58 -040048{
49 int arrayStride;
50 int matrixStride;
51
52 ASSERT(field.fields.empty());
53 getBlockLayoutInfo(field.type, field.arraySize, field.isRowMajorMatrix, &arrayStride, &matrixStride);
54
55 const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, field.isRowMajorMatrix);
56
Jamie Madill834e8b72014-04-11 13:33:58 -040057 advanceOffset(field.type, field.arraySize, field.isRowMajorMatrix, arrayStride, matrixStride);
Jamie Madille04a5b72014-07-18 10:33:12 -040058
59 return memberInfo;
Jamie Madill834e8b72014-04-11 13:33:58 -040060}
61
62void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
63{
64 int arrayStride;
65 int matrixStride;
66
67 getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
68
69 const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
70
Jamie Madill834e8b72014-04-11 13:33:58 -040071 advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
72}
73
74void BlockLayoutEncoder::nextRegister()
75{
76 mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
77}
78
Jamie Madille04a5b72014-07-18 10:33:12 -040079Std140BlockEncoder::Std140BlockEncoder()
Jamie Madill834e8b72014-04-11 13:33:58 -040080{
81}
82
83void Std140BlockEncoder::enterAggregateType()
84{
85 nextRegister();
86}
87
88void Std140BlockEncoder::exitAggregateType()
89{
90 nextRegister();
91}
92
93void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
94{
95 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
Jamie Madillf2575982014-06-25 16:04:54 -040096 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
Jamie Madill834e8b72014-04-11 13:33:58 -040097
98 size_t baseAlignment = 0;
99 int matrixStride = 0;
100 int arrayStride = 0;
101
102 if (gl::IsMatrixType(type))
103 {
104 baseAlignment = ComponentsPerRegister;
105 matrixStride = ComponentsPerRegister;
106
107 if (arraySize > 0)
108 {
109 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
110 arrayStride = ComponentsPerRegister * numRegisters;
111 }
112 }
113 else if (arraySize > 0)
114 {
115 baseAlignment = ComponentsPerRegister;
116 arrayStride = ComponentsPerRegister;
117 }
118 else
119 {
Jamie Madillf2575982014-06-25 16:04:54 -0400120 const int numComponents = gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400121 baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
122 }
123
124 mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
125
126 *matrixStrideOut = matrixStride;
127 *arrayStrideOut = arrayStride;
128}
129
130void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
131{
132 if (arraySize > 0)
133 {
134 mCurrentOffset += arrayStride * arraySize;
135 }
136 else if (gl::IsMatrixType(type))
137 {
138 ASSERT(matrixStride == ComponentsPerRegister);
139 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
140 mCurrentOffset += ComponentsPerRegister * numRegisters;
141 }
142 else
143 {
Jamie Madillf2575982014-06-25 16:04:54 -0400144 mCurrentOffset += gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400145 }
146}
147
Jamie Madille04a5b72014-07-18 10:33:12 -0400148HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy)
149 : mEncoderStrategy(strategy)
Jamie Madillbf9cce22014-07-18 10:33:09 -0400150{
151}
152
Jamie Madill834e8b72014-04-11 13:33:58 -0400153void HLSLBlockEncoder::enterAggregateType()
154{
155 nextRegister();
156}
157
158void HLSLBlockEncoder::exitAggregateType()
159{
160}
161
162void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
163{
164 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
Jamie Madillf2575982014-06-25 16:04:54 -0400165 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
Jamie Madill834e8b72014-04-11 13:33:58 -0400166
167 int matrixStride = 0;
168 int arrayStride = 0;
169
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400170 // if variables are not to be packed, or we're about to
171 // pack a matrix or array, skip to the start of the next
172 // register
173 if (!isPacked() ||
174 gl::IsMatrixType(type) ||
175 arraySize > 0)
Jamie Madill834e8b72014-04-11 13:33:58 -0400176 {
177 nextRegister();
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400178 }
179
180 if (gl::IsMatrixType(type))
181 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400182 matrixStride = ComponentsPerRegister;
183
184 if (arraySize > 0)
185 {
186 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
187 arrayStride = ComponentsPerRegister * numRegisters;
188 }
189 }
190 else if (arraySize > 0)
191 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400192 arrayStride = ComponentsPerRegister;
193 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400194 else if (isPacked())
Jamie Madill834e8b72014-04-11 13:33:58 -0400195 {
Jamie Madillf2575982014-06-25 16:04:54 -0400196 int numComponents = gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400197 if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
198 {
199 nextRegister();
200 }
201 }
202
203 *matrixStrideOut = matrixStride;
204 *arrayStrideOut = arrayStride;
205}
206
207void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
208{
209 if (arraySize > 0)
210 {
211 mCurrentOffset += arrayStride * (arraySize - 1);
212 }
213
214 if (gl::IsMatrixType(type))
215 {
216 ASSERT(matrixStride == ComponentsPerRegister);
217 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
218 const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
219 mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
220 mCurrentOffset += numComponents;
221 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400222 else if (isPacked())
Jamie Madill834e8b72014-04-11 13:33:58 -0400223 {
Jamie Madillf2575982014-06-25 16:04:54 -0400224 mCurrentOffset += gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400225 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400226 else
227 {
228 mCurrentOffset += ComponentsPerRegister;
229 }
Jamie Madill834e8b72014-04-11 13:33:58 -0400230}
231
Jamie Madillc600c8c2014-05-16 11:22:21 -0400232void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
233{
234 mCurrentOffset += (numRegisters * ComponentsPerRegister);
235}
236
Jamie Madillbf9cce22014-07-18 10:33:09 -0400237HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
238{
239 switch (outputType)
240 {
241 case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
242 case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
243 default: UNREACHABLE(); return ENCODE_PACKED;
244 }
245}
246
Jamie Madill834e8b72014-04-11 13:33:58 -0400247template <class ShaderVarType>
248void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
249{
250 if (variable.isStruct())
251 {
252 for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
253 {
254 encoder->enterAggregateType();
255
256 for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
257 {
258 HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
259 }
260
261 encoder->exitAggregateType();
262 }
263 }
264 else
265 {
266 // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
267 encoder->encodeType(variable.type, variable.arraySize, false);
268 }
269}
270
271unsigned int HLSLVariableRegisterCount(const Varying &variable)
272{
Jamie Madille04a5b72014-07-18 10:33:12 -0400273 HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
Jamie Madill834e8b72014-04-11 13:33:58 -0400274 HLSLVariableRegisterCount(variable, &encoder);
275
276 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
277 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
278}
279
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400280unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
Jamie Madill834e8b72014-04-11 13:33:58 -0400281{
Jamie Madille04a5b72014-07-18 10:33:12 -0400282 HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill834e8b72014-04-11 13:33:58 -0400283 HLSLVariableRegisterCount(variable, &encoder);
284
285 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
286 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
287}
288
289}