blob: c1f0c3a5e26256d363937f403d6d2636d882d83c [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"
Jamie Madill834e8b72014-04-11 13:33:58 -040011#include "common/mathutil.h"
12#include "common/utilities.h"
13
Jamie Madillf2575982014-06-25 16:04:54 -040014namespace sh
Jamie Madill834e8b72014-04-11 13:33:58 -040015{
16
Jamie Madille04a5b72014-07-18 10:33:12 -040017BlockLayoutEncoder::BlockLayoutEncoder()
18 : mCurrentOffset(0)
Jamie Madill834e8b72014-04-11 13:33:58 -040019{
20}
21
22void BlockLayoutEncoder::encodeInterfaceBlockFields(const std::vector<InterfaceBlockField> &fields)
23{
24 for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
25 {
26 const InterfaceBlockField &variable = fields[fieldIndex];
27
28 if (variable.fields.size() > 0)
29 {
30 const unsigned int elementCount = std::max(1u, variable.arraySize);
31
32 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
33 {
34 enterAggregateType();
35 encodeInterfaceBlockFields(variable.fields);
36 exitAggregateType();
37 }
38 }
39 else
40 {
41 encodeInterfaceBlockField(variable);
42 }
43 }
44}
45
Jamie Madille04a5b72014-07-18 10:33:12 -040046BlockMemberInfo BlockLayoutEncoder::encodeInterfaceBlockField(const InterfaceBlockField &field)
Jamie Madill834e8b72014-04-11 13:33:58 -040047{
48 int arrayStride;
49 int matrixStride;
50
51 ASSERT(field.fields.empty());
52 getBlockLayoutInfo(field.type, field.arraySize, field.isRowMajorMatrix, &arrayStride, &matrixStride);
53
54 const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, field.isRowMajorMatrix);
55
Jamie Madill834e8b72014-04-11 13:33:58 -040056 advanceOffset(field.type, field.arraySize, field.isRowMajorMatrix, arrayStride, matrixStride);
Jamie Madille04a5b72014-07-18 10:33:12 -040057
58 return memberInfo;
Jamie Madill834e8b72014-04-11 13:33:58 -040059}
60
61void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
62{
63 int arrayStride;
64 int matrixStride;
65
66 getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
67
68 const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
69
Jamie Madill834e8b72014-04-11 13:33:58 -040070 advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
71}
72
73void BlockLayoutEncoder::nextRegister()
74{
75 mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
76}
77
Jamie Madille04a5b72014-07-18 10:33:12 -040078Std140BlockEncoder::Std140BlockEncoder()
Jamie Madill834e8b72014-04-11 13:33:58 -040079{
80}
81
82void Std140BlockEncoder::enterAggregateType()
83{
84 nextRegister();
85}
86
87void Std140BlockEncoder::exitAggregateType()
88{
89 nextRegister();
90}
91
92void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
93{
94 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
Jamie Madillf2575982014-06-25 16:04:54 -040095 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
Jamie Madill834e8b72014-04-11 13:33:58 -040096
97 size_t baseAlignment = 0;
98 int matrixStride = 0;
99 int arrayStride = 0;
100
101 if (gl::IsMatrixType(type))
102 {
103 baseAlignment = ComponentsPerRegister;
104 matrixStride = ComponentsPerRegister;
105
106 if (arraySize > 0)
107 {
108 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
109 arrayStride = ComponentsPerRegister * numRegisters;
110 }
111 }
112 else if (arraySize > 0)
113 {
114 baseAlignment = ComponentsPerRegister;
115 arrayStride = ComponentsPerRegister;
116 }
117 else
118 {
Jamie Madillf2575982014-06-25 16:04:54 -0400119 const int numComponents = gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400120 baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
121 }
122
123 mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
124
125 *matrixStrideOut = matrixStride;
126 *arrayStrideOut = arrayStride;
127}
128
129void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
130{
131 if (arraySize > 0)
132 {
133 mCurrentOffset += arrayStride * arraySize;
134 }
135 else if (gl::IsMatrixType(type))
136 {
137 ASSERT(matrixStride == ComponentsPerRegister);
138 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
139 mCurrentOffset += ComponentsPerRegister * numRegisters;
140 }
141 else
142 {
Jamie Madillf2575982014-06-25 16:04:54 -0400143 mCurrentOffset += gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400144 }
145}
146
Jamie Madille04a5b72014-07-18 10:33:12 -0400147HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy)
148 : mEncoderStrategy(strategy)
Jamie Madillbf9cce22014-07-18 10:33:09 -0400149{
150}
151
Jamie Madill834e8b72014-04-11 13:33:58 -0400152void HLSLBlockEncoder::enterAggregateType()
153{
154 nextRegister();
155}
156
157void HLSLBlockEncoder::exitAggregateType()
158{
159}
160
161void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
162{
163 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
Jamie Madillf2575982014-06-25 16:04:54 -0400164 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
Jamie Madill834e8b72014-04-11 13:33:58 -0400165
166 int matrixStride = 0;
167 int arrayStride = 0;
168
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400169 // if variables are not to be packed, or we're about to
170 // pack a matrix or array, skip to the start of the next
171 // register
172 if (!isPacked() ||
173 gl::IsMatrixType(type) ||
174 arraySize > 0)
Jamie Madill834e8b72014-04-11 13:33:58 -0400175 {
176 nextRegister();
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400177 }
178
179 if (gl::IsMatrixType(type))
180 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400181 matrixStride = ComponentsPerRegister;
182
183 if (arraySize > 0)
184 {
185 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
186 arrayStride = ComponentsPerRegister * numRegisters;
187 }
188 }
189 else if (arraySize > 0)
190 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400191 arrayStride = ComponentsPerRegister;
192 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400193 else if (isPacked())
Jamie Madill834e8b72014-04-11 13:33:58 -0400194 {
Jamie Madillf2575982014-06-25 16:04:54 -0400195 int numComponents = gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400196 if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
197 {
198 nextRegister();
199 }
200 }
201
202 *matrixStrideOut = matrixStride;
203 *arrayStrideOut = arrayStride;
204}
205
206void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
207{
208 if (arraySize > 0)
209 {
210 mCurrentOffset += arrayStride * (arraySize - 1);
211 }
212
213 if (gl::IsMatrixType(type))
214 {
215 ASSERT(matrixStride == ComponentsPerRegister);
216 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
217 const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
218 mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
219 mCurrentOffset += numComponents;
220 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400221 else if (isPacked())
Jamie Madill834e8b72014-04-11 13:33:58 -0400222 {
Jamie Madillf2575982014-06-25 16:04:54 -0400223 mCurrentOffset += gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400224 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400225 else
226 {
227 mCurrentOffset += ComponentsPerRegister;
228 }
Jamie Madill834e8b72014-04-11 13:33:58 -0400229}
230
Jamie Madillc600c8c2014-05-16 11:22:21 -0400231void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
232{
233 mCurrentOffset += (numRegisters * ComponentsPerRegister);
234}
235
Jamie Madillbf9cce22014-07-18 10:33:09 -0400236HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
237{
238 switch (outputType)
239 {
240 case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
241 case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
242 default: UNREACHABLE(); return ENCODE_PACKED;
243 }
244}
245
Jamie Madill834e8b72014-04-11 13:33:58 -0400246template <class ShaderVarType>
247void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
248{
249 if (variable.isStruct())
250 {
251 for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
252 {
253 encoder->enterAggregateType();
254
255 for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
256 {
257 HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
258 }
259
260 encoder->exitAggregateType();
261 }
262 }
263 else
264 {
265 // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
266 encoder->encodeType(variable.type, variable.arraySize, false);
267 }
268}
269
270unsigned int HLSLVariableRegisterCount(const Varying &variable)
271{
Jamie Madille04a5b72014-07-18 10:33:12 -0400272 HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
Jamie Madill834e8b72014-04-11 13:33:58 -0400273 HLSLVariableRegisterCount(variable, &encoder);
274
275 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
276 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
277}
278
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400279unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
Jamie Madill834e8b72014-04-11 13:33:58 -0400280{
Jamie Madille04a5b72014-07-18 10:33:12 -0400281 HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill834e8b72014-04-11 13:33:58 -0400282 HLSLVariableRegisterCount(variable, &encoder);
283
284 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
285 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
286}
287
288}