blob: 3cd359959b92a2f27f3b39db996863f12830b0da [file] [log] [blame]
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +00001//
2// Copyright (c) 2013 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
7#include "compiler/Uniform.h"
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +00008#include "common/mathutil.h"
9#include "common/utilities.h"
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +000010
11namespace sh
12{
13
Jamie Madilldefb6742013-06-20 11:55:51 -040014ShaderVariable::ShaderVariable()
15 : type(GL_NONE),
16 precision(GL_NONE),
17 arraySize(0),
18 location(-1)
19{
20}
21
Jamie Madill46131a32013-06-20 11:55:50 -040022ShaderVariable::ShaderVariable(GLenum type, GLenum precision, const char *name, unsigned int arraySize, int location)
23 : type(type),
24 precision(precision),
25 name(name),
26 arraySize(arraySize),
27 location(location)
28{
29}
30
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +000031Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex)
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +000032{
33 this->type = type;
34 this->precision = precision;
35 this->name = name;
36 this->arraySize = arraySize;
37 this->registerIndex = registerIndex;
38}
39
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +000040BlockMemberInfo::BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
41 : offset(offset),
42 arrayStride(arrayStride),
43 matrixStride(matrixStride),
44 isRowMajorMatrix(isRowMajorMatrix)
45{
46}
47
48const BlockMemberInfo BlockMemberInfo::defaultBlockInfo(-1, -1, -1, false);
49
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +000050InterfaceBlock::InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex)
51 : name(name),
52 arraySize(arraySize),
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000053 layout(BLOCKLAYOUT_SHARED),
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +000054 registerIndex(registerIndex)
55{
56}
57
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +000058// Use the same layout for packed and shared
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000059void InterfaceBlock::setBlockLayout(BlockLayoutType newLayout)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +000060{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000061 layout = newLayout;
62
63 const size_t componentSize = 4;
64 unsigned int currentOffset = 0;
65
66 blockInfo.clear();
67 getBlockLayoutInfo(activeUniforms, &currentOffset);
68
69 dataSize = currentOffset * componentSize;
70}
71
72void InterfaceBlock::getBlockLayoutInfo(const sh::ActiveUniforms &fields, unsigned int *currentOffset)
73{
74 const size_t componentSize = 4;
75
76 // TODO: row major matrices
77 bool isRowMajorMatrix = false;
78
79 for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
80 {
81 int arrayStride;
82 int matrixStride;
83
84 const sh::Uniform &uniform = fields[fieldIndex];
85
86 if (getBlockLayoutInfo(uniform, currentOffset, &arrayStride, &matrixStride))
87 {
88 const BlockMemberInfo memberInfo(*currentOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, isRowMajorMatrix);
89 blockInfo.push_back(memberInfo);
90
91 if (uniform.arraySize > 0)
92 {
Jamie Madill62431832013-06-10 11:44:28 -040093 *currentOffset += arrayStride * (uniform.arraySize - 1);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000094 }
Jamie Madill62431832013-06-10 11:44:28 -040095
96 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000097 {
98 const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
Jamie Madill62431832013-06-10 11:44:28 -040099 const int numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
100 *currentOffset += matrixStride * (componentGroups - 1);
101 *currentOffset += numComponents;
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000102 }
103 else
104 {
105 *currentOffset += gl::UniformComponentCount(uniform.type);
106 }
107 }
108 }
109}
110
111bool InterfaceBlock::getBlockLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
112{
113 if (!uniform.fields.empty())
114 {
Jamie Madill52660ff2013-06-07 14:11:09 -0400115 const unsigned int elementCount = std::max(1u, uniform.arraySize);
116
117 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +0000118 {
Jamie Madill52660ff2013-06-07 14:11:09 -0400119 // align struct to register size
120 *currentOffset = rx::roundUp(*currentOffset, 4u);
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +0000121 getBlockLayoutInfo(uniform.fields, currentOffset);
122 }
Jamie Madill52660ff2013-06-07 14:11:09 -0400123
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000124 return false;
125 }
126
127 switch (layout)
128 {
129 case BLOCKLAYOUT_SHARED:
130 case BLOCKLAYOUT_PACKED:
131 getD3DLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
132 return true;
133
134 case BLOCKLAYOUT_STANDARD:
135 getStandardLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
136 return true;
137
138 default:
139 UNREACHABLE();
140 return false;
141 }
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000142}
143
144// Block layout packed according to the default D3D11 register packing rules
145// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000146void InterfaceBlock::getD3DLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000147{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000148 ASSERT(uniform.fields.empty());
149
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000150 const unsigned int registerSize = 4;
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000151 const size_t componentSize = 4;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000152
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000153 // TODO: row major matrices
154 bool isRowMajorMatrix = false;
155 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
156 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
157 int matrixStride = 0;
158 int arrayStride = 0;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000159
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000160 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000161 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000162 *currentOffset = rx::roundUp(*currentOffset, 4u);
163 matrixStride = registerSize;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000164
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000165 if (uniform.arraySize > 0)
166 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000167 const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
168 arrayStride = matrixStride * componentGroups;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000169 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000170 }
171 else if (uniform.arraySize > 0)
172 {
173 *currentOffset = rx::roundUp(*currentOffset, registerSize);
174 arrayStride = registerSize;
175 }
176 else
177 {
178 int numComponents = gl::UniformComponentCount(uniform.type);
Jamie Madill62431832013-06-10 11:44:28 -0400179 if ((numComponents + (*currentOffset % registerSize)) > registerSize)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000180 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000181 *currentOffset = rx::roundUp(*currentOffset, registerSize);
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000182 }
183 }
184
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000185 *matrixStrideOut = matrixStride;
186 *arrayStrideOut = arrayStride;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000187}
188
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000189// Block layout according to the std140 block layout
190// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
191void InterfaceBlock::getStandardLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000192{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000193 ASSERT(uniform.fields.empty());
194
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000195 const size_t componentSize = 4;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000196
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000197 // TODO: row major matrices
198 bool isRowMajorMatrix = false;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000199
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000200 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
201 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
202
203 int numComponents = gl::UniformComponentCount(uniform.type);
204 size_t baseAlignment = static_cast<size_t>(numComponents == 3 ? 4 : numComponents);
205 int matrixStride = 0;
206 int arrayStride = 0;
207
208 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000209 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000210 numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
211 baseAlignment = rx::roundUp(baseAlignment, 4u);
212 matrixStride = baseAlignment;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000213
214 if (uniform.arraySize > 0)
215 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000216 const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
217 arrayStride = matrixStride * componentGroups;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000218 }
219 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000220 else if (uniform.arraySize > 0)
221 {
222 baseAlignment = rx::roundUp(baseAlignment, 4u);
223 arrayStride = baseAlignment;
224 }
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000225
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000226 *currentOffset = rx::roundUp(*currentOffset, baseAlignment);
227
228 *matrixStrideOut = matrixStride;
229 *arrayStrideOut = arrayStride;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000230}
231
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +0000232}