blob: 602eed5430225ccea1035684759df27ce9fa0a0e [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 Madill46131a32013-06-20 11:55:50 -040014ShaderVariable::ShaderVariable(GLenum type, GLenum precision, const char *name, unsigned int arraySize, int location)
15 : type(type),
16 precision(precision),
17 name(name),
18 arraySize(arraySize),
19 location(location)
20{
21}
22
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +000023Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex)
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +000024{
25 this->type = type;
26 this->precision = precision;
27 this->name = name;
28 this->arraySize = arraySize;
29 this->registerIndex = registerIndex;
30}
31
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +000032BlockMemberInfo::BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
33 : offset(offset),
34 arrayStride(arrayStride),
35 matrixStride(matrixStride),
36 isRowMajorMatrix(isRowMajorMatrix)
37{
38}
39
40const BlockMemberInfo BlockMemberInfo::defaultBlockInfo(-1, -1, -1, false);
41
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +000042InterfaceBlock::InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex)
43 : name(name),
44 arraySize(arraySize),
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000045 layout(BLOCKLAYOUT_SHARED),
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +000046 registerIndex(registerIndex)
47{
48}
49
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +000050// Use the same layout for packed and shared
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000051void InterfaceBlock::setBlockLayout(BlockLayoutType newLayout)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +000052{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000053 layout = newLayout;
54
55 const size_t componentSize = 4;
56 unsigned int currentOffset = 0;
57
58 blockInfo.clear();
59 getBlockLayoutInfo(activeUniforms, &currentOffset);
60
61 dataSize = currentOffset * componentSize;
62}
63
64void InterfaceBlock::getBlockLayoutInfo(const sh::ActiveUniforms &fields, unsigned int *currentOffset)
65{
66 const size_t componentSize = 4;
67
68 // TODO: row major matrices
69 bool isRowMajorMatrix = false;
70
71 for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
72 {
73 int arrayStride;
74 int matrixStride;
75
76 const sh::Uniform &uniform = fields[fieldIndex];
77
78 if (getBlockLayoutInfo(uniform, currentOffset, &arrayStride, &matrixStride))
79 {
80 const BlockMemberInfo memberInfo(*currentOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, isRowMajorMatrix);
81 blockInfo.push_back(memberInfo);
82
83 if (uniform.arraySize > 0)
84 {
Jamie Madill62431832013-06-10 11:44:28 -040085 *currentOffset += arrayStride * (uniform.arraySize - 1);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000086 }
Jamie Madill62431832013-06-10 11:44:28 -040087
88 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000089 {
90 const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
Jamie Madill62431832013-06-10 11:44:28 -040091 const int numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
92 *currentOffset += matrixStride * (componentGroups - 1);
93 *currentOffset += numComponents;
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000094 }
95 else
96 {
97 *currentOffset += gl::UniformComponentCount(uniform.type);
98 }
99 }
100 }
101}
102
103bool InterfaceBlock::getBlockLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
104{
105 if (!uniform.fields.empty())
106 {
Jamie Madill52660ff2013-06-07 14:11:09 -0400107 const unsigned int elementCount = std::max(1u, uniform.arraySize);
108
109 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +0000110 {
Jamie Madill52660ff2013-06-07 14:11:09 -0400111 // align struct to register size
112 *currentOffset = rx::roundUp(*currentOffset, 4u);
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +0000113 getBlockLayoutInfo(uniform.fields, currentOffset);
114 }
Jamie Madill52660ff2013-06-07 14:11:09 -0400115
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000116 return false;
117 }
118
119 switch (layout)
120 {
121 case BLOCKLAYOUT_SHARED:
122 case BLOCKLAYOUT_PACKED:
123 getD3DLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
124 return true;
125
126 case BLOCKLAYOUT_STANDARD:
127 getStandardLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
128 return true;
129
130 default:
131 UNREACHABLE();
132 return false;
133 }
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000134}
135
136// Block layout packed according to the default D3D11 register packing rules
137// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000138void InterfaceBlock::getD3DLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000139{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000140 ASSERT(uniform.fields.empty());
141
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000142 const unsigned int registerSize = 4;
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000143 const size_t componentSize = 4;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000144
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000145 // TODO: row major matrices
146 bool isRowMajorMatrix = false;
147 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
148 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
149 int matrixStride = 0;
150 int arrayStride = 0;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000151
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000152 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000153 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000154 *currentOffset = rx::roundUp(*currentOffset, 4u);
155 matrixStride = registerSize;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000156
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000157 if (uniform.arraySize > 0)
158 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000159 const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
160 arrayStride = matrixStride * componentGroups;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000161 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000162 }
163 else if (uniform.arraySize > 0)
164 {
165 *currentOffset = rx::roundUp(*currentOffset, registerSize);
166 arrayStride = registerSize;
167 }
168 else
169 {
170 int numComponents = gl::UniformComponentCount(uniform.type);
Jamie Madill62431832013-06-10 11:44:28 -0400171 if ((numComponents + (*currentOffset % registerSize)) > registerSize)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000172 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000173 *currentOffset = rx::roundUp(*currentOffset, registerSize);
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000174 }
175 }
176
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000177 *matrixStrideOut = matrixStride;
178 *arrayStrideOut = arrayStride;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000179}
180
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000181// Block layout according to the std140 block layout
182// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
183void InterfaceBlock::getStandardLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000184{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000185 ASSERT(uniform.fields.empty());
186
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000187 const size_t componentSize = 4;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000188
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000189 // TODO: row major matrices
190 bool isRowMajorMatrix = false;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000191
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000192 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
193 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
194
195 int numComponents = gl::UniformComponentCount(uniform.type);
196 size_t baseAlignment = static_cast<size_t>(numComponents == 3 ? 4 : numComponents);
197 int matrixStride = 0;
198 int arrayStride = 0;
199
200 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000201 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000202 numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
203 baseAlignment = rx::roundUp(baseAlignment, 4u);
204 matrixStride = baseAlignment;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000205
206 if (uniform.arraySize > 0)
207 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000208 const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
209 arrayStride = matrixStride * componentGroups;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000210 }
211 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000212 else if (uniform.arraySize > 0)
213 {
214 baseAlignment = rx::roundUp(baseAlignment, 4u);
215 arrayStride = baseAlignment;
216 }
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000217
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000218 *currentOffset = rx::roundUp(*currentOffset, baseAlignment);
219
220 *matrixStrideOut = matrixStride;
221 *arrayStrideOut = arrayStride;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000222}
223
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +0000224}