1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program OpenGL (ES) Module
3*35238bceSAndroid Build Coastguard Worker * -----------------------------------------------
4*35238bceSAndroid Build Coastguard Worker *
5*35238bceSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker *
7*35238bceSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker *
11*35238bceSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker *
13*35238bceSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker *
19*35238bceSAndroid Build Coastguard Worker *//*!
20*35238bceSAndroid Build Coastguard Worker * \file
21*35238bceSAndroid Build Coastguard Worker * \brief Uniform block case.
22*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker
24*35238bceSAndroid Build Coastguard Worker #include "glsUniformBlockCase.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "gluContextInfo.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "gluDrawUtil.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "tcuSurface.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "deInt32.h"
37*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
38*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
39*35238bceSAndroid Build Coastguard Worker #include "deString.h"
40*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
41*35238bceSAndroid Build Coastguard Worker
42*35238bceSAndroid Build Coastguard Worker #include <algorithm>
43*35238bceSAndroid Build Coastguard Worker #include <map>
44*35238bceSAndroid Build Coastguard Worker
45*35238bceSAndroid Build Coastguard Worker using std::map;
46*35238bceSAndroid Build Coastguard Worker using std::string;
47*35238bceSAndroid Build Coastguard Worker using std::vector;
48*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
49*35238bceSAndroid Build Coastguard Worker
50*35238bceSAndroid Build Coastguard Worker namespace deqp
51*35238bceSAndroid Build Coastguard Worker {
52*35238bceSAndroid Build Coastguard Worker namespace gls
53*35238bceSAndroid Build Coastguard Worker {
54*35238bceSAndroid Build Coastguard Worker namespace ub
55*35238bceSAndroid Build Coastguard Worker {
56*35238bceSAndroid Build Coastguard Worker
isSupportedGLSLVersion(glu::GLSLVersion version)57*35238bceSAndroid Build Coastguard Worker static bool isSupportedGLSLVersion(glu::GLSLVersion version)
58*35238bceSAndroid Build Coastguard Worker {
59*35238bceSAndroid Build Coastguard Worker return version >= (glslVersionIsES(version) ? glu::GLSL_VERSION_300_ES : glu::GLSL_VERSION_330);
60*35238bceSAndroid Build Coastguard Worker }
61*35238bceSAndroid Build Coastguard Worker
62*35238bceSAndroid Build Coastguard Worker struct PrecisionFlagsFmt
63*35238bceSAndroid Build Coastguard Worker {
64*35238bceSAndroid Build Coastguard Worker uint32_t flags;
PrecisionFlagsFmtdeqp::gls::ub::PrecisionFlagsFmt65*35238bceSAndroid Build Coastguard Worker PrecisionFlagsFmt(uint32_t flags_) : flags(flags_)
66*35238bceSAndroid Build Coastguard Worker {
67*35238bceSAndroid Build Coastguard Worker }
68*35238bceSAndroid Build Coastguard Worker };
69*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & str,const PrecisionFlagsFmt & fmt)70*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const PrecisionFlagsFmt &fmt)
71*35238bceSAndroid Build Coastguard Worker {
72*35238bceSAndroid Build Coastguard Worker // Precision.
73*35238bceSAndroid Build Coastguard Worker DE_ASSERT(dePop32(fmt.flags & (PRECISION_LOW | PRECISION_MEDIUM | PRECISION_HIGH)) <= 1);
74*35238bceSAndroid Build Coastguard Worker str << (fmt.flags & PRECISION_LOW ? "lowp" :
75*35238bceSAndroid Build Coastguard Worker fmt.flags & PRECISION_MEDIUM ? "mediump" :
76*35238bceSAndroid Build Coastguard Worker fmt.flags & PRECISION_HIGH ? "highp" :
77*35238bceSAndroid Build Coastguard Worker "");
78*35238bceSAndroid Build Coastguard Worker return str;
79*35238bceSAndroid Build Coastguard Worker }
80*35238bceSAndroid Build Coastguard Worker
81*35238bceSAndroid Build Coastguard Worker struct LayoutFlagsFmt
82*35238bceSAndroid Build Coastguard Worker {
83*35238bceSAndroid Build Coastguard Worker uint32_t flags;
LayoutFlagsFmtdeqp::gls::ub::LayoutFlagsFmt84*35238bceSAndroid Build Coastguard Worker LayoutFlagsFmt(uint32_t flags_) : flags(flags_)
85*35238bceSAndroid Build Coastguard Worker {
86*35238bceSAndroid Build Coastguard Worker }
87*35238bceSAndroid Build Coastguard Worker };
88*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & str,const LayoutFlagsFmt & fmt)89*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const LayoutFlagsFmt &fmt)
90*35238bceSAndroid Build Coastguard Worker {
91*35238bceSAndroid Build Coastguard Worker static const struct
92*35238bceSAndroid Build Coastguard Worker {
93*35238bceSAndroid Build Coastguard Worker uint32_t bit;
94*35238bceSAndroid Build Coastguard Worker const char *token;
95*35238bceSAndroid Build Coastguard Worker } bitDesc[] = {{LAYOUT_SHARED, "shared"},
96*35238bceSAndroid Build Coastguard Worker {LAYOUT_PACKED, "packed"},
97*35238bceSAndroid Build Coastguard Worker {LAYOUT_STD140, "std140"},
98*35238bceSAndroid Build Coastguard Worker {LAYOUT_ROW_MAJOR, "row_major"},
99*35238bceSAndroid Build Coastguard Worker {LAYOUT_COLUMN_MAJOR, "column_major"}};
100*35238bceSAndroid Build Coastguard Worker
101*35238bceSAndroid Build Coastguard Worker uint32_t remBits = fmt.flags;
102*35238bceSAndroid Build Coastguard Worker for (int descNdx = 0; descNdx < DE_LENGTH_OF_ARRAY(bitDesc); descNdx++)
103*35238bceSAndroid Build Coastguard Worker {
104*35238bceSAndroid Build Coastguard Worker if (remBits & bitDesc[descNdx].bit)
105*35238bceSAndroid Build Coastguard Worker {
106*35238bceSAndroid Build Coastguard Worker if (remBits != fmt.flags)
107*35238bceSAndroid Build Coastguard Worker str << ", ";
108*35238bceSAndroid Build Coastguard Worker str << bitDesc[descNdx].token;
109*35238bceSAndroid Build Coastguard Worker remBits &= ~bitDesc[descNdx].bit;
110*35238bceSAndroid Build Coastguard Worker }
111*35238bceSAndroid Build Coastguard Worker }
112*35238bceSAndroid Build Coastguard Worker DE_ASSERT(remBits == 0);
113*35238bceSAndroid Build Coastguard Worker return str;
114*35238bceSAndroid Build Coastguard Worker }
115*35238bceSAndroid Build Coastguard Worker
116*35238bceSAndroid Build Coastguard Worker // VarType implementation.
117*35238bceSAndroid Build Coastguard Worker
VarType(void)118*35238bceSAndroid Build Coastguard Worker VarType::VarType(void) : m_type(TYPE_LAST), m_flags(0)
119*35238bceSAndroid Build Coastguard Worker {
120*35238bceSAndroid Build Coastguard Worker }
121*35238bceSAndroid Build Coastguard Worker
VarType(const VarType & other)122*35238bceSAndroid Build Coastguard Worker VarType::VarType(const VarType &other) : m_type(TYPE_LAST), m_flags(0)
123*35238bceSAndroid Build Coastguard Worker {
124*35238bceSAndroid Build Coastguard Worker *this = other;
125*35238bceSAndroid Build Coastguard Worker }
126*35238bceSAndroid Build Coastguard Worker
VarType(glu::DataType basicType,uint32_t flags)127*35238bceSAndroid Build Coastguard Worker VarType::VarType(glu::DataType basicType, uint32_t flags) : m_type(TYPE_BASIC), m_flags(flags)
128*35238bceSAndroid Build Coastguard Worker {
129*35238bceSAndroid Build Coastguard Worker m_data.basicType = basicType;
130*35238bceSAndroid Build Coastguard Worker }
131*35238bceSAndroid Build Coastguard Worker
VarType(const VarType & elementType,int arraySize)132*35238bceSAndroid Build Coastguard Worker VarType::VarType(const VarType &elementType, int arraySize) : m_type(TYPE_ARRAY), m_flags(0)
133*35238bceSAndroid Build Coastguard Worker {
134*35238bceSAndroid Build Coastguard Worker m_data.array.size = arraySize;
135*35238bceSAndroid Build Coastguard Worker m_data.array.elementType = new VarType(elementType);
136*35238bceSAndroid Build Coastguard Worker }
137*35238bceSAndroid Build Coastguard Worker
VarType(const StructType * structPtr,uint32_t flags)138*35238bceSAndroid Build Coastguard Worker VarType::VarType(const StructType *structPtr, uint32_t flags) : m_type(TYPE_STRUCT), m_flags(flags)
139*35238bceSAndroid Build Coastguard Worker {
140*35238bceSAndroid Build Coastguard Worker m_data.structPtr = structPtr;
141*35238bceSAndroid Build Coastguard Worker }
142*35238bceSAndroid Build Coastguard Worker
~VarType(void)143*35238bceSAndroid Build Coastguard Worker VarType::~VarType(void)
144*35238bceSAndroid Build Coastguard Worker {
145*35238bceSAndroid Build Coastguard Worker if (m_type == TYPE_ARRAY)
146*35238bceSAndroid Build Coastguard Worker delete m_data.array.elementType;
147*35238bceSAndroid Build Coastguard Worker }
148*35238bceSAndroid Build Coastguard Worker
operator =(const VarType & other)149*35238bceSAndroid Build Coastguard Worker VarType &VarType::operator=(const VarType &other)
150*35238bceSAndroid Build Coastguard Worker {
151*35238bceSAndroid Build Coastguard Worker if (this == &other)
152*35238bceSAndroid Build Coastguard Worker return *this; // Self-assignment.
153*35238bceSAndroid Build Coastguard Worker
154*35238bceSAndroid Build Coastguard Worker if (m_type == TYPE_ARRAY)
155*35238bceSAndroid Build Coastguard Worker delete m_data.array.elementType;
156*35238bceSAndroid Build Coastguard Worker
157*35238bceSAndroid Build Coastguard Worker m_type = other.m_type;
158*35238bceSAndroid Build Coastguard Worker m_flags = other.m_flags;
159*35238bceSAndroid Build Coastguard Worker m_data = Data();
160*35238bceSAndroid Build Coastguard Worker
161*35238bceSAndroid Build Coastguard Worker if (m_type == TYPE_ARRAY)
162*35238bceSAndroid Build Coastguard Worker {
163*35238bceSAndroid Build Coastguard Worker m_data.array.elementType = new VarType(*other.m_data.array.elementType);
164*35238bceSAndroid Build Coastguard Worker m_data.array.size = other.m_data.array.size;
165*35238bceSAndroid Build Coastguard Worker }
166*35238bceSAndroid Build Coastguard Worker else
167*35238bceSAndroid Build Coastguard Worker m_data = other.m_data;
168*35238bceSAndroid Build Coastguard Worker
169*35238bceSAndroid Build Coastguard Worker return *this;
170*35238bceSAndroid Build Coastguard Worker }
171*35238bceSAndroid Build Coastguard Worker
172*35238bceSAndroid Build Coastguard Worker // StructType implementation.
173*35238bceSAndroid Build Coastguard Worker
addMember(const char * name,const VarType & type,uint32_t flags)174*35238bceSAndroid Build Coastguard Worker void StructType::addMember(const char *name, const VarType &type, uint32_t flags)
175*35238bceSAndroid Build Coastguard Worker {
176*35238bceSAndroid Build Coastguard Worker m_members.push_back(StructMember(name, type, flags));
177*35238bceSAndroid Build Coastguard Worker }
178*35238bceSAndroid Build Coastguard Worker
179*35238bceSAndroid Build Coastguard Worker // Uniform implementation.
180*35238bceSAndroid Build Coastguard Worker
Uniform(const char * name,const VarType & type,uint32_t flags)181*35238bceSAndroid Build Coastguard Worker Uniform::Uniform(const char *name, const VarType &type, uint32_t flags) : m_name(name), m_type(type), m_flags(flags)
182*35238bceSAndroid Build Coastguard Worker {
183*35238bceSAndroid Build Coastguard Worker }
184*35238bceSAndroid Build Coastguard Worker
185*35238bceSAndroid Build Coastguard Worker // UniformBlock implementation.
186*35238bceSAndroid Build Coastguard Worker
UniformBlock(const char * blockName)187*35238bceSAndroid Build Coastguard Worker UniformBlock::UniformBlock(const char *blockName) : m_blockName(blockName), m_arraySize(0), m_flags(0)
188*35238bceSAndroid Build Coastguard Worker {
189*35238bceSAndroid Build Coastguard Worker }
190*35238bceSAndroid Build Coastguard Worker
191*35238bceSAndroid Build Coastguard Worker struct BlockLayoutEntry
192*35238bceSAndroid Build Coastguard Worker {
BlockLayoutEntrydeqp::gls::ub::BlockLayoutEntry193*35238bceSAndroid Build Coastguard Worker BlockLayoutEntry(void) : size(0)
194*35238bceSAndroid Build Coastguard Worker {
195*35238bceSAndroid Build Coastguard Worker }
196*35238bceSAndroid Build Coastguard Worker
197*35238bceSAndroid Build Coastguard Worker std::string name;
198*35238bceSAndroid Build Coastguard Worker int size;
199*35238bceSAndroid Build Coastguard Worker std::vector<int> activeUniformIndices;
200*35238bceSAndroid Build Coastguard Worker };
201*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & stream,const BlockLayoutEntry & entry)202*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &stream, const BlockLayoutEntry &entry)
203*35238bceSAndroid Build Coastguard Worker {
204*35238bceSAndroid Build Coastguard Worker stream << entry.name << " { name = " << entry.name << ", size = " << entry.size << ", activeUniformIndices = [";
205*35238bceSAndroid Build Coastguard Worker
206*35238bceSAndroid Build Coastguard Worker for (vector<int>::const_iterator i = entry.activeUniformIndices.begin(); i != entry.activeUniformIndices.end(); i++)
207*35238bceSAndroid Build Coastguard Worker {
208*35238bceSAndroid Build Coastguard Worker if (i != entry.activeUniformIndices.begin())
209*35238bceSAndroid Build Coastguard Worker stream << ", ";
210*35238bceSAndroid Build Coastguard Worker stream << *i;
211*35238bceSAndroid Build Coastguard Worker }
212*35238bceSAndroid Build Coastguard Worker
213*35238bceSAndroid Build Coastguard Worker stream << "] }";
214*35238bceSAndroid Build Coastguard Worker return stream;
215*35238bceSAndroid Build Coastguard Worker }
216*35238bceSAndroid Build Coastguard Worker
217*35238bceSAndroid Build Coastguard Worker struct UniformLayoutEntry
218*35238bceSAndroid Build Coastguard Worker {
UniformLayoutEntrydeqp::gls::ub::UniformLayoutEntry219*35238bceSAndroid Build Coastguard Worker UniformLayoutEntry(void)
220*35238bceSAndroid Build Coastguard Worker : type(glu::TYPE_LAST)
221*35238bceSAndroid Build Coastguard Worker , size(0)
222*35238bceSAndroid Build Coastguard Worker , blockNdx(-1)
223*35238bceSAndroid Build Coastguard Worker , offset(-1)
224*35238bceSAndroid Build Coastguard Worker , arrayStride(-1)
225*35238bceSAndroid Build Coastguard Worker , matrixStride(-1)
226*35238bceSAndroid Build Coastguard Worker , isRowMajor(false)
227*35238bceSAndroid Build Coastguard Worker {
228*35238bceSAndroid Build Coastguard Worker }
229*35238bceSAndroid Build Coastguard Worker
230*35238bceSAndroid Build Coastguard Worker std::string name;
231*35238bceSAndroid Build Coastguard Worker glu::DataType type;
232*35238bceSAndroid Build Coastguard Worker int size;
233*35238bceSAndroid Build Coastguard Worker int blockNdx;
234*35238bceSAndroid Build Coastguard Worker int offset;
235*35238bceSAndroid Build Coastguard Worker int arrayStride;
236*35238bceSAndroid Build Coastguard Worker int matrixStride;
237*35238bceSAndroid Build Coastguard Worker bool isRowMajor;
238*35238bceSAndroid Build Coastguard Worker };
239*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & stream,const UniformLayoutEntry & entry)240*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &stream, const UniformLayoutEntry &entry)
241*35238bceSAndroid Build Coastguard Worker {
242*35238bceSAndroid Build Coastguard Worker stream << entry.name << " { type = " << glu::getDataTypeName(entry.type) << ", size = " << entry.size
243*35238bceSAndroid Build Coastguard Worker << ", blockNdx = " << entry.blockNdx << ", offset = " << entry.offset
244*35238bceSAndroid Build Coastguard Worker << ", arrayStride = " << entry.arrayStride << ", matrixStride = " << entry.matrixStride
245*35238bceSAndroid Build Coastguard Worker << ", isRowMajor = " << (entry.isRowMajor ? "true" : "false") << " }";
246*35238bceSAndroid Build Coastguard Worker return stream;
247*35238bceSAndroid Build Coastguard Worker }
248*35238bceSAndroid Build Coastguard Worker
249*35238bceSAndroid Build Coastguard Worker class UniformLayout
250*35238bceSAndroid Build Coastguard Worker {
251*35238bceSAndroid Build Coastguard Worker public:
252*35238bceSAndroid Build Coastguard Worker std::vector<BlockLayoutEntry> blocks;
253*35238bceSAndroid Build Coastguard Worker std::vector<UniformLayoutEntry> uniforms;
254*35238bceSAndroid Build Coastguard Worker
255*35238bceSAndroid Build Coastguard Worker int getUniformIndex(const char *name) const;
256*35238bceSAndroid Build Coastguard Worker int getBlockIndex(const char *name) const;
257*35238bceSAndroid Build Coastguard Worker };
258*35238bceSAndroid Build Coastguard Worker
259*35238bceSAndroid Build Coastguard Worker // \todo [2012-01-24 pyry] Speed up lookups using hash.
260*35238bceSAndroid Build Coastguard Worker
getUniformIndex(const char * name) const261*35238bceSAndroid Build Coastguard Worker int UniformLayout::getUniformIndex(const char *name) const
262*35238bceSAndroid Build Coastguard Worker {
263*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < (int)uniforms.size(); ndx++)
264*35238bceSAndroid Build Coastguard Worker {
265*35238bceSAndroid Build Coastguard Worker if (uniforms[ndx].name == name)
266*35238bceSAndroid Build Coastguard Worker return ndx;
267*35238bceSAndroid Build Coastguard Worker }
268*35238bceSAndroid Build Coastguard Worker return -1;
269*35238bceSAndroid Build Coastguard Worker }
270*35238bceSAndroid Build Coastguard Worker
getBlockIndex(const char * name) const271*35238bceSAndroid Build Coastguard Worker int UniformLayout::getBlockIndex(const char *name) const
272*35238bceSAndroid Build Coastguard Worker {
273*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < (int)blocks.size(); ndx++)
274*35238bceSAndroid Build Coastguard Worker {
275*35238bceSAndroid Build Coastguard Worker if (blocks[ndx].name == name)
276*35238bceSAndroid Build Coastguard Worker return ndx;
277*35238bceSAndroid Build Coastguard Worker }
278*35238bceSAndroid Build Coastguard Worker return -1;
279*35238bceSAndroid Build Coastguard Worker }
280*35238bceSAndroid Build Coastguard Worker
281*35238bceSAndroid Build Coastguard Worker // ShaderInterface implementation.
282*35238bceSAndroid Build Coastguard Worker
ShaderInterface(void)283*35238bceSAndroid Build Coastguard Worker ShaderInterface::ShaderInterface(void)
284*35238bceSAndroid Build Coastguard Worker {
285*35238bceSAndroid Build Coastguard Worker }
286*35238bceSAndroid Build Coastguard Worker
~ShaderInterface(void)287*35238bceSAndroid Build Coastguard Worker ShaderInterface::~ShaderInterface(void)
288*35238bceSAndroid Build Coastguard Worker {
289*35238bceSAndroid Build Coastguard Worker for (std::vector<StructType *>::iterator i = m_structs.begin(); i != m_structs.end(); i++)
290*35238bceSAndroid Build Coastguard Worker delete *i;
291*35238bceSAndroid Build Coastguard Worker
292*35238bceSAndroid Build Coastguard Worker for (std::vector<UniformBlock *>::iterator i = m_uniformBlocks.begin(); i != m_uniformBlocks.end(); i++)
293*35238bceSAndroid Build Coastguard Worker delete *i;
294*35238bceSAndroid Build Coastguard Worker }
295*35238bceSAndroid Build Coastguard Worker
allocStruct(const char * name)296*35238bceSAndroid Build Coastguard Worker StructType &ShaderInterface::allocStruct(const char *name)
297*35238bceSAndroid Build Coastguard Worker {
298*35238bceSAndroid Build Coastguard Worker m_structs.reserve(m_structs.size() + 1);
299*35238bceSAndroid Build Coastguard Worker m_structs.push_back(new StructType(name));
300*35238bceSAndroid Build Coastguard Worker return *m_structs.back();
301*35238bceSAndroid Build Coastguard Worker }
302*35238bceSAndroid Build Coastguard Worker
303*35238bceSAndroid Build Coastguard Worker struct StructNameEquals
304*35238bceSAndroid Build Coastguard Worker {
305*35238bceSAndroid Build Coastguard Worker std::string name;
306*35238bceSAndroid Build Coastguard Worker
StructNameEqualsdeqp::gls::ub::StructNameEquals307*35238bceSAndroid Build Coastguard Worker StructNameEquals(const char *name_) : name(name_)
308*35238bceSAndroid Build Coastguard Worker {
309*35238bceSAndroid Build Coastguard Worker }
310*35238bceSAndroid Build Coastguard Worker
operator ()deqp::gls::ub::StructNameEquals311*35238bceSAndroid Build Coastguard Worker bool operator()(const StructType *type) const
312*35238bceSAndroid Build Coastguard Worker {
313*35238bceSAndroid Build Coastguard Worker return type->getTypeName() && name == type->getTypeName();
314*35238bceSAndroid Build Coastguard Worker }
315*35238bceSAndroid Build Coastguard Worker };
316*35238bceSAndroid Build Coastguard Worker
findStruct(const char * name) const317*35238bceSAndroid Build Coastguard Worker const StructType *ShaderInterface::findStruct(const char *name) const
318*35238bceSAndroid Build Coastguard Worker {
319*35238bceSAndroid Build Coastguard Worker std::vector<StructType *>::const_iterator pos =
320*35238bceSAndroid Build Coastguard Worker std::find_if(m_structs.begin(), m_structs.end(), StructNameEquals(name));
321*35238bceSAndroid Build Coastguard Worker return pos != m_structs.end() ? *pos : DE_NULL;
322*35238bceSAndroid Build Coastguard Worker }
323*35238bceSAndroid Build Coastguard Worker
getNamedStructs(std::vector<const StructType * > & structs) const324*35238bceSAndroid Build Coastguard Worker void ShaderInterface::getNamedStructs(std::vector<const StructType *> &structs) const
325*35238bceSAndroid Build Coastguard Worker {
326*35238bceSAndroid Build Coastguard Worker for (std::vector<StructType *>::const_iterator i = m_structs.begin(); i != m_structs.end(); i++)
327*35238bceSAndroid Build Coastguard Worker {
328*35238bceSAndroid Build Coastguard Worker if ((*i)->getTypeName() != DE_NULL)
329*35238bceSAndroid Build Coastguard Worker structs.push_back(*i);
330*35238bceSAndroid Build Coastguard Worker }
331*35238bceSAndroid Build Coastguard Worker }
332*35238bceSAndroid Build Coastguard Worker
allocBlock(const char * name)333*35238bceSAndroid Build Coastguard Worker UniformBlock &ShaderInterface::allocBlock(const char *name)
334*35238bceSAndroid Build Coastguard Worker {
335*35238bceSAndroid Build Coastguard Worker m_uniformBlocks.reserve(m_uniformBlocks.size() + 1);
336*35238bceSAndroid Build Coastguard Worker m_uniformBlocks.push_back(new UniformBlock(name));
337*35238bceSAndroid Build Coastguard Worker return *m_uniformBlocks.back();
338*35238bceSAndroid Build Coastguard Worker }
339*35238bceSAndroid Build Coastguard Worker
340*35238bceSAndroid Build Coastguard Worker namespace // Utilities
341*35238bceSAndroid Build Coastguard Worker {
342*35238bceSAndroid Build Coastguard Worker
343*35238bceSAndroid Build Coastguard Worker // Layout computation.
344*35238bceSAndroid Build Coastguard Worker
getDataTypeByteSize(glu::DataType type)345*35238bceSAndroid Build Coastguard Worker int getDataTypeByteSize(glu::DataType type)
346*35238bceSAndroid Build Coastguard Worker {
347*35238bceSAndroid Build Coastguard Worker return glu::getDataTypeScalarSize(type) * (int)sizeof(uint32_t);
348*35238bceSAndroid Build Coastguard Worker }
349*35238bceSAndroid Build Coastguard Worker
getDataTypeByteAlignment(glu::DataType type)350*35238bceSAndroid Build Coastguard Worker int getDataTypeByteAlignment(glu::DataType type)
351*35238bceSAndroid Build Coastguard Worker {
352*35238bceSAndroid Build Coastguard Worker switch (type)
353*35238bceSAndroid Build Coastguard Worker {
354*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT:
355*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT:
356*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT:
357*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL:
358*35238bceSAndroid Build Coastguard Worker return 1 * (int)sizeof(uint32_t);
359*35238bceSAndroid Build Coastguard Worker
360*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_VEC2:
361*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT_VEC2:
362*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT_VEC2:
363*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL_VEC2:
364*35238bceSAndroid Build Coastguard Worker return 2 * (int)sizeof(uint32_t);
365*35238bceSAndroid Build Coastguard Worker
366*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_VEC3:
367*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT_VEC3:
368*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT_VEC3:
369*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL_VEC3: // Fall-through to vec4
370*35238bceSAndroid Build Coastguard Worker
371*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_VEC4:
372*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT_VEC4:
373*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT_VEC4:
374*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL_VEC4:
375*35238bceSAndroid Build Coastguard Worker return 4 * (int)sizeof(uint32_t);
376*35238bceSAndroid Build Coastguard Worker
377*35238bceSAndroid Build Coastguard Worker default:
378*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
379*35238bceSAndroid Build Coastguard Worker return 0;
380*35238bceSAndroid Build Coastguard Worker }
381*35238bceSAndroid Build Coastguard Worker }
382*35238bceSAndroid Build Coastguard Worker
getDataTypeArrayStride(glu::DataType type)383*35238bceSAndroid Build Coastguard Worker int getDataTypeArrayStride(glu::DataType type)
384*35238bceSAndroid Build Coastguard Worker {
385*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!glu::isDataTypeMatrix(type));
386*35238bceSAndroid Build Coastguard Worker
387*35238bceSAndroid Build Coastguard Worker const int baseStride = getDataTypeByteSize(type);
388*35238bceSAndroid Build Coastguard Worker const int vec4Alignment = (int)sizeof(uint32_t) * 4;
389*35238bceSAndroid Build Coastguard Worker
390*35238bceSAndroid Build Coastguard Worker DE_ASSERT(baseStride <= vec4Alignment);
391*35238bceSAndroid Build Coastguard Worker return de::max(baseStride, vec4Alignment); // Really? See rule 4.
392*35238bceSAndroid Build Coastguard Worker }
393*35238bceSAndroid Build Coastguard Worker
computeStd140BaseAlignment(const VarType & type)394*35238bceSAndroid Build Coastguard Worker int computeStd140BaseAlignment(const VarType &type)
395*35238bceSAndroid Build Coastguard Worker {
396*35238bceSAndroid Build Coastguard Worker const int vec4Alignment = (int)sizeof(uint32_t) * 4;
397*35238bceSAndroid Build Coastguard Worker
398*35238bceSAndroid Build Coastguard Worker if (type.isBasicType())
399*35238bceSAndroid Build Coastguard Worker {
400*35238bceSAndroid Build Coastguard Worker glu::DataType basicType = type.getBasicType();
401*35238bceSAndroid Build Coastguard Worker
402*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeMatrix(basicType))
403*35238bceSAndroid Build Coastguard Worker {
404*35238bceSAndroid Build Coastguard Worker bool isRowMajor = !!(type.getFlags() & LAYOUT_ROW_MAJOR);
405*35238bceSAndroid Build Coastguard Worker int vecSize =
406*35238bceSAndroid Build Coastguard Worker isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType) : glu::getDataTypeMatrixNumRows(basicType);
407*35238bceSAndroid Build Coastguard Worker
408*35238bceSAndroid Build Coastguard Worker return getDataTypeArrayStride(glu::getDataTypeFloatVec(vecSize));
409*35238bceSAndroid Build Coastguard Worker }
410*35238bceSAndroid Build Coastguard Worker else
411*35238bceSAndroid Build Coastguard Worker return getDataTypeByteAlignment(basicType);
412*35238bceSAndroid Build Coastguard Worker }
413*35238bceSAndroid Build Coastguard Worker else if (type.isArrayType())
414*35238bceSAndroid Build Coastguard Worker {
415*35238bceSAndroid Build Coastguard Worker int elemAlignment = computeStd140BaseAlignment(type.getElementType());
416*35238bceSAndroid Build Coastguard Worker
417*35238bceSAndroid Build Coastguard Worker // Round up to alignment of vec4
418*35238bceSAndroid Build Coastguard Worker return deRoundUp32(elemAlignment, vec4Alignment);
419*35238bceSAndroid Build Coastguard Worker }
420*35238bceSAndroid Build Coastguard Worker else
421*35238bceSAndroid Build Coastguard Worker {
422*35238bceSAndroid Build Coastguard Worker DE_ASSERT(type.isStructType());
423*35238bceSAndroid Build Coastguard Worker
424*35238bceSAndroid Build Coastguard Worker int maxBaseAlignment = 0;
425*35238bceSAndroid Build Coastguard Worker
426*35238bceSAndroid Build Coastguard Worker for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end();
427*35238bceSAndroid Build Coastguard Worker memberIter++)
428*35238bceSAndroid Build Coastguard Worker maxBaseAlignment = de::max(maxBaseAlignment, computeStd140BaseAlignment(memberIter->getType()));
429*35238bceSAndroid Build Coastguard Worker
430*35238bceSAndroid Build Coastguard Worker return deRoundUp32(maxBaseAlignment, vec4Alignment);
431*35238bceSAndroid Build Coastguard Worker }
432*35238bceSAndroid Build Coastguard Worker }
433*35238bceSAndroid Build Coastguard Worker
mergeLayoutFlags(uint32_t prevFlags,uint32_t newFlags)434*35238bceSAndroid Build Coastguard Worker inline uint32_t mergeLayoutFlags(uint32_t prevFlags, uint32_t newFlags)
435*35238bceSAndroid Build Coastguard Worker {
436*35238bceSAndroid Build Coastguard Worker const uint32_t packingMask = LAYOUT_PACKED | LAYOUT_SHARED | LAYOUT_STD140;
437*35238bceSAndroid Build Coastguard Worker const uint32_t matrixMask = LAYOUT_ROW_MAJOR | LAYOUT_COLUMN_MAJOR;
438*35238bceSAndroid Build Coastguard Worker
439*35238bceSAndroid Build Coastguard Worker uint32_t mergedFlags = 0;
440*35238bceSAndroid Build Coastguard Worker
441*35238bceSAndroid Build Coastguard Worker mergedFlags |= ((newFlags & packingMask) ? newFlags : prevFlags) & packingMask;
442*35238bceSAndroid Build Coastguard Worker mergedFlags |= ((newFlags & matrixMask) ? newFlags : prevFlags) & matrixMask;
443*35238bceSAndroid Build Coastguard Worker
444*35238bceSAndroid Build Coastguard Worker return mergedFlags;
445*35238bceSAndroid Build Coastguard Worker }
446*35238bceSAndroid Build Coastguard Worker
computeStd140Layout(UniformLayout & layout,int & curOffset,int curBlockNdx,const std::string & curPrefix,const VarType & type,uint32_t layoutFlags)447*35238bceSAndroid Build Coastguard Worker void computeStd140Layout(UniformLayout &layout, int &curOffset, int curBlockNdx, const std::string &curPrefix,
448*35238bceSAndroid Build Coastguard Worker const VarType &type, uint32_t layoutFlags)
449*35238bceSAndroid Build Coastguard Worker {
450*35238bceSAndroid Build Coastguard Worker int baseAlignment = computeStd140BaseAlignment(type);
451*35238bceSAndroid Build Coastguard Worker
452*35238bceSAndroid Build Coastguard Worker curOffset = deAlign32(curOffset, baseAlignment);
453*35238bceSAndroid Build Coastguard Worker
454*35238bceSAndroid Build Coastguard Worker if (type.isBasicType())
455*35238bceSAndroid Build Coastguard Worker {
456*35238bceSAndroid Build Coastguard Worker glu::DataType basicType = type.getBasicType();
457*35238bceSAndroid Build Coastguard Worker UniformLayoutEntry entry;
458*35238bceSAndroid Build Coastguard Worker
459*35238bceSAndroid Build Coastguard Worker entry.name = curPrefix;
460*35238bceSAndroid Build Coastguard Worker entry.type = basicType;
461*35238bceSAndroid Build Coastguard Worker entry.size = 1;
462*35238bceSAndroid Build Coastguard Worker entry.arrayStride = 0;
463*35238bceSAndroid Build Coastguard Worker entry.matrixStride = 0;
464*35238bceSAndroid Build Coastguard Worker entry.blockNdx = curBlockNdx;
465*35238bceSAndroid Build Coastguard Worker
466*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeMatrix(basicType))
467*35238bceSAndroid Build Coastguard Worker {
468*35238bceSAndroid Build Coastguard Worker // Array of vectors as specified in rules 5 & 7.
469*35238bceSAndroid Build Coastguard Worker bool isRowMajor =
470*35238bceSAndroid Build Coastguard Worker !!(((type.getFlags() & (LAYOUT_ROW_MAJOR | LAYOUT_COLUMN_MAJOR) ? type.getFlags() : layoutFlags) &
471*35238bceSAndroid Build Coastguard Worker LAYOUT_ROW_MAJOR));
472*35238bceSAndroid Build Coastguard Worker
473*35238bceSAndroid Build Coastguard Worker int vecSize =
474*35238bceSAndroid Build Coastguard Worker isRowMajor ? glu::getDataTypeMatrixNumColumns(basicType) : glu::getDataTypeMatrixNumRows(basicType);
475*35238bceSAndroid Build Coastguard Worker int numVecs =
476*35238bceSAndroid Build Coastguard Worker isRowMajor ? glu::getDataTypeMatrixNumRows(basicType) : glu::getDataTypeMatrixNumColumns(basicType);
477*35238bceSAndroid Build Coastguard Worker int stride = getDataTypeArrayStride(glu::getDataTypeFloatVec(vecSize));
478*35238bceSAndroid Build Coastguard Worker
479*35238bceSAndroid Build Coastguard Worker entry.offset = curOffset;
480*35238bceSAndroid Build Coastguard Worker entry.matrixStride = stride;
481*35238bceSAndroid Build Coastguard Worker entry.isRowMajor = isRowMajor;
482*35238bceSAndroid Build Coastguard Worker
483*35238bceSAndroid Build Coastguard Worker curOffset += numVecs * stride;
484*35238bceSAndroid Build Coastguard Worker }
485*35238bceSAndroid Build Coastguard Worker else
486*35238bceSAndroid Build Coastguard Worker {
487*35238bceSAndroid Build Coastguard Worker // Scalar or vector.
488*35238bceSAndroid Build Coastguard Worker entry.offset = curOffset;
489*35238bceSAndroid Build Coastguard Worker
490*35238bceSAndroid Build Coastguard Worker curOffset += getDataTypeByteSize(basicType);
491*35238bceSAndroid Build Coastguard Worker }
492*35238bceSAndroid Build Coastguard Worker
493*35238bceSAndroid Build Coastguard Worker layout.uniforms.push_back(entry);
494*35238bceSAndroid Build Coastguard Worker }
495*35238bceSAndroid Build Coastguard Worker else if (type.isArrayType())
496*35238bceSAndroid Build Coastguard Worker {
497*35238bceSAndroid Build Coastguard Worker const VarType &elemType = type.getElementType();
498*35238bceSAndroid Build Coastguard Worker
499*35238bceSAndroid Build Coastguard Worker if (elemType.isBasicType() && !glu::isDataTypeMatrix(elemType.getBasicType()))
500*35238bceSAndroid Build Coastguard Worker {
501*35238bceSAndroid Build Coastguard Worker // Array of scalars or vectors.
502*35238bceSAndroid Build Coastguard Worker glu::DataType elemBasicType = elemType.getBasicType();
503*35238bceSAndroid Build Coastguard Worker UniformLayoutEntry entry;
504*35238bceSAndroid Build Coastguard Worker int stride = getDataTypeArrayStride(elemBasicType);
505*35238bceSAndroid Build Coastguard Worker
506*35238bceSAndroid Build Coastguard Worker entry.name = curPrefix + "[0]"; // Array uniforms are always postfixed with [0]
507*35238bceSAndroid Build Coastguard Worker entry.type = elemBasicType;
508*35238bceSAndroid Build Coastguard Worker entry.blockNdx = curBlockNdx;
509*35238bceSAndroid Build Coastguard Worker entry.offset = curOffset;
510*35238bceSAndroid Build Coastguard Worker entry.size = type.getArraySize();
511*35238bceSAndroid Build Coastguard Worker entry.arrayStride = stride;
512*35238bceSAndroid Build Coastguard Worker entry.matrixStride = 0;
513*35238bceSAndroid Build Coastguard Worker
514*35238bceSAndroid Build Coastguard Worker curOffset += stride * type.getArraySize();
515*35238bceSAndroid Build Coastguard Worker
516*35238bceSAndroid Build Coastguard Worker layout.uniforms.push_back(entry);
517*35238bceSAndroid Build Coastguard Worker }
518*35238bceSAndroid Build Coastguard Worker else if (elemType.isBasicType() && glu::isDataTypeMatrix(elemType.getBasicType()))
519*35238bceSAndroid Build Coastguard Worker {
520*35238bceSAndroid Build Coastguard Worker // Array of matrices.
521*35238bceSAndroid Build Coastguard Worker glu::DataType elemBasicType = elemType.getBasicType();
522*35238bceSAndroid Build Coastguard Worker bool isRowMajor = !!(
523*35238bceSAndroid Build Coastguard Worker ((elemType.getFlags() & (LAYOUT_ROW_MAJOR | LAYOUT_COLUMN_MAJOR) ? elemType.getFlags() : layoutFlags) &
524*35238bceSAndroid Build Coastguard Worker LAYOUT_ROW_MAJOR));
525*35238bceSAndroid Build Coastguard Worker int vecSize = isRowMajor ? glu::getDataTypeMatrixNumColumns(elemBasicType) :
526*35238bceSAndroid Build Coastguard Worker glu::getDataTypeMatrixNumRows(elemBasicType);
527*35238bceSAndroid Build Coastguard Worker int numVecs = isRowMajor ? glu::getDataTypeMatrixNumRows(elemBasicType) :
528*35238bceSAndroid Build Coastguard Worker glu::getDataTypeMatrixNumColumns(elemBasicType);
529*35238bceSAndroid Build Coastguard Worker int stride = getDataTypeArrayStride(glu::getDataTypeFloatVec(vecSize));
530*35238bceSAndroid Build Coastguard Worker UniformLayoutEntry entry;
531*35238bceSAndroid Build Coastguard Worker
532*35238bceSAndroid Build Coastguard Worker entry.name = curPrefix + "[0]"; // Array uniforms are always postfixed with [0]
533*35238bceSAndroid Build Coastguard Worker entry.type = elemBasicType;
534*35238bceSAndroid Build Coastguard Worker entry.blockNdx = curBlockNdx;
535*35238bceSAndroid Build Coastguard Worker entry.offset = curOffset;
536*35238bceSAndroid Build Coastguard Worker entry.size = type.getArraySize();
537*35238bceSAndroid Build Coastguard Worker entry.arrayStride = stride * numVecs;
538*35238bceSAndroid Build Coastguard Worker entry.matrixStride = stride;
539*35238bceSAndroid Build Coastguard Worker entry.isRowMajor = isRowMajor;
540*35238bceSAndroid Build Coastguard Worker
541*35238bceSAndroid Build Coastguard Worker curOffset += numVecs * type.getArraySize() * stride;
542*35238bceSAndroid Build Coastguard Worker
543*35238bceSAndroid Build Coastguard Worker layout.uniforms.push_back(entry);
544*35238bceSAndroid Build Coastguard Worker }
545*35238bceSAndroid Build Coastguard Worker else
546*35238bceSAndroid Build Coastguard Worker {
547*35238bceSAndroid Build Coastguard Worker DE_ASSERT(elemType.isStructType() || elemType.isArrayType());
548*35238bceSAndroid Build Coastguard Worker
549*35238bceSAndroid Build Coastguard Worker for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
550*35238bceSAndroid Build Coastguard Worker computeStd140Layout(layout, curOffset, curBlockNdx, curPrefix + "[" + de::toString(elemNdx) + "]",
551*35238bceSAndroid Build Coastguard Worker type.getElementType(), layoutFlags);
552*35238bceSAndroid Build Coastguard Worker }
553*35238bceSAndroid Build Coastguard Worker }
554*35238bceSAndroid Build Coastguard Worker else
555*35238bceSAndroid Build Coastguard Worker {
556*35238bceSAndroid Build Coastguard Worker DE_ASSERT(type.isStructType());
557*35238bceSAndroid Build Coastguard Worker
558*35238bceSAndroid Build Coastguard Worker // Override matrix packing layout flags in case the structure has them defined.
559*35238bceSAndroid Build Coastguard Worker const uint32_t matrixLayoutMask = LAYOUT_ROW_MAJOR | LAYOUT_COLUMN_MAJOR;
560*35238bceSAndroid Build Coastguard Worker if (type.getFlags() & matrixLayoutMask)
561*35238bceSAndroid Build Coastguard Worker layoutFlags = (layoutFlags & (~matrixLayoutMask)) | (type.getFlags() & matrixLayoutMask);
562*35238bceSAndroid Build Coastguard Worker
563*35238bceSAndroid Build Coastguard Worker for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end();
564*35238bceSAndroid Build Coastguard Worker memberIter++)
565*35238bceSAndroid Build Coastguard Worker computeStd140Layout(layout, curOffset, curBlockNdx, curPrefix + "." + memberIter->getName(),
566*35238bceSAndroid Build Coastguard Worker memberIter->getType(), layoutFlags);
567*35238bceSAndroid Build Coastguard Worker
568*35238bceSAndroid Build Coastguard Worker curOffset = deAlign32(curOffset, baseAlignment);
569*35238bceSAndroid Build Coastguard Worker }
570*35238bceSAndroid Build Coastguard Worker }
571*35238bceSAndroid Build Coastguard Worker
computeStd140Layout(UniformLayout & layout,const ShaderInterface & interface)572*35238bceSAndroid Build Coastguard Worker void computeStd140Layout(UniformLayout &layout, const ShaderInterface &interface)
573*35238bceSAndroid Build Coastguard Worker {
574*35238bceSAndroid Build Coastguard Worker // \todo [2012-01-23 pyry] Uniforms in default block.
575*35238bceSAndroid Build Coastguard Worker
576*35238bceSAndroid Build Coastguard Worker int numUniformBlocks = interface.getNumUniformBlocks();
577*35238bceSAndroid Build Coastguard Worker
578*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numUniformBlocks; blockNdx++)
579*35238bceSAndroid Build Coastguard Worker {
580*35238bceSAndroid Build Coastguard Worker const UniformBlock &block = interface.getUniformBlock(blockNdx);
581*35238bceSAndroid Build Coastguard Worker bool hasInstanceName = block.getInstanceName() != DE_NULL;
582*35238bceSAndroid Build Coastguard Worker std::string blockPrefix = hasInstanceName ? (std::string(block.getBlockName()) + ".") : std::string("");
583*35238bceSAndroid Build Coastguard Worker int curOffset = 0;
584*35238bceSAndroid Build Coastguard Worker int activeBlockNdx = (int)layout.blocks.size();
585*35238bceSAndroid Build Coastguard Worker int firstUniformNdx = (int)layout.uniforms.size();
586*35238bceSAndroid Build Coastguard Worker
587*35238bceSAndroid Build Coastguard Worker for (UniformBlock::ConstIterator uniformIter = block.begin(); uniformIter != block.end(); uniformIter++)
588*35238bceSAndroid Build Coastguard Worker {
589*35238bceSAndroid Build Coastguard Worker const Uniform &uniform = *uniformIter;
590*35238bceSAndroid Build Coastguard Worker computeStd140Layout(layout, curOffset, activeBlockNdx, blockPrefix + uniform.getName(), uniform.getType(),
591*35238bceSAndroid Build Coastguard Worker mergeLayoutFlags(block.getFlags(), uniform.getFlags()));
592*35238bceSAndroid Build Coastguard Worker }
593*35238bceSAndroid Build Coastguard Worker
594*35238bceSAndroid Build Coastguard Worker int uniformIndicesEnd = (int)layout.uniforms.size();
595*35238bceSAndroid Build Coastguard Worker int blockSize = curOffset;
596*35238bceSAndroid Build Coastguard Worker int numInstances = block.isArray() ? block.getArraySize() : 1;
597*35238bceSAndroid Build Coastguard Worker
598*35238bceSAndroid Build Coastguard Worker // Create block layout entries for each instance.
599*35238bceSAndroid Build Coastguard Worker for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
600*35238bceSAndroid Build Coastguard Worker {
601*35238bceSAndroid Build Coastguard Worker // Allocate entry for instance.
602*35238bceSAndroid Build Coastguard Worker layout.blocks.push_back(BlockLayoutEntry());
603*35238bceSAndroid Build Coastguard Worker BlockLayoutEntry &blockEntry = layout.blocks.back();
604*35238bceSAndroid Build Coastguard Worker
605*35238bceSAndroid Build Coastguard Worker blockEntry.name = block.getBlockName();
606*35238bceSAndroid Build Coastguard Worker blockEntry.size = blockSize;
607*35238bceSAndroid Build Coastguard Worker
608*35238bceSAndroid Build Coastguard Worker // Compute active uniform set for block.
609*35238bceSAndroid Build Coastguard Worker for (int uniformNdx = firstUniformNdx; uniformNdx < uniformIndicesEnd; uniformNdx++)
610*35238bceSAndroid Build Coastguard Worker blockEntry.activeUniformIndices.push_back(uniformNdx);
611*35238bceSAndroid Build Coastguard Worker
612*35238bceSAndroid Build Coastguard Worker if (block.isArray())
613*35238bceSAndroid Build Coastguard Worker blockEntry.name += "[" + de::toString(instanceNdx) + "]";
614*35238bceSAndroid Build Coastguard Worker }
615*35238bceSAndroid Build Coastguard Worker }
616*35238bceSAndroid Build Coastguard Worker }
617*35238bceSAndroid Build Coastguard Worker
618*35238bceSAndroid Build Coastguard Worker // Value generator.
619*35238bceSAndroid Build Coastguard Worker
generateValue(const UniformLayoutEntry & entry,void * basePtr,de::Random & rnd)620*35238bceSAndroid Build Coastguard Worker void generateValue(const UniformLayoutEntry &entry, void *basePtr, de::Random &rnd)
621*35238bceSAndroid Build Coastguard Worker {
622*35238bceSAndroid Build Coastguard Worker glu::DataType scalarType = glu::getDataTypeScalarType(entry.type);
623*35238bceSAndroid Build Coastguard Worker int scalarSize = glu::getDataTypeScalarSize(entry.type);
624*35238bceSAndroid Build Coastguard Worker bool isMatrix = glu::isDataTypeMatrix(entry.type);
625*35238bceSAndroid Build Coastguard Worker int numVecs = isMatrix ? (entry.isRowMajor ? glu::getDataTypeMatrixNumRows(entry.type) :
626*35238bceSAndroid Build Coastguard Worker glu::getDataTypeMatrixNumColumns(entry.type)) :
627*35238bceSAndroid Build Coastguard Worker 1;
628*35238bceSAndroid Build Coastguard Worker int vecSize = scalarSize / numVecs;
629*35238bceSAndroid Build Coastguard Worker bool isArray = entry.size > 1;
630*35238bceSAndroid Build Coastguard Worker const int compSize = sizeof(uint32_t);
631*35238bceSAndroid Build Coastguard Worker
632*35238bceSAndroid Build Coastguard Worker DE_ASSERT(scalarSize % numVecs == 0);
633*35238bceSAndroid Build Coastguard Worker
634*35238bceSAndroid Build Coastguard Worker for (int elemNdx = 0; elemNdx < entry.size; elemNdx++)
635*35238bceSAndroid Build Coastguard Worker {
636*35238bceSAndroid Build Coastguard Worker uint8_t *elemPtr = (uint8_t *)basePtr + entry.offset + (isArray ? elemNdx * entry.arrayStride : 0);
637*35238bceSAndroid Build Coastguard Worker
638*35238bceSAndroid Build Coastguard Worker for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
639*35238bceSAndroid Build Coastguard Worker {
640*35238bceSAndroid Build Coastguard Worker uint8_t *vecPtr = elemPtr + (isMatrix ? vecNdx * entry.matrixStride : 0);
641*35238bceSAndroid Build Coastguard Worker
642*35238bceSAndroid Build Coastguard Worker for (int compNdx = 0; compNdx < vecSize; compNdx++)
643*35238bceSAndroid Build Coastguard Worker {
644*35238bceSAndroid Build Coastguard Worker uint8_t *compPtr = vecPtr + compSize * compNdx;
645*35238bceSAndroid Build Coastguard Worker
646*35238bceSAndroid Build Coastguard Worker switch (scalarType)
647*35238bceSAndroid Build Coastguard Worker {
648*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT:
649*35238bceSAndroid Build Coastguard Worker *((float *)compPtr) = (float)rnd.getInt(-9, 9);
650*35238bceSAndroid Build Coastguard Worker break;
651*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT:
652*35238bceSAndroid Build Coastguard Worker *((int *)compPtr) = rnd.getInt(-9, 9);
653*35238bceSAndroid Build Coastguard Worker break;
654*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT:
655*35238bceSAndroid Build Coastguard Worker *((uint32_t *)compPtr) = (uint32_t)rnd.getInt(0, 9);
656*35238bceSAndroid Build Coastguard Worker break;
657*35238bceSAndroid Build Coastguard Worker // \note Random bit pattern is used for true values. Spec states that all non-zero values are
658*35238bceSAndroid Build Coastguard Worker // interpreted as true but some implementations fail this.
659*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL:
660*35238bceSAndroid Build Coastguard Worker *((uint32_t *)compPtr) = rnd.getBool() ? rnd.getUint32() | 1u : 0u;
661*35238bceSAndroid Build Coastguard Worker break;
662*35238bceSAndroid Build Coastguard Worker default:
663*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
664*35238bceSAndroid Build Coastguard Worker }
665*35238bceSAndroid Build Coastguard Worker }
666*35238bceSAndroid Build Coastguard Worker }
667*35238bceSAndroid Build Coastguard Worker }
668*35238bceSAndroid Build Coastguard Worker }
669*35238bceSAndroid Build Coastguard Worker
generateValues(const UniformLayout & layout,const std::map<int,void * > & blockPointers,uint32_t seed)670*35238bceSAndroid Build Coastguard Worker void generateValues(const UniformLayout &layout, const std::map<int, void *> &blockPointers, uint32_t seed)
671*35238bceSAndroid Build Coastguard Worker {
672*35238bceSAndroid Build Coastguard Worker de::Random rnd(seed);
673*35238bceSAndroid Build Coastguard Worker int numBlocks = (int)layout.blocks.size();
674*35238bceSAndroid Build Coastguard Worker
675*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
676*35238bceSAndroid Build Coastguard Worker {
677*35238bceSAndroid Build Coastguard Worker void *basePtr = blockPointers.find(blockNdx)->second;
678*35238bceSAndroid Build Coastguard Worker int numEntries = (int)layout.blocks[blockNdx].activeUniformIndices.size();
679*35238bceSAndroid Build Coastguard Worker
680*35238bceSAndroid Build Coastguard Worker for (int entryNdx = 0; entryNdx < numEntries; entryNdx++)
681*35238bceSAndroid Build Coastguard Worker {
682*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &entry = layout.uniforms[layout.blocks[blockNdx].activeUniformIndices[entryNdx]];
683*35238bceSAndroid Build Coastguard Worker generateValue(entry, basePtr, rnd);
684*35238bceSAndroid Build Coastguard Worker }
685*35238bceSAndroid Build Coastguard Worker }
686*35238bceSAndroid Build Coastguard Worker }
687*35238bceSAndroid Build Coastguard Worker
688*35238bceSAndroid Build Coastguard Worker // Shader generator.
689*35238bceSAndroid Build Coastguard Worker
getCompareFuncForType(glu::DataType type)690*35238bceSAndroid Build Coastguard Worker const char *getCompareFuncForType(glu::DataType type)
691*35238bceSAndroid Build Coastguard Worker {
692*35238bceSAndroid Build Coastguard Worker switch (type)
693*35238bceSAndroid Build Coastguard Worker {
694*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT:
695*35238bceSAndroid Build Coastguard Worker return "mediump float compare_float (highp float a, highp float b) { return abs(a - b) < 0.05 ? 1.0 : 0.0; "
696*35238bceSAndroid Build Coastguard Worker "}\n";
697*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_VEC2:
698*35238bceSAndroid Build Coastguard Worker return "mediump float compare_vec2 (highp vec2 a, highp vec2 b) { return compare_float(a.x, "
699*35238bceSAndroid Build Coastguard Worker "b.x)*compare_float(a.y, b.y); }\n";
700*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_VEC3:
701*35238bceSAndroid Build Coastguard Worker return "mediump float compare_vec3 (highp vec3 a, highp vec3 b) { return compare_float(a.x, "
702*35238bceSAndroid Build Coastguard Worker "b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z); }\n";
703*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_VEC4:
704*35238bceSAndroid Build Coastguard Worker return "mediump float compare_vec4 (highp vec4 a, highp vec4 b) { return compare_float(a.x, "
705*35238bceSAndroid Build Coastguard Worker "b.x)*compare_float(a.y, b.y)*compare_float(a.z, b.z)*compare_float(a.w, b.w); }\n";
706*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT2:
707*35238bceSAndroid Build Coastguard Worker return "mediump float compare_mat2 (highp mat2 a, highp mat2 b) { return compare_vec2(a[0], "
708*35238bceSAndroid Build Coastguard Worker "b[0])*compare_vec2(a[1], b[1]); }\n";
709*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT2X3:
710*35238bceSAndroid Build Coastguard Worker return "mediump float compare_mat2x3 (highp mat2x3 a, highp mat2x3 b){ return compare_vec3(a[0], "
711*35238bceSAndroid Build Coastguard Worker "b[0])*compare_vec3(a[1], b[1]); }\n";
712*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT2X4:
713*35238bceSAndroid Build Coastguard Worker return "mediump float compare_mat2x4 (highp mat2x4 a, highp mat2x4 b){ return compare_vec4(a[0], "
714*35238bceSAndroid Build Coastguard Worker "b[0])*compare_vec4(a[1], b[1]); }\n";
715*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT3X2:
716*35238bceSAndroid Build Coastguard Worker return "mediump float compare_mat3x2 (highp mat3x2 a, highp mat3x2 b){ return compare_vec2(a[0], "
717*35238bceSAndroid Build Coastguard Worker "b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2]); }\n";
718*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT3:
719*35238bceSAndroid Build Coastguard Worker return "mediump float compare_mat3 (highp mat3 a, highp mat3 b) { return compare_vec3(a[0], "
720*35238bceSAndroid Build Coastguard Worker "b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2]); }\n";
721*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT3X4:
722*35238bceSAndroid Build Coastguard Worker return "mediump float compare_mat3x4 (highp mat3x4 a, highp mat3x4 b){ return compare_vec4(a[0], "
723*35238bceSAndroid Build Coastguard Worker "b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2]); }\n";
724*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT4X2:
725*35238bceSAndroid Build Coastguard Worker return "mediump float compare_mat4x2 (highp mat4x2 a, highp mat4x2 b){ return compare_vec2(a[0], "
726*35238bceSAndroid Build Coastguard Worker "b[0])*compare_vec2(a[1], b[1])*compare_vec2(a[2], b[2])*compare_vec2(a[3], b[3]); }\n";
727*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT4X3:
728*35238bceSAndroid Build Coastguard Worker return "mediump float compare_mat4x3 (highp mat4x3 a, highp mat4x3 b){ return compare_vec3(a[0], "
729*35238bceSAndroid Build Coastguard Worker "b[0])*compare_vec3(a[1], b[1])*compare_vec3(a[2], b[2])*compare_vec3(a[3], b[3]); }\n";
730*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT4:
731*35238bceSAndroid Build Coastguard Worker return "mediump float compare_mat4 (highp mat4 a, highp mat4 b) { return compare_vec4(a[0], "
732*35238bceSAndroid Build Coastguard Worker "b[0])*compare_vec4(a[1], b[1])*compare_vec4(a[2], b[2])*compare_vec4(a[3], b[3]); }\n";
733*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT:
734*35238bceSAndroid Build Coastguard Worker return "mediump float compare_int (highp int a, highp int b) { return a == b ? 1.0 : 0.0; }\n";
735*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT_VEC2:
736*35238bceSAndroid Build Coastguard Worker return "mediump float compare_ivec2 (highp ivec2 a, highp ivec2 b) { return a == b ? 1.0 : 0.0; }\n";
737*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT_VEC3:
738*35238bceSAndroid Build Coastguard Worker return "mediump float compare_ivec3 (highp ivec3 a, highp ivec3 b) { return a == b ? 1.0 : 0.0; }\n";
739*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT_VEC4:
740*35238bceSAndroid Build Coastguard Worker return "mediump float compare_ivec4 (highp ivec4 a, highp ivec4 b) { return a == b ? 1.0 : 0.0; }\n";
741*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT:
742*35238bceSAndroid Build Coastguard Worker return "mediump float compare_uint (highp uint a, highp uint b) { return a == b ? 1.0 : 0.0; }\n";
743*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT_VEC2:
744*35238bceSAndroid Build Coastguard Worker return "mediump float compare_uvec2 (highp uvec2 a, highp uvec2 b) { return a == b ? 1.0 : 0.0; }\n";
745*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT_VEC3:
746*35238bceSAndroid Build Coastguard Worker return "mediump float compare_uvec3 (highp uvec3 a, highp uvec3 b) { return a == b ? 1.0 : 0.0; }\n";
747*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT_VEC4:
748*35238bceSAndroid Build Coastguard Worker return "mediump float compare_uvec4 (highp uvec4 a, highp uvec4 b) { return a == b ? 1.0 : 0.0; }\n";
749*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL:
750*35238bceSAndroid Build Coastguard Worker return "mediump float compare_bool (bool a, bool b) { return a == b ? 1.0 : 0.0; }\n";
751*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL_VEC2:
752*35238bceSAndroid Build Coastguard Worker return "mediump float compare_bvec2 (bvec2 a, bvec2 b) { return a == b ? 1.0 : 0.0; }\n";
753*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL_VEC3:
754*35238bceSAndroid Build Coastguard Worker return "mediump float compare_bvec3 (bvec3 a, bvec3 b) { return a == b ? 1.0 : 0.0; }\n";
755*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL_VEC4:
756*35238bceSAndroid Build Coastguard Worker return "mediump float compare_bvec4 (bvec4 a, bvec4 b) { return a == b ? 1.0 : 0.0; }\n";
757*35238bceSAndroid Build Coastguard Worker default:
758*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
759*35238bceSAndroid Build Coastguard Worker return DE_NULL;
760*35238bceSAndroid Build Coastguard Worker }
761*35238bceSAndroid Build Coastguard Worker }
762*35238bceSAndroid Build Coastguard Worker
getCompareDependencies(std::set<glu::DataType> & compareFuncs,glu::DataType basicType)763*35238bceSAndroid Build Coastguard Worker void getCompareDependencies(std::set<glu::DataType> &compareFuncs, glu::DataType basicType)
764*35238bceSAndroid Build Coastguard Worker {
765*35238bceSAndroid Build Coastguard Worker switch (basicType)
766*35238bceSAndroid Build Coastguard Worker {
767*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_VEC2:
768*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_VEC3:
769*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_VEC4:
770*35238bceSAndroid Build Coastguard Worker compareFuncs.insert(glu::TYPE_FLOAT);
771*35238bceSAndroid Build Coastguard Worker compareFuncs.insert(basicType);
772*35238bceSAndroid Build Coastguard Worker break;
773*35238bceSAndroid Build Coastguard Worker
774*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT2:
775*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT2X3:
776*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT2X4:
777*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT3X2:
778*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT3:
779*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT3X4:
780*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT4X2:
781*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT4X3:
782*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT_MAT4:
783*35238bceSAndroid Build Coastguard Worker compareFuncs.insert(glu::TYPE_FLOAT);
784*35238bceSAndroid Build Coastguard Worker compareFuncs.insert(glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType)));
785*35238bceSAndroid Build Coastguard Worker compareFuncs.insert(basicType);
786*35238bceSAndroid Build Coastguard Worker break;
787*35238bceSAndroid Build Coastguard Worker
788*35238bceSAndroid Build Coastguard Worker default:
789*35238bceSAndroid Build Coastguard Worker compareFuncs.insert(basicType);
790*35238bceSAndroid Build Coastguard Worker break;
791*35238bceSAndroid Build Coastguard Worker }
792*35238bceSAndroid Build Coastguard Worker }
793*35238bceSAndroid Build Coastguard Worker
collectUniqueBasicTypes(std::set<glu::DataType> & basicTypes,const VarType & type)794*35238bceSAndroid Build Coastguard Worker void collectUniqueBasicTypes(std::set<glu::DataType> &basicTypes, const VarType &type)
795*35238bceSAndroid Build Coastguard Worker {
796*35238bceSAndroid Build Coastguard Worker if (type.isStructType())
797*35238bceSAndroid Build Coastguard Worker {
798*35238bceSAndroid Build Coastguard Worker for (StructType::ConstIterator iter = type.getStruct().begin(); iter != type.getStruct().end(); ++iter)
799*35238bceSAndroid Build Coastguard Worker collectUniqueBasicTypes(basicTypes, iter->getType());
800*35238bceSAndroid Build Coastguard Worker }
801*35238bceSAndroid Build Coastguard Worker else if (type.isArrayType())
802*35238bceSAndroid Build Coastguard Worker collectUniqueBasicTypes(basicTypes, type.getElementType());
803*35238bceSAndroid Build Coastguard Worker else
804*35238bceSAndroid Build Coastguard Worker {
805*35238bceSAndroid Build Coastguard Worker DE_ASSERT(type.isBasicType());
806*35238bceSAndroid Build Coastguard Worker basicTypes.insert(type.getBasicType());
807*35238bceSAndroid Build Coastguard Worker }
808*35238bceSAndroid Build Coastguard Worker }
809*35238bceSAndroid Build Coastguard Worker
collectUniqueBasicTypes(std::set<glu::DataType> & basicTypes,const UniformBlock & uniformBlock)810*35238bceSAndroid Build Coastguard Worker void collectUniqueBasicTypes(std::set<glu::DataType> &basicTypes, const UniformBlock &uniformBlock)
811*35238bceSAndroid Build Coastguard Worker {
812*35238bceSAndroid Build Coastguard Worker for (UniformBlock::ConstIterator iter = uniformBlock.begin(); iter != uniformBlock.end(); ++iter)
813*35238bceSAndroid Build Coastguard Worker collectUniqueBasicTypes(basicTypes, iter->getType());
814*35238bceSAndroid Build Coastguard Worker }
815*35238bceSAndroid Build Coastguard Worker
collectUniqueBasicTypes(std::set<glu::DataType> & basicTypes,const ShaderInterface & interface)816*35238bceSAndroid Build Coastguard Worker void collectUniqueBasicTypes(std::set<glu::DataType> &basicTypes, const ShaderInterface &interface)
817*35238bceSAndroid Build Coastguard Worker {
818*35238bceSAndroid Build Coastguard Worker for (int ndx = 0; ndx < interface.getNumUniformBlocks(); ++ndx)
819*35238bceSAndroid Build Coastguard Worker collectUniqueBasicTypes(basicTypes, interface.getUniformBlock(ndx));
820*35238bceSAndroid Build Coastguard Worker }
821*35238bceSAndroid Build Coastguard Worker
generateCompareFuncs(std::ostream & str,const ShaderInterface & interface)822*35238bceSAndroid Build Coastguard Worker void generateCompareFuncs(std::ostream &str, const ShaderInterface &interface)
823*35238bceSAndroid Build Coastguard Worker {
824*35238bceSAndroid Build Coastguard Worker std::set<glu::DataType> types;
825*35238bceSAndroid Build Coastguard Worker std::set<glu::DataType> compareFuncs;
826*35238bceSAndroid Build Coastguard Worker
827*35238bceSAndroid Build Coastguard Worker // Collect unique basic types
828*35238bceSAndroid Build Coastguard Worker collectUniqueBasicTypes(types, interface);
829*35238bceSAndroid Build Coastguard Worker
830*35238bceSAndroid Build Coastguard Worker // Set of compare functions required
831*35238bceSAndroid Build Coastguard Worker for (std::set<glu::DataType>::const_iterator iter = types.begin(); iter != types.end(); ++iter)
832*35238bceSAndroid Build Coastguard Worker {
833*35238bceSAndroid Build Coastguard Worker getCompareDependencies(compareFuncs, *iter);
834*35238bceSAndroid Build Coastguard Worker }
835*35238bceSAndroid Build Coastguard Worker
836*35238bceSAndroid Build Coastguard Worker for (int type = 0; type < glu::TYPE_LAST; ++type)
837*35238bceSAndroid Build Coastguard Worker {
838*35238bceSAndroid Build Coastguard Worker if (compareFuncs.find(glu::DataType(type)) != compareFuncs.end())
839*35238bceSAndroid Build Coastguard Worker str << getCompareFuncForType(glu::DataType(type));
840*35238bceSAndroid Build Coastguard Worker }
841*35238bceSAndroid Build Coastguard Worker }
842*35238bceSAndroid Build Coastguard Worker
843*35238bceSAndroid Build Coastguard Worker struct Indent
844*35238bceSAndroid Build Coastguard Worker {
845*35238bceSAndroid Build Coastguard Worker int level;
Indentdeqp::gls::ub::__anon82a1c7ff0211::Indent846*35238bceSAndroid Build Coastguard Worker Indent(int level_) : level(level_)
847*35238bceSAndroid Build Coastguard Worker {
848*35238bceSAndroid Build Coastguard Worker }
849*35238bceSAndroid Build Coastguard Worker };
850*35238bceSAndroid Build Coastguard Worker
operator <<(std::ostream & str,const Indent & indent)851*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const Indent &indent)
852*35238bceSAndroid Build Coastguard Worker {
853*35238bceSAndroid Build Coastguard Worker for (int i = 0; i < indent.level; i++)
854*35238bceSAndroid Build Coastguard Worker str << "\t";
855*35238bceSAndroid Build Coastguard Worker return str;
856*35238bceSAndroid Build Coastguard Worker }
857*35238bceSAndroid Build Coastguard Worker
858*35238bceSAndroid Build Coastguard Worker void generateDeclaration(std::ostringstream &src, const VarType &type, const char *name, int indentLevel,
859*35238bceSAndroid Build Coastguard Worker uint32_t unusedHints);
860*35238bceSAndroid Build Coastguard Worker void generateDeclaration(std::ostringstream &src, const Uniform &uniform, int indentLevel);
861*35238bceSAndroid Build Coastguard Worker void generateDeclaration(std::ostringstream &src, const StructType &structType, int indentLevel);
862*35238bceSAndroid Build Coastguard Worker
863*35238bceSAndroid Build Coastguard Worker void generateLocalDeclaration(std::ostringstream &src, const StructType &structType, int indentLevel);
864*35238bceSAndroid Build Coastguard Worker void generateFullDeclaration(std::ostringstream &src, const StructType &structType, int indentLevel);
865*35238bceSAndroid Build Coastguard Worker
generateDeclaration(std::ostringstream & src,const StructType & structType,int indentLevel)866*35238bceSAndroid Build Coastguard Worker void generateDeclaration(std::ostringstream &src, const StructType &structType, int indentLevel)
867*35238bceSAndroid Build Coastguard Worker {
868*35238bceSAndroid Build Coastguard Worker DE_ASSERT(structType.getTypeName() != DE_NULL);
869*35238bceSAndroid Build Coastguard Worker generateFullDeclaration(src, structType, indentLevel);
870*35238bceSAndroid Build Coastguard Worker src << ";\n";
871*35238bceSAndroid Build Coastguard Worker }
872*35238bceSAndroid Build Coastguard Worker
generateFullDeclaration(std::ostringstream & src,const StructType & structType,int indentLevel)873*35238bceSAndroid Build Coastguard Worker void generateFullDeclaration(std::ostringstream &src, const StructType &structType, int indentLevel)
874*35238bceSAndroid Build Coastguard Worker {
875*35238bceSAndroid Build Coastguard Worker src << "struct";
876*35238bceSAndroid Build Coastguard Worker if (structType.getTypeName())
877*35238bceSAndroid Build Coastguard Worker src << " " << structType.getTypeName();
878*35238bceSAndroid Build Coastguard Worker src << "\n" << Indent(indentLevel) << "{\n";
879*35238bceSAndroid Build Coastguard Worker
880*35238bceSAndroid Build Coastguard Worker for (StructType::ConstIterator memberIter = structType.begin(); memberIter != structType.end(); memberIter++)
881*35238bceSAndroid Build Coastguard Worker {
882*35238bceSAndroid Build Coastguard Worker src << Indent(indentLevel + 1);
883*35238bceSAndroid Build Coastguard Worker generateDeclaration(src, memberIter->getType(), memberIter->getName(), indentLevel + 1,
884*35238bceSAndroid Build Coastguard Worker memberIter->getFlags() & UNUSED_BOTH);
885*35238bceSAndroid Build Coastguard Worker }
886*35238bceSAndroid Build Coastguard Worker
887*35238bceSAndroid Build Coastguard Worker src << Indent(indentLevel) << "}";
888*35238bceSAndroid Build Coastguard Worker }
889*35238bceSAndroid Build Coastguard Worker
generateLocalDeclaration(std::ostringstream & src,const StructType & structType,int indentLevel)890*35238bceSAndroid Build Coastguard Worker void generateLocalDeclaration(std::ostringstream &src, const StructType &structType, int indentLevel)
891*35238bceSAndroid Build Coastguard Worker {
892*35238bceSAndroid Build Coastguard Worker if (structType.getTypeName() == DE_NULL)
893*35238bceSAndroid Build Coastguard Worker generateFullDeclaration(src, structType, indentLevel);
894*35238bceSAndroid Build Coastguard Worker else
895*35238bceSAndroid Build Coastguard Worker src << structType.getTypeName();
896*35238bceSAndroid Build Coastguard Worker }
897*35238bceSAndroid Build Coastguard Worker
generateDeclaration(std::ostringstream & src,const VarType & type,const char * name,int indentLevel,uint32_t unusedHints)898*35238bceSAndroid Build Coastguard Worker void generateDeclaration(std::ostringstream &src, const VarType &type, const char *name, int indentLevel,
899*35238bceSAndroid Build Coastguard Worker uint32_t unusedHints)
900*35238bceSAndroid Build Coastguard Worker {
901*35238bceSAndroid Build Coastguard Worker uint32_t flags = type.getFlags();
902*35238bceSAndroid Build Coastguard Worker
903*35238bceSAndroid Build Coastguard Worker if ((flags & LAYOUT_MASK) != 0)
904*35238bceSAndroid Build Coastguard Worker src << "layout(" << LayoutFlagsFmt(flags & LAYOUT_MASK) << ") ";
905*35238bceSAndroid Build Coastguard Worker
906*35238bceSAndroid Build Coastguard Worker if ((flags & PRECISION_MASK) != 0)
907*35238bceSAndroid Build Coastguard Worker src << PrecisionFlagsFmt(flags & PRECISION_MASK) << " ";
908*35238bceSAndroid Build Coastguard Worker
909*35238bceSAndroid Build Coastguard Worker if (type.isBasicType())
910*35238bceSAndroid Build Coastguard Worker src << glu::getDataTypeName(type.getBasicType()) << " " << name;
911*35238bceSAndroid Build Coastguard Worker else if (type.isArrayType())
912*35238bceSAndroid Build Coastguard Worker {
913*35238bceSAndroid Build Coastguard Worker std::vector<int> arraySizes;
914*35238bceSAndroid Build Coastguard Worker const VarType *curType = &type;
915*35238bceSAndroid Build Coastguard Worker while (curType->isArrayType())
916*35238bceSAndroid Build Coastguard Worker {
917*35238bceSAndroid Build Coastguard Worker arraySizes.push_back(curType->getArraySize());
918*35238bceSAndroid Build Coastguard Worker curType = &curType->getElementType();
919*35238bceSAndroid Build Coastguard Worker }
920*35238bceSAndroid Build Coastguard Worker
921*35238bceSAndroid Build Coastguard Worker if (curType->isBasicType())
922*35238bceSAndroid Build Coastguard Worker {
923*35238bceSAndroid Build Coastguard Worker if ((curType->getFlags() & LAYOUT_MASK) != 0)
924*35238bceSAndroid Build Coastguard Worker src << "layout(" << LayoutFlagsFmt(curType->getFlags() & LAYOUT_MASK) << ") ";
925*35238bceSAndroid Build Coastguard Worker if ((curType->getFlags() & PRECISION_MASK) != 0)
926*35238bceSAndroid Build Coastguard Worker src << PrecisionFlagsFmt(curType->getFlags() & PRECISION_MASK) << " ";
927*35238bceSAndroid Build Coastguard Worker src << glu::getDataTypeName(curType->getBasicType());
928*35238bceSAndroid Build Coastguard Worker }
929*35238bceSAndroid Build Coastguard Worker else
930*35238bceSAndroid Build Coastguard Worker {
931*35238bceSAndroid Build Coastguard Worker DE_ASSERT(curType->isStructType());
932*35238bceSAndroid Build Coastguard Worker generateLocalDeclaration(src, curType->getStruct(), indentLevel + 1);
933*35238bceSAndroid Build Coastguard Worker }
934*35238bceSAndroid Build Coastguard Worker
935*35238bceSAndroid Build Coastguard Worker src << " " << name;
936*35238bceSAndroid Build Coastguard Worker
937*35238bceSAndroid Build Coastguard Worker for (std::vector<int>::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++)
938*35238bceSAndroid Build Coastguard Worker src << "[" << *sizeIter << "]";
939*35238bceSAndroid Build Coastguard Worker }
940*35238bceSAndroid Build Coastguard Worker else
941*35238bceSAndroid Build Coastguard Worker {
942*35238bceSAndroid Build Coastguard Worker generateLocalDeclaration(src, type.getStruct(), indentLevel + 1);
943*35238bceSAndroid Build Coastguard Worker src << " " << name;
944*35238bceSAndroid Build Coastguard Worker }
945*35238bceSAndroid Build Coastguard Worker
946*35238bceSAndroid Build Coastguard Worker src << ";";
947*35238bceSAndroid Build Coastguard Worker
948*35238bceSAndroid Build Coastguard Worker // Print out unused hints.
949*35238bceSAndroid Build Coastguard Worker if (unusedHints != 0)
950*35238bceSAndroid Build Coastguard Worker src << " // unused in "
951*35238bceSAndroid Build Coastguard Worker << (unusedHints == UNUSED_BOTH ? "both shaders" :
952*35238bceSAndroid Build Coastguard Worker unusedHints == UNUSED_VERTEX ? "vertex shader" :
953*35238bceSAndroid Build Coastguard Worker unusedHints == UNUSED_FRAGMENT ? "fragment shader" :
954*35238bceSAndroid Build Coastguard Worker "???");
955*35238bceSAndroid Build Coastguard Worker
956*35238bceSAndroid Build Coastguard Worker src << "\n";
957*35238bceSAndroid Build Coastguard Worker }
958*35238bceSAndroid Build Coastguard Worker
generateDeclaration(std::ostringstream & src,const Uniform & uniform,int indentLevel)959*35238bceSAndroid Build Coastguard Worker void generateDeclaration(std::ostringstream &src, const Uniform &uniform, int indentLevel)
960*35238bceSAndroid Build Coastguard Worker {
961*35238bceSAndroid Build Coastguard Worker if ((uniform.getFlags() & LAYOUT_MASK) != 0)
962*35238bceSAndroid Build Coastguard Worker src << "layout(" << LayoutFlagsFmt(uniform.getFlags() & LAYOUT_MASK) << ") ";
963*35238bceSAndroid Build Coastguard Worker
964*35238bceSAndroid Build Coastguard Worker generateDeclaration(src, uniform.getType(), uniform.getName(), indentLevel, uniform.getFlags() & UNUSED_BOTH);
965*35238bceSAndroid Build Coastguard Worker }
966*35238bceSAndroid Build Coastguard Worker
generateDeclaration(std::ostringstream & src,const UniformBlock & block)967*35238bceSAndroid Build Coastguard Worker void generateDeclaration(std::ostringstream &src, const UniformBlock &block)
968*35238bceSAndroid Build Coastguard Worker {
969*35238bceSAndroid Build Coastguard Worker if ((block.getFlags() & LAYOUT_MASK) != 0)
970*35238bceSAndroid Build Coastguard Worker src << "layout(" << LayoutFlagsFmt(block.getFlags() & LAYOUT_MASK) << ") ";
971*35238bceSAndroid Build Coastguard Worker
972*35238bceSAndroid Build Coastguard Worker src << "uniform " << block.getBlockName();
973*35238bceSAndroid Build Coastguard Worker src << "\n{\n";
974*35238bceSAndroid Build Coastguard Worker
975*35238bceSAndroid Build Coastguard Worker for (UniformBlock::ConstIterator uniformIter = block.begin(); uniformIter != block.end(); uniformIter++)
976*35238bceSAndroid Build Coastguard Worker {
977*35238bceSAndroid Build Coastguard Worker src << Indent(1);
978*35238bceSAndroid Build Coastguard Worker generateDeclaration(src, *uniformIter, 1 /* indent level */);
979*35238bceSAndroid Build Coastguard Worker }
980*35238bceSAndroid Build Coastguard Worker
981*35238bceSAndroid Build Coastguard Worker src << "}";
982*35238bceSAndroid Build Coastguard Worker
983*35238bceSAndroid Build Coastguard Worker if (block.getInstanceName() != DE_NULL)
984*35238bceSAndroid Build Coastguard Worker {
985*35238bceSAndroid Build Coastguard Worker src << " " << block.getInstanceName();
986*35238bceSAndroid Build Coastguard Worker if (block.isArray())
987*35238bceSAndroid Build Coastguard Worker src << "[" << block.getArraySize() << "]";
988*35238bceSAndroid Build Coastguard Worker }
989*35238bceSAndroid Build Coastguard Worker else
990*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!block.isArray());
991*35238bceSAndroid Build Coastguard Worker
992*35238bceSAndroid Build Coastguard Worker src << ";\n";
993*35238bceSAndroid Build Coastguard Worker }
994*35238bceSAndroid Build Coastguard Worker
generateValueSrc(std::ostringstream & src,const UniformLayoutEntry & entry,const void * basePtr,int elementNdx)995*35238bceSAndroid Build Coastguard Worker void generateValueSrc(std::ostringstream &src, const UniformLayoutEntry &entry, const void *basePtr, int elementNdx)
996*35238bceSAndroid Build Coastguard Worker {
997*35238bceSAndroid Build Coastguard Worker glu::DataType scalarType = glu::getDataTypeScalarType(entry.type);
998*35238bceSAndroid Build Coastguard Worker int scalarSize = glu::getDataTypeScalarSize(entry.type);
999*35238bceSAndroid Build Coastguard Worker bool isArray = entry.size > 1;
1000*35238bceSAndroid Build Coastguard Worker const uint8_t *elemPtr = (const uint8_t *)basePtr + entry.offset + (isArray ? elementNdx * entry.arrayStride : 0);
1001*35238bceSAndroid Build Coastguard Worker const int compSize = sizeof(uint32_t);
1002*35238bceSAndroid Build Coastguard Worker
1003*35238bceSAndroid Build Coastguard Worker if (scalarSize > 1)
1004*35238bceSAndroid Build Coastguard Worker src << glu::getDataTypeName(entry.type) << "(";
1005*35238bceSAndroid Build Coastguard Worker
1006*35238bceSAndroid Build Coastguard Worker if (glu::isDataTypeMatrix(entry.type))
1007*35238bceSAndroid Build Coastguard Worker {
1008*35238bceSAndroid Build Coastguard Worker int numRows = glu::getDataTypeMatrixNumRows(entry.type);
1009*35238bceSAndroid Build Coastguard Worker int numCols = glu::getDataTypeMatrixNumColumns(entry.type);
1010*35238bceSAndroid Build Coastguard Worker
1011*35238bceSAndroid Build Coastguard Worker DE_ASSERT(scalarType == glu::TYPE_FLOAT);
1012*35238bceSAndroid Build Coastguard Worker
1013*35238bceSAndroid Build Coastguard Worker // Constructed in column-wise order.
1014*35238bceSAndroid Build Coastguard Worker for (int colNdx = 0; colNdx < numCols; colNdx++)
1015*35238bceSAndroid Build Coastguard Worker {
1016*35238bceSAndroid Build Coastguard Worker for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
1017*35238bceSAndroid Build Coastguard Worker {
1018*35238bceSAndroid Build Coastguard Worker const uint8_t *compPtr = elemPtr + (entry.isRowMajor ? rowNdx * entry.matrixStride + colNdx * compSize :
1019*35238bceSAndroid Build Coastguard Worker colNdx * entry.matrixStride + rowNdx * compSize);
1020*35238bceSAndroid Build Coastguard Worker
1021*35238bceSAndroid Build Coastguard Worker if (colNdx > 0 || rowNdx > 0)
1022*35238bceSAndroid Build Coastguard Worker src << ", ";
1023*35238bceSAndroid Build Coastguard Worker
1024*35238bceSAndroid Build Coastguard Worker src << de::floatToString(*((const float *)compPtr), 1);
1025*35238bceSAndroid Build Coastguard Worker }
1026*35238bceSAndroid Build Coastguard Worker }
1027*35238bceSAndroid Build Coastguard Worker }
1028*35238bceSAndroid Build Coastguard Worker else
1029*35238bceSAndroid Build Coastguard Worker {
1030*35238bceSAndroid Build Coastguard Worker for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
1031*35238bceSAndroid Build Coastguard Worker {
1032*35238bceSAndroid Build Coastguard Worker const uint8_t *compPtr = elemPtr + scalarNdx * compSize;
1033*35238bceSAndroid Build Coastguard Worker
1034*35238bceSAndroid Build Coastguard Worker if (scalarNdx > 0)
1035*35238bceSAndroid Build Coastguard Worker src << ", ";
1036*35238bceSAndroid Build Coastguard Worker
1037*35238bceSAndroid Build Coastguard Worker switch (scalarType)
1038*35238bceSAndroid Build Coastguard Worker {
1039*35238bceSAndroid Build Coastguard Worker case glu::TYPE_FLOAT:
1040*35238bceSAndroid Build Coastguard Worker src << de::floatToString(*((const float *)compPtr), 1);
1041*35238bceSAndroid Build Coastguard Worker break;
1042*35238bceSAndroid Build Coastguard Worker case glu::TYPE_INT:
1043*35238bceSAndroid Build Coastguard Worker src << *((const int *)compPtr);
1044*35238bceSAndroid Build Coastguard Worker break;
1045*35238bceSAndroid Build Coastguard Worker case glu::TYPE_UINT:
1046*35238bceSAndroid Build Coastguard Worker src << *((const uint32_t *)compPtr) << "u";
1047*35238bceSAndroid Build Coastguard Worker break;
1048*35238bceSAndroid Build Coastguard Worker case glu::TYPE_BOOL:
1049*35238bceSAndroid Build Coastguard Worker src << (*((const uint32_t *)compPtr) != 0u ? "true" : "false");
1050*35238bceSAndroid Build Coastguard Worker break;
1051*35238bceSAndroid Build Coastguard Worker default:
1052*35238bceSAndroid Build Coastguard Worker DE_ASSERT(false);
1053*35238bceSAndroid Build Coastguard Worker }
1054*35238bceSAndroid Build Coastguard Worker }
1055*35238bceSAndroid Build Coastguard Worker }
1056*35238bceSAndroid Build Coastguard Worker
1057*35238bceSAndroid Build Coastguard Worker if (scalarSize > 1)
1058*35238bceSAndroid Build Coastguard Worker src << ")";
1059*35238bceSAndroid Build Coastguard Worker }
1060*35238bceSAndroid Build Coastguard Worker
generateCompareSrc(std::ostringstream & src,const char * resultVar,const VarType & type,const char * srcName,const char * apiName,const UniformLayout & layout,const void * basePtr,uint32_t unusedMask)1061*35238bceSAndroid Build Coastguard Worker void generateCompareSrc(std::ostringstream &src, const char *resultVar, const VarType &type, const char *srcName,
1062*35238bceSAndroid Build Coastguard Worker const char *apiName, const UniformLayout &layout, const void *basePtr, uint32_t unusedMask)
1063*35238bceSAndroid Build Coastguard Worker {
1064*35238bceSAndroid Build Coastguard Worker if (type.isBasicType() || (type.isArrayType() && type.getElementType().isBasicType()))
1065*35238bceSAndroid Build Coastguard Worker {
1066*35238bceSAndroid Build Coastguard Worker // Basic type or array of basic types.
1067*35238bceSAndroid Build Coastguard Worker bool isArray = type.isArrayType();
1068*35238bceSAndroid Build Coastguard Worker glu::DataType elementType = isArray ? type.getElementType().getBasicType() : type.getBasicType();
1069*35238bceSAndroid Build Coastguard Worker const char *typeName = glu::getDataTypeName(elementType);
1070*35238bceSAndroid Build Coastguard Worker std::string fullApiName = string(apiName) + (isArray ? "[0]" : ""); // Arrays are always postfixed with [0]
1071*35238bceSAndroid Build Coastguard Worker int uniformNdx = layout.getUniformIndex(fullApiName.c_str());
1072*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &entry = layout.uniforms[uniformNdx];
1073*35238bceSAndroid Build Coastguard Worker
1074*35238bceSAndroid Build Coastguard Worker if (isArray)
1075*35238bceSAndroid Build Coastguard Worker {
1076*35238bceSAndroid Build Coastguard Worker for (int elemNdx = 0; elemNdx < type.getArraySize(); elemNdx++)
1077*35238bceSAndroid Build Coastguard Worker {
1078*35238bceSAndroid Build Coastguard Worker src << "\tresult *= compare_" << typeName << "(" << srcName << "[" << elemNdx << "], ";
1079*35238bceSAndroid Build Coastguard Worker generateValueSrc(src, entry, basePtr, elemNdx);
1080*35238bceSAndroid Build Coastguard Worker src << ");\n";
1081*35238bceSAndroid Build Coastguard Worker }
1082*35238bceSAndroid Build Coastguard Worker }
1083*35238bceSAndroid Build Coastguard Worker else
1084*35238bceSAndroid Build Coastguard Worker {
1085*35238bceSAndroid Build Coastguard Worker src << "\tresult *= compare_" << typeName << "(" << srcName << ", ";
1086*35238bceSAndroid Build Coastguard Worker generateValueSrc(src, entry, basePtr, 0);
1087*35238bceSAndroid Build Coastguard Worker src << ");\n";
1088*35238bceSAndroid Build Coastguard Worker }
1089*35238bceSAndroid Build Coastguard Worker }
1090*35238bceSAndroid Build Coastguard Worker else if (type.isArrayType())
1091*35238bceSAndroid Build Coastguard Worker {
1092*35238bceSAndroid Build Coastguard Worker const VarType &elementType = type.getElementType();
1093*35238bceSAndroid Build Coastguard Worker
1094*35238bceSAndroid Build Coastguard Worker for (int elementNdx = 0; elementNdx < type.getArraySize(); elementNdx++)
1095*35238bceSAndroid Build Coastguard Worker {
1096*35238bceSAndroid Build Coastguard Worker std::string op = string("[") + de::toString(elementNdx) + "]";
1097*35238bceSAndroid Build Coastguard Worker generateCompareSrc(src, resultVar, elementType, (string(srcName) + op).c_str(),
1098*35238bceSAndroid Build Coastguard Worker (string(apiName) + op).c_str(), layout, basePtr, unusedMask);
1099*35238bceSAndroid Build Coastguard Worker }
1100*35238bceSAndroid Build Coastguard Worker }
1101*35238bceSAndroid Build Coastguard Worker else
1102*35238bceSAndroid Build Coastguard Worker {
1103*35238bceSAndroid Build Coastguard Worker DE_ASSERT(type.isStructType());
1104*35238bceSAndroid Build Coastguard Worker
1105*35238bceSAndroid Build Coastguard Worker for (StructType::ConstIterator memberIter = type.getStruct().begin(); memberIter != type.getStruct().end();
1106*35238bceSAndroid Build Coastguard Worker memberIter++)
1107*35238bceSAndroid Build Coastguard Worker {
1108*35238bceSAndroid Build Coastguard Worker if (memberIter->getFlags() & unusedMask)
1109*35238bceSAndroid Build Coastguard Worker continue; // Skip member.
1110*35238bceSAndroid Build Coastguard Worker
1111*35238bceSAndroid Build Coastguard Worker string op = string(".") + memberIter->getName();
1112*35238bceSAndroid Build Coastguard Worker generateCompareSrc(src, resultVar, memberIter->getType(), (string(srcName) + op).c_str(),
1113*35238bceSAndroid Build Coastguard Worker (string(apiName) + op).c_str(), layout, basePtr, unusedMask);
1114*35238bceSAndroid Build Coastguard Worker }
1115*35238bceSAndroid Build Coastguard Worker }
1116*35238bceSAndroid Build Coastguard Worker }
1117*35238bceSAndroid Build Coastguard Worker
generateCompareSrc(std::ostringstream & src,const char * resultVar,const ShaderInterface & interface,const UniformLayout & layout,const std::map<int,void * > & blockPointers,bool isVertex)1118*35238bceSAndroid Build Coastguard Worker void generateCompareSrc(std::ostringstream &src, const char *resultVar, const ShaderInterface &interface,
1119*35238bceSAndroid Build Coastguard Worker const UniformLayout &layout, const std::map<int, void *> &blockPointers, bool isVertex)
1120*35238bceSAndroid Build Coastguard Worker {
1121*35238bceSAndroid Build Coastguard Worker uint32_t unusedMask = isVertex ? UNUSED_VERTEX : UNUSED_FRAGMENT;
1122*35238bceSAndroid Build Coastguard Worker
1123*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
1124*35238bceSAndroid Build Coastguard Worker {
1125*35238bceSAndroid Build Coastguard Worker const UniformBlock &block = interface.getUniformBlock(blockNdx);
1126*35238bceSAndroid Build Coastguard Worker
1127*35238bceSAndroid Build Coastguard Worker if ((block.getFlags() & (isVertex ? DECLARE_VERTEX : DECLARE_FRAGMENT)) == 0)
1128*35238bceSAndroid Build Coastguard Worker continue; // Skip.
1129*35238bceSAndroid Build Coastguard Worker
1130*35238bceSAndroid Build Coastguard Worker bool hasInstanceName = block.getInstanceName() != DE_NULL;
1131*35238bceSAndroid Build Coastguard Worker bool isArray = block.isArray();
1132*35238bceSAndroid Build Coastguard Worker int numInstances = isArray ? block.getArraySize() : 1;
1133*35238bceSAndroid Build Coastguard Worker std::string apiPrefix = hasInstanceName ? string(block.getBlockName()) + "." : string("");
1134*35238bceSAndroid Build Coastguard Worker
1135*35238bceSAndroid Build Coastguard Worker DE_ASSERT(!isArray || hasInstanceName);
1136*35238bceSAndroid Build Coastguard Worker
1137*35238bceSAndroid Build Coastguard Worker for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
1138*35238bceSAndroid Build Coastguard Worker {
1139*35238bceSAndroid Build Coastguard Worker std::string instancePostfix = isArray ? string("[") + de::toString(instanceNdx) + "]" : string("");
1140*35238bceSAndroid Build Coastguard Worker std::string blockInstanceName = block.getBlockName() + instancePostfix;
1141*35238bceSAndroid Build Coastguard Worker std::string srcPrefix =
1142*35238bceSAndroid Build Coastguard Worker hasInstanceName ? string(block.getInstanceName()) + instancePostfix + "." : string("");
1143*35238bceSAndroid Build Coastguard Worker int activeBlockNdx = layout.getBlockIndex(blockInstanceName.c_str());
1144*35238bceSAndroid Build Coastguard Worker void *basePtr = blockPointers.find(activeBlockNdx)->second;
1145*35238bceSAndroid Build Coastguard Worker
1146*35238bceSAndroid Build Coastguard Worker for (UniformBlock::ConstIterator uniformIter = block.begin(); uniformIter != block.end(); uniformIter++)
1147*35238bceSAndroid Build Coastguard Worker {
1148*35238bceSAndroid Build Coastguard Worker const Uniform &uniform = *uniformIter;
1149*35238bceSAndroid Build Coastguard Worker
1150*35238bceSAndroid Build Coastguard Worker if (uniform.getFlags() & unusedMask)
1151*35238bceSAndroid Build Coastguard Worker continue; // Don't read from that uniform.
1152*35238bceSAndroid Build Coastguard Worker
1153*35238bceSAndroid Build Coastguard Worker generateCompareSrc(src, resultVar, uniform.getType(), (srcPrefix + uniform.getName()).c_str(),
1154*35238bceSAndroid Build Coastguard Worker (apiPrefix + uniform.getName()).c_str(), layout, basePtr, unusedMask);
1155*35238bceSAndroid Build Coastguard Worker }
1156*35238bceSAndroid Build Coastguard Worker }
1157*35238bceSAndroid Build Coastguard Worker }
1158*35238bceSAndroid Build Coastguard Worker }
1159*35238bceSAndroid Build Coastguard Worker
generateVertexShader(std::ostringstream & src,glu::GLSLVersion glslVersion,const ShaderInterface & interface,const UniformLayout & layout,const std::map<int,void * > & blockPointers)1160*35238bceSAndroid Build Coastguard Worker void generateVertexShader(std::ostringstream &src, glu::GLSLVersion glslVersion, const ShaderInterface &interface,
1161*35238bceSAndroid Build Coastguard Worker const UniformLayout &layout, const std::map<int, void *> &blockPointers)
1162*35238bceSAndroid Build Coastguard Worker {
1163*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSupportedGLSLVersion(glslVersion));
1164*35238bceSAndroid Build Coastguard Worker
1165*35238bceSAndroid Build Coastguard Worker src << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
1166*35238bceSAndroid Build Coastguard Worker src << "in highp vec4 a_position;\n";
1167*35238bceSAndroid Build Coastguard Worker src << "out mediump float v_vtxResult;\n";
1168*35238bceSAndroid Build Coastguard Worker src << "\n";
1169*35238bceSAndroid Build Coastguard Worker
1170*35238bceSAndroid Build Coastguard Worker std::vector<const StructType *> namedStructs;
1171*35238bceSAndroid Build Coastguard Worker interface.getNamedStructs(namedStructs);
1172*35238bceSAndroid Build Coastguard Worker for (std::vector<const StructType *>::const_iterator structIter = namedStructs.begin();
1173*35238bceSAndroid Build Coastguard Worker structIter != namedStructs.end(); structIter++)
1174*35238bceSAndroid Build Coastguard Worker generateDeclaration(src, **structIter, 0);
1175*35238bceSAndroid Build Coastguard Worker
1176*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
1177*35238bceSAndroid Build Coastguard Worker {
1178*35238bceSAndroid Build Coastguard Worker const UniformBlock &block = interface.getUniformBlock(blockNdx);
1179*35238bceSAndroid Build Coastguard Worker if (block.getFlags() & DECLARE_VERTEX)
1180*35238bceSAndroid Build Coastguard Worker generateDeclaration(src, block);
1181*35238bceSAndroid Build Coastguard Worker }
1182*35238bceSAndroid Build Coastguard Worker
1183*35238bceSAndroid Build Coastguard Worker // Comparison utilities.
1184*35238bceSAndroid Build Coastguard Worker src << "\n";
1185*35238bceSAndroid Build Coastguard Worker generateCompareFuncs(src, interface);
1186*35238bceSAndroid Build Coastguard Worker
1187*35238bceSAndroid Build Coastguard Worker src << "\n"
1188*35238bceSAndroid Build Coastguard Worker "void main (void)\n"
1189*35238bceSAndroid Build Coastguard Worker "{\n"
1190*35238bceSAndroid Build Coastguard Worker " gl_Position = a_position;\n"
1191*35238bceSAndroid Build Coastguard Worker " mediump float result = 1.0;\n";
1192*35238bceSAndroid Build Coastguard Worker
1193*35238bceSAndroid Build Coastguard Worker // Value compare.
1194*35238bceSAndroid Build Coastguard Worker generateCompareSrc(src, "result", interface, layout, blockPointers, true);
1195*35238bceSAndroid Build Coastguard Worker
1196*35238bceSAndroid Build Coastguard Worker src << " v_vtxResult = result;\n"
1197*35238bceSAndroid Build Coastguard Worker "}\n";
1198*35238bceSAndroid Build Coastguard Worker }
1199*35238bceSAndroid Build Coastguard Worker
generateFragmentShader(std::ostringstream & src,glu::GLSLVersion glslVersion,const ShaderInterface & interface,const UniformLayout & layout,const std::map<int,void * > & blockPointers)1200*35238bceSAndroid Build Coastguard Worker void generateFragmentShader(std::ostringstream &src, glu::GLSLVersion glslVersion, const ShaderInterface &interface,
1201*35238bceSAndroid Build Coastguard Worker const UniformLayout &layout, const std::map<int, void *> &blockPointers)
1202*35238bceSAndroid Build Coastguard Worker {
1203*35238bceSAndroid Build Coastguard Worker DE_ASSERT(isSupportedGLSLVersion(glslVersion));
1204*35238bceSAndroid Build Coastguard Worker
1205*35238bceSAndroid Build Coastguard Worker src << glu::getGLSLVersionDeclaration(glslVersion) << "\n";
1206*35238bceSAndroid Build Coastguard Worker src << "in mediump float v_vtxResult;\n";
1207*35238bceSAndroid Build Coastguard Worker src << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1208*35238bceSAndroid Build Coastguard Worker src << "\n";
1209*35238bceSAndroid Build Coastguard Worker
1210*35238bceSAndroid Build Coastguard Worker std::vector<const StructType *> namedStructs;
1211*35238bceSAndroid Build Coastguard Worker interface.getNamedStructs(namedStructs);
1212*35238bceSAndroid Build Coastguard Worker for (std::vector<const StructType *>::const_iterator structIter = namedStructs.begin();
1213*35238bceSAndroid Build Coastguard Worker structIter != namedStructs.end(); structIter++)
1214*35238bceSAndroid Build Coastguard Worker generateDeclaration(src, **structIter, 0);
1215*35238bceSAndroid Build Coastguard Worker
1216*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < interface.getNumUniformBlocks(); blockNdx++)
1217*35238bceSAndroid Build Coastguard Worker {
1218*35238bceSAndroid Build Coastguard Worker const UniformBlock &block = interface.getUniformBlock(blockNdx);
1219*35238bceSAndroid Build Coastguard Worker if (block.getFlags() & DECLARE_FRAGMENT)
1220*35238bceSAndroid Build Coastguard Worker generateDeclaration(src, block);
1221*35238bceSAndroid Build Coastguard Worker }
1222*35238bceSAndroid Build Coastguard Worker
1223*35238bceSAndroid Build Coastguard Worker // Comparison utilities.
1224*35238bceSAndroid Build Coastguard Worker src << "\n";
1225*35238bceSAndroid Build Coastguard Worker generateCompareFuncs(src, interface);
1226*35238bceSAndroid Build Coastguard Worker
1227*35238bceSAndroid Build Coastguard Worker src << "\n"
1228*35238bceSAndroid Build Coastguard Worker "void main (void)\n"
1229*35238bceSAndroid Build Coastguard Worker "{\n"
1230*35238bceSAndroid Build Coastguard Worker " mediump float result = 1.0;\n";
1231*35238bceSAndroid Build Coastguard Worker
1232*35238bceSAndroid Build Coastguard Worker // Value compare.
1233*35238bceSAndroid Build Coastguard Worker generateCompareSrc(src, "result", interface, layout, blockPointers, false);
1234*35238bceSAndroid Build Coastguard Worker
1235*35238bceSAndroid Build Coastguard Worker src << " dEQP_FragColor = vec4(1.0, v_vtxResult, result, 1.0);\n"
1236*35238bceSAndroid Build Coastguard Worker "}\n";
1237*35238bceSAndroid Build Coastguard Worker }
1238*35238bceSAndroid Build Coastguard Worker
getGLUniformLayout(const glw::Functions & gl,UniformLayout & layout,uint32_t program)1239*35238bceSAndroid Build Coastguard Worker void getGLUniformLayout(const glw::Functions &gl, UniformLayout &layout, uint32_t program)
1240*35238bceSAndroid Build Coastguard Worker {
1241*35238bceSAndroid Build Coastguard Worker int numActiveUniforms = 0;
1242*35238bceSAndroid Build Coastguard Worker int numActiveBlocks = 0;
1243*35238bceSAndroid Build Coastguard Worker
1244*35238bceSAndroid Build Coastguard Worker gl.getProgramiv(program, GL_ACTIVE_UNIFORMS, &numActiveUniforms);
1245*35238bceSAndroid Build Coastguard Worker gl.getProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numActiveBlocks);
1246*35238bceSAndroid Build Coastguard Worker
1247*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get number of uniforms and uniform blocks");
1248*35238bceSAndroid Build Coastguard Worker
1249*35238bceSAndroid Build Coastguard Worker // Block entries.
1250*35238bceSAndroid Build Coastguard Worker layout.blocks.resize(numActiveBlocks);
1251*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numActiveBlocks; blockNdx++)
1252*35238bceSAndroid Build Coastguard Worker {
1253*35238bceSAndroid Build Coastguard Worker BlockLayoutEntry &entry = layout.blocks[blockNdx];
1254*35238bceSAndroid Build Coastguard Worker int size;
1255*35238bceSAndroid Build Coastguard Worker int nameLen;
1256*35238bceSAndroid Build Coastguard Worker int numBlockUniforms;
1257*35238bceSAndroid Build Coastguard Worker
1258*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformBlockiv(program, (uint32_t)blockNdx, GL_UNIFORM_BLOCK_DATA_SIZE, &size);
1259*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformBlockiv(program, (uint32_t)blockNdx, GL_UNIFORM_BLOCK_NAME_LENGTH, &nameLen);
1260*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformBlockiv(program, (uint32_t)blockNdx, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &numBlockUniforms);
1261*35238bceSAndroid Build Coastguard Worker
1262*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform block query failed");
1263*35238bceSAndroid Build Coastguard Worker
1264*35238bceSAndroid Build Coastguard Worker // \note Some implementations incorrectly return 0 as name length even though the length should include null terminator.
1265*35238bceSAndroid Build Coastguard Worker std::vector<char> nameBuf(nameLen > 0 ? nameLen : 1);
1266*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformBlockName(program, (uint32_t)blockNdx, (glw::GLsizei)nameBuf.size(), DE_NULL, &nameBuf[0]);
1267*35238bceSAndroid Build Coastguard Worker
1268*35238bceSAndroid Build Coastguard Worker entry.name = std::string(&nameBuf[0]);
1269*35238bceSAndroid Build Coastguard Worker entry.size = size;
1270*35238bceSAndroid Build Coastguard Worker entry.activeUniformIndices.resize(numBlockUniforms);
1271*35238bceSAndroid Build Coastguard Worker
1272*35238bceSAndroid Build Coastguard Worker if (numBlockUniforms > 0)
1273*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformBlockiv(program, (uint32_t)blockNdx, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
1274*35238bceSAndroid Build Coastguard Worker &entry.activeUniformIndices[0]);
1275*35238bceSAndroid Build Coastguard Worker
1276*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform block query failed");
1277*35238bceSAndroid Build Coastguard Worker }
1278*35238bceSAndroid Build Coastguard Worker
1279*35238bceSAndroid Build Coastguard Worker if (numActiveUniforms > 0)
1280*35238bceSAndroid Build Coastguard Worker {
1281*35238bceSAndroid Build Coastguard Worker // Uniform entries.
1282*35238bceSAndroid Build Coastguard Worker std::vector<uint32_t> uniformIndices(numActiveUniforms);
1283*35238bceSAndroid Build Coastguard Worker for (int i = 0; i < numActiveUniforms; i++)
1284*35238bceSAndroid Build Coastguard Worker uniformIndices[i] = (uint32_t)i;
1285*35238bceSAndroid Build Coastguard Worker
1286*35238bceSAndroid Build Coastguard Worker std::vector<int> types(numActiveUniforms);
1287*35238bceSAndroid Build Coastguard Worker std::vector<int> sizes(numActiveUniforms);
1288*35238bceSAndroid Build Coastguard Worker std::vector<int> nameLengths(numActiveUniforms);
1289*35238bceSAndroid Build Coastguard Worker std::vector<int> blockIndices(numActiveUniforms);
1290*35238bceSAndroid Build Coastguard Worker std::vector<int> offsets(numActiveUniforms);
1291*35238bceSAndroid Build Coastguard Worker std::vector<int> arrayStrides(numActiveUniforms);
1292*35238bceSAndroid Build Coastguard Worker std::vector<int> matrixStrides(numActiveUniforms);
1293*35238bceSAndroid Build Coastguard Worker std::vector<int> rowMajorFlags(numActiveUniforms);
1294*35238bceSAndroid Build Coastguard Worker
1295*35238bceSAndroid Build Coastguard Worker // Execute queries.
1296*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_TYPE,
1297*35238bceSAndroid Build Coastguard Worker &types[0]);
1298*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_SIZE,
1299*35238bceSAndroid Build Coastguard Worker &sizes[0]);
1300*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_NAME_LENGTH,
1301*35238bceSAndroid Build Coastguard Worker &nameLengths[0]);
1302*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_BLOCK_INDEX,
1303*35238bceSAndroid Build Coastguard Worker &blockIndices[0]);
1304*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0], GL_UNIFORM_OFFSET,
1305*35238bceSAndroid Build Coastguard Worker &offsets[0]);
1306*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0],
1307*35238bceSAndroid Build Coastguard Worker GL_UNIFORM_ARRAY_STRIDE, &arrayStrides[0]);
1308*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0],
1309*35238bceSAndroid Build Coastguard Worker GL_UNIFORM_MATRIX_STRIDE, &matrixStrides[0]);
1310*35238bceSAndroid Build Coastguard Worker gl.getActiveUniformsiv(program, (glw::GLsizei)uniformIndices.size(), &uniformIndices[0],
1311*35238bceSAndroid Build Coastguard Worker GL_UNIFORM_IS_ROW_MAJOR, &rowMajorFlags[0]);
1312*35238bceSAndroid Build Coastguard Worker
1313*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Active uniform query failed");
1314*35238bceSAndroid Build Coastguard Worker
1315*35238bceSAndroid Build Coastguard Worker // Translate to LayoutEntries
1316*35238bceSAndroid Build Coastguard Worker layout.uniforms.resize(numActiveUniforms);
1317*35238bceSAndroid Build Coastguard Worker for (int uniformNdx = 0; uniformNdx < numActiveUniforms; uniformNdx++)
1318*35238bceSAndroid Build Coastguard Worker {
1319*35238bceSAndroid Build Coastguard Worker UniformLayoutEntry &entry = layout.uniforms[uniformNdx];
1320*35238bceSAndroid Build Coastguard Worker std::vector<char> nameBuf(nameLengths[uniformNdx]);
1321*35238bceSAndroid Build Coastguard Worker glw::GLsizei nameLen = 0;
1322*35238bceSAndroid Build Coastguard Worker int size = 0;
1323*35238bceSAndroid Build Coastguard Worker uint32_t type = GL_NONE;
1324*35238bceSAndroid Build Coastguard Worker
1325*35238bceSAndroid Build Coastguard Worker gl.getActiveUniform(program, (uint32_t)uniformNdx, (glw::GLsizei)nameBuf.size(), &nameLen, &size, &type,
1326*35238bceSAndroid Build Coastguard Worker &nameBuf[0]);
1327*35238bceSAndroid Build Coastguard Worker
1328*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform name query failed");
1329*35238bceSAndroid Build Coastguard Worker
1330*35238bceSAndroid Build Coastguard Worker // \note glGetActiveUniform() returns length without \0 and glGetActiveUniformsiv() with \0
1331*35238bceSAndroid Build Coastguard Worker if (nameLen + 1 != nameLengths[uniformNdx] || size != sizes[uniformNdx] ||
1332*35238bceSAndroid Build Coastguard Worker type != (uint32_t)types[uniformNdx])
1333*35238bceSAndroid Build Coastguard Worker TCU_FAIL("Values returned by glGetActiveUniform() don't match with values queried with "
1334*35238bceSAndroid Build Coastguard Worker "glGetActiveUniformsiv().");
1335*35238bceSAndroid Build Coastguard Worker
1336*35238bceSAndroid Build Coastguard Worker entry.name = std::string(&nameBuf[0]);
1337*35238bceSAndroid Build Coastguard Worker entry.type = glu::getDataTypeFromGLType(types[uniformNdx]);
1338*35238bceSAndroid Build Coastguard Worker entry.size = sizes[uniformNdx];
1339*35238bceSAndroid Build Coastguard Worker entry.blockNdx = blockIndices[uniformNdx];
1340*35238bceSAndroid Build Coastguard Worker entry.offset = offsets[uniformNdx];
1341*35238bceSAndroid Build Coastguard Worker entry.arrayStride = arrayStrides[uniformNdx];
1342*35238bceSAndroid Build Coastguard Worker entry.matrixStride = matrixStrides[uniformNdx];
1343*35238bceSAndroid Build Coastguard Worker entry.isRowMajor = rowMajorFlags[uniformNdx] != GL_FALSE;
1344*35238bceSAndroid Build Coastguard Worker }
1345*35238bceSAndroid Build Coastguard Worker }
1346*35238bceSAndroid Build Coastguard Worker }
1347*35238bceSAndroid Build Coastguard Worker
copyUniformData(const UniformLayoutEntry & dstEntry,void * dstBlockPtr,const UniformLayoutEntry & srcEntry,const void * srcBlockPtr)1348*35238bceSAndroid Build Coastguard Worker void copyUniformData(const UniformLayoutEntry &dstEntry, void *dstBlockPtr, const UniformLayoutEntry &srcEntry,
1349*35238bceSAndroid Build Coastguard Worker const void *srcBlockPtr)
1350*35238bceSAndroid Build Coastguard Worker {
1351*35238bceSAndroid Build Coastguard Worker uint8_t *dstBasePtr = (uint8_t *)dstBlockPtr + dstEntry.offset;
1352*35238bceSAndroid Build Coastguard Worker const uint8_t *srcBasePtr = (const uint8_t *)srcBlockPtr + srcEntry.offset;
1353*35238bceSAndroid Build Coastguard Worker
1354*35238bceSAndroid Build Coastguard Worker DE_ASSERT(dstEntry.size <= srcEntry.size);
1355*35238bceSAndroid Build Coastguard Worker DE_ASSERT(dstEntry.type == srcEntry.type);
1356*35238bceSAndroid Build Coastguard Worker
1357*35238bceSAndroid Build Coastguard Worker int scalarSize = glu::getDataTypeScalarSize(dstEntry.type);
1358*35238bceSAndroid Build Coastguard Worker bool isMatrix = glu::isDataTypeMatrix(dstEntry.type);
1359*35238bceSAndroid Build Coastguard Worker const int compSize = sizeof(uint32_t);
1360*35238bceSAndroid Build Coastguard Worker
1361*35238bceSAndroid Build Coastguard Worker for (int elementNdx = 0; elementNdx < dstEntry.size; elementNdx++)
1362*35238bceSAndroid Build Coastguard Worker {
1363*35238bceSAndroid Build Coastguard Worker uint8_t *dstElemPtr = dstBasePtr + elementNdx * dstEntry.arrayStride;
1364*35238bceSAndroid Build Coastguard Worker const uint8_t *srcElemPtr = srcBasePtr + elementNdx * srcEntry.arrayStride;
1365*35238bceSAndroid Build Coastguard Worker
1366*35238bceSAndroid Build Coastguard Worker if (isMatrix)
1367*35238bceSAndroid Build Coastguard Worker {
1368*35238bceSAndroid Build Coastguard Worker int numRows = glu::getDataTypeMatrixNumRows(dstEntry.type);
1369*35238bceSAndroid Build Coastguard Worker int numCols = glu::getDataTypeMatrixNumColumns(dstEntry.type);
1370*35238bceSAndroid Build Coastguard Worker
1371*35238bceSAndroid Build Coastguard Worker for (int colNdx = 0; colNdx < numCols; colNdx++)
1372*35238bceSAndroid Build Coastguard Worker {
1373*35238bceSAndroid Build Coastguard Worker for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
1374*35238bceSAndroid Build Coastguard Worker {
1375*35238bceSAndroid Build Coastguard Worker uint8_t *dstCompPtr =
1376*35238bceSAndroid Build Coastguard Worker dstElemPtr + (dstEntry.isRowMajor ? rowNdx * dstEntry.matrixStride + colNdx * compSize :
1377*35238bceSAndroid Build Coastguard Worker colNdx * dstEntry.matrixStride + rowNdx * compSize);
1378*35238bceSAndroid Build Coastguard Worker const uint8_t *srcCompPtr =
1379*35238bceSAndroid Build Coastguard Worker srcElemPtr + (srcEntry.isRowMajor ? rowNdx * srcEntry.matrixStride + colNdx * compSize :
1380*35238bceSAndroid Build Coastguard Worker colNdx * srcEntry.matrixStride + rowNdx * compSize);
1381*35238bceSAndroid Build Coastguard Worker deMemcpy(dstCompPtr, srcCompPtr, compSize);
1382*35238bceSAndroid Build Coastguard Worker }
1383*35238bceSAndroid Build Coastguard Worker }
1384*35238bceSAndroid Build Coastguard Worker }
1385*35238bceSAndroid Build Coastguard Worker else
1386*35238bceSAndroid Build Coastguard Worker deMemcpy(dstElemPtr, srcElemPtr, scalarSize * compSize);
1387*35238bceSAndroid Build Coastguard Worker }
1388*35238bceSAndroid Build Coastguard Worker }
1389*35238bceSAndroid Build Coastguard Worker
copyUniformData(const UniformLayout & dstLayout,const std::map<int,void * > & dstBlockPointers,const UniformLayout & srcLayout,const std::map<int,void * > & srcBlockPointers)1390*35238bceSAndroid Build Coastguard Worker void copyUniformData(const UniformLayout &dstLayout, const std::map<int, void *> &dstBlockPointers,
1391*35238bceSAndroid Build Coastguard Worker const UniformLayout &srcLayout, const std::map<int, void *> &srcBlockPointers)
1392*35238bceSAndroid Build Coastguard Worker {
1393*35238bceSAndroid Build Coastguard Worker // \note Src layout is used as reference in case of activeUniforms happens to be incorrect in dstLayout blocks.
1394*35238bceSAndroid Build Coastguard Worker int numBlocks = (int)srcLayout.blocks.size();
1395*35238bceSAndroid Build Coastguard Worker
1396*35238bceSAndroid Build Coastguard Worker for (int srcBlockNdx = 0; srcBlockNdx < numBlocks; srcBlockNdx++)
1397*35238bceSAndroid Build Coastguard Worker {
1398*35238bceSAndroid Build Coastguard Worker const BlockLayoutEntry &srcBlock = srcLayout.blocks[srcBlockNdx];
1399*35238bceSAndroid Build Coastguard Worker const void *srcBlockPtr = srcBlockPointers.find(srcBlockNdx)->second;
1400*35238bceSAndroid Build Coastguard Worker int dstBlockNdx = dstLayout.getBlockIndex(srcBlock.name.c_str());
1401*35238bceSAndroid Build Coastguard Worker void *dstBlockPtr = dstBlockNdx >= 0 ? dstBlockPointers.find(dstBlockNdx)->second : DE_NULL;
1402*35238bceSAndroid Build Coastguard Worker
1403*35238bceSAndroid Build Coastguard Worker if (dstBlockNdx < 0)
1404*35238bceSAndroid Build Coastguard Worker continue;
1405*35238bceSAndroid Build Coastguard Worker
1406*35238bceSAndroid Build Coastguard Worker for (vector<int>::const_iterator srcUniformNdxIter = srcBlock.activeUniformIndices.begin();
1407*35238bceSAndroid Build Coastguard Worker srcUniformNdxIter != srcBlock.activeUniformIndices.end(); srcUniformNdxIter++)
1408*35238bceSAndroid Build Coastguard Worker {
1409*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &srcEntry = srcLayout.uniforms[*srcUniformNdxIter];
1410*35238bceSAndroid Build Coastguard Worker int dstUniformNdx = dstLayout.getUniformIndex(srcEntry.name.c_str());
1411*35238bceSAndroid Build Coastguard Worker
1412*35238bceSAndroid Build Coastguard Worker if (dstUniformNdx < 0)
1413*35238bceSAndroid Build Coastguard Worker continue;
1414*35238bceSAndroid Build Coastguard Worker
1415*35238bceSAndroid Build Coastguard Worker copyUniformData(dstLayout.uniforms[dstUniformNdx], dstBlockPtr, srcEntry, srcBlockPtr);
1416*35238bceSAndroid Build Coastguard Worker }
1417*35238bceSAndroid Build Coastguard Worker }
1418*35238bceSAndroid Build Coastguard Worker }
1419*35238bceSAndroid Build Coastguard Worker
1420*35238bceSAndroid Build Coastguard Worker } // namespace
1421*35238bceSAndroid Build Coastguard Worker
1422*35238bceSAndroid Build Coastguard Worker class UniformBufferManager
1423*35238bceSAndroid Build Coastguard Worker {
1424*35238bceSAndroid Build Coastguard Worker public:
1425*35238bceSAndroid Build Coastguard Worker UniformBufferManager(const glu::RenderContext &renderCtx);
1426*35238bceSAndroid Build Coastguard Worker ~UniformBufferManager(void);
1427*35238bceSAndroid Build Coastguard Worker
1428*35238bceSAndroid Build Coastguard Worker uint32_t allocBuffer(void);
1429*35238bceSAndroid Build Coastguard Worker
1430*35238bceSAndroid Build Coastguard Worker private:
1431*35238bceSAndroid Build Coastguard Worker UniformBufferManager(const UniformBufferManager &other);
1432*35238bceSAndroid Build Coastguard Worker UniformBufferManager &operator=(const UniformBufferManager &other);
1433*35238bceSAndroid Build Coastguard Worker
1434*35238bceSAndroid Build Coastguard Worker const glu::RenderContext &m_renderCtx;
1435*35238bceSAndroid Build Coastguard Worker std::vector<uint32_t> m_buffers;
1436*35238bceSAndroid Build Coastguard Worker };
1437*35238bceSAndroid Build Coastguard Worker
UniformBufferManager(const glu::RenderContext & renderCtx)1438*35238bceSAndroid Build Coastguard Worker UniformBufferManager::UniformBufferManager(const glu::RenderContext &renderCtx) : m_renderCtx(renderCtx)
1439*35238bceSAndroid Build Coastguard Worker {
1440*35238bceSAndroid Build Coastguard Worker }
1441*35238bceSAndroid Build Coastguard Worker
~UniformBufferManager(void)1442*35238bceSAndroid Build Coastguard Worker UniformBufferManager::~UniformBufferManager(void)
1443*35238bceSAndroid Build Coastguard Worker {
1444*35238bceSAndroid Build Coastguard Worker if (!m_buffers.empty())
1445*35238bceSAndroid Build Coastguard Worker m_renderCtx.getFunctions().deleteBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]);
1446*35238bceSAndroid Build Coastguard Worker }
1447*35238bceSAndroid Build Coastguard Worker
allocBuffer(void)1448*35238bceSAndroid Build Coastguard Worker uint32_t UniformBufferManager::allocBuffer(void)
1449*35238bceSAndroid Build Coastguard Worker {
1450*35238bceSAndroid Build Coastguard Worker uint32_t buf = 0;
1451*35238bceSAndroid Build Coastguard Worker
1452*35238bceSAndroid Build Coastguard Worker m_buffers.reserve(m_buffers.size() + 1);
1453*35238bceSAndroid Build Coastguard Worker m_renderCtx.getFunctions().genBuffers(1, &buf);
1454*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(m_renderCtx.getFunctions().getError(), "Failed to allocate uniform buffer");
1455*35238bceSAndroid Build Coastguard Worker m_buffers.push_back(buf);
1456*35238bceSAndroid Build Coastguard Worker
1457*35238bceSAndroid Build Coastguard Worker return buf;
1458*35238bceSAndroid Build Coastguard Worker }
1459*35238bceSAndroid Build Coastguard Worker
1460*35238bceSAndroid Build Coastguard Worker } // namespace ub
1461*35238bceSAndroid Build Coastguard Worker
1462*35238bceSAndroid Build Coastguard Worker using namespace ub;
1463*35238bceSAndroid Build Coastguard Worker
1464*35238bceSAndroid Build Coastguard Worker // UniformBlockCase.
1465*35238bceSAndroid Build Coastguard Worker
UniformBlockCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * description,glu::GLSLVersion glslVersion,BufferMode bufferMode)1466*35238bceSAndroid Build Coastguard Worker UniformBlockCase::UniformBlockCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const char *name,
1467*35238bceSAndroid Build Coastguard Worker const char *description, glu::GLSLVersion glslVersion, BufferMode bufferMode)
1468*35238bceSAndroid Build Coastguard Worker : TestCase(testCtx, name, description)
1469*35238bceSAndroid Build Coastguard Worker , m_renderCtx(renderCtx)
1470*35238bceSAndroid Build Coastguard Worker , m_glslVersion(glslVersion)
1471*35238bceSAndroid Build Coastguard Worker , m_bufferMode(bufferMode)
1472*35238bceSAndroid Build Coastguard Worker {
1473*35238bceSAndroid Build Coastguard Worker TCU_CHECK_INTERNAL(isSupportedGLSLVersion(glslVersion));
1474*35238bceSAndroid Build Coastguard Worker }
1475*35238bceSAndroid Build Coastguard Worker
~UniformBlockCase(void)1476*35238bceSAndroid Build Coastguard Worker UniformBlockCase::~UniformBlockCase(void)
1477*35238bceSAndroid Build Coastguard Worker {
1478*35238bceSAndroid Build Coastguard Worker }
1479*35238bceSAndroid Build Coastguard Worker
iterate(void)1480*35238bceSAndroid Build Coastguard Worker UniformBlockCase::IterateResult UniformBlockCase::iterate(void)
1481*35238bceSAndroid Build Coastguard Worker {
1482*35238bceSAndroid Build Coastguard Worker TestLog &log = m_testCtx.getLog();
1483*35238bceSAndroid Build Coastguard Worker const glw::Functions &gl = m_renderCtx.getFunctions();
1484*35238bceSAndroid Build Coastguard Worker UniformLayout refLayout; //!< std140 layout.
1485*35238bceSAndroid Build Coastguard Worker vector<uint8_t> data; //!< Data.
1486*35238bceSAndroid Build Coastguard Worker map<int, void *> blockPointers; //!< Reference block pointers.
1487*35238bceSAndroid Build Coastguard Worker
1488*35238bceSAndroid Build Coastguard Worker // Initialize result to pass.
1489*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1490*35238bceSAndroid Build Coastguard Worker
1491*35238bceSAndroid Build Coastguard Worker // Compute reference layout.
1492*35238bceSAndroid Build Coastguard Worker computeStd140Layout(refLayout, m_interface);
1493*35238bceSAndroid Build Coastguard Worker
1494*35238bceSAndroid Build Coastguard Worker // Assign storage for reference values.
1495*35238bceSAndroid Build Coastguard Worker {
1496*35238bceSAndroid Build Coastguard Worker int totalSize = 0;
1497*35238bceSAndroid Build Coastguard Worker for (vector<BlockLayoutEntry>::const_iterator blockIter = refLayout.blocks.begin();
1498*35238bceSAndroid Build Coastguard Worker blockIter != refLayout.blocks.end(); blockIter++)
1499*35238bceSAndroid Build Coastguard Worker totalSize += blockIter->size;
1500*35238bceSAndroid Build Coastguard Worker data.resize(totalSize);
1501*35238bceSAndroid Build Coastguard Worker
1502*35238bceSAndroid Build Coastguard Worker // Pointers for each block.
1503*35238bceSAndroid Build Coastguard Worker int curOffset = 0;
1504*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < (int)refLayout.blocks.size(); blockNdx++)
1505*35238bceSAndroid Build Coastguard Worker {
1506*35238bceSAndroid Build Coastguard Worker blockPointers[blockNdx] = &data[0] + curOffset;
1507*35238bceSAndroid Build Coastguard Worker curOffset += refLayout.blocks[blockNdx].size;
1508*35238bceSAndroid Build Coastguard Worker }
1509*35238bceSAndroid Build Coastguard Worker }
1510*35238bceSAndroid Build Coastguard Worker
1511*35238bceSAndroid Build Coastguard Worker // Generate values.
1512*35238bceSAndroid Build Coastguard Worker generateValues(refLayout, blockPointers, 1 /* seed */);
1513*35238bceSAndroid Build Coastguard Worker
1514*35238bceSAndroid Build Coastguard Worker // Generate shaders and build program.
1515*35238bceSAndroid Build Coastguard Worker std::ostringstream vtxSrc;
1516*35238bceSAndroid Build Coastguard Worker std::ostringstream fragSrc;
1517*35238bceSAndroid Build Coastguard Worker
1518*35238bceSAndroid Build Coastguard Worker generateVertexShader(vtxSrc, m_glslVersion, m_interface, refLayout, blockPointers);
1519*35238bceSAndroid Build Coastguard Worker generateFragmentShader(fragSrc, m_glslVersion, m_interface, refLayout, blockPointers);
1520*35238bceSAndroid Build Coastguard Worker
1521*35238bceSAndroid Build Coastguard Worker glu::ShaderProgram program(m_renderCtx, glu::makeVtxFragSources(vtxSrc.str(), fragSrc.str()));
1522*35238bceSAndroid Build Coastguard Worker log << program;
1523*35238bceSAndroid Build Coastguard Worker
1524*35238bceSAndroid Build Coastguard Worker if (!program.isOk())
1525*35238bceSAndroid Build Coastguard Worker {
1526*35238bceSAndroid Build Coastguard Worker // Compile failed.
1527*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Compile failed");
1528*35238bceSAndroid Build Coastguard Worker return STOP;
1529*35238bceSAndroid Build Coastguard Worker }
1530*35238bceSAndroid Build Coastguard Worker
1531*35238bceSAndroid Build Coastguard Worker // Query layout from GL.
1532*35238bceSAndroid Build Coastguard Worker UniformLayout glLayout;
1533*35238bceSAndroid Build Coastguard Worker getGLUniformLayout(gl, glLayout, program.getProgram());
1534*35238bceSAndroid Build Coastguard Worker
1535*35238bceSAndroid Build Coastguard Worker // Print layout to log.
1536*35238bceSAndroid Build Coastguard Worker log << TestLog::Section("ActiveUniformBlocks", "Active Uniform Blocks");
1537*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < (int)glLayout.blocks.size(); blockNdx++)
1538*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << blockNdx << ": " << glLayout.blocks[blockNdx] << TestLog::EndMessage;
1539*35238bceSAndroid Build Coastguard Worker log << TestLog::EndSection;
1540*35238bceSAndroid Build Coastguard Worker
1541*35238bceSAndroid Build Coastguard Worker log << TestLog::Section("ActiveUniforms", "Active Uniforms");
1542*35238bceSAndroid Build Coastguard Worker for (int uniformNdx = 0; uniformNdx < (int)glLayout.uniforms.size(); uniformNdx++)
1543*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << uniformNdx << ": " << glLayout.uniforms[uniformNdx] << TestLog::EndMessage;
1544*35238bceSAndroid Build Coastguard Worker log << TestLog::EndSection;
1545*35238bceSAndroid Build Coastguard Worker
1546*35238bceSAndroid Build Coastguard Worker // Check that we can even try rendering with given layout.
1547*35238bceSAndroid Build Coastguard Worker if (!checkLayoutIndices(glLayout) || !checkLayoutBounds(glLayout) || !compareTypes(refLayout, glLayout))
1548*35238bceSAndroid Build Coastguard Worker {
1549*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid layout");
1550*35238bceSAndroid Build Coastguard Worker return STOP; // It is not safe to use the given layout.
1551*35238bceSAndroid Build Coastguard Worker }
1552*35238bceSAndroid Build Coastguard Worker
1553*35238bceSAndroid Build Coastguard Worker // Verify all std140 blocks.
1554*35238bceSAndroid Build Coastguard Worker if (!compareStd140Blocks(refLayout, glLayout))
1555*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid std140 layout");
1556*35238bceSAndroid Build Coastguard Worker
1557*35238bceSAndroid Build Coastguard Worker // Verify all shared blocks - all uniforms should be active, and certain properties match.
1558*35238bceSAndroid Build Coastguard Worker if (!compareSharedBlocks(refLayout, glLayout))
1559*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid shared layout");
1560*35238bceSAndroid Build Coastguard Worker
1561*35238bceSAndroid Build Coastguard Worker // Check consistency with index queries
1562*35238bceSAndroid Build Coastguard Worker if (!checkIndexQueries(program.getProgram(), glLayout))
1563*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Inconsintent block index query results");
1564*35238bceSAndroid Build Coastguard Worker
1565*35238bceSAndroid Build Coastguard Worker // Use program.
1566*35238bceSAndroid Build Coastguard Worker gl.useProgram(program.getProgram());
1567*35238bceSAndroid Build Coastguard Worker
1568*35238bceSAndroid Build Coastguard Worker // Assign binding points to all active uniform blocks.
1569*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < (int)glLayout.blocks.size(); blockNdx++)
1570*35238bceSAndroid Build Coastguard Worker {
1571*35238bceSAndroid Build Coastguard Worker uint32_t binding = (uint32_t)blockNdx; // \todo [2012-01-25 pyry] Randomize order?
1572*35238bceSAndroid Build Coastguard Worker gl.uniformBlockBinding(program.getProgram(), (uint32_t)blockNdx, binding);
1573*35238bceSAndroid Build Coastguard Worker }
1574*35238bceSAndroid Build Coastguard Worker
1575*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set uniform block bindings");
1576*35238bceSAndroid Build Coastguard Worker
1577*35238bceSAndroid Build Coastguard Worker // Allocate buffers, write data and bind to targets.
1578*35238bceSAndroid Build Coastguard Worker UniformBufferManager bufferManager(m_renderCtx);
1579*35238bceSAndroid Build Coastguard Worker if (m_bufferMode == BUFFERMODE_PER_BLOCK)
1580*35238bceSAndroid Build Coastguard Worker {
1581*35238bceSAndroid Build Coastguard Worker int numBlocks = (int)glLayout.blocks.size();
1582*35238bceSAndroid Build Coastguard Worker vector<vector<uint8_t>> glData(numBlocks);
1583*35238bceSAndroid Build Coastguard Worker map<int, void *> glBlockPointers;
1584*35238bceSAndroid Build Coastguard Worker
1585*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1586*35238bceSAndroid Build Coastguard Worker {
1587*35238bceSAndroid Build Coastguard Worker glData[blockNdx].resize(glLayout.blocks[blockNdx].size);
1588*35238bceSAndroid Build Coastguard Worker glBlockPointers[blockNdx] = &glData[blockNdx][0];
1589*35238bceSAndroid Build Coastguard Worker }
1590*35238bceSAndroid Build Coastguard Worker
1591*35238bceSAndroid Build Coastguard Worker copyUniformData(glLayout, glBlockPointers, refLayout, blockPointers);
1592*35238bceSAndroid Build Coastguard Worker
1593*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1594*35238bceSAndroid Build Coastguard Worker {
1595*35238bceSAndroid Build Coastguard Worker uint32_t buffer = bufferManager.allocBuffer();
1596*35238bceSAndroid Build Coastguard Worker uint32_t binding = (uint32_t)blockNdx;
1597*35238bceSAndroid Build Coastguard Worker
1598*35238bceSAndroid Build Coastguard Worker gl.bindBuffer(GL_UNIFORM_BUFFER, buffer);
1599*35238bceSAndroid Build Coastguard Worker gl.bufferData(GL_UNIFORM_BUFFER, (glw::GLsizeiptr)glData[blockNdx].size(), &glData[blockNdx][0],
1600*35238bceSAndroid Build Coastguard Worker GL_STATIC_DRAW);
1601*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload uniform buffer data");
1602*35238bceSAndroid Build Coastguard Worker
1603*35238bceSAndroid Build Coastguard Worker gl.bindBufferBase(GL_UNIFORM_BUFFER, binding, buffer);
1604*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(GL_UNIFORM_BUFFER) failed");
1605*35238bceSAndroid Build Coastguard Worker }
1606*35238bceSAndroid Build Coastguard Worker }
1607*35238bceSAndroid Build Coastguard Worker else
1608*35238bceSAndroid Build Coastguard Worker {
1609*35238bceSAndroid Build Coastguard Worker DE_ASSERT(m_bufferMode == BUFFERMODE_SINGLE);
1610*35238bceSAndroid Build Coastguard Worker
1611*35238bceSAndroid Build Coastguard Worker int totalSize = 0;
1612*35238bceSAndroid Build Coastguard Worker int curOffset = 0;
1613*35238bceSAndroid Build Coastguard Worker int numBlocks = (int)glLayout.blocks.size();
1614*35238bceSAndroid Build Coastguard Worker int bindingAlignment = 0;
1615*35238bceSAndroid Build Coastguard Worker map<int, int> glBlockOffsets;
1616*35238bceSAndroid Build Coastguard Worker
1617*35238bceSAndroid Build Coastguard Worker gl.getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &bindingAlignment);
1618*35238bceSAndroid Build Coastguard Worker
1619*35238bceSAndroid Build Coastguard Worker // Compute total size and offsets.
1620*35238bceSAndroid Build Coastguard Worker curOffset = 0;
1621*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1622*35238bceSAndroid Build Coastguard Worker {
1623*35238bceSAndroid Build Coastguard Worker if (bindingAlignment > 0)
1624*35238bceSAndroid Build Coastguard Worker curOffset = deRoundUp32(curOffset, bindingAlignment);
1625*35238bceSAndroid Build Coastguard Worker glBlockOffsets[blockNdx] = curOffset;
1626*35238bceSAndroid Build Coastguard Worker curOffset += glLayout.blocks[blockNdx].size;
1627*35238bceSAndroid Build Coastguard Worker }
1628*35238bceSAndroid Build Coastguard Worker totalSize = curOffset;
1629*35238bceSAndroid Build Coastguard Worker
1630*35238bceSAndroid Build Coastguard Worker // Assign block pointers.
1631*35238bceSAndroid Build Coastguard Worker vector<uint8_t> glData(totalSize);
1632*35238bceSAndroid Build Coastguard Worker map<int, void *> glBlockPointers;
1633*35238bceSAndroid Build Coastguard Worker
1634*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1635*35238bceSAndroid Build Coastguard Worker glBlockPointers[blockNdx] = &glData[glBlockOffsets[blockNdx]];
1636*35238bceSAndroid Build Coastguard Worker
1637*35238bceSAndroid Build Coastguard Worker // Copy to gl format.
1638*35238bceSAndroid Build Coastguard Worker copyUniformData(glLayout, glBlockPointers, refLayout, blockPointers);
1639*35238bceSAndroid Build Coastguard Worker
1640*35238bceSAndroid Build Coastguard Worker // Allocate buffer and upload data.
1641*35238bceSAndroid Build Coastguard Worker uint32_t buffer = bufferManager.allocBuffer();
1642*35238bceSAndroid Build Coastguard Worker gl.bindBuffer(GL_UNIFORM_BUFFER, buffer);
1643*35238bceSAndroid Build Coastguard Worker if (!glData.empty())
1644*35238bceSAndroid Build Coastguard Worker gl.bufferData(GL_UNIFORM_BUFFER, (glw::GLsizeiptr)glData.size(), &glData[0], GL_STATIC_DRAW);
1645*35238bceSAndroid Build Coastguard Worker
1646*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload uniform buffer data");
1647*35238bceSAndroid Build Coastguard Worker
1648*35238bceSAndroid Build Coastguard Worker // Bind ranges to binding points.
1649*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1650*35238bceSAndroid Build Coastguard Worker {
1651*35238bceSAndroid Build Coastguard Worker uint32_t binding = (uint32_t)blockNdx;
1652*35238bceSAndroid Build Coastguard Worker gl.bindBufferRange(GL_UNIFORM_BUFFER, binding, buffer, (glw::GLintptr)glBlockOffsets[blockNdx],
1653*35238bceSAndroid Build Coastguard Worker (glw::GLsizeiptr)glLayout.blocks[blockNdx].size);
1654*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange(GL_UNIFORM_BUFFER) failed");
1655*35238bceSAndroid Build Coastguard Worker }
1656*35238bceSAndroid Build Coastguard Worker }
1657*35238bceSAndroid Build Coastguard Worker
1658*35238bceSAndroid Build Coastguard Worker bool renderOk = render(program.getProgram());
1659*35238bceSAndroid Build Coastguard Worker if (!renderOk)
1660*35238bceSAndroid Build Coastguard Worker m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image compare failed");
1661*35238bceSAndroid Build Coastguard Worker
1662*35238bceSAndroid Build Coastguard Worker return STOP;
1663*35238bceSAndroid Build Coastguard Worker }
1664*35238bceSAndroid Build Coastguard Worker
compareStd140Blocks(const UniformLayout & refLayout,const UniformLayout & cmpLayout) const1665*35238bceSAndroid Build Coastguard Worker bool UniformBlockCase::compareStd140Blocks(const UniformLayout &refLayout, const UniformLayout &cmpLayout) const
1666*35238bceSAndroid Build Coastguard Worker {
1667*35238bceSAndroid Build Coastguard Worker TestLog &log = m_testCtx.getLog();
1668*35238bceSAndroid Build Coastguard Worker bool isOk = true;
1669*35238bceSAndroid Build Coastguard Worker int numBlocks = m_interface.getNumUniformBlocks();
1670*35238bceSAndroid Build Coastguard Worker
1671*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1672*35238bceSAndroid Build Coastguard Worker {
1673*35238bceSAndroid Build Coastguard Worker const UniformBlock &block = m_interface.getUniformBlock(blockNdx);
1674*35238bceSAndroid Build Coastguard Worker bool isArray = block.isArray();
1675*35238bceSAndroid Build Coastguard Worker std::string instanceName = string(block.getBlockName()) + (isArray ? "[0]" : "");
1676*35238bceSAndroid Build Coastguard Worker int refBlockNdx = refLayout.getBlockIndex(instanceName.c_str());
1677*35238bceSAndroid Build Coastguard Worker int cmpBlockNdx = cmpLayout.getBlockIndex(instanceName.c_str());
1678*35238bceSAndroid Build Coastguard Worker bool isUsed = (block.getFlags() & (DECLARE_VERTEX | DECLARE_FRAGMENT)) != 0;
1679*35238bceSAndroid Build Coastguard Worker
1680*35238bceSAndroid Build Coastguard Worker if ((block.getFlags() & LAYOUT_STD140) == 0)
1681*35238bceSAndroid Build Coastguard Worker continue; // Not std140 layout.
1682*35238bceSAndroid Build Coastguard Worker
1683*35238bceSAndroid Build Coastguard Worker DE_ASSERT(refBlockNdx >= 0);
1684*35238bceSAndroid Build Coastguard Worker
1685*35238bceSAndroid Build Coastguard Worker if (cmpBlockNdx < 0)
1686*35238bceSAndroid Build Coastguard Worker {
1687*35238bceSAndroid Build Coastguard Worker // Not found, should it?
1688*35238bceSAndroid Build Coastguard Worker if (isUsed)
1689*35238bceSAndroid Build Coastguard Worker {
1690*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Uniform block '" << instanceName << "' not found"
1691*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
1692*35238bceSAndroid Build Coastguard Worker isOk = false;
1693*35238bceSAndroid Build Coastguard Worker }
1694*35238bceSAndroid Build Coastguard Worker
1695*35238bceSAndroid Build Coastguard Worker continue; // Skip block.
1696*35238bceSAndroid Build Coastguard Worker }
1697*35238bceSAndroid Build Coastguard Worker
1698*35238bceSAndroid Build Coastguard Worker const BlockLayoutEntry &refBlockLayout = refLayout.blocks[refBlockNdx];
1699*35238bceSAndroid Build Coastguard Worker const BlockLayoutEntry &cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx];
1700*35238bceSAndroid Build Coastguard Worker
1701*35238bceSAndroid Build Coastguard Worker // \todo [2012-01-24 pyry] Verify that activeUniformIndices is correct.
1702*35238bceSAndroid Build Coastguard Worker // \todo [2012-01-24 pyry] Verify all instances.
1703*35238bceSAndroid Build Coastguard Worker if (refBlockLayout.activeUniformIndices.size() != cmpBlockLayout.activeUniformIndices.size())
1704*35238bceSAndroid Build Coastguard Worker {
1705*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Number of active uniforms differ in block '" << instanceName
1706*35238bceSAndroid Build Coastguard Worker << "' (expected " << refBlockLayout.activeUniformIndices.size() << ", got "
1707*35238bceSAndroid Build Coastguard Worker << cmpBlockLayout.activeUniformIndices.size() << ")" << TestLog::EndMessage;
1708*35238bceSAndroid Build Coastguard Worker isOk = false;
1709*35238bceSAndroid Build Coastguard Worker }
1710*35238bceSAndroid Build Coastguard Worker
1711*35238bceSAndroid Build Coastguard Worker for (vector<int>::const_iterator ndxIter = refBlockLayout.activeUniformIndices.begin();
1712*35238bceSAndroid Build Coastguard Worker ndxIter != refBlockLayout.activeUniformIndices.end(); ndxIter++)
1713*35238bceSAndroid Build Coastguard Worker {
1714*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &refEntry = refLayout.uniforms[*ndxIter];
1715*35238bceSAndroid Build Coastguard Worker int cmpEntryNdx = cmpLayout.getUniformIndex(refEntry.name.c_str());
1716*35238bceSAndroid Build Coastguard Worker
1717*35238bceSAndroid Build Coastguard Worker if (cmpEntryNdx < 0)
1718*35238bceSAndroid Build Coastguard Worker {
1719*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Uniform '" << refEntry.name << "' not found" << TestLog::EndMessage;
1720*35238bceSAndroid Build Coastguard Worker isOk = false;
1721*35238bceSAndroid Build Coastguard Worker continue;
1722*35238bceSAndroid Build Coastguard Worker }
1723*35238bceSAndroid Build Coastguard Worker
1724*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &cmpEntry = cmpLayout.uniforms[cmpEntryNdx];
1725*35238bceSAndroid Build Coastguard Worker
1726*35238bceSAndroid Build Coastguard Worker if (refEntry.type != cmpEntry.type || refEntry.size != cmpEntry.size ||
1727*35238bceSAndroid Build Coastguard Worker refEntry.offset != cmpEntry.offset || refEntry.arrayStride != cmpEntry.arrayStride ||
1728*35238bceSAndroid Build Coastguard Worker refEntry.matrixStride != cmpEntry.matrixStride || refEntry.isRowMajor != cmpEntry.isRowMajor)
1729*35238bceSAndroid Build Coastguard Worker {
1730*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Layout mismatch in '" << refEntry.name << "':\n"
1731*35238bceSAndroid Build Coastguard Worker << " expected: type = " << glu::getDataTypeName(refEntry.type) << ", size = " << refEntry.size
1732*35238bceSAndroid Build Coastguard Worker << ", offset = " << refEntry.offset << ", array stride = " << refEntry.arrayStride
1733*35238bceSAndroid Build Coastguard Worker << ", matrix stride = " << refEntry.matrixStride
1734*35238bceSAndroid Build Coastguard Worker << ", row major = " << (refEntry.isRowMajor ? "true" : "false") << "\n"
1735*35238bceSAndroid Build Coastguard Worker << " got: type = " << glu::getDataTypeName(cmpEntry.type) << ", size = " << cmpEntry.size
1736*35238bceSAndroid Build Coastguard Worker << ", offset = " << cmpEntry.offset << ", array stride = " << cmpEntry.arrayStride
1737*35238bceSAndroid Build Coastguard Worker << ", matrix stride = " << cmpEntry.matrixStride
1738*35238bceSAndroid Build Coastguard Worker << ", row major = " << (cmpEntry.isRowMajor ? "true" : "false") << TestLog::EndMessage;
1739*35238bceSAndroid Build Coastguard Worker isOk = false;
1740*35238bceSAndroid Build Coastguard Worker }
1741*35238bceSAndroid Build Coastguard Worker }
1742*35238bceSAndroid Build Coastguard Worker }
1743*35238bceSAndroid Build Coastguard Worker
1744*35238bceSAndroid Build Coastguard Worker return isOk;
1745*35238bceSAndroid Build Coastguard Worker }
1746*35238bceSAndroid Build Coastguard Worker
compareSharedBlocks(const UniformLayout & refLayout,const UniformLayout & cmpLayout) const1747*35238bceSAndroid Build Coastguard Worker bool UniformBlockCase::compareSharedBlocks(const UniformLayout &refLayout, const UniformLayout &cmpLayout) const
1748*35238bceSAndroid Build Coastguard Worker {
1749*35238bceSAndroid Build Coastguard Worker TestLog &log = m_testCtx.getLog();
1750*35238bceSAndroid Build Coastguard Worker bool isOk = true;
1751*35238bceSAndroid Build Coastguard Worker int numBlocks = m_interface.getNumUniformBlocks();
1752*35238bceSAndroid Build Coastguard Worker
1753*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1754*35238bceSAndroid Build Coastguard Worker {
1755*35238bceSAndroid Build Coastguard Worker const UniformBlock &block = m_interface.getUniformBlock(blockNdx);
1756*35238bceSAndroid Build Coastguard Worker bool isArray = block.isArray();
1757*35238bceSAndroid Build Coastguard Worker std::string instanceName = string(block.getBlockName()) + (isArray ? "[0]" : "");
1758*35238bceSAndroid Build Coastguard Worker int refBlockNdx = refLayout.getBlockIndex(instanceName.c_str());
1759*35238bceSAndroid Build Coastguard Worker int cmpBlockNdx = cmpLayout.getBlockIndex(instanceName.c_str());
1760*35238bceSAndroid Build Coastguard Worker bool isUsed = (block.getFlags() & (DECLARE_VERTEX | DECLARE_FRAGMENT)) != 0;
1761*35238bceSAndroid Build Coastguard Worker
1762*35238bceSAndroid Build Coastguard Worker if ((block.getFlags() & LAYOUT_SHARED) == 0)
1763*35238bceSAndroid Build Coastguard Worker continue; // Not shared layout.
1764*35238bceSAndroid Build Coastguard Worker
1765*35238bceSAndroid Build Coastguard Worker DE_ASSERT(refBlockNdx >= 0);
1766*35238bceSAndroid Build Coastguard Worker
1767*35238bceSAndroid Build Coastguard Worker if (cmpBlockNdx < 0)
1768*35238bceSAndroid Build Coastguard Worker {
1769*35238bceSAndroid Build Coastguard Worker // Not found, should it?
1770*35238bceSAndroid Build Coastguard Worker if (isUsed)
1771*35238bceSAndroid Build Coastguard Worker {
1772*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Uniform block '" << instanceName << "' not found"
1773*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
1774*35238bceSAndroid Build Coastguard Worker isOk = false;
1775*35238bceSAndroid Build Coastguard Worker }
1776*35238bceSAndroid Build Coastguard Worker
1777*35238bceSAndroid Build Coastguard Worker continue; // Skip block.
1778*35238bceSAndroid Build Coastguard Worker }
1779*35238bceSAndroid Build Coastguard Worker
1780*35238bceSAndroid Build Coastguard Worker const BlockLayoutEntry &refBlockLayout = refLayout.blocks[refBlockNdx];
1781*35238bceSAndroid Build Coastguard Worker const BlockLayoutEntry &cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx];
1782*35238bceSAndroid Build Coastguard Worker
1783*35238bceSAndroid Build Coastguard Worker if (refBlockLayout.activeUniformIndices.size() != cmpBlockLayout.activeUniformIndices.size())
1784*35238bceSAndroid Build Coastguard Worker {
1785*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Number of active uniforms differ in block '" << instanceName
1786*35238bceSAndroid Build Coastguard Worker << "' (expected " << refBlockLayout.activeUniformIndices.size() << ", got "
1787*35238bceSAndroid Build Coastguard Worker << cmpBlockLayout.activeUniformIndices.size() << ")" << TestLog::EndMessage;
1788*35238bceSAndroid Build Coastguard Worker isOk = false;
1789*35238bceSAndroid Build Coastguard Worker }
1790*35238bceSAndroid Build Coastguard Worker
1791*35238bceSAndroid Build Coastguard Worker for (vector<int>::const_iterator ndxIter = refBlockLayout.activeUniformIndices.begin();
1792*35238bceSAndroid Build Coastguard Worker ndxIter != refBlockLayout.activeUniformIndices.end(); ndxIter++)
1793*35238bceSAndroid Build Coastguard Worker {
1794*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &refEntry = refLayout.uniforms[*ndxIter];
1795*35238bceSAndroid Build Coastguard Worker int cmpEntryNdx = cmpLayout.getUniformIndex(refEntry.name.c_str());
1796*35238bceSAndroid Build Coastguard Worker
1797*35238bceSAndroid Build Coastguard Worker if (cmpEntryNdx < 0)
1798*35238bceSAndroid Build Coastguard Worker {
1799*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Uniform '" << refEntry.name << "' not found" << TestLog::EndMessage;
1800*35238bceSAndroid Build Coastguard Worker isOk = false;
1801*35238bceSAndroid Build Coastguard Worker continue;
1802*35238bceSAndroid Build Coastguard Worker }
1803*35238bceSAndroid Build Coastguard Worker
1804*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &cmpEntry = cmpLayout.uniforms[cmpEntryNdx];
1805*35238bceSAndroid Build Coastguard Worker
1806*35238bceSAndroid Build Coastguard Worker if (refEntry.type != cmpEntry.type || refEntry.size != cmpEntry.size ||
1807*35238bceSAndroid Build Coastguard Worker refEntry.isRowMajor != cmpEntry.isRowMajor)
1808*35238bceSAndroid Build Coastguard Worker {
1809*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Layout mismatch in '" << refEntry.name << "':\n"
1810*35238bceSAndroid Build Coastguard Worker << " expected: type = " << glu::getDataTypeName(refEntry.type) << ", size = " << refEntry.size
1811*35238bceSAndroid Build Coastguard Worker << ", row major = " << (refEntry.isRowMajor ? "true" : "false") << "\n"
1812*35238bceSAndroid Build Coastguard Worker << " got: type = " << glu::getDataTypeName(cmpEntry.type) << ", size = " << cmpEntry.size
1813*35238bceSAndroid Build Coastguard Worker << ", row major = " << (cmpEntry.isRowMajor ? "true" : "false") << TestLog::EndMessage;
1814*35238bceSAndroid Build Coastguard Worker isOk = false;
1815*35238bceSAndroid Build Coastguard Worker }
1816*35238bceSAndroid Build Coastguard Worker }
1817*35238bceSAndroid Build Coastguard Worker }
1818*35238bceSAndroid Build Coastguard Worker
1819*35238bceSAndroid Build Coastguard Worker return isOk;
1820*35238bceSAndroid Build Coastguard Worker }
1821*35238bceSAndroid Build Coastguard Worker
compareTypes(const UniformLayout & refLayout,const UniformLayout & cmpLayout) const1822*35238bceSAndroid Build Coastguard Worker bool UniformBlockCase::compareTypes(const UniformLayout &refLayout, const UniformLayout &cmpLayout) const
1823*35238bceSAndroid Build Coastguard Worker {
1824*35238bceSAndroid Build Coastguard Worker TestLog &log = m_testCtx.getLog();
1825*35238bceSAndroid Build Coastguard Worker bool isOk = true;
1826*35238bceSAndroid Build Coastguard Worker int numBlocks = m_interface.getNumUniformBlocks();
1827*35238bceSAndroid Build Coastguard Worker
1828*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1829*35238bceSAndroid Build Coastguard Worker {
1830*35238bceSAndroid Build Coastguard Worker const UniformBlock &block = m_interface.getUniformBlock(blockNdx);
1831*35238bceSAndroid Build Coastguard Worker bool isArray = block.isArray();
1832*35238bceSAndroid Build Coastguard Worker int numInstances = isArray ? block.getArraySize() : 1;
1833*35238bceSAndroid Build Coastguard Worker
1834*35238bceSAndroid Build Coastguard Worker for (int instanceNdx = 0; instanceNdx < numInstances; instanceNdx++)
1835*35238bceSAndroid Build Coastguard Worker {
1836*35238bceSAndroid Build Coastguard Worker std::ostringstream instanceName;
1837*35238bceSAndroid Build Coastguard Worker
1838*35238bceSAndroid Build Coastguard Worker instanceName << block.getBlockName();
1839*35238bceSAndroid Build Coastguard Worker if (isArray)
1840*35238bceSAndroid Build Coastguard Worker instanceName << "[" << instanceNdx << "]";
1841*35238bceSAndroid Build Coastguard Worker
1842*35238bceSAndroid Build Coastguard Worker int cmpBlockNdx = cmpLayout.getBlockIndex(instanceName.str().c_str());
1843*35238bceSAndroid Build Coastguard Worker
1844*35238bceSAndroid Build Coastguard Worker if (cmpBlockNdx < 0)
1845*35238bceSAndroid Build Coastguard Worker continue;
1846*35238bceSAndroid Build Coastguard Worker
1847*35238bceSAndroid Build Coastguard Worker const BlockLayoutEntry &cmpBlockLayout = cmpLayout.blocks[cmpBlockNdx];
1848*35238bceSAndroid Build Coastguard Worker
1849*35238bceSAndroid Build Coastguard Worker for (vector<int>::const_iterator ndxIter = cmpBlockLayout.activeUniformIndices.begin();
1850*35238bceSAndroid Build Coastguard Worker ndxIter != cmpBlockLayout.activeUniformIndices.end(); ndxIter++)
1851*35238bceSAndroid Build Coastguard Worker {
1852*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &cmpEntry = cmpLayout.uniforms[*ndxIter];
1853*35238bceSAndroid Build Coastguard Worker int refEntryNdx = refLayout.getUniformIndex(cmpEntry.name.c_str());
1854*35238bceSAndroid Build Coastguard Worker
1855*35238bceSAndroid Build Coastguard Worker if (refEntryNdx < 0)
1856*35238bceSAndroid Build Coastguard Worker {
1857*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Uniform '" << cmpEntry.name << "' not found in reference layout"
1858*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
1859*35238bceSAndroid Build Coastguard Worker isOk = false;
1860*35238bceSAndroid Build Coastguard Worker continue;
1861*35238bceSAndroid Build Coastguard Worker }
1862*35238bceSAndroid Build Coastguard Worker
1863*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &refEntry = refLayout.uniforms[refEntryNdx];
1864*35238bceSAndroid Build Coastguard Worker
1865*35238bceSAndroid Build Coastguard Worker // \todo [2012-11-26 pyry] Should we check other properties as well?
1866*35238bceSAndroid Build Coastguard Worker if (refEntry.type != cmpEntry.type)
1867*35238bceSAndroid Build Coastguard Worker {
1868*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Uniform type mismatch in '" << refEntry.name << "':\n"
1869*35238bceSAndroid Build Coastguard Worker << " expected: " << glu::getDataTypeName(refEntry.type) << "\n"
1870*35238bceSAndroid Build Coastguard Worker << " got: " << glu::getDataTypeName(cmpEntry.type) << TestLog::EndMessage;
1871*35238bceSAndroid Build Coastguard Worker isOk = false;
1872*35238bceSAndroid Build Coastguard Worker }
1873*35238bceSAndroid Build Coastguard Worker }
1874*35238bceSAndroid Build Coastguard Worker }
1875*35238bceSAndroid Build Coastguard Worker }
1876*35238bceSAndroid Build Coastguard Worker
1877*35238bceSAndroid Build Coastguard Worker return isOk;
1878*35238bceSAndroid Build Coastguard Worker }
1879*35238bceSAndroid Build Coastguard Worker
checkLayoutIndices(const UniformLayout & layout) const1880*35238bceSAndroid Build Coastguard Worker bool UniformBlockCase::checkLayoutIndices(const UniformLayout &layout) const
1881*35238bceSAndroid Build Coastguard Worker {
1882*35238bceSAndroid Build Coastguard Worker TestLog &log = m_testCtx.getLog();
1883*35238bceSAndroid Build Coastguard Worker int numUniforms = (int)layout.uniforms.size();
1884*35238bceSAndroid Build Coastguard Worker int numBlocks = (int)layout.blocks.size();
1885*35238bceSAndroid Build Coastguard Worker bool isOk = true;
1886*35238bceSAndroid Build Coastguard Worker
1887*35238bceSAndroid Build Coastguard Worker // Check uniform block indices.
1888*35238bceSAndroid Build Coastguard Worker for (int uniformNdx = 0; uniformNdx < numUniforms; uniformNdx++)
1889*35238bceSAndroid Build Coastguard Worker {
1890*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &uniform = layout.uniforms[uniformNdx];
1891*35238bceSAndroid Build Coastguard Worker
1892*35238bceSAndroid Build Coastguard Worker if (uniform.blockNdx < 0 || !deInBounds32(uniform.blockNdx, 0, numBlocks))
1893*35238bceSAndroid Build Coastguard Worker {
1894*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Invalid block index in uniform '" << uniform.name << "'"
1895*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
1896*35238bceSAndroid Build Coastguard Worker isOk = false;
1897*35238bceSAndroid Build Coastguard Worker }
1898*35238bceSAndroid Build Coastguard Worker }
1899*35238bceSAndroid Build Coastguard Worker
1900*35238bceSAndroid Build Coastguard Worker // Check active uniforms.
1901*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
1902*35238bceSAndroid Build Coastguard Worker {
1903*35238bceSAndroid Build Coastguard Worker const BlockLayoutEntry &block = layout.blocks[blockNdx];
1904*35238bceSAndroid Build Coastguard Worker
1905*35238bceSAndroid Build Coastguard Worker for (vector<int>::const_iterator uniformIter = block.activeUniformIndices.begin();
1906*35238bceSAndroid Build Coastguard Worker uniformIter != block.activeUniformIndices.end(); uniformIter++)
1907*35238bceSAndroid Build Coastguard Worker {
1908*35238bceSAndroid Build Coastguard Worker if (!deInBounds32(*uniformIter, 0, numUniforms))
1909*35238bceSAndroid Build Coastguard Worker {
1910*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Invalid active uniform index " << *uniformIter << " in block '"
1911*35238bceSAndroid Build Coastguard Worker << block.name << "'" << TestLog::EndMessage;
1912*35238bceSAndroid Build Coastguard Worker isOk = false;
1913*35238bceSAndroid Build Coastguard Worker }
1914*35238bceSAndroid Build Coastguard Worker }
1915*35238bceSAndroid Build Coastguard Worker }
1916*35238bceSAndroid Build Coastguard Worker
1917*35238bceSAndroid Build Coastguard Worker return isOk;
1918*35238bceSAndroid Build Coastguard Worker }
1919*35238bceSAndroid Build Coastguard Worker
checkLayoutBounds(const UniformLayout & layout) const1920*35238bceSAndroid Build Coastguard Worker bool UniformBlockCase::checkLayoutBounds(const UniformLayout &layout) const
1921*35238bceSAndroid Build Coastguard Worker {
1922*35238bceSAndroid Build Coastguard Worker TestLog &log = m_testCtx.getLog();
1923*35238bceSAndroid Build Coastguard Worker int numUniforms = (int)layout.uniforms.size();
1924*35238bceSAndroid Build Coastguard Worker bool isOk = true;
1925*35238bceSAndroid Build Coastguard Worker
1926*35238bceSAndroid Build Coastguard Worker for (int uniformNdx = 0; uniformNdx < numUniforms; uniformNdx++)
1927*35238bceSAndroid Build Coastguard Worker {
1928*35238bceSAndroid Build Coastguard Worker const UniformLayoutEntry &uniform = layout.uniforms[uniformNdx];
1929*35238bceSAndroid Build Coastguard Worker
1930*35238bceSAndroid Build Coastguard Worker if (uniform.blockNdx < 0)
1931*35238bceSAndroid Build Coastguard Worker continue;
1932*35238bceSAndroid Build Coastguard Worker
1933*35238bceSAndroid Build Coastguard Worker const BlockLayoutEntry &block = layout.blocks[uniform.blockNdx];
1934*35238bceSAndroid Build Coastguard Worker bool isMatrix = glu::isDataTypeMatrix(uniform.type);
1935*35238bceSAndroid Build Coastguard Worker int numVecs = isMatrix ? (uniform.isRowMajor ? glu::getDataTypeMatrixNumRows(uniform.type) :
1936*35238bceSAndroid Build Coastguard Worker glu::getDataTypeMatrixNumColumns(uniform.type)) :
1937*35238bceSAndroid Build Coastguard Worker 1;
1938*35238bceSAndroid Build Coastguard Worker int numComps = isMatrix ? (uniform.isRowMajor ? glu::getDataTypeMatrixNumColumns(uniform.type) :
1939*35238bceSAndroid Build Coastguard Worker glu::getDataTypeMatrixNumRows(uniform.type)) :
1940*35238bceSAndroid Build Coastguard Worker glu::getDataTypeScalarSize(uniform.type);
1941*35238bceSAndroid Build Coastguard Worker int numElements = uniform.size;
1942*35238bceSAndroid Build Coastguard Worker const int compSize = sizeof(uint32_t);
1943*35238bceSAndroid Build Coastguard Worker int vecSize = numComps * compSize;
1944*35238bceSAndroid Build Coastguard Worker
1945*35238bceSAndroid Build Coastguard Worker int minOffset = 0;
1946*35238bceSAndroid Build Coastguard Worker int maxOffset = 0;
1947*35238bceSAndroid Build Coastguard Worker
1948*35238bceSAndroid Build Coastguard Worker // For negative strides.
1949*35238bceSAndroid Build Coastguard Worker minOffset = de::min(minOffset, (numVecs - 1) * uniform.matrixStride);
1950*35238bceSAndroid Build Coastguard Worker minOffset = de::min(minOffset, (numElements - 1) * uniform.arrayStride);
1951*35238bceSAndroid Build Coastguard Worker minOffset = de::min(minOffset, (numElements - 1) * uniform.arrayStride + (numVecs - 1) * uniform.matrixStride);
1952*35238bceSAndroid Build Coastguard Worker
1953*35238bceSAndroid Build Coastguard Worker maxOffset = de::max(maxOffset, vecSize);
1954*35238bceSAndroid Build Coastguard Worker maxOffset = de::max(maxOffset, (numVecs - 1) * uniform.matrixStride + vecSize);
1955*35238bceSAndroid Build Coastguard Worker maxOffset = de::max(maxOffset, (numElements - 1) * uniform.arrayStride + vecSize);
1956*35238bceSAndroid Build Coastguard Worker maxOffset = de::max(maxOffset,
1957*35238bceSAndroid Build Coastguard Worker (numElements - 1) * uniform.arrayStride + (numVecs - 1) * uniform.matrixStride + vecSize);
1958*35238bceSAndroid Build Coastguard Worker
1959*35238bceSAndroid Build Coastguard Worker if (uniform.offset + minOffset < 0 || uniform.offset + maxOffset > block.size)
1960*35238bceSAndroid Build Coastguard Worker {
1961*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Error: Uniform '" << uniform.name << "' out of block bounds"
1962*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
1963*35238bceSAndroid Build Coastguard Worker isOk = false;
1964*35238bceSAndroid Build Coastguard Worker }
1965*35238bceSAndroid Build Coastguard Worker }
1966*35238bceSAndroid Build Coastguard Worker
1967*35238bceSAndroid Build Coastguard Worker return isOk;
1968*35238bceSAndroid Build Coastguard Worker }
1969*35238bceSAndroid Build Coastguard Worker
checkIndexQueries(uint32_t program,const UniformLayout & layout) const1970*35238bceSAndroid Build Coastguard Worker bool UniformBlockCase::checkIndexQueries(uint32_t program, const UniformLayout &layout) const
1971*35238bceSAndroid Build Coastguard Worker {
1972*35238bceSAndroid Build Coastguard Worker tcu::TestLog &log = m_testCtx.getLog();
1973*35238bceSAndroid Build Coastguard Worker const glw::Functions &gl = m_renderCtx.getFunctions();
1974*35238bceSAndroid Build Coastguard Worker bool allOk = true;
1975*35238bceSAndroid Build Coastguard Worker
1976*35238bceSAndroid Build Coastguard Worker // \note Spec mandates that uniform blocks are assigned consecutive locations from 0
1977*35238bceSAndroid Build Coastguard Worker // to ACTIVE_UNIFORM_BLOCKS. BlockLayoutEntries are stored in that order in UniformLayout.
1978*35238bceSAndroid Build Coastguard Worker for (int blockNdx = 0; blockNdx < (int)layout.blocks.size(); blockNdx++)
1979*35238bceSAndroid Build Coastguard Worker {
1980*35238bceSAndroid Build Coastguard Worker const BlockLayoutEntry &block = layout.blocks[blockNdx];
1981*35238bceSAndroid Build Coastguard Worker const int queriedNdx = gl.getUniformBlockIndex(program, block.name.c_str());
1982*35238bceSAndroid Build Coastguard Worker
1983*35238bceSAndroid Build Coastguard Worker if (queriedNdx != blockNdx)
1984*35238bceSAndroid Build Coastguard Worker {
1985*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "ERROR: glGetUniformBlockIndex(" << block.name << ") returned " << queriedNdx
1986*35238bceSAndroid Build Coastguard Worker << ", expected " << blockNdx << "!" << TestLog::EndMessage;
1987*35238bceSAndroid Build Coastguard Worker allOk = false;
1988*35238bceSAndroid Build Coastguard Worker }
1989*35238bceSAndroid Build Coastguard Worker
1990*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex()");
1991*35238bceSAndroid Build Coastguard Worker }
1992*35238bceSAndroid Build Coastguard Worker
1993*35238bceSAndroid Build Coastguard Worker return allOk;
1994*35238bceSAndroid Build Coastguard Worker }
1995*35238bceSAndroid Build Coastguard Worker
render(uint32_t program) const1996*35238bceSAndroid Build Coastguard Worker bool UniformBlockCase::render(uint32_t program) const
1997*35238bceSAndroid Build Coastguard Worker {
1998*35238bceSAndroid Build Coastguard Worker tcu::TestLog &log = m_testCtx.getLog();
1999*35238bceSAndroid Build Coastguard Worker const glw::Functions &gl = m_renderCtx.getFunctions();
2000*35238bceSAndroid Build Coastguard Worker de::Random rnd(deStringHash(getName()));
2001*35238bceSAndroid Build Coastguard Worker const tcu::RenderTarget &renderTarget = m_renderCtx.getRenderTarget();
2002*35238bceSAndroid Build Coastguard Worker const int viewportW = de::min(renderTarget.getWidth(), 128);
2003*35238bceSAndroid Build Coastguard Worker const int viewportH = de::min(renderTarget.getHeight(), 128);
2004*35238bceSAndroid Build Coastguard Worker const int viewportX = rnd.getInt(0, renderTarget.getWidth() - viewportW);
2005*35238bceSAndroid Build Coastguard Worker const int viewportY = rnd.getInt(0, renderTarget.getHeight() - viewportH);
2006*35238bceSAndroid Build Coastguard Worker
2007*35238bceSAndroid Build Coastguard Worker gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
2008*35238bceSAndroid Build Coastguard Worker gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2009*35238bceSAndroid Build Coastguard Worker
2010*35238bceSAndroid Build Coastguard Worker // Draw
2011*35238bceSAndroid Build Coastguard Worker {
2012*35238bceSAndroid Build Coastguard Worker const float position[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, +1.0f, 0.0f, 1.0f,
2013*35238bceSAndroid Build Coastguard Worker +1.0f, -1.0f, 0.0f, 1.0f, +1.0f, +1.0f, 0.0f, 1.0f};
2014*35238bceSAndroid Build Coastguard Worker const uint16_t indices[] = {0, 1, 2, 2, 1, 3};
2015*35238bceSAndroid Build Coastguard Worker
2016*35238bceSAndroid Build Coastguard Worker gl.viewport(viewportX, viewportY, viewportW, viewportH);
2017*35238bceSAndroid Build Coastguard Worker
2018*35238bceSAndroid Build Coastguard Worker glu::VertexArrayBinding posArray = glu::va::Float("a_position", 4, 4, 0, &position[0]);
2019*35238bceSAndroid Build Coastguard Worker glu::draw(m_renderCtx, program, 1, &posArray, glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
2020*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
2021*35238bceSAndroid Build Coastguard Worker }
2022*35238bceSAndroid Build Coastguard Worker
2023*35238bceSAndroid Build Coastguard Worker // Verify that all pixels are white.
2024*35238bceSAndroid Build Coastguard Worker {
2025*35238bceSAndroid Build Coastguard Worker tcu::Surface pixels(viewportW, viewportH);
2026*35238bceSAndroid Build Coastguard Worker int numFailedPixels = 0;
2027*35238bceSAndroid Build Coastguard Worker
2028*35238bceSAndroid Build Coastguard Worker glu::readPixels(m_renderCtx, viewportX, viewportY, pixels.getAccess());
2029*35238bceSAndroid Build Coastguard Worker GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels failed");
2030*35238bceSAndroid Build Coastguard Worker
2031*35238bceSAndroid Build Coastguard Worker for (int y = 0; y < pixels.getHeight(); y++)
2032*35238bceSAndroid Build Coastguard Worker {
2033*35238bceSAndroid Build Coastguard Worker for (int x = 0; x < pixels.getWidth(); x++)
2034*35238bceSAndroid Build Coastguard Worker {
2035*35238bceSAndroid Build Coastguard Worker if (pixels.getPixel(x, y) != tcu::RGBA::white())
2036*35238bceSAndroid Build Coastguard Worker numFailedPixels += 1;
2037*35238bceSAndroid Build Coastguard Worker }
2038*35238bceSAndroid Build Coastguard Worker }
2039*35238bceSAndroid Build Coastguard Worker
2040*35238bceSAndroid Build Coastguard Worker if (numFailedPixels > 0)
2041*35238bceSAndroid Build Coastguard Worker {
2042*35238bceSAndroid Build Coastguard Worker log << TestLog::Image("Image", "Rendered image", pixels);
2043*35238bceSAndroid Build Coastguard Worker log << TestLog::Message << "Image comparison failed, got " << numFailedPixels << " non-white pixels"
2044*35238bceSAndroid Build Coastguard Worker << TestLog::EndMessage;
2045*35238bceSAndroid Build Coastguard Worker }
2046*35238bceSAndroid Build Coastguard Worker
2047*35238bceSAndroid Build Coastguard Worker return numFailedPixels == 0;
2048*35238bceSAndroid Build Coastguard Worker }
2049*35238bceSAndroid Build Coastguard Worker }
2050*35238bceSAndroid Build Coastguard Worker
2051*35238bceSAndroid Build Coastguard Worker } // namespace gls
2052*35238bceSAndroid Build Coastguard Worker } // namespace deqp
2053