blob: ff933f2448620806534a68f0bc9726e6875253ae [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
Jamie Madill010fffa2013-06-20 11:55:53 -040031Uniform::Uniform(GLenum type, GLenum precision, const char *name, unsigned int arraySize, unsigned int registerIndex, bool isRowMajorMatrix)
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;
Jamie Madill010fffa2013-06-20 11:55:53 -040038 this->isRowMajorMatrix = isRowMajorMatrix;
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +000039}
40
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +000041BlockMemberInfo::BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
42 : offset(offset),
43 arrayStride(arrayStride),
44 matrixStride(matrixStride),
45 isRowMajorMatrix(isRowMajorMatrix)
46{
47}
48
49const BlockMemberInfo BlockMemberInfo::defaultBlockInfo(-1, -1, -1, false);
50
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +000051InterfaceBlock::InterfaceBlock(const char *name, unsigned int arraySize, unsigned int registerIndex)
52 : name(name),
53 arraySize(arraySize),
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000054 layout(BLOCKLAYOUT_SHARED),
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +000055 registerIndex(registerIndex)
56{
57}
58
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +000059// Use the same layout for packed and shared
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000060void InterfaceBlock::setBlockLayout(BlockLayoutType newLayout)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +000061{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000062 layout = newLayout;
63
64 const size_t componentSize = 4;
65 unsigned int currentOffset = 0;
66
67 blockInfo.clear();
68 getBlockLayoutInfo(activeUniforms, &currentOffset);
69
70 dataSize = currentOffset * componentSize;
71}
72
73void InterfaceBlock::getBlockLayoutInfo(const sh::ActiveUniforms &fields, unsigned int *currentOffset)
74{
75 const size_t componentSize = 4;
76
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000077 for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
78 {
79 int arrayStride;
80 int matrixStride;
81
82 const sh::Uniform &uniform = fields[fieldIndex];
83
84 if (getBlockLayoutInfo(uniform, currentOffset, &arrayStride, &matrixStride))
85 {
Jamie Madill010fffa2013-06-20 11:55:53 -040086 const BlockMemberInfo memberInfo(*currentOffset * componentSize, arrayStride * componentSize, matrixStride * componentSize, uniform.isRowMajorMatrix);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000087 blockInfo.push_back(memberInfo);
88
89 if (uniform.arraySize > 0)
90 {
Jamie Madill62431832013-06-10 11:44:28 -040091 *currentOffset += arrayStride * (uniform.arraySize - 1);
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000092 }
Jamie Madill62431832013-06-10 11:44:28 -040093
94 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +000095 {
Jamie Madill010fffa2013-06-20 11:55:53 -040096 const int componentGroups = (uniform.isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
97 const int numComponents = (uniform.isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
Jamie Madill62431832013-06-10 11:44:28 -040098 *currentOffset += matrixStride * (componentGroups - 1);
99 *currentOffset += numComponents;
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000100 }
101 else
102 {
103 *currentOffset += gl::UniformComponentCount(uniform.type);
104 }
105 }
106 }
107}
108
109bool InterfaceBlock::getBlockLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
110{
111 if (!uniform.fields.empty())
112 {
Jamie Madill52660ff2013-06-07 14:11:09 -0400113 const unsigned int elementCount = std::max(1u, uniform.arraySize);
114
115 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +0000116 {
Jamie Madill52660ff2013-06-07 14:11:09 -0400117 // align struct to register size
118 *currentOffset = rx::roundUp(*currentOffset, 4u);
shannonwoods@chromium.org5f8d9b42013-05-30 00:17:57 +0000119 getBlockLayoutInfo(uniform.fields, currentOffset);
120 }
Jamie Madill52660ff2013-06-07 14:11:09 -0400121
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000122 return false;
123 }
124
125 switch (layout)
126 {
127 case BLOCKLAYOUT_SHARED:
128 case BLOCKLAYOUT_PACKED:
129 getD3DLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
130 return true;
131
132 case BLOCKLAYOUT_STANDARD:
133 getStandardLayoutInfo(uniform, currentOffset, arrayStrideOut, matrixStrideOut);
134 return true;
135
136 default:
137 UNREACHABLE();
138 return false;
139 }
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000140}
141
142// Block layout packed according to the default D3D11 register packing rules
143// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000144void InterfaceBlock::getD3DLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000145{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000146 ASSERT(uniform.fields.empty());
147
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000148 const unsigned int registerSize = 4;
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000149 const size_t componentSize = 4;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000150
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000151 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
152 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
153 int matrixStride = 0;
154 int arrayStride = 0;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000155
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000156 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000157 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000158 *currentOffset = rx::roundUp(*currentOffset, 4u);
159 matrixStride = registerSize;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000160
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000161 if (uniform.arraySize > 0)
162 {
Jamie Madill010fffa2013-06-20 11:55:53 -0400163 const int componentGroups = (uniform.isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000164 arrayStride = matrixStride * componentGroups;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000165 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000166 }
167 else if (uniform.arraySize > 0)
168 {
169 *currentOffset = rx::roundUp(*currentOffset, registerSize);
170 arrayStride = registerSize;
171 }
172 else
173 {
174 int numComponents = gl::UniformComponentCount(uniform.type);
Jamie Madill62431832013-06-10 11:44:28 -0400175 if ((numComponents + (*currentOffset % registerSize)) > registerSize)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000176 {
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000177 *currentOffset = rx::roundUp(*currentOffset, registerSize);
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000178 }
179 }
180
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000181 *matrixStrideOut = matrixStride;
182 *arrayStrideOut = arrayStride;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000183}
184
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000185// Block layout according to the std140 block layout
186// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
187void InterfaceBlock::getStandardLayoutInfo(const sh::Uniform &uniform, unsigned int *currentOffset, int *arrayStrideOut, int *matrixStrideOut)
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000188{
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000189 ASSERT(uniform.fields.empty());
190
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000191 const size_t componentSize = 4;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000192
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000193 // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
194 ASSERT(gl::UniformComponentSize(gl::UniformComponentType(uniform.type)) == componentSize);
195
196 int numComponents = gl::UniformComponentCount(uniform.type);
197 size_t baseAlignment = static_cast<size_t>(numComponents == 3 ? 4 : numComponents);
198 int matrixStride = 0;
199 int arrayStride = 0;
200
201 if (gl::IsMatrixType(uniform.type))
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000202 {
Jamie Madill010fffa2013-06-20 11:55:53 -0400203 numComponents = (uniform.isRowMajorMatrix ? gl::VariableColumnCount(uniform.type) : gl::VariableRowCount(uniform.type));
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000204 baseAlignment = rx::roundUp(baseAlignment, 4u);
205 matrixStride = baseAlignment;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000206
207 if (uniform.arraySize > 0)
208 {
Jamie Madill010fffa2013-06-20 11:55:53 -0400209 const int componentGroups = (uniform.isRowMajorMatrix ? gl::VariableRowCount(uniform.type) : gl::VariableColumnCount(uniform.type));
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000210 arrayStride = matrixStride * componentGroups;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000211 }
212 }
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000213 else if (uniform.arraySize > 0)
214 {
215 baseAlignment = rx::roundUp(baseAlignment, 4u);
216 arrayStride = baseAlignment;
217 }
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000218
shannonwoods@chromium.org70961b32013-05-30 00:17:48 +0000219 *currentOffset = rx::roundUp(*currentOffset, baseAlignment);
220
221 *matrixStrideOut = matrixStride;
222 *arrayStrideOut = arrayStride;
shannonwoods@chromium.org61aaf242013-05-30 00:12:20 +0000223}
224
shannonwoods@chromium.org7e0904d2013-05-30 00:06:45 +0000225}