xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fUniformBlockTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 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 Uniform block tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fUniformBlockTests.hpp"
25 #include "glsUniformBlockCase.hpp"
26 #include "glsRandomUniformBlockCase.hpp"
27 #include "tcuCommandLine.hpp"
28 #include "deRandom.hpp"
29 #include "deStringUtil.hpp"
30 
31 using std::string;
32 using std::vector;
33 
34 namespace deqp
35 {
36 namespace gles31
37 {
38 namespace Functional
39 {
40 namespace
41 {
42 
43 using gls::RandomUniformBlockCase;
44 using gls::UniformBlockCase;
45 using namespace gls::ub;
46 
createRandomCaseGroup(tcu::TestCaseGroup * parentGroup,Context & context,const char * groupName,const char * description,UniformBlockCase::BufferMode bufferMode,uint32_t features,int numCases,uint32_t baseSeed)47 void createRandomCaseGroup(tcu::TestCaseGroup *parentGroup, Context &context, const char *groupName,
48                            const char *description, UniformBlockCase::BufferMode bufferMode, uint32_t features,
49                            int numCases, uint32_t baseSeed)
50 {
51     tcu::TestCaseGroup *group = new tcu::TestCaseGroup(context.getTestContext(), groupName, description);
52     parentGroup->addChild(group);
53 
54     baseSeed += (uint32_t)context.getTestContext().getCommandLine().getBaseSeed();
55 
56     for (int ndx = 0; ndx < numCases; ndx++)
57         group->addChild(new RandomUniformBlockCase(context.getTestContext(), context.getRenderContext(),
58                                                    glu::GLSL_VERSION_310_ES, de::toString(ndx).c_str(), "", bufferMode,
59                                                    features, (uint32_t)ndx + baseSeed));
60 }
61 
62 class BlockBasicTypeCase : public UniformBlockCase
63 {
64 public:
BlockBasicTypeCase(Context & context,const char * name,const char * description,const VarType & type,uint32_t layoutFlags,int numInstances)65     BlockBasicTypeCase(Context &context, const char *name, const char *description, const VarType &type,
66                        uint32_t layoutFlags, int numInstances)
67         : UniformBlockCase(context.getTestContext(), context.getRenderContext(), name, description,
68                            glu::GLSL_VERSION_310_ES, BUFFERMODE_PER_BLOCK)
69     {
70         UniformBlock &block = m_interface.allocBlock("Block");
71         block.addUniform(Uniform("var", type, 0));
72         block.setFlags(layoutFlags);
73 
74         if (numInstances > 0)
75         {
76             block.setArraySize(numInstances);
77             block.setInstanceName("block");
78         }
79     }
80 };
81 
createBlockBasicTypeCases(tcu::TestCaseGroup * group,Context & context,const char * name,const VarType & type,uint32_t layoutFlags,int numInstances=0)82 static void createBlockBasicTypeCases(tcu::TestCaseGroup *group, Context &context, const char *name,
83                                       const VarType &type, uint32_t layoutFlags, int numInstances = 0)
84 {
85     group->addChild(new BlockBasicTypeCase(context, (string(name) + "_vertex").c_str(), "", type,
86                                            layoutFlags | DECLARE_VERTEX, numInstances));
87     group->addChild(new BlockBasicTypeCase(context, (string(name) + "_fragment").c_str(), "", type,
88                                            layoutFlags | DECLARE_FRAGMENT, numInstances));
89 
90     if (!(layoutFlags & LAYOUT_PACKED))
91         group->addChild(new BlockBasicTypeCase(context, (string(name) + "_both").c_str(), "", type,
92                                                layoutFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, numInstances));
93 }
94 
95 class Block2LevelStructArrayCase : public UniformBlockCase
96 {
97 public:
Block2LevelStructArrayCase(Context & context,const char * name,const char * description,uint32_t layoutFlags,BufferMode bufferMode,int numInstances)98     Block2LevelStructArrayCase(Context &context, const char *name, const char *description, uint32_t layoutFlags,
99                                BufferMode bufferMode, int numInstances)
100         : UniformBlockCase(context.getTestContext(), context.getRenderContext(), name, description,
101                            glu::GLSL_VERSION_310_ES, bufferMode)
102         , m_layoutFlags(layoutFlags)
103         , m_numInstances(numInstances)
104     {
105     }
106 
init(void)107     void init(void)
108     {
109         StructType &typeS = m_interface.allocStruct("S");
110         typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
111         typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 4));
112         typeS.addMember("c", VarType(glu::TYPE_UINT, PRECISION_LOW));
113 
114         UniformBlock &block = m_interface.allocBlock("Block");
115         block.addUniform(Uniform("u", VarType(glu::TYPE_INT, PRECISION_MEDIUM)));
116         block.addUniform(Uniform("s", VarType(VarType(VarType(&typeS), 3), 2)));
117         block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM)));
118         block.setFlags(m_layoutFlags);
119 
120         if (m_numInstances > 0)
121         {
122             block.setInstanceName("block");
123             block.setArraySize(m_numInstances);
124         }
125     }
126 
127 private:
128     uint32_t m_layoutFlags;
129     int m_numInstances;
130 };
131 
132 } // namespace
133 
UniformBlockTests(Context & context)134 UniformBlockTests::UniformBlockTests(Context &context) : TestCaseGroup(context, "ubo", "Uniform Block tests")
135 {
136 }
137 
~UniformBlockTests(void)138 UniformBlockTests::~UniformBlockTests(void)
139 {
140 }
141 
init(void)142 void UniformBlockTests::init(void)
143 {
144     static const glu::DataType basicTypes[] = {
145         glu::TYPE_FLOAT,        glu::TYPE_FLOAT_VEC2,   glu::TYPE_FLOAT_VEC3,   glu::TYPE_FLOAT_VEC4,
146         glu::TYPE_INT,          glu::TYPE_INT_VEC2,     glu::TYPE_INT_VEC3,     glu::TYPE_INT_VEC4,
147         glu::TYPE_UINT,         glu::TYPE_UINT_VEC2,    glu::TYPE_UINT_VEC3,    glu::TYPE_UINT_VEC4,
148         glu::TYPE_BOOL,         glu::TYPE_BOOL_VEC2,    glu::TYPE_BOOL_VEC3,    glu::TYPE_BOOL_VEC4,
149         glu::TYPE_FLOAT_MAT2,   glu::TYPE_FLOAT_MAT3,   glu::TYPE_FLOAT_MAT4,   glu::TYPE_FLOAT_MAT2X3,
150         glu::TYPE_FLOAT_MAT2X4, glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3X4, glu::TYPE_FLOAT_MAT4X2,
151         glu::TYPE_FLOAT_MAT4X3};
152 
153     static const struct
154     {
155         const char *name;
156         uint32_t flags;
157     } layoutFlags[] = {{"shared", LAYOUT_SHARED}, {"packed", LAYOUT_PACKED}, {"std140", LAYOUT_STD140}};
158 
159     static const struct
160     {
161         const char *name;
162         uint32_t flags;
163     } matrixFlags[] = {{"row_major", LAYOUT_ROW_MAJOR}, {"column_major", LAYOUT_COLUMN_MAJOR}};
164 
165     static const struct
166     {
167         const char *name;
168         UniformBlockCase::BufferMode mode;
169     } bufferModes[] = {{"per_block_buffer", UniformBlockCase::BUFFERMODE_PER_BLOCK},
170                        {"single_buffer", UniformBlockCase::BUFFERMODE_SINGLE}};
171 
172     // ubo.2_level_array
173     {
174         tcu::TestCaseGroup *nestedArrayGroup =
175             new tcu::TestCaseGroup(m_testCtx, "2_level_array", "2-level basic array variable in single buffer");
176         addChild(nestedArrayGroup);
177 
178         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
179         {
180             tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
181             nestedArrayGroup->addChild(layoutGroup);
182 
183             for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
184             {
185                 const glu::DataType type = basicTypes[basicTypeNdx];
186                 const char *typeName     = glu::getDataTypeName(type);
187                 const int childSize      = 4;
188                 const int parentSize     = 3;
189                 const VarType childType(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize);
190                 const VarType parentType(childType, parentSize);
191 
192                 createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType,
193                                           layoutFlags[layoutFlagNdx].flags);
194 
195                 if (glu::isDataTypeMatrix(type))
196                 {
197                     for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
198                         createBlockBasicTypeCases(
199                             layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(),
200                             parentType, layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
201                 }
202             }
203         }
204     }
205 
206     // ubo.3_level_array
207     {
208         tcu::TestCaseGroup *nestedArrayGroup =
209             new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level basic array variable in single buffer");
210         addChild(nestedArrayGroup);
211 
212         for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
213         {
214             tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
215             nestedArrayGroup->addChild(layoutGroup);
216 
217             for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
218             {
219                 const glu::DataType type = basicTypes[basicTypeNdx];
220                 const char *typeName     = glu::getDataTypeName(type);
221                 const int childSize0     = 2;
222                 const int childSize1     = 4;
223                 const int parentSize     = 3;
224                 const VarType childType0(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH),
225                                          childSize0);
226                 const VarType childType1(childType0, childSize1);
227                 const VarType parentType(childType1, parentSize);
228 
229                 createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType,
230                                           layoutFlags[layoutFlagNdx].flags);
231 
232                 if (glu::isDataTypeMatrix(type))
233                 {
234                     for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
235                         createBlockBasicTypeCases(
236                             layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(),
237                             parentType, layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
238                 }
239             }
240         }
241     }
242 
243     // ubo.2_level_struct_array
244     {
245         tcu::TestCaseGroup *structArrayArrayGroup =
246             new tcu::TestCaseGroup(m_testCtx, "2_level_struct_array", "Struct array in one uniform block");
247         addChild(structArrayArrayGroup);
248 
249         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
250         {
251             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
252             structArrayArrayGroup->addChild(modeGroup);
253 
254             for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
255             {
256                 for (int isArray = 0; isArray < 2; isArray++)
257                 {
258                     std::string baseName = layoutFlags[layoutFlagNdx].name;
259                     uint32_t baseFlags   = layoutFlags[layoutFlagNdx].flags;
260 
261                     if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
262                         continue; // Doesn't make sense to add this variant.
263 
264                     if (isArray)
265                         baseName += "_instance_array";
266 
267                     modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_vertex").c_str(), "",
268                                                                        baseFlags | DECLARE_VERTEX,
269                                                                        bufferModes[modeNdx].mode, isArray ? 3 : 0));
270                     modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_fragment").c_str(), "",
271                                                                        baseFlags | DECLARE_FRAGMENT,
272                                                                        bufferModes[modeNdx].mode, isArray ? 3 : 0));
273 
274                     if (!(baseFlags & LAYOUT_PACKED))
275                         modeGroup->addChild(new Block2LevelStructArrayCase(
276                             m_context, (baseName + "_both").c_str(), "", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
277                             bufferModes[modeNdx].mode, isArray ? 3 : 0));
278                 }
279             }
280         }
281     }
282 
283     // ubo.random
284     {
285         const uint32_t allShaders    = FEATURE_VERTEX_BLOCKS | FEATURE_FRAGMENT_BLOCKS | FEATURE_SHARED_BLOCKS;
286         const uint32_t allLayouts    = FEATURE_PACKED_LAYOUT | FEATURE_SHARED_LAYOUT | FEATURE_STD140_LAYOUT;
287         const uint32_t allBasicTypes = FEATURE_VECTORS | FEATURE_MATRICES;
288         const uint32_t unused        = FEATURE_UNUSED_MEMBERS | FEATURE_UNUSED_UNIFORMS;
289         const uint32_t matFlags      = FEATURE_MATRIX_LAYOUT;
290         const uint32_t basicTypeArrays =
291             allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_ARRAYS | FEATURE_ARRAYS_OF_ARRAYS;
292         const uint32_t allFeatures = ~0u;
293 
294         tcu::TestCaseGroup *randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
295         addChild(randomGroup);
296 
297         createRandomCaseGroup(randomGroup, m_context, "basic_type_arrays", "Arrays, per-block buffers",
298                               UniformBlockCase::BUFFERMODE_PER_BLOCK, basicTypeArrays, 25, 1150);
299         createRandomCaseGroup(randomGroup, m_context, "all_per_block_buffers", "All random features, per-block buffers",
300                               UniformBlockCase::BUFFERMODE_PER_BLOCK, allFeatures, 50, 11200);
301         createRandomCaseGroup(randomGroup, m_context, "all_shared_buffer", "All random features, shared buffer",
302                               UniformBlockCase::BUFFERMODE_SINGLE, allFeatures, 50, 11250);
303     }
304 }
305 
306 } // namespace Functional
307 } // namespace gles31
308 } // namespace deqp
309