blob: 8a8b998829a119a23f357d7b5efdab5f0707441a [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
shannonwoods@chromium.org38676dc2013-05-30 00:06:52 +000014Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex)
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +000015{
16 this->type = type;
17 this->precision = precision;
18 this->name = name;
19 this->arraySize = arraySize;
20 this->registerIndex = registerIndex;
21}
22
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +000023BlockMemberInfo::BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
24 : offset(offset),
25 arrayStride(arrayStride),
26 matrixStride(matrixStride),
27 isRowMajorMatrix(isRowMajorMatrix)
28{
29}
30
31const BlockMemberInfo BlockMemberInfo::defaultBlockInfo(-1, -1, -1, false);
32
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +000033InterfaceBlock::InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex)
34 : name(name),
35 arraySize(arraySize),
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000036 layout(BLOCKLAYOUT_SHARED),
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +000037 registerIndex(registerIndex)
38{
39}
40
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +000041// Use the same layout for packed and shared
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000042void InterfaceBlock::setBlockLayout(BlockLayoutType newLayout)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +000043{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000044 layout = newLayout;
45
46 const size_t componentSize = 4;
47 unsigned int currentOffset = 0;
48
49 blockInfo.clear();
50 getBlockLayoutInfo(activeUniforms, &currentOffset);
51
52 dataSize = currentOffset * componentSize;
53}
54
55void InterfaceBlock::getBlockLayoutInfo(const sh::ActiveUniforms &fields, unsigned int *currentOffset)
56{
57 const size_t componentSize = 4;
58
59 // TODO: row major matrices
60 bool isRowMajorMatrix = false;
61
62 for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
63 {
64 int arrayStride;
65 int matrixStride;
66
67 const sh::Uniform &uniform = fields[fieldIndex];
68
69 if (getBlockLayoutInfo(uniform, currentOffset, &arrayStride, &matrixStride))
70 {
71 const BlockMemberInfo memberInfo(*currentOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, isRowMajorMatrix);
72 blockInfo.push_back(memberInfo);
73
74 if (uniform.arraySize > 0)
75 {
Jamie Madill62431832013-06-10 11:44:28 -040076 *currentOffset += arrayStride * (uniform.arraySize - 1);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000077 }
Jamie Madill62431832013-06-10 11:44:28 -040078
79 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000080 {
81 const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
Jamie Madill62431832013-06-10 11:44:28 -040082 const int numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
83 *currentOffset += matrixStride * (componentGroups - 1);
84 *currentOffset += numComponents;
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000085 }
86 else
87 {
88 *currentOffset += gl::UniformComponentCount(uniform.type);
89 }
90 }
91 }
92}
93
94bool InterfaceBlock::getBlockLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
95{
96 if (!uniform.fields.empty())
97 {
Jamie Madill52660ff2013-06-07 14:11:09 -040098 const unsigned int elementCount = std::max(1u, uniform.arraySize);
99
100 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +0000101 {
Jamie Madill52660ff2013-06-07 14:11:09 -0400102 // align struct to register size
103 *currentOffset = rx::roundUp(*currentOffset, 4u);
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +0000104 getBlockLayoutInfo(uniform.fields, currentOffset);
105 }
Jamie Madill52660ff2013-06-07 14:11:09 -0400106
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000107 return false;
108 }
109
110 switch (layout)
111 {
112 case BLOCKLAYOUT_SHARED:
113 case BLOCKLAYOUT_PACKED:
114 getD3DLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
115 return true;
116
117 case BLOCKLAYOUT_STANDARD:
118 getStandardLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
119 return true;
120
121 default:
122 UNREACHABLE();
123 return false;
124 }
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000125}
126
127// Block layout packed according to the default D3D11 register packing rules
128// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000129void InterfaceBlock::getD3DLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000130{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000131 ASSERT(uniform.fields.empty());
132
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000133 const unsigned int registerSize = 4;
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000134 const size_t componentSize = 4;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000135
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000136 // TODO: row major matrices
137 bool isRowMajorMatrix = false;
138 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
139 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
140 int matrixStride = 0;
141 int arrayStride = 0;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000142
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000143 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000144 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000145 *currentOffset = rx::roundUp(*currentOffset, 4u);
146 matrixStride = registerSize;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000147
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000148 if (uniform.arraySize > 0)
149 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000150 const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
151 arrayStride = matrixStride * componentGroups;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000152 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000153 }
154 else if (uniform.arraySize > 0)
155 {
156 *currentOffset = rx::roundUp(*currentOffset, registerSize);
157 arrayStride = registerSize;
158 }
159 else
160 {
161 int numComponents = gl::UniformComponentCount(uniform.type);
Jamie Madill62431832013-06-10 11:44:28 -0400162 if ((numComponents + (*currentOffset % registerSize)) > registerSize)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000163 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000164 *currentOffset = rx::roundUp(*currentOffset, registerSize);
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000165 }
166 }
167
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000168 *matrixStrideOut = matrixStride;
169 *arrayStrideOut = arrayStride;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000170}
171
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000172// Block layout according to the std140 block layout
173// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
174void InterfaceBlock::getStandardLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000175{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000176 ASSERT(uniform.fields.empty());
177
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000178 const size_t componentSize = 4;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000179
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000180 // TODO: row major matrices
181 bool isRowMajorMatrix = false;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000182
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000183 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
184 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
185
186 int numComponents = gl::UniformComponentCount(uniform.type);
187 size_t baseAlignment = static_cast<size_t>(numComponents == 3 ? 4 : numComponents);
188 int matrixStride = 0;
189 int arrayStride = 0;
190
191 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000192 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000193 numComponents = (isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
194 baseAlignment = rx::roundUp(baseAlignment, 4u);
195 matrixStride = baseAlignment;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000196
197 if (uniform.arraySize > 0)
198 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000199 const int componentGroups = (isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
200 arrayStride = matrixStride * componentGroups;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000201 }
202 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000203 else if (uniform.arraySize > 0)
204 {
205 baseAlignment = rx::roundUp(baseAlignment, 4u);
206 arrayStride = baseAlignment;
207 }
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000208
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000209 *currentOffset = rx::roundUp(*currentOffset, baseAlignment);
210
211 *matrixStrideOut = matrixStride;
212 *arrayStrideOut = arrayStride;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000213}
214
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +0000215}