blob: e3b2d43566c9c3ce414a9ddd6b02f8ac8644a703 [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()
Jamie Madilla6f267f2014-08-27 11:44:15 -040018 : mCurrentOffset(0)
Jamie Madill834e8b72014-04-11 13:33:58 -040019{
20}
21
Jamie Madilla6f267f2014-08-27 11:44:15 -040022BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
Jamie Madill834e8b72014-04-11 13:33:58 -040023{
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
Jamie Madill834e8b72014-04-11 13:33:58 -040031 advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
Jamie Madilla6f267f2014-08-27 11:44:15 -040032
33 return memberInfo;
Jamie Madill834e8b72014-04-11 13:33:58 -040034}
35
36void BlockLayoutEncoder::nextRegister()
37{
38 mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
39}
40
Jamie Madille04a5b72014-07-18 10:33:12 -040041Std140BlockEncoder::Std140BlockEncoder()
Jamie Madill834e8b72014-04-11 13:33:58 -040042{
43}
44
45void Std140BlockEncoder::enterAggregateType()
46{
47 nextRegister();
48}
49
50void Std140BlockEncoder::exitAggregateType()
51{
52 nextRegister();
53}
54
55void 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)
Jamie Madillf2575982014-06-25 16:04:54 -040058 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
Jamie Madill834e8b72014-04-11 13:33:58 -040059
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 {
Jamie Madillf2575982014-06-25 16:04:54 -040082 const int numComponents = gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -040083 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
92void 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 {
Jamie Madillf2575982014-06-25 16:04:54 -0400106 mCurrentOffset += gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400107 }
108}
109
Jamie Madille04a5b72014-07-18 10:33:12 -0400110HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy)
111 : mEncoderStrategy(strategy)
Jamie Madillbf9cce22014-07-18 10:33:09 -0400112{
113}
114
Jamie Madill834e8b72014-04-11 13:33:58 -0400115void HLSLBlockEncoder::enterAggregateType()
116{
117 nextRegister();
118}
119
120void HLSLBlockEncoder::exitAggregateType()
121{
122}
123
124void 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)
Jamie Madillf2575982014-06-25 16:04:54 -0400127 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
Jamie Madill834e8b72014-04-11 13:33:58 -0400128
129 int matrixStride = 0;
130 int arrayStride = 0;
131
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400132 // 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)
Jamie Madill834e8b72014-04-11 13:33:58 -0400138 {
139 nextRegister();
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400140 }
141
142 if (gl::IsMatrixType(type))
143 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400144 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 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400154 arrayStride = ComponentsPerRegister;
155 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400156 else if (isPacked())
Jamie Madill834e8b72014-04-11 13:33:58 -0400157 {
Jamie Madillf2575982014-06-25 16:04:54 -0400158 int numComponents = gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400159 if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
160 {
161 nextRegister();
162 }
163 }
164
165 *matrixStrideOut = matrixStride;
166 *arrayStrideOut = arrayStride;
167}
168
169void 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 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400184 else if (isPacked())
Jamie Madill834e8b72014-04-11 13:33:58 -0400185 {
Jamie Madillf2575982014-06-25 16:04:54 -0400186 mCurrentOffset += gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400187 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400188 else
189 {
190 mCurrentOffset += ComponentsPerRegister;
191 }
Jamie Madill834e8b72014-04-11 13:33:58 -0400192}
193
Jamie Madillc600c8c2014-05-16 11:22:21 -0400194void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
195{
196 mCurrentOffset += (numRegisters * ComponentsPerRegister);
197}
198
Jamie Madillbf9cce22014-07-18 10:33:09 -0400199HLSLBlockEncoder::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
Jamie Madill834e8b72014-04-11 13:33:58 -0400209template <class ShaderVarType>
210void 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
233unsigned int HLSLVariableRegisterCount(const Varying &variable)
234{
Jamie Madille04a5b72014-07-18 10:33:12 -0400235 HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
Jamie Madill834e8b72014-04-11 13:33:58 -0400236 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
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400242unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
Jamie Madill834e8b72014-04-11 13:33:58 -0400243{
Jamie Madille04a5b72014-07-18 10:33:12 -0400244 HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill834e8b72014-04-11 13:33:58 -0400245 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}