xref: /aosp_15_r20/external/deqp/modules/glshared/glsRandomUniformBlockCase.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 
RandomUniformBlockCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,glu::GLSLVersion glslVersion,const char * name,const char * description,BufferMode bufferMode,uint32_t features,uint32_t seed)39 RandomUniformBlockCase::RandomUniformBlockCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx,
40                                                glu::GLSLVersion glslVersion, const char *name, const char *description,
41                                                BufferMode bufferMode, uint32_t features, uint32_t seed)
42     : UniformBlockCase(testCtx, renderCtx, name, description, glslVersion, bufferMode)
43     , m_features(features)
44     , m_maxVertexBlocks((features & FEATURE_VERTEX_BLOCKS) ? 4 : 0)
45     , m_maxFragmentBlocks((features & FEATURE_FRAGMENT_BLOCKS) ? 4 : 0)
46     , m_maxSharedBlocks((features & FEATURE_SHARED_BLOCKS) ? 4 : 0)
47     , m_maxInstances((features & FEATURE_INSTANCE_ARRAYS) ? 3 : 0)
48     , m_maxArrayLength((features & FEATURE_ARRAYS) ? 8 : 0)
49     , m_maxStructDepth((features & FEATURE_STRUCTS) ? 2 : 0)
50     , m_maxBlockMembers(5)
51     , m_maxStructMembers(4)
52     , m_seed(seed)
53     , m_blockNdx(1)
54     , m_uniformNdx(1)
55     , m_structNdx(1)
56 {
57 }
58 
init(void)59 void RandomUniformBlockCase::init(void)
60 {
61     de::Random rnd(m_seed);
62 
63     int numShared     = m_maxSharedBlocks > 0 ? rnd.getInt(1, m_maxSharedBlocks) : 0;
64     int numVtxBlocks  = m_maxVertexBlocks - numShared > 0 ? rnd.getInt(1, m_maxVertexBlocks - numShared) : 0;
65     int numFragBlocks = m_maxFragmentBlocks - numShared > 0 ? rnd.getInt(1, m_maxFragmentBlocks - numShared) : 0;
66 
67     for (int ndx = 0; ndx < numShared; ndx++)
68         generateBlock(rnd, DECLARE_VERTEX | DECLARE_FRAGMENT);
69 
70     for (int ndx = 0; ndx < numVtxBlocks; ndx++)
71         generateBlock(rnd, DECLARE_VERTEX);
72 
73     for (int ndx = 0; ndx < numFragBlocks; ndx++)
74         generateBlock(rnd, DECLARE_FRAGMENT);
75 }
76 
generateBlock(de::Random & rnd,uint32_t layoutFlags)77 void RandomUniformBlockCase::generateBlock(de::Random &rnd, uint32_t layoutFlags)
78 {
79     DE_ASSERT(m_blockNdx <= 'z' - 'a');
80 
81     const float instanceArrayWeight = 0.3f;
82     UniformBlock &block             = m_interface.allocBlock((string("Block") + (char)('A' + m_blockNdx)).c_str());
83     int numInstances = (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
84     int numUniforms  = rnd.getInt(1, m_maxBlockMembers);
85 
86     if (numInstances > 0)
87         block.setArraySize(numInstances);
88 
89     if (numInstances > 0 || rnd.getBool())
90         block.setInstanceName((string("block") + (char)('A' + m_blockNdx)).c_str());
91 
92     // Layout flag candidates.
93     vector<uint32_t> layoutFlagCandidates;
94     layoutFlagCandidates.push_back(0);
95     if (m_features & FEATURE_PACKED_LAYOUT)
96         layoutFlagCandidates.push_back(LAYOUT_SHARED);
97     if ((m_features & FEATURE_SHARED_LAYOUT) && ((layoutFlags & DECLARE_BOTH) != DECLARE_BOTH))
98         layoutFlagCandidates.push_back(LAYOUT_PACKED); // \note packed layout can only be used in a single shader stage.
99     if (m_features & FEATURE_STD140_LAYOUT)
100         layoutFlagCandidates.push_back(LAYOUT_STD140);
101 
102     layoutFlags |= rnd.choose<uint32_t>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
103 
104     if (m_features & FEATURE_MATRIX_LAYOUT)
105     {
106         static const uint32_t matrixCandidates[] = {0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR};
107         layoutFlags |=
108             rnd.choose<uint32_t>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
109     }
110 
111     block.setFlags(layoutFlags);
112 
113     for (int ndx = 0; ndx < numUniforms; ndx++)
114         generateUniform(rnd, block);
115 
116     m_blockNdx += 1;
117 }
118 
genName(char first,char last,int ndx)119 static std::string genName(char first, char last, int ndx)
120 {
121     std::string str = "";
122     int alphabetLen = last - first + 1;
123 
124     while (ndx > alphabetLen)
125     {
126         str.insert(str.begin(), (char)(first + ((ndx - 1) % alphabetLen)));
127         ndx = ((ndx - 1) / alphabetLen);
128     }
129 
130     str.insert(str.begin(), (char)(first + (ndx % (alphabetLen + 1)) - 1));
131 
132     return str;
133 }
134 
generateUniform(de::Random & rnd,UniformBlock & block)135 void RandomUniformBlockCase::generateUniform(de::Random &rnd, UniformBlock &block)
136 {
137     const float unusedVtxWeight  = 0.15f;
138     const float unusedFragWeight = 0.15f;
139     bool unusedOk                = (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
140     uint32_t flags               = 0;
141     std::string name             = genName('a', 'z', m_uniformNdx);
142     VarType type                 = generateType(rnd, 0, true);
143 
144     flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
145     flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
146 
147     block.addUniform(Uniform(name.c_str(), type, flags));
148 
149     m_uniformNdx += 1;
150 }
151 
generateType(de::Random & rnd,int typeDepth,bool arrayOk)152 VarType RandomUniformBlockCase::generateType(de::Random &rnd, int typeDepth, bool arrayOk)
153 {
154     const float structWeight = 0.1f;
155     const float arrayWeight  = 0.1f;
156 
157     if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
158     {
159         const float unusedVtxWeight  = 0.15f;
160         const float unusedFragWeight = 0.15f;
161         bool unusedOk                = (m_features & FEATURE_UNUSED_MEMBERS) != 0;
162         vector<VarType> memberTypes;
163         int numMembers = rnd.getInt(1, m_maxStructMembers);
164 
165         // Generate members first so nested struct declarations are in correct order.
166         for (int ndx = 0; ndx < numMembers; ndx++)
167             memberTypes.push_back(generateType(rnd, typeDepth + 1, true));
168 
169         StructType &structType = m_interface.allocStruct((string("s") + genName('A', 'Z', m_structNdx)).c_str());
170         m_structNdx += 1;
171 
172         DE_ASSERT(numMembers <= 'Z' - 'A');
173         for (int ndx = 0; ndx < numMembers; ndx++)
174         {
175             uint32_t flags = 0;
176 
177             flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
178             flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
179 
180             structType.addMember((string("m") + (char)('A' + ndx)).c_str(), memberTypes[ndx], flags);
181         }
182 
183         return VarType(&structType);
184     }
185     else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
186     {
187         const bool arraysOfArraysOk = (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
188         const int arrayLength       = rnd.getInt(1, m_maxArrayLength);
189         VarType elementType         = generateType(rnd, typeDepth, arraysOfArraysOk);
190         return VarType(elementType, arrayLength);
191     }
192     else
193     {
194         vector<glu::DataType> typeCandidates;
195 
196         typeCandidates.push_back(glu::TYPE_FLOAT);
197         typeCandidates.push_back(glu::TYPE_INT);
198         typeCandidates.push_back(glu::TYPE_UINT);
199         typeCandidates.push_back(glu::TYPE_BOOL);
200 
201         if (m_features & FEATURE_VECTORS)
202         {
203             typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
204             typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
205             typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
206             typeCandidates.push_back(glu::TYPE_INT_VEC2);
207             typeCandidates.push_back(glu::TYPE_INT_VEC3);
208             typeCandidates.push_back(glu::TYPE_INT_VEC4);
209             typeCandidates.push_back(glu::TYPE_UINT_VEC2);
210             typeCandidates.push_back(glu::TYPE_UINT_VEC3);
211             typeCandidates.push_back(glu::TYPE_UINT_VEC4);
212             typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
213             typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
214             typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
215         }
216 
217         if (m_features & FEATURE_MATRICES)
218         {
219             typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
220             typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
221             typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
222             typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
223             typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
224             typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
225             typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
226             typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
227         }
228 
229         glu::DataType type = rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
230         uint32_t flags     = 0;
231 
232         if (!glu::isDataTypeBoolOrBVec(type))
233         {
234             // Precision.
235             static const uint32_t precisionCandidates[] = {PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH};
236             flags |= rnd.choose<uint32_t>(&precisionCandidates[0],
237                                           &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
238         }
239 
240         return VarType(type, flags);
241     }
242 }
243 
244 } // namespace gls
245 } // namespace deqp
246