Merge "Fix color change verification in dithering tests" into nougat-cts-dev am:...
[platform/upstream/VK-GL-CTS.git] / modules / glshared / glsRandomUniformBlockCase.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) Module
3  * -----------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Random uniform block layout case.
22  *//*--------------------------------------------------------------------*/
23
24 #include "glsRandomUniformBlockCase.hpp"
25 #include "tcuCommandLine.hpp"
26 #include "deRandom.hpp"
27 #include "deStringUtil.hpp"
28
29 using std::string;
30 using std::vector;
31
32 namespace deqp
33 {
34 namespace gls
35 {
36
37 using namespace gls::ub;
38
39 RandomUniformBlockCase::RandomUniformBlockCase (tcu::TestContext&       testCtx,
40                                                                                                 glu::RenderContext&     renderCtx,
41                                                                                                 glu::GLSLVersion        glslVersion,
42                                                                                                 const char*                     name,
43                                                                                                 const char*                     description,
44                                                                                                 BufferMode                      bufferMode,
45                                                                                                 deUint32                        features,
46                                                                                                 deUint32                        seed)
47         : UniformBlockCase              (testCtx, renderCtx, name, description, glslVersion, bufferMode)
48         , m_features                    (features)
49         , m_maxVertexBlocks             ((features & FEATURE_VERTEX_BLOCKS)             ? 4 : 0)
50         , m_maxFragmentBlocks   ((features & FEATURE_FRAGMENT_BLOCKS)   ? 4 : 0)
51         , m_maxSharedBlocks             ((features & FEATURE_SHARED_BLOCKS)             ? 4 : 0)
52         , m_maxInstances                ((features & FEATURE_INSTANCE_ARRAYS)   ? 3 : 0)
53         , m_maxArrayLength              ((features & FEATURE_ARRAYS)                    ? 8 : 0)
54         , m_maxStructDepth              ((features & FEATURE_STRUCTS)                   ? 2 : 0)
55         , m_maxBlockMembers             (5)
56         , m_maxStructMembers    (4)
57         , m_seed                                (seed)
58         , m_blockNdx                    (1)
59         , m_uniformNdx                  (1)
60         , m_structNdx                   (1)
61 {
62 }
63
64 void RandomUniformBlockCase::init (void)
65 {
66         de::Random rnd(m_seed);
67
68         int numShared           = m_maxSharedBlocks                             > 0     ? rnd.getInt(1, m_maxSharedBlocks)                              : 0;
69         int numVtxBlocks        = m_maxVertexBlocks-numShared   > 0     ? rnd.getInt(1, m_maxVertexBlocks-numShared)    : 0;
70         int     numFragBlocks   = m_maxFragmentBlocks-numShared > 0 ? rnd.getInt(1, m_maxFragmentBlocks-numShared)      : 0;
71
72         for (int ndx = 0; ndx < numShared; ndx++)
73                 generateBlock(rnd, DECLARE_VERTEX|DECLARE_FRAGMENT);
74
75         for (int ndx = 0; ndx < numVtxBlocks; ndx++)
76                 generateBlock(rnd, DECLARE_VERTEX);
77
78         for (int ndx = 0; ndx < numFragBlocks; ndx++)
79                 generateBlock(rnd, DECLARE_FRAGMENT);
80 }
81
82 void RandomUniformBlockCase::generateBlock (de::Random& rnd, deUint32 layoutFlags)
83 {
84         DE_ASSERT(m_blockNdx <= 'z' - 'a');
85
86         const float             instanceArrayWeight     = 0.3f;
87         UniformBlock&   block                           = m_interface.allocBlock((string("Block") + (char)('A' + m_blockNdx)).c_str());
88         int                             numInstances            = (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
89         int                             numUniforms                     = rnd.getInt(1, m_maxBlockMembers);
90
91         if (numInstances > 0)
92                 block.setArraySize(numInstances);
93
94         if (numInstances > 0 || rnd.getBool())
95                 block.setInstanceName((string("block") + (char)('A' + m_blockNdx)).c_str());
96
97         // Layout flag candidates.
98         vector<deUint32> layoutFlagCandidates;
99         layoutFlagCandidates.push_back(0);
100         if (m_features & FEATURE_PACKED_LAYOUT)
101                 layoutFlagCandidates.push_back(LAYOUT_SHARED);
102         if ((m_features & FEATURE_SHARED_LAYOUT) && ((layoutFlags & DECLARE_BOTH) != DECLARE_BOTH))
103                 layoutFlagCandidates.push_back(LAYOUT_PACKED); // \note packed layout can only be used in a single shader stage.
104         if (m_features & FEATURE_STD140_LAYOUT)
105                 layoutFlagCandidates.push_back(LAYOUT_STD140);
106
107         layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
108
109         if (m_features & FEATURE_MATRIX_LAYOUT)
110         {
111                 static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
112                 layoutFlags |= rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
113         }
114
115         block.setFlags(layoutFlags);
116
117         for (int ndx = 0; ndx < numUniforms; ndx++)
118                 generateUniform(rnd, block);
119
120         m_blockNdx += 1;
121 }
122
123 static std::string genName (char first, char last, int ndx)
124 {
125         std::string     str                     = "";
126         int                     alphabetLen     = last - first + 1;
127
128         while (ndx > alphabetLen)
129         {
130                 str.insert(str.begin(), (char)(first + ((ndx-1)%alphabetLen)));
131                 ndx = ((ndx-1) / alphabetLen);
132         }
133
134         str.insert(str.begin(), (char)(first + (ndx%(alphabetLen+1)) - 1));
135
136         return str;
137 }
138
139 void RandomUniformBlockCase::generateUniform (de::Random& rnd, UniformBlock& block)
140 {
141         const float             unusedVtxWeight         = 0.15f;
142         const float             unusedFragWeight        = 0.15f;
143         bool                    unusedOk                        = (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
144         deUint32                flags                           = 0;
145         std::string             name                            = genName('a', 'z', m_uniformNdx);
146         VarType                 type                            = generateType(rnd, 0, true);
147
148         flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)         ? UNUSED_VERTEX         : 0;
149         flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)        ? UNUSED_FRAGMENT       : 0;
150
151         block.addUniform(Uniform(name.c_str(), type, flags));
152
153         m_uniformNdx += 1;
154 }
155
156 VarType RandomUniformBlockCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk)
157 {
158         const float structWeight        = 0.1f;
159         const float arrayWeight         = 0.1f;
160
161         if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
162         {
163                 const float             unusedVtxWeight         = 0.15f;
164                 const float             unusedFragWeight        = 0.15f;
165                 bool                    unusedOk                        = (m_features & FEATURE_UNUSED_MEMBERS) != 0;
166                 vector<VarType> memberTypes;
167                 int                             numMembers = rnd.getInt(1, m_maxStructMembers);
168
169                 // Generate members first so nested struct declarations are in correct order.
170                 for (int ndx = 0; ndx < numMembers; ndx++)
171                         memberTypes.push_back(generateType(rnd, typeDepth+1, true));
172
173                 StructType& structType = m_interface.allocStruct((string("s") + genName('A', 'Z', m_structNdx)).c_str());
174                 m_structNdx += 1;
175
176                 DE_ASSERT(numMembers <= 'Z' - 'A');
177                 for (int ndx = 0; ndx < numMembers; ndx++)
178                 {
179                         deUint32 flags = 0;
180
181                         flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight)         ? UNUSED_VERTEX         : 0;
182                         flags |= (unusedOk && rnd.getFloat() < unusedFragWeight)        ? UNUSED_FRAGMENT       : 0;
183
184                         structType.addMember((string("m") + (char)('A' + ndx)).c_str(), memberTypes[ndx], flags);
185                 }
186
187                 return VarType(&structType);
188         }
189         else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
190         {
191                 const bool      arraysOfArraysOk        = (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
192                 const int       arrayLength                     = rnd.getInt(1, m_maxArrayLength);
193                 VarType elementType     = generateType(rnd, typeDepth, arraysOfArraysOk);
194                 return VarType(elementType, arrayLength);
195         }
196         else
197         {
198                 vector<glu::DataType> typeCandidates;
199
200                 typeCandidates.push_back(glu::TYPE_FLOAT);
201                 typeCandidates.push_back(glu::TYPE_INT);
202                 typeCandidates.push_back(glu::TYPE_UINT);
203                 typeCandidates.push_back(glu::TYPE_BOOL);
204
205                 if (m_features & FEATURE_VECTORS)
206                 {
207                         typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
208                         typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
209                         typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
210                         typeCandidates.push_back(glu::TYPE_INT_VEC2);
211                         typeCandidates.push_back(glu::TYPE_INT_VEC3);
212                         typeCandidates.push_back(glu::TYPE_INT_VEC4);
213                         typeCandidates.push_back(glu::TYPE_UINT_VEC2);
214                         typeCandidates.push_back(glu::TYPE_UINT_VEC3);
215                         typeCandidates.push_back(glu::TYPE_UINT_VEC4);
216                         typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
217                         typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
218                         typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
219                 }
220
221                 if (m_features & FEATURE_MATRICES)
222                 {
223                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
224                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
225                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
226                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
227                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
228                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
229                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
230                         typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
231                 }
232
233                 glu::DataType   type    = rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
234                 deUint32                flags   = 0;
235
236                 if (!glu::isDataTypeBoolOrBVec(type))
237                 {
238                         // Precision.
239                         static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
240                         flags |= rnd.choose<deUint32>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
241                 }
242
243                 return VarType(type, flags);
244         }
245 }
246
247 } // gls
248 } // deqp