| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL ES 3.1 Module |
| * ------------------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Uniform block tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es31fUniformBlockTests.hpp" |
| #include "glsUniformBlockCase.hpp" |
| #include "glsRandomUniformBlockCase.hpp" |
| #include "tcuCommandLine.hpp" |
| #include "deRandom.hpp" |
| #include "deStringUtil.hpp" |
| |
| using std::string; |
| using std::vector; |
| |
| namespace deqp |
| { |
| namespace gles31 |
| { |
| namespace Functional |
| { |
| namespace |
| { |
| |
| using gls::RandomUniformBlockCase; |
| using gls::UniformBlockCase; |
| using namespace gls::ub; |
| |
| void createRandomCaseGroup(tcu::TestCaseGroup *parentGroup, Context &context, const char *groupName, |
| const char *description, UniformBlockCase::BufferMode bufferMode, uint32_t features, |
| int numCases, uint32_t baseSeed) |
| { |
| tcu::TestCaseGroup *group = new tcu::TestCaseGroup(context.getTestContext(), groupName, description); |
| parentGroup->addChild(group); |
| |
| baseSeed += (uint32_t)context.getTestContext().getCommandLine().getBaseSeed(); |
| |
| for (int ndx = 0; ndx < numCases; ndx++) |
| group->addChild(new RandomUniformBlockCase(context.getTestContext(), context.getRenderContext(), |
| glu::GLSL_VERSION_310_ES, de::toString(ndx).c_str(), "", bufferMode, |
| features, (uint32_t)ndx + baseSeed)); |
| } |
| |
| class BlockBasicTypeCase : public UniformBlockCase |
| { |
| public: |
| BlockBasicTypeCase(Context &context, const char *name, const char *description, const VarType &type, |
| uint32_t layoutFlags, int numInstances) |
| : UniformBlockCase(context.getTestContext(), context.getRenderContext(), name, description, |
| glu::GLSL_VERSION_310_ES, BUFFERMODE_PER_BLOCK) |
| { |
| UniformBlock &block = m_interface.allocBlock("Block"); |
| block.addUniform(Uniform("var", type, 0)); |
| block.setFlags(layoutFlags); |
| |
| if (numInstances > 0) |
| { |
| block.setArraySize(numInstances); |
| block.setInstanceName("block"); |
| } |
| } |
| }; |
| |
| static void createBlockBasicTypeCases(tcu::TestCaseGroup *group, Context &context, const char *name, |
| const VarType &type, uint32_t layoutFlags, int numInstances = 0) |
| { |
| group->addChild(new BlockBasicTypeCase(context, (string(name) + "_vertex").c_str(), "", type, |
| layoutFlags | DECLARE_VERTEX, numInstances)); |
| group->addChild(new BlockBasicTypeCase(context, (string(name) + "_fragment").c_str(), "", type, |
| layoutFlags | DECLARE_FRAGMENT, numInstances)); |
| |
| if (!(layoutFlags & LAYOUT_PACKED)) |
| group->addChild(new BlockBasicTypeCase(context, (string(name) + "_both").c_str(), "", type, |
| layoutFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, numInstances)); |
| } |
| |
| class Block2LevelStructArrayCase : public UniformBlockCase |
| { |
| public: |
| Block2LevelStructArrayCase(Context &context, const char *name, const char *description, uint32_t layoutFlags, |
| BufferMode bufferMode, int numInstances) |
| : UniformBlockCase(context.getTestContext(), context.getRenderContext(), name, description, |
| glu::GLSL_VERSION_310_ES, bufferMode) |
| , m_layoutFlags(layoutFlags) |
| , m_numInstances(numInstances) |
| { |
| } |
| |
| void init(void) |
| { |
| StructType &typeS = m_interface.allocStruct("S"); |
| typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, PRECISION_HIGH), UNUSED_BOTH); |
| typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 4)); |
| typeS.addMember("c", VarType(glu::TYPE_UINT, PRECISION_LOW)); |
| |
| UniformBlock &block = m_interface.allocBlock("Block"); |
| block.addUniform(Uniform("u", VarType(glu::TYPE_INT, PRECISION_MEDIUM))); |
| block.addUniform(Uniform("s", VarType(VarType(VarType(&typeS), 3), 2))); |
| block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM))); |
| block.setFlags(m_layoutFlags); |
| |
| if (m_numInstances > 0) |
| { |
| block.setInstanceName("block"); |
| block.setArraySize(m_numInstances); |
| } |
| } |
| |
| private: |
| uint32_t m_layoutFlags; |
| int m_numInstances; |
| }; |
| |
| } // namespace |
| |
| UniformBlockTests::UniformBlockTests(Context &context) : TestCaseGroup(context, "ubo", "Uniform Block tests") |
| { |
| } |
| |
| UniformBlockTests::~UniformBlockTests(void) |
| { |
| } |
| |
| void UniformBlockTests::init(void) |
| { |
| static const glu::DataType basicTypes[] = { |
| glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC4, |
| glu::TYPE_INT, glu::TYPE_INT_VEC2, glu::TYPE_INT_VEC3, glu::TYPE_INT_VEC4, |
| glu::TYPE_UINT, glu::TYPE_UINT_VEC2, glu::TYPE_UINT_VEC3, glu::TYPE_UINT_VEC4, |
| glu::TYPE_BOOL, glu::TYPE_BOOL_VEC2, glu::TYPE_BOOL_VEC3, glu::TYPE_BOOL_VEC4, |
| glu::TYPE_FLOAT_MAT2, glu::TYPE_FLOAT_MAT3, glu::TYPE_FLOAT_MAT4, glu::TYPE_FLOAT_MAT2X3, |
| glu::TYPE_FLOAT_MAT2X4, glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3X4, glu::TYPE_FLOAT_MAT4X2, |
| glu::TYPE_FLOAT_MAT4X3}; |
| |
| static const struct |
| { |
| const char *name; |
| uint32_t flags; |
| } layoutFlags[] = {{"shared", LAYOUT_SHARED}, {"packed", LAYOUT_PACKED}, {"std140", LAYOUT_STD140}}; |
| |
| static const struct |
| { |
| const char *name; |
| uint32_t flags; |
| } matrixFlags[] = {{"row_major", LAYOUT_ROW_MAJOR}, {"column_major", LAYOUT_COLUMN_MAJOR}}; |
| |
| static const struct |
| { |
| const char *name; |
| UniformBlockCase::BufferMode mode; |
| } bufferModes[] = {{"per_block_buffer", UniformBlockCase::BUFFERMODE_PER_BLOCK}, |
| {"single_buffer", UniformBlockCase::BUFFERMODE_SINGLE}}; |
| |
| // ubo.2_level_array |
| { |
| tcu::TestCaseGroup *nestedArrayGroup = |
| new tcu::TestCaseGroup(m_testCtx, "2_level_array", "2-level basic array variable in single buffer"); |
| addChild(nestedArrayGroup); |
| |
| for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++) |
| { |
| tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, ""); |
| nestedArrayGroup->addChild(layoutGroup); |
| |
| for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++) |
| { |
| const glu::DataType type = basicTypes[basicTypeNdx]; |
| const char *typeName = glu::getDataTypeName(type); |
| const int childSize = 4; |
| const int parentSize = 3; |
| const VarType childType(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize); |
| const VarType parentType(childType, parentSize); |
| |
| createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType, |
| layoutFlags[layoutFlagNdx].flags); |
| |
| if (glu::isDataTypeMatrix(type)) |
| { |
| for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++) |
| createBlockBasicTypeCases( |
| layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), |
| parentType, layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags); |
| } |
| } |
| } |
| } |
| |
| // ubo.3_level_array |
| { |
| tcu::TestCaseGroup *nestedArrayGroup = |
| new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level basic array variable in single buffer"); |
| addChild(nestedArrayGroup); |
| |
| for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++) |
| { |
| tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, ""); |
| nestedArrayGroup->addChild(layoutGroup); |
| |
| for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++) |
| { |
| const glu::DataType type = basicTypes[basicTypeNdx]; |
| const char *typeName = glu::getDataTypeName(type); |
| const int childSize0 = 2; |
| const int childSize1 = 4; |
| const int parentSize = 3; |
| const VarType childType0(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), |
| childSize0); |
| const VarType childType1(childType0, childSize1); |
| const VarType parentType(childType1, parentSize); |
| |
| createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType, |
| layoutFlags[layoutFlagNdx].flags); |
| |
| if (glu::isDataTypeMatrix(type)) |
| { |
| for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++) |
| createBlockBasicTypeCases( |
| layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), |
| parentType, layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags); |
| } |
| } |
| } |
| } |
| |
| // ubo.2_level_struct_array |
| { |
| tcu::TestCaseGroup *structArrayArrayGroup = |
| new tcu::TestCaseGroup(m_testCtx, "2_level_struct_array", "Struct array in one uniform block"); |
| addChild(structArrayArrayGroup); |
| |
| for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++) |
| { |
| tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, ""); |
| structArrayArrayGroup->addChild(modeGroup); |
| |
| for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++) |
| { |
| for (int isArray = 0; isArray < 2; isArray++) |
| { |
| std::string baseName = layoutFlags[layoutFlagNdx].name; |
| uint32_t baseFlags = layoutFlags[layoutFlagNdx].flags; |
| |
| if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0) |
| continue; // Doesn't make sense to add this variant. |
| |
| if (isArray) |
| baseName += "_instance_array"; |
| |
| modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_vertex").c_str(), "", |
| baseFlags | DECLARE_VERTEX, |
| bufferModes[modeNdx].mode, isArray ? 3 : 0)); |
| modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_fragment").c_str(), "", |
| baseFlags | DECLARE_FRAGMENT, |
| bufferModes[modeNdx].mode, isArray ? 3 : 0)); |
| |
| if (!(baseFlags & LAYOUT_PACKED)) |
| modeGroup->addChild(new Block2LevelStructArrayCase( |
| m_context, (baseName + "_both").c_str(), "", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, |
| bufferModes[modeNdx].mode, isArray ? 3 : 0)); |
| } |
| } |
| } |
| } |
| |
| // ubo.random |
| { |
| const uint32_t allShaders = FEATURE_VERTEX_BLOCKS | FEATURE_FRAGMENT_BLOCKS | FEATURE_SHARED_BLOCKS; |
| const uint32_t allLayouts = FEATURE_PACKED_LAYOUT | FEATURE_SHARED_LAYOUT | FEATURE_STD140_LAYOUT; |
| const uint32_t allBasicTypes = FEATURE_VECTORS | FEATURE_MATRICES; |
| const uint32_t unused = FEATURE_UNUSED_MEMBERS | FEATURE_UNUSED_UNIFORMS; |
| const uint32_t matFlags = FEATURE_MATRIX_LAYOUT; |
| const uint32_t basicTypeArrays = |
| allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_ARRAYS | FEATURE_ARRAYS_OF_ARRAYS; |
| const uint32_t allFeatures = ~0u; |
| |
| tcu::TestCaseGroup *randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases"); |
| addChild(randomGroup); |
| |
| createRandomCaseGroup(randomGroup, m_context, "basic_type_arrays", "Arrays, per-block buffers", |
| UniformBlockCase::BUFFERMODE_PER_BLOCK, basicTypeArrays, 25, 1150); |
| createRandomCaseGroup(randomGroup, m_context, "all_per_block_buffers", "All random features, per-block buffers", |
| UniformBlockCase::BUFFERMODE_PER_BLOCK, allFeatures, 50, 11200); |
| createRandomCaseGroup(randomGroup, m_context, "all_shared_buffer", "All random features, shared buffer", |
| UniformBlockCase::BUFFERMODE_SINGLE, allFeatures, 50, 11250); |
| } |
| } |
| |
| } // namespace Functional |
| } // namespace gles31 |
| } // namespace deqp |