blob: 970678415689cad2894a4e81607aeb5f0de1f7a1 [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
Jamie Madill9e0478f2015-01-13 11:13:54 -050010#include "compiler/translator/blocklayout.h"
11
Jamie Madill834e8b72014-04-11 13:33:58 -040012#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()
Jamie Madilla6f267f2014-08-27 11:44:15 -040019 : mCurrentOffset(0)
Jamie Madill834e8b72014-04-11 13:33:58 -040020{
21}
22
Jamie Madilla6f267f2014-08-27 11:44:15 -040023BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
Jamie Madill834e8b72014-04-11 13:33:58 -040024{
25 int arrayStride;
26 int matrixStride;
27
28 getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
29
30 const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
31
Jamie Madill834e8b72014-04-11 13:33:58 -040032 advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
Jamie Madilla6f267f2014-08-27 11:44:15 -040033
34 return memberInfo;
Jamie Madill834e8b72014-04-11 13:33:58 -040035}
36
37void BlockLayoutEncoder::nextRegister()
38{
39 mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, ComponentsPerRegister);
40}
41
Jamie Madille04a5b72014-07-18 10:33:12 -040042Std140BlockEncoder::Std140BlockEncoder()
Jamie Madill834e8b72014-04-11 13:33:58 -040043{
44}
45
46void Std140BlockEncoder::enterAggregateType()
47{
48 nextRegister();
49}
50
51void Std140BlockEncoder::exitAggregateType()
52{
53 nextRegister();
54}
55
56void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
57{
58 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
Jamie Madillf2575982014-06-25 16:04:54 -040059 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
Jamie Madill834e8b72014-04-11 13:33:58 -040060
61 size_t baseAlignment = 0;
62 int matrixStride = 0;
63 int arrayStride = 0;
64
65 if (gl::IsMatrixType(type))
66 {
67 baseAlignment = ComponentsPerRegister;
68 matrixStride = ComponentsPerRegister;
69
70 if (arraySize > 0)
71 {
72 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
73 arrayStride = ComponentsPerRegister * numRegisters;
74 }
75 }
76 else if (arraySize > 0)
77 {
78 baseAlignment = ComponentsPerRegister;
79 arrayStride = ComponentsPerRegister;
80 }
81 else
82 {
Jamie Madillf2575982014-06-25 16:04:54 -040083 const int numComponents = gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -040084 baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
85 }
86
87 mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
88
89 *matrixStrideOut = matrixStride;
90 *arrayStrideOut = arrayStride;
91}
92
93void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
94{
95 if (arraySize > 0)
96 {
97 mCurrentOffset += arrayStride * arraySize;
98 }
99 else if (gl::IsMatrixType(type))
100 {
101 ASSERT(matrixStride == ComponentsPerRegister);
102 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
103 mCurrentOffset += ComponentsPerRegister * numRegisters;
104 }
105 else
106 {
Jamie Madillf2575982014-06-25 16:04:54 -0400107 mCurrentOffset += gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400108 }
109}
110
Jamie Madille04a5b72014-07-18 10:33:12 -0400111HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy)
112 : mEncoderStrategy(strategy)
Jamie Madillbf9cce22014-07-18 10:33:09 -0400113{
114}
115
Jamie Madill834e8b72014-04-11 13:33:58 -0400116void HLSLBlockEncoder::enterAggregateType()
117{
118 nextRegister();
119}
120
121void HLSLBlockEncoder::exitAggregateType()
122{
123}
124
125void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
126{
127 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
Jamie Madillf2575982014-06-25 16:04:54 -0400128 ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
Jamie Madill834e8b72014-04-11 13:33:58 -0400129
130 int matrixStride = 0;
131 int arrayStride = 0;
132
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400133 // if variables are not to be packed, or we're about to
134 // pack a matrix or array, skip to the start of the next
135 // register
136 if (!isPacked() ||
137 gl::IsMatrixType(type) ||
138 arraySize > 0)
Jamie Madill834e8b72014-04-11 13:33:58 -0400139 {
140 nextRegister();
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400141 }
142
143 if (gl::IsMatrixType(type))
144 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400145 matrixStride = ComponentsPerRegister;
146
147 if (arraySize > 0)
148 {
149 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
150 arrayStride = ComponentsPerRegister * numRegisters;
151 }
152 }
153 else if (arraySize > 0)
154 {
Jamie Madill834e8b72014-04-11 13:33:58 -0400155 arrayStride = ComponentsPerRegister;
156 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400157 else if (isPacked())
Jamie Madill834e8b72014-04-11 13:33:58 -0400158 {
Jamie Madillf2575982014-06-25 16:04:54 -0400159 int numComponents = gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400160 if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister)
161 {
162 nextRegister();
163 }
164 }
165
166 *matrixStrideOut = matrixStride;
167 *arrayStrideOut = arrayStride;
168}
169
170void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
171{
172 if (arraySize > 0)
173 {
174 mCurrentOffset += arrayStride * (arraySize - 1);
175 }
176
177 if (gl::IsMatrixType(type))
178 {
179 ASSERT(matrixStride == ComponentsPerRegister);
180 const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
181 const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
182 mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
183 mCurrentOffset += numComponents;
184 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400185 else if (isPacked())
Jamie Madill834e8b72014-04-11 13:33:58 -0400186 {
Jamie Madillf2575982014-06-25 16:04:54 -0400187 mCurrentOffset += gl::VariableComponentCount(type);
Jamie Madill834e8b72014-04-11 13:33:58 -0400188 }
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400189 else
190 {
191 mCurrentOffset += ComponentsPerRegister;
192 }
Jamie Madill834e8b72014-04-11 13:33:58 -0400193}
194
Jamie Madillc600c8c2014-05-16 11:22:21 -0400195void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
196{
197 mCurrentOffset += (numRegisters * ComponentsPerRegister);
198}
199
Jamie Madillbf9cce22014-07-18 10:33:09 -0400200HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
201{
202 switch (outputType)
203 {
204 case SH_HLSL9_OUTPUT: return ENCODE_LOOSE;
205 case SH_HLSL11_OUTPUT: return ENCODE_PACKED;
206 default: UNREACHABLE(); return ENCODE_PACKED;
207 }
208}
209
Jamie Madill834e8b72014-04-11 13:33:58 -0400210template <class ShaderVarType>
211void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
212{
213 if (variable.isStruct())
214 {
215 for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
216 {
217 encoder->enterAggregateType();
218
219 for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++)
220 {
221 HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder);
222 }
223
224 encoder->exitAggregateType();
225 }
226 }
227 else
228 {
229 // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
230 encoder->encodeType(variable.type, variable.arraySize, false);
231 }
232}
233
234unsigned int HLSLVariableRegisterCount(const Varying &variable)
235{
Jamie Madille04a5b72014-07-18 10:33:12 -0400236 HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
Jamie Madill834e8b72014-04-11 13:33:58 -0400237 HLSLVariableRegisterCount(variable, &encoder);
238
239 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
240 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
241}
242
Vladimir Vukicevic24d8d672014-05-27 12:07:51 -0400243unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
Jamie Madill834e8b72014-04-11 13:33:58 -0400244{
Jamie Madille04a5b72014-07-18 10:33:12 -0400245 HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
Jamie Madill834e8b72014-04-11 13:33:58 -0400246 HLSLVariableRegisterCount(variable, &encoder);
247
248 const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
249 return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
250}
251
252}