1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.1 Module 3e5c31af7Sopenharmony_ci * ------------------------------------------------- 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief Program interface query test case 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "es31fProgramInterfaceQueryTestCase.hpp" 25e5c31af7Sopenharmony_ci#include "es31fProgramInterfaceDefinitionUtil.hpp" 26e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 27e5c31af7Sopenharmony_ci#include "gluVarTypeUtil.hpp" 28e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp" 29e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp" 30e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp" 31e5c31af7Sopenharmony_ci#include "glwFunctions.hpp" 32e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 33e5c31af7Sopenharmony_ci#include "deString.h" 34e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 35e5c31af7Sopenharmony_ci#include "deSTLUtil.hpp" 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_cinamespace deqp 38e5c31af7Sopenharmony_ci{ 39e5c31af7Sopenharmony_cinamespace gles31 40e5c31af7Sopenharmony_ci{ 41e5c31af7Sopenharmony_cinamespace Functional 42e5c31af7Sopenharmony_ci{ 43e5c31af7Sopenharmony_cinamespace 44e5c31af7Sopenharmony_ci{ 45e5c31af7Sopenharmony_ci 46e5c31af7Sopenharmony_ciusing ProgramInterfaceDefinition::VariablePathComponent; 47e5c31af7Sopenharmony_ciusing ProgramInterfaceDefinition::VariableSearchFilter; 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_cistatic glw::GLenum getProgramDefaultBlockInterfaceFromStorage (glu::Storage storage) 50e5c31af7Sopenharmony_ci{ 51e5c31af7Sopenharmony_ci switch (storage) 52e5c31af7Sopenharmony_ci { 53e5c31af7Sopenharmony_ci case glu::STORAGE_IN: 54e5c31af7Sopenharmony_ci case glu::STORAGE_PATCH_IN: 55e5c31af7Sopenharmony_ci return GL_PROGRAM_INPUT; 56e5c31af7Sopenharmony_ci 57e5c31af7Sopenharmony_ci case glu::STORAGE_OUT: 58e5c31af7Sopenharmony_ci case glu::STORAGE_PATCH_OUT: 59e5c31af7Sopenharmony_ci return GL_PROGRAM_OUTPUT; 60e5c31af7Sopenharmony_ci 61e5c31af7Sopenharmony_ci case glu::STORAGE_UNIFORM: 62e5c31af7Sopenharmony_ci return GL_UNIFORM; 63e5c31af7Sopenharmony_ci 64e5c31af7Sopenharmony_ci default: 65e5c31af7Sopenharmony_ci DE_ASSERT(false); 66e5c31af7Sopenharmony_ci return 0; 67e5c31af7Sopenharmony_ci } 68e5c31af7Sopenharmony_ci} 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_cistatic bool isBufferBackedInterfaceBlockStorage (glu::Storage storage) 71e5c31af7Sopenharmony_ci{ 72e5c31af7Sopenharmony_ci return storage == glu::STORAGE_BUFFER || storage == glu::STORAGE_UNIFORM; 73e5c31af7Sopenharmony_ci} 74e5c31af7Sopenharmony_ci 75e5c31af7Sopenharmony_ciconst char* getRequiredExtensionForStage (glu::ShaderType stage) 76e5c31af7Sopenharmony_ci{ 77e5c31af7Sopenharmony_ci switch (stage) 78e5c31af7Sopenharmony_ci { 79e5c31af7Sopenharmony_ci case glu::SHADERTYPE_COMPUTE: 80e5c31af7Sopenharmony_ci case glu::SHADERTYPE_VERTEX: 81e5c31af7Sopenharmony_ci case glu::SHADERTYPE_FRAGMENT: 82e5c31af7Sopenharmony_ci return DE_NULL; 83e5c31af7Sopenharmony_ci 84e5c31af7Sopenharmony_ci case glu::SHADERTYPE_GEOMETRY: 85e5c31af7Sopenharmony_ci return "GL_EXT_geometry_shader"; 86e5c31af7Sopenharmony_ci 87e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_CONTROL: 88e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_EVALUATION: 89e5c31af7Sopenharmony_ci return "GL_EXT_tessellation_shader"; 90e5c31af7Sopenharmony_ci 91e5c31af7Sopenharmony_ci default: 92e5c31af7Sopenharmony_ci DE_ASSERT(false); 93e5c31af7Sopenharmony_ci return DE_NULL; 94e5c31af7Sopenharmony_ci } 95e5c31af7Sopenharmony_ci} 96e5c31af7Sopenharmony_ci 97e5c31af7Sopenharmony_cistatic int getTypeSize (glu::DataType type) 98e5c31af7Sopenharmony_ci{ 99e5c31af7Sopenharmony_ci if (type == glu::TYPE_FLOAT) 100e5c31af7Sopenharmony_ci return 4; 101e5c31af7Sopenharmony_ci else if (type == glu::TYPE_INT || type == glu::TYPE_UINT) 102e5c31af7Sopenharmony_ci return 4; 103e5c31af7Sopenharmony_ci else if (type == glu::TYPE_BOOL) 104e5c31af7Sopenharmony_ci return 4; // uint 105e5c31af7Sopenharmony_ci 106e5c31af7Sopenharmony_ci DE_ASSERT(false); 107e5c31af7Sopenharmony_ci return 0; 108e5c31af7Sopenharmony_ci} 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_cistatic int getVarTypeSize (const glu::VarType& type) 111e5c31af7Sopenharmony_ci{ 112e5c31af7Sopenharmony_ci if (type.isBasicType()) 113e5c31af7Sopenharmony_ci { 114e5c31af7Sopenharmony_ci // return in basic machine units 115e5c31af7Sopenharmony_ci return glu::getDataTypeScalarSize(type.getBasicType()) * getTypeSize(glu::getDataTypeScalarType(type.getBasicType())); 116e5c31af7Sopenharmony_ci } 117e5c31af7Sopenharmony_ci else if (type.isStructType()) 118e5c31af7Sopenharmony_ci { 119e5c31af7Sopenharmony_ci int size = 0; 120e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx) 121e5c31af7Sopenharmony_ci size += getVarTypeSize(type.getStructPtr()->getMember(ndx).getType()); 122e5c31af7Sopenharmony_ci return size; 123e5c31af7Sopenharmony_ci } 124e5c31af7Sopenharmony_ci else if (type.isArrayType()) 125e5c31af7Sopenharmony_ci { 126e5c31af7Sopenharmony_ci // unsized arrays are handled as if they had only one element 127e5c31af7Sopenharmony_ci if (type.getArraySize() == glu::VarType::UNSIZED_ARRAY) 128e5c31af7Sopenharmony_ci return getVarTypeSize(type.getElementType()); 129e5c31af7Sopenharmony_ci else 130e5c31af7Sopenharmony_ci return type.getArraySize() * getVarTypeSize(type.getElementType()); 131e5c31af7Sopenharmony_ci } 132e5c31af7Sopenharmony_ci else 133e5c31af7Sopenharmony_ci { 134e5c31af7Sopenharmony_ci DE_ASSERT(false); 135e5c31af7Sopenharmony_ci return 0; 136e5c31af7Sopenharmony_ci } 137e5c31af7Sopenharmony_ci} 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_cistatic glu::MatrixOrder getMatrixOrderFromPath (const std::vector<VariablePathComponent>& path) 140e5c31af7Sopenharmony_ci{ 141e5c31af7Sopenharmony_ci glu::MatrixOrder order = glu::MATRIXORDER_LAST; 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci // inherit majority 144e5c31af7Sopenharmony_ci for (int pathNdx = 0; pathNdx < (int)path.size(); ++pathNdx) 145e5c31af7Sopenharmony_ci { 146e5c31af7Sopenharmony_ci glu::MatrixOrder matOrder; 147e5c31af7Sopenharmony_ci 148e5c31af7Sopenharmony_ci if (path[pathNdx].isInterfaceBlock()) 149e5c31af7Sopenharmony_ci matOrder = path[pathNdx].getInterfaceBlock()->layout.matrixOrder; 150e5c31af7Sopenharmony_ci else if (path[pathNdx].isDeclaration()) 151e5c31af7Sopenharmony_ci matOrder = path[pathNdx].getDeclaration()->layout.matrixOrder; 152e5c31af7Sopenharmony_ci else if (path[pathNdx].isVariableType()) 153e5c31af7Sopenharmony_ci matOrder = glu::MATRIXORDER_LAST; 154e5c31af7Sopenharmony_ci else 155e5c31af7Sopenharmony_ci { 156e5c31af7Sopenharmony_ci DE_ASSERT(false); 157e5c31af7Sopenharmony_ci return glu::MATRIXORDER_LAST; 158e5c31af7Sopenharmony_ci } 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ci if (matOrder != glu::MATRIXORDER_LAST) 161e5c31af7Sopenharmony_ci order = matOrder; 162e5c31af7Sopenharmony_ci } 163e5c31af7Sopenharmony_ci 164e5c31af7Sopenharmony_ci return order; 165e5c31af7Sopenharmony_ci} 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ciclass PropValidator 168e5c31af7Sopenharmony_ci{ 169e5c31af7Sopenharmony_cipublic: 170e5c31af7Sopenharmony_ci PropValidator (Context& context, ProgramResourcePropFlags validationProp, const char* requiredExtension); 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_ci virtual std::string getHumanReadablePropertyString (glw::GLint propVal) const; 173e5c31af7Sopenharmony_ci virtual void validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const = 0; 174e5c31af7Sopenharmony_ci 175e5c31af7Sopenharmony_ci bool isSupported (void) const; 176e5c31af7Sopenharmony_ci bool isSelected (deUint32 caseFlags) const; 177e5c31af7Sopenharmony_ci 178e5c31af7Sopenharmony_ciprotected: 179e5c31af7Sopenharmony_ci void setError (const std::string& err) const; 180e5c31af7Sopenharmony_ci 181e5c31af7Sopenharmony_ci tcu::TestContext& m_testCtx; 182e5c31af7Sopenharmony_ci const glu::RenderContext& m_renderContext; 183e5c31af7Sopenharmony_ci 184e5c31af7Sopenharmony_ciprivate: 185e5c31af7Sopenharmony_ci const glu::ContextInfo& m_contextInfo; 186e5c31af7Sopenharmony_ci const char* m_extension; 187e5c31af7Sopenharmony_ci const ProgramResourcePropFlags m_validationProp; 188e5c31af7Sopenharmony_ci}; 189e5c31af7Sopenharmony_ci 190e5c31af7Sopenharmony_ciPropValidator::PropValidator (Context& context, ProgramResourcePropFlags validationProp, const char* requiredExtension) 191e5c31af7Sopenharmony_ci : m_testCtx (context.getTestContext()) 192e5c31af7Sopenharmony_ci , m_renderContext (context.getRenderContext()) 193e5c31af7Sopenharmony_ci , m_contextInfo (context.getContextInfo()) 194e5c31af7Sopenharmony_ci , m_extension (requiredExtension) 195e5c31af7Sopenharmony_ci , m_validationProp (validationProp) 196e5c31af7Sopenharmony_ci{ 197e5c31af7Sopenharmony_ci} 198e5c31af7Sopenharmony_ci 199e5c31af7Sopenharmony_cistd::string PropValidator::getHumanReadablePropertyString (glw::GLint propVal) const 200e5c31af7Sopenharmony_ci{ 201e5c31af7Sopenharmony_ci return de::toString(propVal); 202e5c31af7Sopenharmony_ci} 203e5c31af7Sopenharmony_ci 204e5c31af7Sopenharmony_cibool PropValidator::isSupported (void) const 205e5c31af7Sopenharmony_ci{ 206e5c31af7Sopenharmony_ci if(glu::contextSupports(m_renderContext.getType(), glu::ApiType::es(3, 2)) || 207e5c31af7Sopenharmony_ci glu::contextSupports(m_renderContext.getType(), glu::ApiType::core(4, 5))) 208e5c31af7Sopenharmony_ci return true; 209e5c31af7Sopenharmony_ci return m_extension == DE_NULL || m_contextInfo.isExtensionSupported(m_extension); 210e5c31af7Sopenharmony_ci} 211e5c31af7Sopenharmony_ci 212e5c31af7Sopenharmony_cibool PropValidator::isSelected (deUint32 caseFlags) const 213e5c31af7Sopenharmony_ci{ 214e5c31af7Sopenharmony_ci return (caseFlags & (deUint32)m_validationProp) != 0; 215e5c31af7Sopenharmony_ci} 216e5c31af7Sopenharmony_ci 217e5c31af7Sopenharmony_civoid PropValidator::setError (const std::string& err) const 218e5c31af7Sopenharmony_ci{ 219e5c31af7Sopenharmony_ci // don't overwrite earlier errors 220e5c31af7Sopenharmony_ci if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 221e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, err.c_str()); 222e5c31af7Sopenharmony_ci} 223e5c31af7Sopenharmony_ci 224e5c31af7Sopenharmony_ciclass SingleVariableValidator : public PropValidator 225e5c31af7Sopenharmony_ci{ 226e5c31af7Sopenharmony_cipublic: 227e5c31af7Sopenharmony_ci SingleVariableValidator (Context& context, ProgramResourcePropFlags validationProp, glw::GLuint programID, const VariableSearchFilter& filter, const char* requiredExtension); 228e5c31af7Sopenharmony_ci 229e5c31af7Sopenharmony_ci void validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 230e5c31af7Sopenharmony_ci virtual void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const = 0; 231e5c31af7Sopenharmony_ci virtual void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 232e5c31af7Sopenharmony_ci 233e5c31af7Sopenharmony_ciprotected: 234e5c31af7Sopenharmony_ci const VariableSearchFilter m_filter; 235e5c31af7Sopenharmony_ci const glw::GLuint m_programID; 236e5c31af7Sopenharmony_ci}; 237e5c31af7Sopenharmony_ci 238e5c31af7Sopenharmony_ciSingleVariableValidator::SingleVariableValidator (Context& context, ProgramResourcePropFlags validationProp, glw::GLuint programID, const VariableSearchFilter& filter, const char* requiredExtension) 239e5c31af7Sopenharmony_ci : PropValidator (context, validationProp, requiredExtension) 240e5c31af7Sopenharmony_ci , m_filter (filter) 241e5c31af7Sopenharmony_ci , m_programID (programID) 242e5c31af7Sopenharmony_ci{ 243e5c31af7Sopenharmony_ci} 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_civoid SingleVariableValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 246e5c31af7Sopenharmony_ci{ 247e5c31af7Sopenharmony_ci std::vector<VariablePathComponent> path; 248e5c31af7Sopenharmony_ci 249e5c31af7Sopenharmony_ci if (findProgramVariablePathByPathName(path, program, resource, m_filter)) 250e5c31af7Sopenharmony_ci { 251e5c31af7Sopenharmony_ci const glu::VarType* variable = (path.back().isVariableType()) ? (path.back().getVariableType()) : (DE_NULL); 252e5c31af7Sopenharmony_ci 253e5c31af7Sopenharmony_ci if (!variable || !variable->isBasicType()) 254e5c31af7Sopenharmony_ci { 255e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Error, resource name \"" << resource << "\" refers to a non-basic type." << tcu::TestLog::EndMessage; 256e5c31af7Sopenharmony_ci setError("resource not basic type"); 257e5c31af7Sopenharmony_ci } 258e5c31af7Sopenharmony_ci else 259e5c31af7Sopenharmony_ci validateSingleVariable(path, resource, propValue, implementationName); 260e5c31af7Sopenharmony_ci 261e5c31af7Sopenharmony_ci // finding matching variable in any shader is sufficient 262e5c31af7Sopenharmony_ci return; 263e5c31af7Sopenharmony_ci } 264e5c31af7Sopenharmony_ci else if (deStringBeginsWith(resource.c_str(), "gl_")) 265e5c31af7Sopenharmony_ci { 266e5c31af7Sopenharmony_ci // special case for builtins 267e5c31af7Sopenharmony_ci validateBuiltinVariable(resource, propValue, implementationName); 268e5c31af7Sopenharmony_ci return; 269e5c31af7Sopenharmony_ci } 270e5c31af7Sopenharmony_ci 271e5c31af7Sopenharmony_ci // we are only supplied good names, generated by ourselves 272e5c31af7Sopenharmony_ci DE_ASSERT(false); 273e5c31af7Sopenharmony_ci throw tcu::InternalError("Resource name consistency error"); 274e5c31af7Sopenharmony_ci} 275e5c31af7Sopenharmony_ci 276e5c31af7Sopenharmony_civoid SingleVariableValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 277e5c31af7Sopenharmony_ci{ 278e5c31af7Sopenharmony_ci DE_UNREF(resource); 279e5c31af7Sopenharmony_ci DE_UNREF(propValue); 280e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 281e5c31af7Sopenharmony_ci DE_ASSERT(false); 282e5c31af7Sopenharmony_ci} 283e5c31af7Sopenharmony_ci 284e5c31af7Sopenharmony_ciclass SingleBlockValidator : public PropValidator 285e5c31af7Sopenharmony_ci{ 286e5c31af7Sopenharmony_cipublic: 287e5c31af7Sopenharmony_ci SingleBlockValidator (Context& context, ProgramResourcePropFlags validationProp, glw::GLuint programID, const VariableSearchFilter& filter, const char* requiredExtension); 288e5c31af7Sopenharmony_ci 289e5c31af7Sopenharmony_ci void validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 290e5c31af7Sopenharmony_ci virtual void validateSingleBlock (const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const = 0; 291e5c31af7Sopenharmony_ci 292e5c31af7Sopenharmony_ciprotected: 293e5c31af7Sopenharmony_ci const VariableSearchFilter m_filter; 294e5c31af7Sopenharmony_ci const glw::GLuint m_programID; 295e5c31af7Sopenharmony_ci}; 296e5c31af7Sopenharmony_ci 297e5c31af7Sopenharmony_ciSingleBlockValidator::SingleBlockValidator (Context& context, ProgramResourcePropFlags validationProp, glw::GLuint programID, const VariableSearchFilter& filter, const char* requiredExtension) 298e5c31af7Sopenharmony_ci : PropValidator (context, validationProp, requiredExtension) 299e5c31af7Sopenharmony_ci , m_filter (filter) 300e5c31af7Sopenharmony_ci , m_programID (programID) 301e5c31af7Sopenharmony_ci{ 302e5c31af7Sopenharmony_ci} 303e5c31af7Sopenharmony_ci 304e5c31af7Sopenharmony_civoid SingleBlockValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 305e5c31af7Sopenharmony_ci{ 306e5c31af7Sopenharmony_ci glu::VarTokenizer tokenizer (resource.c_str()); 307e5c31af7Sopenharmony_ci const std::string blockName = tokenizer.getIdentifier(); 308e5c31af7Sopenharmony_ci std::vector<int> instanceIndex; 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci tokenizer.advance(); 311e5c31af7Sopenharmony_ci 312e5c31af7Sopenharmony_ci // array index 313e5c31af7Sopenharmony_ci while (tokenizer.getToken() == glu::VarTokenizer::TOKEN_LEFT_BRACKET) 314e5c31af7Sopenharmony_ci { 315e5c31af7Sopenharmony_ci tokenizer.advance(); 316e5c31af7Sopenharmony_ci DE_ASSERT(tokenizer.getToken() == glu::VarTokenizer::TOKEN_NUMBER); 317e5c31af7Sopenharmony_ci 318e5c31af7Sopenharmony_ci instanceIndex.push_back(tokenizer.getNumber()); 319e5c31af7Sopenharmony_ci 320e5c31af7Sopenharmony_ci tokenizer.advance(); 321e5c31af7Sopenharmony_ci DE_ASSERT(tokenizer.getToken() == glu::VarTokenizer::TOKEN_RIGHT_BRACKET); 322e5c31af7Sopenharmony_ci 323e5c31af7Sopenharmony_ci tokenizer.advance(); 324e5c31af7Sopenharmony_ci } 325e5c31af7Sopenharmony_ci 326e5c31af7Sopenharmony_ci // no trailing garbage 327e5c31af7Sopenharmony_ci DE_ASSERT(tokenizer.getToken() == glu::VarTokenizer::TOKEN_END); 328e5c31af7Sopenharmony_ci 329e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 330e5c31af7Sopenharmony_ci { 331e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx]; 332e5c31af7Sopenharmony_ci if (!m_filter.matchesFilter(shader)) 333e5c31af7Sopenharmony_ci continue; 334e5c31af7Sopenharmony_ci 335e5c31af7Sopenharmony_ci for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx) 336e5c31af7Sopenharmony_ci { 337e5c31af7Sopenharmony_ci const glu::InterfaceBlock& block = shader->getDefaultBlock().interfaceBlocks[blockNdx]; 338e5c31af7Sopenharmony_ci 339e5c31af7Sopenharmony_ci if (m_filter.matchesFilter(block) && block.interfaceName == blockName) 340e5c31af7Sopenharmony_ci { 341e5c31af7Sopenharmony_ci // dimensions match 342e5c31af7Sopenharmony_ci DE_ASSERT(instanceIndex.size() == block.dimensions.size()); 343e5c31af7Sopenharmony_ci 344e5c31af7Sopenharmony_ci validateSingleBlock(block, instanceIndex, resource, propValue, implementationName); 345e5c31af7Sopenharmony_ci return; 346e5c31af7Sopenharmony_ci } 347e5c31af7Sopenharmony_ci } 348e5c31af7Sopenharmony_ci } 349e5c31af7Sopenharmony_ci 350e5c31af7Sopenharmony_ci // we are only supplied good names, generated by ourselves 351e5c31af7Sopenharmony_ci DE_ASSERT(false); 352e5c31af7Sopenharmony_ci throw tcu::InternalError("Resource name consistency error"); 353e5c31af7Sopenharmony_ci} 354e5c31af7Sopenharmony_ci 355e5c31af7Sopenharmony_ciclass TypeValidator : public SingleVariableValidator 356e5c31af7Sopenharmony_ci{ 357e5c31af7Sopenharmony_cipublic: 358e5c31af7Sopenharmony_ci TypeValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 359e5c31af7Sopenharmony_ci 360e5c31af7Sopenharmony_ci std::string getHumanReadablePropertyString (glw::GLint propVal) const; 361e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 362e5c31af7Sopenharmony_ci void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 363e5c31af7Sopenharmony_ci}; 364e5c31af7Sopenharmony_ci 365e5c31af7Sopenharmony_ciTypeValidator::TypeValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 366e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_TYPE, programID, filter, DE_NULL) 367e5c31af7Sopenharmony_ci{ 368e5c31af7Sopenharmony_ci} 369e5c31af7Sopenharmony_ci 370e5c31af7Sopenharmony_cistd::string TypeValidator::getHumanReadablePropertyString (glw::GLint propVal) const 371e5c31af7Sopenharmony_ci{ 372e5c31af7Sopenharmony_ci return de::toString(glu::getShaderVarTypeStr(propVal)); 373e5c31af7Sopenharmony_ci} 374e5c31af7Sopenharmony_ci 375e5c31af7Sopenharmony_civoid TypeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 376e5c31af7Sopenharmony_ci{ 377e5c31af7Sopenharmony_ci const glu::VarType* variable = path.back().getVariableType(); 378e5c31af7Sopenharmony_ci 379e5c31af7Sopenharmony_ci DE_UNREF(resource); 380e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 381e5c31af7Sopenharmony_ci 382e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(variable->getBasicType()) << tcu::TestLog::EndMessage; 383e5c31af7Sopenharmony_ci 384e5c31af7Sopenharmony_ci if (variable->getBasicType() != glu::getDataTypeFromGLType(propValue)) 385e5c31af7Sopenharmony_ci { 386e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage; 387e5c31af7Sopenharmony_ci setError("resource type invalid"); 388e5c31af7Sopenharmony_ci } 389e5c31af7Sopenharmony_ci} 390e5c31af7Sopenharmony_ci 391e5c31af7Sopenharmony_civoid TypeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 392e5c31af7Sopenharmony_ci{ 393e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 394e5c31af7Sopenharmony_ci 395e5c31af7Sopenharmony_ci static const struct 396e5c31af7Sopenharmony_ci { 397e5c31af7Sopenharmony_ci const char* name; 398e5c31af7Sopenharmony_ci glu::DataType type; 399e5c31af7Sopenharmony_ci } builtins[] = 400e5c31af7Sopenharmony_ci { 401e5c31af7Sopenharmony_ci { "gl_Position", glu::TYPE_FLOAT_VEC4 }, 402e5c31af7Sopenharmony_ci { "gl_FragCoord", glu::TYPE_FLOAT_VEC4 }, 403e5c31af7Sopenharmony_ci { "gl_PerVertex.gl_Position", glu::TYPE_FLOAT_VEC4 }, 404e5c31af7Sopenharmony_ci { "gl_VertexID", glu::TYPE_INT }, 405e5c31af7Sopenharmony_ci { "gl_InvocationID", glu::TYPE_INT }, 406e5c31af7Sopenharmony_ci { "gl_NumWorkGroups", glu::TYPE_UINT_VEC3 }, 407e5c31af7Sopenharmony_ci { "gl_FragDepth", glu::TYPE_FLOAT }, 408e5c31af7Sopenharmony_ci { "gl_TessLevelOuter[0]", glu::TYPE_FLOAT }, 409e5c31af7Sopenharmony_ci { "gl_TessLevelInner[0]", glu::TYPE_FLOAT }, 410e5c31af7Sopenharmony_ci }; 411e5c31af7Sopenharmony_ci 412e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtins); ++ndx) 413e5c31af7Sopenharmony_ci { 414e5c31af7Sopenharmony_ci if (resource == builtins[ndx].name) 415e5c31af7Sopenharmony_ci { 416e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(builtins[ndx].type) << tcu::TestLog::EndMessage; 417e5c31af7Sopenharmony_ci 418e5c31af7Sopenharmony_ci if (glu::getDataTypeFromGLType(propValue) != builtins[ndx].type) 419e5c31af7Sopenharmony_ci { 420e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage; 421e5c31af7Sopenharmony_ci setError("resource type invalid"); 422e5c31af7Sopenharmony_ci } 423e5c31af7Sopenharmony_ci return; 424e5c31af7Sopenharmony_ci } 425e5c31af7Sopenharmony_ci } 426e5c31af7Sopenharmony_ci 427e5c31af7Sopenharmony_ci DE_ASSERT(false); 428e5c31af7Sopenharmony_ci} 429e5c31af7Sopenharmony_ci 430e5c31af7Sopenharmony_ciclass ArraySizeValidator : public SingleVariableValidator 431e5c31af7Sopenharmony_ci{ 432e5c31af7Sopenharmony_cipublic: 433e5c31af7Sopenharmony_ci ArraySizeValidator (Context& context, glw::GLuint programID, int unsizedArraySize, const VariableSearchFilter& filter); 434e5c31af7Sopenharmony_ci 435e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 436e5c31af7Sopenharmony_ci void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 437e5c31af7Sopenharmony_ci 438e5c31af7Sopenharmony_ciprivate: 439e5c31af7Sopenharmony_ci const int m_unsizedArraySize; 440e5c31af7Sopenharmony_ci}; 441e5c31af7Sopenharmony_ci 442e5c31af7Sopenharmony_ciArraySizeValidator::ArraySizeValidator (Context& context, glw::GLuint programID, int unsizedArraySize, const VariableSearchFilter& filter) 443e5c31af7Sopenharmony_ci : SingleVariableValidator (context, PROGRAMRESOURCEPROP_ARRAY_SIZE, programID, filter, DE_NULL) 444e5c31af7Sopenharmony_ci , m_unsizedArraySize (unsizedArraySize) 445e5c31af7Sopenharmony_ci{ 446e5c31af7Sopenharmony_ci} 447e5c31af7Sopenharmony_ci 448e5c31af7Sopenharmony_civoid ArraySizeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 449e5c31af7Sopenharmony_ci{ 450e5c31af7Sopenharmony_ci const VariablePathComponent nullComponent; 451e5c31af7Sopenharmony_ci const VariablePathComponent& enclosingcomponent = (path.size() > 1) ? (path[path.size()-2]) : (nullComponent); 452e5c31af7Sopenharmony_ci 453e5c31af7Sopenharmony_ci const bool isArray = enclosingcomponent.isVariableType() && enclosingcomponent.getVariableType()->isArrayType(); 454e5c31af7Sopenharmony_ci const bool inUnsizedArray = isArray && (enclosingcomponent.getVariableType()->getArraySize() == glu::VarType::UNSIZED_ARRAY); 455e5c31af7Sopenharmony_ci const int arraySize = (!isArray) ? (1) : (inUnsizedArray) ? (m_unsizedArraySize) : (enclosingcomponent.getVariableType()->getArraySize()); 456e5c31af7Sopenharmony_ci 457e5c31af7Sopenharmony_ci DE_ASSERT(arraySize >= 0); 458e5c31af7Sopenharmony_ci DE_UNREF(resource); 459e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 460e5c31af7Sopenharmony_ci 461e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize << tcu::TestLog::EndMessage; 462e5c31af7Sopenharmony_ci 463e5c31af7Sopenharmony_ci if (arraySize != propValue) 464e5c31af7Sopenharmony_ci { 465e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 466e5c31af7Sopenharmony_ci setError("resource array size invalid"); 467e5c31af7Sopenharmony_ci } 468e5c31af7Sopenharmony_ci} 469e5c31af7Sopenharmony_ci 470e5c31af7Sopenharmony_civoid ArraySizeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 471e5c31af7Sopenharmony_ci{ 472e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 473e5c31af7Sopenharmony_ci 474e5c31af7Sopenharmony_ci static const struct 475e5c31af7Sopenharmony_ci { 476e5c31af7Sopenharmony_ci const char* name; 477e5c31af7Sopenharmony_ci int arraySize; 478e5c31af7Sopenharmony_ci } builtins[] = 479e5c31af7Sopenharmony_ci { 480e5c31af7Sopenharmony_ci { "gl_Position", 1 }, 481e5c31af7Sopenharmony_ci { "gl_VertexID", 1 }, 482e5c31af7Sopenharmony_ci { "gl_FragCoord", 1 }, 483e5c31af7Sopenharmony_ci { "gl_PerVertex.gl_Position", 1 }, 484e5c31af7Sopenharmony_ci { "gl_InvocationID", 1 }, 485e5c31af7Sopenharmony_ci { "gl_NumWorkGroups", 1 }, 486e5c31af7Sopenharmony_ci { "gl_FragDepth", 1 }, 487e5c31af7Sopenharmony_ci { "gl_TessLevelOuter[0]", 4 }, 488e5c31af7Sopenharmony_ci { "gl_TessLevelInner[0]", 2 }, 489e5c31af7Sopenharmony_ci }; 490e5c31af7Sopenharmony_ci 491e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtins); ++ndx) 492e5c31af7Sopenharmony_ci { 493e5c31af7Sopenharmony_ci if (resource == builtins[ndx].name) 494e5c31af7Sopenharmony_ci { 495e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << builtins[ndx].arraySize << tcu::TestLog::EndMessage; 496e5c31af7Sopenharmony_ci 497e5c31af7Sopenharmony_ci if (propValue != builtins[ndx].arraySize) 498e5c31af7Sopenharmony_ci { 499e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 500e5c31af7Sopenharmony_ci setError("resource array size invalid"); 501e5c31af7Sopenharmony_ci } 502e5c31af7Sopenharmony_ci return; 503e5c31af7Sopenharmony_ci } 504e5c31af7Sopenharmony_ci } 505e5c31af7Sopenharmony_ci 506e5c31af7Sopenharmony_ci DE_ASSERT(false); 507e5c31af7Sopenharmony_ci} 508e5c31af7Sopenharmony_ci 509e5c31af7Sopenharmony_ciclass ArrayStrideValidator : public SingleVariableValidator 510e5c31af7Sopenharmony_ci{ 511e5c31af7Sopenharmony_cipublic: 512e5c31af7Sopenharmony_ci ArrayStrideValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 513e5c31af7Sopenharmony_ci 514e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 515e5c31af7Sopenharmony_ci}; 516e5c31af7Sopenharmony_ci 517e5c31af7Sopenharmony_ciArrayStrideValidator::ArrayStrideValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 518e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_ARRAY_STRIDE, programID, filter, DE_NULL) 519e5c31af7Sopenharmony_ci{ 520e5c31af7Sopenharmony_ci} 521e5c31af7Sopenharmony_ci 522e5c31af7Sopenharmony_civoid ArrayStrideValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 523e5c31af7Sopenharmony_ci{ 524e5c31af7Sopenharmony_ci const VariablePathComponent nullComponent; 525e5c31af7Sopenharmony_ci const VariablePathComponent& component = path.back(); 526e5c31af7Sopenharmony_ci const VariablePathComponent& enclosingcomponent = (path.size() > 1) ? (path[path.size()-2]) : (nullComponent); 527e5c31af7Sopenharmony_ci const VariablePathComponent& firstComponent = path.front(); 528e5c31af7Sopenharmony_ci 529e5c31af7Sopenharmony_ci const bool isBufferBlock = firstComponent.isInterfaceBlock() && isBufferBackedInterfaceBlockStorage(firstComponent.getInterfaceBlock()->storage); 530e5c31af7Sopenharmony_ci const bool isArray = enclosingcomponent.isVariableType() && enclosingcomponent.getVariableType()->isArrayType(); 531e5c31af7Sopenharmony_ci const bool isAtomicCounter = glu::isDataTypeAtomicCounter(component.getVariableType()->getBasicType()); // atomic counters are buffer backed with a stride of 4 basic machine units 532e5c31af7Sopenharmony_ci 533e5c31af7Sopenharmony_ci DE_UNREF(resource); 534e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 535e5c31af7Sopenharmony_ci 536e5c31af7Sopenharmony_ci // Layout tests will verify layouts of buffer backed arrays properly. Here we just check values are greater or equal to the element size 537e5c31af7Sopenharmony_ci if (isBufferBlock && isArray) 538e5c31af7Sopenharmony_ci { 539e5c31af7Sopenharmony_ci const int elementSize = glu::getDataTypeScalarSize(component.getVariableType()->getBasicType()) * getTypeSize(glu::getDataTypeScalarType(component.getVariableType()->getBasicType())); 540e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array stride, expecting greater or equal to " << elementSize << tcu::TestLog::EndMessage; 541e5c31af7Sopenharmony_ci 542e5c31af7Sopenharmony_ci if (propValue < elementSize) 543e5c31af7Sopenharmony_ci { 544e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 545e5c31af7Sopenharmony_ci setError("resource array stride invalid"); 546e5c31af7Sopenharmony_ci } 547e5c31af7Sopenharmony_ci } 548e5c31af7Sopenharmony_ci else 549e5c31af7Sopenharmony_ci { 550e5c31af7Sopenharmony_ci // Atomics are buffer backed with stride of 4 even though they are not in an interface block 551e5c31af7Sopenharmony_ci const int arrayStride = (isAtomicCounter && isArray) ? (4) : (!isBufferBlock && !isAtomicCounter) ? (-1) : (0); 552e5c31af7Sopenharmony_ci 553e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array stride, expecting " << arrayStride << tcu::TestLog::EndMessage; 554e5c31af7Sopenharmony_ci 555e5c31af7Sopenharmony_ci if (arrayStride != propValue) 556e5c31af7Sopenharmony_ci { 557e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 558e5c31af7Sopenharmony_ci setError("resource array stride invalid"); 559e5c31af7Sopenharmony_ci } 560e5c31af7Sopenharmony_ci } 561e5c31af7Sopenharmony_ci} 562e5c31af7Sopenharmony_ci 563e5c31af7Sopenharmony_ciclass BlockIndexValidator : public SingleVariableValidator 564e5c31af7Sopenharmony_ci{ 565e5c31af7Sopenharmony_cipublic: 566e5c31af7Sopenharmony_ci BlockIndexValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 567e5c31af7Sopenharmony_ci 568e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 569e5c31af7Sopenharmony_ci}; 570e5c31af7Sopenharmony_ci 571e5c31af7Sopenharmony_ciBlockIndexValidator::BlockIndexValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 572e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_BLOCK_INDEX, programID, filter, DE_NULL) 573e5c31af7Sopenharmony_ci{ 574e5c31af7Sopenharmony_ci} 575e5c31af7Sopenharmony_ci 576e5c31af7Sopenharmony_civoid BlockIndexValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 577e5c31af7Sopenharmony_ci{ 578e5c31af7Sopenharmony_ci const VariablePathComponent& firstComponent = path.front(); 579e5c31af7Sopenharmony_ci 580e5c31af7Sopenharmony_ci DE_UNREF(resource); 581e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 582e5c31af7Sopenharmony_ci 583e5c31af7Sopenharmony_ci if (!firstComponent.isInterfaceBlock()) 584e5c31af7Sopenharmony_ci { 585e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying block index, expecting -1" << tcu::TestLog::EndMessage; 586e5c31af7Sopenharmony_ci 587e5c31af7Sopenharmony_ci if (propValue != -1) 588e5c31af7Sopenharmony_ci { 589e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 590e5c31af7Sopenharmony_ci setError("resource block index invalid"); 591e5c31af7Sopenharmony_ci } 592e5c31af7Sopenharmony_ci } 593e5c31af7Sopenharmony_ci else 594e5c31af7Sopenharmony_ci { 595e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying block index, expecting a valid block index" << tcu::TestLog::EndMessage; 596e5c31af7Sopenharmony_ci 597e5c31af7Sopenharmony_ci if (propValue == -1) 598e5c31af7Sopenharmony_ci { 599e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 600e5c31af7Sopenharmony_ci setError("resource block index invalid"); 601e5c31af7Sopenharmony_ci } 602e5c31af7Sopenharmony_ci else 603e5c31af7Sopenharmony_ci { 604e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderContext.getFunctions(); 605e5c31af7Sopenharmony_ci const glw::GLenum interface = (firstComponent.getInterfaceBlock()->storage == glu::STORAGE_UNIFORM) ? (GL_UNIFORM_BLOCK) : 606e5c31af7Sopenharmony_ci (firstComponent.getInterfaceBlock()->storage == glu::STORAGE_BUFFER) ? (GL_SHADER_STORAGE_BLOCK) : 607e5c31af7Sopenharmony_ci (0); 608e5c31af7Sopenharmony_ci glw::GLint written = 0; 609e5c31af7Sopenharmony_ci std::vector<char> nameBuffer (firstComponent.getInterfaceBlock()->interfaceName.size() + 3 * firstComponent.getInterfaceBlock()->dimensions.size() + 2, '\0'); // +3 for appended "[N]", +1 for '\0' and +1 just for safety 610e5c31af7Sopenharmony_ci 611e5c31af7Sopenharmony_ci gl.getProgramResourceName(m_programID, interface, propValue, (int)nameBuffer.size() - 1, &written, &nameBuffer[0]); 612e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "query block name"); 613e5c31af7Sopenharmony_ci TCU_CHECK(written < (int)nameBuffer.size()); 614e5c31af7Sopenharmony_ci TCU_CHECK(nameBuffer.back() == '\0'); 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci { 617e5c31af7Sopenharmony_ci const std::string blockName (&nameBuffer[0], written); 618e5c31af7Sopenharmony_ci std::ostringstream expectedName; 619e5c31af7Sopenharmony_ci 620e5c31af7Sopenharmony_ci expectedName << firstComponent.getInterfaceBlock()->interfaceName; 621e5c31af7Sopenharmony_ci for (int dimensionNdx = 0; dimensionNdx < (int)firstComponent.getInterfaceBlock()->dimensions.size(); ++dimensionNdx) 622e5c31af7Sopenharmony_ci expectedName << "[0]"; 623e5c31af7Sopenharmony_ci 624e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Block name with index " << propValue << " is \"" << blockName << "\"" << tcu::TestLog::EndMessage; 625e5c31af7Sopenharmony_ci if (blockName != expectedName.str()) 626e5c31af7Sopenharmony_ci { 627e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, expected " << expectedName.str() << tcu::TestLog::EndMessage; 628e5c31af7Sopenharmony_ci setError("resource block index invalid"); 629e5c31af7Sopenharmony_ci } 630e5c31af7Sopenharmony_ci } 631e5c31af7Sopenharmony_ci } 632e5c31af7Sopenharmony_ci } 633e5c31af7Sopenharmony_ci} 634e5c31af7Sopenharmony_ci 635e5c31af7Sopenharmony_ciclass IsRowMajorValidator : public SingleVariableValidator 636e5c31af7Sopenharmony_ci{ 637e5c31af7Sopenharmony_cipublic: 638e5c31af7Sopenharmony_ci IsRowMajorValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 639e5c31af7Sopenharmony_ci 640e5c31af7Sopenharmony_ci std::string getHumanReadablePropertyString (glw::GLint propVal) const; 641e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 642e5c31af7Sopenharmony_ci}; 643e5c31af7Sopenharmony_ci 644e5c31af7Sopenharmony_ciIsRowMajorValidator::IsRowMajorValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 645e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_MATRIX_ROW_MAJOR, programID, filter, DE_NULL) 646e5c31af7Sopenharmony_ci{ 647e5c31af7Sopenharmony_ci} 648e5c31af7Sopenharmony_ci 649e5c31af7Sopenharmony_cistd::string IsRowMajorValidator::getHumanReadablePropertyString (glw::GLint propVal) const 650e5c31af7Sopenharmony_ci{ 651e5c31af7Sopenharmony_ci return de::toString(glu::getBooleanStr(propVal)); 652e5c31af7Sopenharmony_ci} 653e5c31af7Sopenharmony_ci 654e5c31af7Sopenharmony_civoid IsRowMajorValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 655e5c31af7Sopenharmony_ci{ 656e5c31af7Sopenharmony_ci const VariablePathComponent& component = path.back(); 657e5c31af7Sopenharmony_ci const VariablePathComponent& firstComponent = path.front(); 658e5c31af7Sopenharmony_ci 659e5c31af7Sopenharmony_ci const bool isBufferBlock = firstComponent.isInterfaceBlock() && isBufferBackedInterfaceBlockStorage(firstComponent.getInterfaceBlock()->storage); 660e5c31af7Sopenharmony_ci const bool isMatrix = glu::isDataTypeMatrix(component.getVariableType()->getBasicType()); 661e5c31af7Sopenharmony_ci const int expected = (isBufferBlock && isMatrix && getMatrixOrderFromPath(path) == glu::MATRIXORDER_ROW_MAJOR) ? (1) : (0); 662e5c31af7Sopenharmony_ci 663e5c31af7Sopenharmony_ci DE_UNREF(resource); 664e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 665e5c31af7Sopenharmony_ci 666e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying matrix order, expecting IS_ROW_MAJOR = " << expected << tcu::TestLog::EndMessage; 667e5c31af7Sopenharmony_ci 668e5c31af7Sopenharmony_ci if (propValue != expected) 669e5c31af7Sopenharmony_ci { 670e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 671e5c31af7Sopenharmony_ci setError("resource matrix order invalid"); 672e5c31af7Sopenharmony_ci } 673e5c31af7Sopenharmony_ci} 674e5c31af7Sopenharmony_ci 675e5c31af7Sopenharmony_ciclass MatrixStrideValidator : public SingleVariableValidator 676e5c31af7Sopenharmony_ci{ 677e5c31af7Sopenharmony_cipublic: 678e5c31af7Sopenharmony_ci MatrixStrideValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 679e5c31af7Sopenharmony_ci 680e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 681e5c31af7Sopenharmony_ci}; 682e5c31af7Sopenharmony_ci 683e5c31af7Sopenharmony_ciMatrixStrideValidator::MatrixStrideValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 684e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_MATRIX_STRIDE, programID, filter, DE_NULL) 685e5c31af7Sopenharmony_ci{ 686e5c31af7Sopenharmony_ci} 687e5c31af7Sopenharmony_ci 688e5c31af7Sopenharmony_civoid MatrixStrideValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 689e5c31af7Sopenharmony_ci{ 690e5c31af7Sopenharmony_ci const VariablePathComponent& component = path.back(); 691e5c31af7Sopenharmony_ci const VariablePathComponent& firstComponent = path.front(); 692e5c31af7Sopenharmony_ci 693e5c31af7Sopenharmony_ci const bool isBufferBlock = firstComponent.isInterfaceBlock() && isBufferBackedInterfaceBlockStorage(firstComponent.getInterfaceBlock()->storage); 694e5c31af7Sopenharmony_ci const bool isMatrix = glu::isDataTypeMatrix(component.getVariableType()->getBasicType()); 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci DE_UNREF(resource); 697e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 698e5c31af7Sopenharmony_ci 699e5c31af7Sopenharmony_ci // Layout tests will verify layouts of buffer backed arrays properly. Here we just check the stride is is greater or equal to the row/column size 700e5c31af7Sopenharmony_ci if (isBufferBlock && isMatrix) 701e5c31af7Sopenharmony_ci { 702e5c31af7Sopenharmony_ci const bool columnMajor = getMatrixOrderFromPath(path) != glu::MATRIXORDER_ROW_MAJOR; 703e5c31af7Sopenharmony_ci const int numMajorElements = (columnMajor) ? (glu::getDataTypeMatrixNumRows(component.getVariableType()->getBasicType())) : (glu::getDataTypeMatrixNumColumns(component.getVariableType()->getBasicType())); 704e5c31af7Sopenharmony_ci const int majorSize = numMajorElements * getTypeSize(glu::getDataTypeScalarType(component.getVariableType()->getBasicType())); 705e5c31af7Sopenharmony_ci 706e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying matrix stride, expecting greater or equal to " << majorSize << tcu::TestLog::EndMessage; 707e5c31af7Sopenharmony_ci 708e5c31af7Sopenharmony_ci if (propValue < majorSize) 709e5c31af7Sopenharmony_ci { 710e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 711e5c31af7Sopenharmony_ci setError("resource matrix stride invalid"); 712e5c31af7Sopenharmony_ci } 713e5c31af7Sopenharmony_ci } 714e5c31af7Sopenharmony_ci else 715e5c31af7Sopenharmony_ci { 716e5c31af7Sopenharmony_ci const int matrixStride = (!isBufferBlock && !glu::isDataTypeAtomicCounter(component.getVariableType()->getBasicType())) ? (-1) : (0); 717e5c31af7Sopenharmony_ci 718e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying matrix stride, expecting " << matrixStride << tcu::TestLog::EndMessage; 719e5c31af7Sopenharmony_ci 720e5c31af7Sopenharmony_ci if (matrixStride != propValue) 721e5c31af7Sopenharmony_ci { 722e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 723e5c31af7Sopenharmony_ci setError("resource matrix stride invalid"); 724e5c31af7Sopenharmony_ci } 725e5c31af7Sopenharmony_ci } 726e5c31af7Sopenharmony_ci} 727e5c31af7Sopenharmony_ci 728e5c31af7Sopenharmony_ciclass AtomicCounterBufferIndexVerifier : public SingleVariableValidator 729e5c31af7Sopenharmony_ci{ 730e5c31af7Sopenharmony_cipublic: 731e5c31af7Sopenharmony_ci AtomicCounterBufferIndexVerifier (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 732e5c31af7Sopenharmony_ci 733e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 734e5c31af7Sopenharmony_ci}; 735e5c31af7Sopenharmony_ci 736e5c31af7Sopenharmony_ciAtomicCounterBufferIndexVerifier::AtomicCounterBufferIndexVerifier (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 737e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_ATOMIC_COUNTER_BUFFER_INDEX, programID, filter, DE_NULL) 738e5c31af7Sopenharmony_ci{ 739e5c31af7Sopenharmony_ci} 740e5c31af7Sopenharmony_ci 741e5c31af7Sopenharmony_civoid AtomicCounterBufferIndexVerifier::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 742e5c31af7Sopenharmony_ci{ 743e5c31af7Sopenharmony_ci DE_UNREF(resource); 744e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 745e5c31af7Sopenharmony_ci 746e5c31af7Sopenharmony_ci if (!glu::isDataTypeAtomicCounter(path.back().getVariableType()->getBasicType())) 747e5c31af7Sopenharmony_ci { 748e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying atomic counter buffer index, expecting -1" << tcu::TestLog::EndMessage; 749e5c31af7Sopenharmony_ci 750e5c31af7Sopenharmony_ci if (propValue != -1) 751e5c31af7Sopenharmony_ci { 752e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 753e5c31af7Sopenharmony_ci setError("resource atomic counter buffer index invalid"); 754e5c31af7Sopenharmony_ci } 755e5c31af7Sopenharmony_ci } 756e5c31af7Sopenharmony_ci else 757e5c31af7Sopenharmony_ci { 758e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying atomic counter buffer index, expecting a valid index" << tcu::TestLog::EndMessage; 759e5c31af7Sopenharmony_ci 760e5c31af7Sopenharmony_ci if (propValue == -1) 761e5c31af7Sopenharmony_ci { 762e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 763e5c31af7Sopenharmony_ci setError("resource atomic counter buffer index invalid"); 764e5c31af7Sopenharmony_ci } 765e5c31af7Sopenharmony_ci else 766e5c31af7Sopenharmony_ci { 767e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderContext.getFunctions(); 768e5c31af7Sopenharmony_ci glw::GLint numActiveResources = 0; 769e5c31af7Sopenharmony_ci 770e5c31af7Sopenharmony_ci gl.getProgramInterfaceiv(m_programID, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &numActiveResources); 771e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramInterfaceiv(..., GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, ...)"); 772e5c31af7Sopenharmony_ci 773e5c31af7Sopenharmony_ci if (propValue >= numActiveResources) 774e5c31af7Sopenharmony_ci { 775e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << ", GL_ACTIVE_RESOURCES = " << numActiveResources << tcu::TestLog::EndMessage; 776e5c31af7Sopenharmony_ci setError("resource atomic counter buffer index invalid"); 777e5c31af7Sopenharmony_ci } 778e5c31af7Sopenharmony_ci } 779e5c31af7Sopenharmony_ci } 780e5c31af7Sopenharmony_ci} 781e5c31af7Sopenharmony_ci 782e5c31af7Sopenharmony_ciclass LocationValidator : public SingleVariableValidator 783e5c31af7Sopenharmony_ci{ 784e5c31af7Sopenharmony_cipublic: 785e5c31af7Sopenharmony_ci LocationValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 786e5c31af7Sopenharmony_ci 787e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 788e5c31af7Sopenharmony_ci void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 789e5c31af7Sopenharmony_ci}; 790e5c31af7Sopenharmony_ci 791e5c31af7Sopenharmony_ciLocationValidator::LocationValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 792e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_LOCATION, programID, filter, DE_NULL) 793e5c31af7Sopenharmony_ci{ 794e5c31af7Sopenharmony_ci} 795e5c31af7Sopenharmony_ci 796e5c31af7Sopenharmony_cistatic int getVariableLocationLength (const glu::VarType& type) 797e5c31af7Sopenharmony_ci{ 798e5c31af7Sopenharmony_ci if (type.isBasicType()) 799e5c31af7Sopenharmony_ci { 800e5c31af7Sopenharmony_ci if (glu::isDataTypeMatrix(type.getBasicType())) 801e5c31af7Sopenharmony_ci return glu::getDataTypeMatrixNumColumns(type.getBasicType()); 802e5c31af7Sopenharmony_ci else 803e5c31af7Sopenharmony_ci return 1; 804e5c31af7Sopenharmony_ci } 805e5c31af7Sopenharmony_ci else if (type.isStructType()) 806e5c31af7Sopenharmony_ci { 807e5c31af7Sopenharmony_ci int size = 0; 808e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx) 809e5c31af7Sopenharmony_ci size += getVariableLocationLength(type.getStructPtr()->getMember(ndx).getType()); 810e5c31af7Sopenharmony_ci return size; 811e5c31af7Sopenharmony_ci } 812e5c31af7Sopenharmony_ci else if (type.isArrayType()) 813e5c31af7Sopenharmony_ci return type.getArraySize() * getVariableLocationLength(type.getElementType()); 814e5c31af7Sopenharmony_ci else 815e5c31af7Sopenharmony_ci { 816e5c31af7Sopenharmony_ci DE_ASSERT(false); 817e5c31af7Sopenharmony_ci return 0; 818e5c31af7Sopenharmony_ci } 819e5c31af7Sopenharmony_ci} 820e5c31af7Sopenharmony_ci 821e5c31af7Sopenharmony_cistatic int getIOSubVariableLocation (const std::vector<VariablePathComponent>& path, int startNdx, int currentLocation) 822e5c31af7Sopenharmony_ci{ 823e5c31af7Sopenharmony_ci if (currentLocation == -1) 824e5c31af7Sopenharmony_ci return -1; 825e5c31af7Sopenharmony_ci 826e5c31af7Sopenharmony_ci if (path[startNdx].getVariableType()->isBasicType()) 827e5c31af7Sopenharmony_ci return currentLocation; 828e5c31af7Sopenharmony_ci else if (path[startNdx].getVariableType()->isArrayType()) 829e5c31af7Sopenharmony_ci return getIOSubVariableLocation(path, startNdx+1, currentLocation); 830e5c31af7Sopenharmony_ci else if (path[startNdx].getVariableType()->isStructType()) 831e5c31af7Sopenharmony_ci { 832e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < path[startNdx].getVariableType()->getStructPtr()->getNumMembers(); ++ndx) 833e5c31af7Sopenharmony_ci { 834e5c31af7Sopenharmony_ci if (&path[startNdx].getVariableType()->getStructPtr()->getMember(ndx).getType() == path[startNdx + 1].getVariableType()) 835e5c31af7Sopenharmony_ci return getIOSubVariableLocation(path, startNdx + 1, currentLocation); 836e5c31af7Sopenharmony_ci 837e5c31af7Sopenharmony_ci if (currentLocation != -1) 838e5c31af7Sopenharmony_ci currentLocation += getVariableLocationLength(path[startNdx].getVariableType()->getStructPtr()->getMember(ndx).getType()); 839e5c31af7Sopenharmony_ci } 840e5c31af7Sopenharmony_ci 841e5c31af7Sopenharmony_ci // could not find member, never happens 842e5c31af7Sopenharmony_ci DE_ASSERT(false); 843e5c31af7Sopenharmony_ci return -1; 844e5c31af7Sopenharmony_ci } 845e5c31af7Sopenharmony_ci else 846e5c31af7Sopenharmony_ci { 847e5c31af7Sopenharmony_ci DE_ASSERT(false); 848e5c31af7Sopenharmony_ci return -1; 849e5c31af7Sopenharmony_ci } 850e5c31af7Sopenharmony_ci} 851e5c31af7Sopenharmony_ci 852e5c31af7Sopenharmony_cistatic int getIOBlockVariableLocation (const std::vector<VariablePathComponent>& path) 853e5c31af7Sopenharmony_ci{ 854e5c31af7Sopenharmony_ci const glu::InterfaceBlock* block = path.front().getInterfaceBlock(); 855e5c31af7Sopenharmony_ci int currentLocation = block->layout.location; 856e5c31af7Sopenharmony_ci 857e5c31af7Sopenharmony_ci // Find the block member 858e5c31af7Sopenharmony_ci for (int memberNdx = 0; memberNdx < (int)block->variables.size(); ++memberNdx) 859e5c31af7Sopenharmony_ci { 860e5c31af7Sopenharmony_ci if (block->variables[memberNdx].layout.location != -1) 861e5c31af7Sopenharmony_ci currentLocation = block->variables[memberNdx].layout.location; 862e5c31af7Sopenharmony_ci 863e5c31af7Sopenharmony_ci if (&block->variables[memberNdx] == path[1].getDeclaration()) 864e5c31af7Sopenharmony_ci break; 865e5c31af7Sopenharmony_ci 866e5c31af7Sopenharmony_ci // unspecified + unspecified = unspecified 867e5c31af7Sopenharmony_ci if (currentLocation != -1) 868e5c31af7Sopenharmony_ci currentLocation += getVariableLocationLength(block->variables[memberNdx].varType); 869e5c31af7Sopenharmony_ci } 870e5c31af7Sopenharmony_ci 871e5c31af7Sopenharmony_ci // Find subtype location in the complex type 872e5c31af7Sopenharmony_ci return getIOSubVariableLocation(path, 2, currentLocation); 873e5c31af7Sopenharmony_ci} 874e5c31af7Sopenharmony_ci 875e5c31af7Sopenharmony_cistatic int getExplicitLocationFromPath (const std::vector<VariablePathComponent>& path) 876e5c31af7Sopenharmony_ci{ 877e5c31af7Sopenharmony_ci const glu::VariableDeclaration* varDecl = (path[0].isInterfaceBlock()) ? (path[1].getDeclaration()) : (path[0].getDeclaration()); 878e5c31af7Sopenharmony_ci 879e5c31af7Sopenharmony_ci if (path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_UNIFORM) 880e5c31af7Sopenharmony_ci { 881e5c31af7Sopenharmony_ci // inside uniform block 882e5c31af7Sopenharmony_ci return -1; 883e5c31af7Sopenharmony_ci } 884e5c31af7Sopenharmony_ci else if (path.front().isInterfaceBlock() && (path.front().getInterfaceBlock()->storage == glu::STORAGE_IN || 885e5c31af7Sopenharmony_ci path.front().getInterfaceBlock()->storage == glu::STORAGE_OUT || 886e5c31af7Sopenharmony_ci path.front().getInterfaceBlock()->storage == glu::STORAGE_PATCH_IN || 887e5c31af7Sopenharmony_ci path.front().getInterfaceBlock()->storage == glu::STORAGE_PATCH_OUT)) 888e5c31af7Sopenharmony_ci { 889e5c31af7Sopenharmony_ci // inside ioblock 890e5c31af7Sopenharmony_ci return getIOBlockVariableLocation(path); 891e5c31af7Sopenharmony_ci } 892e5c31af7Sopenharmony_ci else if (varDecl->storage == glu::STORAGE_UNIFORM) 893e5c31af7Sopenharmony_ci { 894e5c31af7Sopenharmony_ci // default block uniform 895e5c31af7Sopenharmony_ci return varDecl->layout.location; 896e5c31af7Sopenharmony_ci } 897e5c31af7Sopenharmony_ci else if (varDecl->storage == glu::STORAGE_IN || 898e5c31af7Sopenharmony_ci varDecl->storage == glu::STORAGE_OUT || 899e5c31af7Sopenharmony_ci varDecl->storage == glu::STORAGE_PATCH_IN || 900e5c31af7Sopenharmony_ci varDecl->storage == glu::STORAGE_PATCH_OUT) 901e5c31af7Sopenharmony_ci { 902e5c31af7Sopenharmony_ci // default block input/output 903e5c31af7Sopenharmony_ci return getIOSubVariableLocation(path, 1, varDecl->layout.location); 904e5c31af7Sopenharmony_ci } 905e5c31af7Sopenharmony_ci else 906e5c31af7Sopenharmony_ci { 907e5c31af7Sopenharmony_ci DE_ASSERT(false); 908e5c31af7Sopenharmony_ci return -1; 909e5c31af7Sopenharmony_ci } 910e5c31af7Sopenharmony_ci} 911e5c31af7Sopenharmony_ci 912e5c31af7Sopenharmony_civoid LocationValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 913e5c31af7Sopenharmony_ci{ 914e5c31af7Sopenharmony_ci const bool isAtomicCounterUniform = glu::isDataTypeAtomicCounter(path.back().getVariableType()->getBasicType()); 915e5c31af7Sopenharmony_ci const bool isUniformBlockVariable = path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_UNIFORM; 916e5c31af7Sopenharmony_ci const bool isVertexShader = m_filter.getShaderTypeBits() == (1u << glu::SHADERTYPE_VERTEX); 917e5c31af7Sopenharmony_ci const bool isFragmentShader = m_filter.getShaderTypeBits() == (1u << glu::SHADERTYPE_FRAGMENT); 918e5c31af7Sopenharmony_ci const glu::Storage storage = (path.front().isInterfaceBlock()) ? (path.front().getInterfaceBlock()->storage) : (path.front().getDeclaration()->storage); 919e5c31af7Sopenharmony_ci const bool isInputVariable = (storage == glu::STORAGE_IN || storage == glu::STORAGE_PATCH_IN); 920e5c31af7Sopenharmony_ci const bool isOutputVariable = (storage == glu::STORAGE_OUT || storage == glu::STORAGE_PATCH_OUT); 921e5c31af7Sopenharmony_ci const int explicitLayoutLocation = getExplicitLocationFromPath(path); 922e5c31af7Sopenharmony_ci 923e5c31af7Sopenharmony_ci bool expectLocation; 924e5c31af7Sopenharmony_ci std::string reasonStr; 925e5c31af7Sopenharmony_ci 926e5c31af7Sopenharmony_ci DE_UNREF(resource); 927e5c31af7Sopenharmony_ci 928e5c31af7Sopenharmony_ci if (isAtomicCounterUniform) 929e5c31af7Sopenharmony_ci { 930e5c31af7Sopenharmony_ci expectLocation = false; 931e5c31af7Sopenharmony_ci reasonStr = "Atomic counter uniforms have effective location of -1"; 932e5c31af7Sopenharmony_ci } 933e5c31af7Sopenharmony_ci else if (isUniformBlockVariable) 934e5c31af7Sopenharmony_ci { 935e5c31af7Sopenharmony_ci expectLocation = false; 936e5c31af7Sopenharmony_ci reasonStr = "Uniform block variables have effective location of -1"; 937e5c31af7Sopenharmony_ci } 938e5c31af7Sopenharmony_ci else if (isInputVariable && !isVertexShader && explicitLayoutLocation == -1) 939e5c31af7Sopenharmony_ci { 940e5c31af7Sopenharmony_ci expectLocation = false; 941e5c31af7Sopenharmony_ci reasonStr = "Inputs (except for vertex shader inputs) not declared with a location layout qualifier have effective location of -1"; 942e5c31af7Sopenharmony_ci } 943e5c31af7Sopenharmony_ci else if (isOutputVariable && !isFragmentShader && explicitLayoutLocation == -1) 944e5c31af7Sopenharmony_ci { 945e5c31af7Sopenharmony_ci expectLocation = false; 946e5c31af7Sopenharmony_ci reasonStr = "Outputs (except for fragment shader outputs) not declared with a location layout qualifier have effective location of -1"; 947e5c31af7Sopenharmony_ci } 948e5c31af7Sopenharmony_ci else 949e5c31af7Sopenharmony_ci { 950e5c31af7Sopenharmony_ci expectLocation = true; 951e5c31af7Sopenharmony_ci } 952e5c31af7Sopenharmony_ci 953e5c31af7Sopenharmony_ci if (!expectLocation) 954e5c31af7Sopenharmony_ci { 955e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying uniform location, expecting -1. (" << reasonStr << ")" << tcu::TestLog::EndMessage; 956e5c31af7Sopenharmony_ci 957e5c31af7Sopenharmony_ci if (propValue != -1) 958e5c31af7Sopenharmony_ci { 959e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 960e5c31af7Sopenharmony_ci setError("resource location invalid"); 961e5c31af7Sopenharmony_ci } 962e5c31af7Sopenharmony_ci } 963e5c31af7Sopenharmony_ci else 964e5c31af7Sopenharmony_ci { 965e5c31af7Sopenharmony_ci bool locationOk; 966e5c31af7Sopenharmony_ci 967e5c31af7Sopenharmony_ci if (explicitLayoutLocation == -1) 968e5c31af7Sopenharmony_ci { 969e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying location, expecting a valid location" << tcu::TestLog::EndMessage; 970e5c31af7Sopenharmony_ci locationOk = (propValue != -1); 971e5c31af7Sopenharmony_ci } 972e5c31af7Sopenharmony_ci else 973e5c31af7Sopenharmony_ci { 974e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying location, expecting " << explicitLayoutLocation << tcu::TestLog::EndMessage; 975e5c31af7Sopenharmony_ci locationOk = (propValue == explicitLayoutLocation); 976e5c31af7Sopenharmony_ci } 977e5c31af7Sopenharmony_ci 978e5c31af7Sopenharmony_ci if (!locationOk) 979e5c31af7Sopenharmony_ci { 980e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 981e5c31af7Sopenharmony_ci setError("resource location invalid"); 982e5c31af7Sopenharmony_ci } 983e5c31af7Sopenharmony_ci else 984e5c31af7Sopenharmony_ci { 985e5c31af7Sopenharmony_ci const VariablePathComponent nullComponent; 986e5c31af7Sopenharmony_ci const VariablePathComponent& enclosingcomponent = (path.size() > 1) ? (path[path.size()-2]) : (nullComponent); 987e5c31af7Sopenharmony_ci const bool isArray = enclosingcomponent.isVariableType() && enclosingcomponent.getVariableType()->isArrayType(); 988e5c31af7Sopenharmony_ci 989e5c31af7Sopenharmony_ci const glw::Functions& gl = m_renderContext.getFunctions(); 990e5c31af7Sopenharmony_ci const glw::GLenum interface = getProgramDefaultBlockInterfaceFromStorage(storage); 991e5c31af7Sopenharmony_ci 992e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Comparing location to the values returned by GetProgramResourceLocation" << tcu::TestLog::EndMessage; 993e5c31af7Sopenharmony_ci 994e5c31af7Sopenharmony_ci // Test all bottom-level array elements 995e5c31af7Sopenharmony_ci if (isArray) 996e5c31af7Sopenharmony_ci { 997e5c31af7Sopenharmony_ci const std::string arrayResourceName = (implementationName.size() > 3) ? (implementationName.substr(0, implementationName.size() - 3)) : (""); // chop "[0]" 998e5c31af7Sopenharmony_ci 999e5c31af7Sopenharmony_ci for (int arrayElementNdx = 0; arrayElementNdx < enclosingcomponent.getVariableType()->getArraySize(); ++arrayElementNdx) 1000e5c31af7Sopenharmony_ci { 1001e5c31af7Sopenharmony_ci const std::string elementResourceName = arrayResourceName + "[" + de::toString(arrayElementNdx) + "]"; 1002e5c31af7Sopenharmony_ci const glw::GLint location = gl.getProgramResourceLocation(m_programID, interface, elementResourceName.c_str()); 1003e5c31af7Sopenharmony_ci 1004e5c31af7Sopenharmony_ci if (location != propValue+arrayElementNdx) 1005e5c31af7Sopenharmony_ci { 1006e5c31af7Sopenharmony_ci m_testCtx.getLog() 1007e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1008e5c31af7Sopenharmony_ci << "\tError, getProgramResourceLocation (resource=\"" << elementResourceName << "\") returned location " << location 1009e5c31af7Sopenharmony_ci << ", expected " << (propValue+arrayElementNdx) 1010e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1011e5c31af7Sopenharmony_ci setError("resource location invalid"); 1012e5c31af7Sopenharmony_ci } 1013e5c31af7Sopenharmony_ci else 1014e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tLocation of \"" << elementResourceName << "\":\t" << location << tcu::TestLog::EndMessage; 1015e5c31af7Sopenharmony_ci } 1016e5c31af7Sopenharmony_ci } 1017e5c31af7Sopenharmony_ci else 1018e5c31af7Sopenharmony_ci { 1019e5c31af7Sopenharmony_ci const glw::GLint location = gl.getProgramResourceLocation(m_programID, interface, implementationName.c_str()); 1020e5c31af7Sopenharmony_ci 1021e5c31af7Sopenharmony_ci if (location != propValue) 1022e5c31af7Sopenharmony_ci { 1023e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, getProgramResourceLocation returned location " << location << ", expected " << propValue << tcu::TestLog::EndMessage; 1024e5c31af7Sopenharmony_ci setError("resource location invalid"); 1025e5c31af7Sopenharmony_ci } 1026e5c31af7Sopenharmony_ci } 1027e5c31af7Sopenharmony_ci 1028e5c31af7Sopenharmony_ci } 1029e5c31af7Sopenharmony_ci } 1030e5c31af7Sopenharmony_ci} 1031e5c31af7Sopenharmony_ci 1032e5c31af7Sopenharmony_civoid LocationValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1033e5c31af7Sopenharmony_ci{ 1034e5c31af7Sopenharmony_ci DE_UNREF(resource); 1035e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1036e5c31af7Sopenharmony_ci 1037e5c31af7Sopenharmony_ci // built-ins have no location 1038e5c31af7Sopenharmony_ci 1039e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying location, expecting -1" << tcu::TestLog::EndMessage; 1040e5c31af7Sopenharmony_ci 1041e5c31af7Sopenharmony_ci if (propValue != -1) 1042e5c31af7Sopenharmony_ci { 1043e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 1044e5c31af7Sopenharmony_ci setError("resource location invalid"); 1045e5c31af7Sopenharmony_ci } 1046e5c31af7Sopenharmony_ci} 1047e5c31af7Sopenharmony_ci 1048e5c31af7Sopenharmony_ciclass VariableNameLengthValidator : public SingleVariableValidator 1049e5c31af7Sopenharmony_ci{ 1050e5c31af7Sopenharmony_cipublic: 1051e5c31af7Sopenharmony_ci VariableNameLengthValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 1052e5c31af7Sopenharmony_ci 1053e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1054e5c31af7Sopenharmony_ci void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1055e5c31af7Sopenharmony_ci void validateNameLength (const std::string& implementationName, glw::GLint propValue) const; 1056e5c31af7Sopenharmony_ci}; 1057e5c31af7Sopenharmony_ci 1058e5c31af7Sopenharmony_ciVariableNameLengthValidator::VariableNameLengthValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 1059e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH, programID, filter, DE_NULL) 1060e5c31af7Sopenharmony_ci{ 1061e5c31af7Sopenharmony_ci} 1062e5c31af7Sopenharmony_ci 1063e5c31af7Sopenharmony_civoid VariableNameLengthValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1064e5c31af7Sopenharmony_ci{ 1065e5c31af7Sopenharmony_ci DE_UNREF(path); 1066e5c31af7Sopenharmony_ci DE_UNREF(resource); 1067e5c31af7Sopenharmony_ci validateNameLength(implementationName, propValue); 1068e5c31af7Sopenharmony_ci} 1069e5c31af7Sopenharmony_ci 1070e5c31af7Sopenharmony_civoid VariableNameLengthValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1071e5c31af7Sopenharmony_ci{ 1072e5c31af7Sopenharmony_ci DE_UNREF(resource); 1073e5c31af7Sopenharmony_ci validateNameLength(implementationName, propValue); 1074e5c31af7Sopenharmony_ci} 1075e5c31af7Sopenharmony_ci 1076e5c31af7Sopenharmony_civoid VariableNameLengthValidator::validateNameLength (const std::string& implementationName, glw::GLint propValue) const 1077e5c31af7Sopenharmony_ci{ 1078e5c31af7Sopenharmony_ci const int expected = (int)implementationName.length() + 1; // includes null byte 1079e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " (" << (int)implementationName.length() << " for \"" << implementationName << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage; 1080e5c31af7Sopenharmony_ci 1081e5c31af7Sopenharmony_ci if (propValue != expected) 1082e5c31af7Sopenharmony_ci { 1083e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue << tcu::TestLog::EndMessage; 1084e5c31af7Sopenharmony_ci setError("name length invalid"); 1085e5c31af7Sopenharmony_ci } 1086e5c31af7Sopenharmony_ci} 1087e5c31af7Sopenharmony_ci 1088e5c31af7Sopenharmony_ciclass OffsetValidator : public SingleVariableValidator 1089e5c31af7Sopenharmony_ci{ 1090e5c31af7Sopenharmony_cipublic: 1091e5c31af7Sopenharmony_ci OffsetValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 1092e5c31af7Sopenharmony_ci 1093e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1094e5c31af7Sopenharmony_ci}; 1095e5c31af7Sopenharmony_ci 1096e5c31af7Sopenharmony_ciOffsetValidator::OffsetValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 1097e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_OFFSET, programID, filter, DE_NULL) 1098e5c31af7Sopenharmony_ci{ 1099e5c31af7Sopenharmony_ci} 1100e5c31af7Sopenharmony_ci 1101e5c31af7Sopenharmony_civoid OffsetValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1102e5c31af7Sopenharmony_ci{ 1103e5c31af7Sopenharmony_ci const bool isAtomicCounterUniform = glu::isDataTypeAtomicCounter(path.back().getVariableType()->getBasicType()); 1104e5c31af7Sopenharmony_ci const bool isBufferBackedBlockStorage = path.front().isInterfaceBlock() && isBufferBackedInterfaceBlockStorage(path.front().getInterfaceBlock()->storage); 1105e5c31af7Sopenharmony_ci 1106e5c31af7Sopenharmony_ci DE_UNREF(resource); 1107e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1108e5c31af7Sopenharmony_ci 1109e5c31af7Sopenharmony_ci if (!isAtomicCounterUniform && !isBufferBackedBlockStorage) 1110e5c31af7Sopenharmony_ci { 1111e5c31af7Sopenharmony_ci // Not buffer backed 1112e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying offset, expecting -1" << tcu::TestLog::EndMessage; 1113e5c31af7Sopenharmony_ci 1114e5c31af7Sopenharmony_ci if (propValue != -1) 1115e5c31af7Sopenharmony_ci { 1116e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid offset, got " << propValue << tcu::TestLog::EndMessage; 1117e5c31af7Sopenharmony_ci setError("offset invalid"); 1118e5c31af7Sopenharmony_ci } 1119e5c31af7Sopenharmony_ci } 1120e5c31af7Sopenharmony_ci else 1121e5c31af7Sopenharmony_ci { 1122e5c31af7Sopenharmony_ci // Expect a valid offset 1123e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying offset, expecting a valid offset" << tcu::TestLog::EndMessage; 1124e5c31af7Sopenharmony_ci 1125e5c31af7Sopenharmony_ci if (propValue < 0) 1126e5c31af7Sopenharmony_ci { 1127e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid offset, got " << propValue << tcu::TestLog::EndMessage; 1128e5c31af7Sopenharmony_ci setError("offset invalid"); 1129e5c31af7Sopenharmony_ci } 1130e5c31af7Sopenharmony_ci } 1131e5c31af7Sopenharmony_ci} 1132e5c31af7Sopenharmony_ci 1133e5c31af7Sopenharmony_ciclass VariableReferencedByShaderValidator : public PropValidator 1134e5c31af7Sopenharmony_ci{ 1135e5c31af7Sopenharmony_cipublic: 1136e5c31af7Sopenharmony_ci VariableReferencedByShaderValidator (Context& context, glu::ShaderType shaderType, const VariableSearchFilter& searchFilter); 1137e5c31af7Sopenharmony_ci 1138e5c31af7Sopenharmony_ci std::string getHumanReadablePropertyString (glw::GLint propVal) const; 1139e5c31af7Sopenharmony_ci void validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1140e5c31af7Sopenharmony_ci 1141e5c31af7Sopenharmony_ciprivate: 1142e5c31af7Sopenharmony_ci const VariableSearchFilter m_filter; 1143e5c31af7Sopenharmony_ci const glu::ShaderType m_shaderType; 1144e5c31af7Sopenharmony_ci}; 1145e5c31af7Sopenharmony_ci 1146e5c31af7Sopenharmony_ciVariableReferencedByShaderValidator::VariableReferencedByShaderValidator (Context& context, glu::ShaderType shaderType, const VariableSearchFilter& searchFilter) 1147e5c31af7Sopenharmony_ci : PropValidator (context, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER, getRequiredExtensionForStage(shaderType)) 1148e5c31af7Sopenharmony_ci , m_filter (VariableSearchFilter::logicalAnd(VariableSearchFilter::createShaderTypeFilter(shaderType), searchFilter)) 1149e5c31af7Sopenharmony_ci , m_shaderType (shaderType) 1150e5c31af7Sopenharmony_ci{ 1151e5c31af7Sopenharmony_ci DE_ASSERT(m_shaderType < glu::SHADERTYPE_LAST); 1152e5c31af7Sopenharmony_ci} 1153e5c31af7Sopenharmony_ci 1154e5c31af7Sopenharmony_cistd::string VariableReferencedByShaderValidator::getHumanReadablePropertyString (glw::GLint propVal) const 1155e5c31af7Sopenharmony_ci{ 1156e5c31af7Sopenharmony_ci return de::toString(glu::getBooleanStr(propVal)); 1157e5c31af7Sopenharmony_ci} 1158e5c31af7Sopenharmony_ci 1159e5c31af7Sopenharmony_civoid VariableReferencedByShaderValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1160e5c31af7Sopenharmony_ci{ 1161e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1162e5c31af7Sopenharmony_ci 1163e5c31af7Sopenharmony_ci std::vector<VariablePathComponent> unusedPath; 1164e5c31af7Sopenharmony_ci const bool referencedByShader = findProgramVariablePathByPathName(unusedPath, program, resource, m_filter); 1165e5c31af7Sopenharmony_ci 1166e5c31af7Sopenharmony_ci m_testCtx.getLog() 1167e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1168e5c31af7Sopenharmony_ci << "Verifying referenced by " << glu::getShaderTypeName(m_shaderType) << " shader, expecting " 1169e5c31af7Sopenharmony_ci << ((referencedByShader) ? ("GL_TRUE") : ("GL_FALSE")) 1170e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1171e5c31af7Sopenharmony_ci 1172e5c31af7Sopenharmony_ci if (propValue != ((referencedByShader) ? (1) : (0))) 1173e5c31af7Sopenharmony_ci { 1174e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid referenced_by_" << glu::getShaderTypeName(m_shaderType) << ", got " << propValue << tcu::TestLog::EndMessage; 1175e5c31af7Sopenharmony_ci setError("referenced_by_" + std::string(glu::getShaderTypeName(m_shaderType)) + " invalid"); 1176e5c31af7Sopenharmony_ci } 1177e5c31af7Sopenharmony_ci} 1178e5c31af7Sopenharmony_ci 1179e5c31af7Sopenharmony_ciclass BlockNameLengthValidator : public SingleBlockValidator 1180e5c31af7Sopenharmony_ci{ 1181e5c31af7Sopenharmony_cipublic: 1182e5c31af7Sopenharmony_ci BlockNameLengthValidator (Context& context, const glw::GLuint programID, const VariableSearchFilter& filter); 1183e5c31af7Sopenharmony_ci 1184e5c31af7Sopenharmony_ci void validateSingleBlock (const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1185e5c31af7Sopenharmony_ci}; 1186e5c31af7Sopenharmony_ci 1187e5c31af7Sopenharmony_ciBlockNameLengthValidator::BlockNameLengthValidator (Context& context, const glw::GLuint programID, const VariableSearchFilter& filter) 1188e5c31af7Sopenharmony_ci : SingleBlockValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH, programID, filter, DE_NULL) 1189e5c31af7Sopenharmony_ci{ 1190e5c31af7Sopenharmony_ci} 1191e5c31af7Sopenharmony_ci 1192e5c31af7Sopenharmony_civoid BlockNameLengthValidator::validateSingleBlock (const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1193e5c31af7Sopenharmony_ci{ 1194e5c31af7Sopenharmony_ci DE_UNREF(instanceIndex); 1195e5c31af7Sopenharmony_ci DE_UNREF(block); 1196e5c31af7Sopenharmony_ci DE_UNREF(resource); 1197e5c31af7Sopenharmony_ci 1198e5c31af7Sopenharmony_ci const int expected = (int)implementationName.length() + 1; // includes null byte 1199e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " (" << (int)implementationName.length() << " for \"" << implementationName << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage; 1200e5c31af7Sopenharmony_ci 1201e5c31af7Sopenharmony_ci if (propValue != expected) 1202e5c31af7Sopenharmony_ci { 1203e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue << tcu::TestLog::EndMessage; 1204e5c31af7Sopenharmony_ci setError("name length invalid"); 1205e5c31af7Sopenharmony_ci } 1206e5c31af7Sopenharmony_ci} 1207e5c31af7Sopenharmony_ci 1208e5c31af7Sopenharmony_ciclass BufferBindingValidator : public SingleBlockValidator 1209e5c31af7Sopenharmony_ci{ 1210e5c31af7Sopenharmony_cipublic: 1211e5c31af7Sopenharmony_ci BufferBindingValidator (Context& context, const glw::GLuint programID, const VariableSearchFilter& filter); 1212e5c31af7Sopenharmony_ci 1213e5c31af7Sopenharmony_ci void validateSingleBlock (const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1214e5c31af7Sopenharmony_ci}; 1215e5c31af7Sopenharmony_ci 1216e5c31af7Sopenharmony_ciBufferBindingValidator::BufferBindingValidator (Context& context, const glw::GLuint programID, const VariableSearchFilter& filter) 1217e5c31af7Sopenharmony_ci : SingleBlockValidator(context, PROGRAMRESOURCEPROP_BUFFER_BINDING, programID, filter, DE_NULL) 1218e5c31af7Sopenharmony_ci{ 1219e5c31af7Sopenharmony_ci} 1220e5c31af7Sopenharmony_ci 1221e5c31af7Sopenharmony_civoid BufferBindingValidator::validateSingleBlock (const glu::InterfaceBlock& block, const std::vector<int>& instanceIndex, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1222e5c31af7Sopenharmony_ci{ 1223e5c31af7Sopenharmony_ci DE_UNREF(resource); 1224e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1225e5c31af7Sopenharmony_ci 1226e5c31af7Sopenharmony_ci if (block.layout.binding != -1) 1227e5c31af7Sopenharmony_ci { 1228e5c31af7Sopenharmony_ci int flatIndex = 0; 1229e5c31af7Sopenharmony_ci int dimensionSize = 1; 1230e5c31af7Sopenharmony_ci 1231e5c31af7Sopenharmony_ci for (int dimensionNdx = (int)(block.dimensions.size()) - 1; dimensionNdx >= 0; --dimensionNdx) 1232e5c31af7Sopenharmony_ci { 1233e5c31af7Sopenharmony_ci flatIndex += dimensionSize * instanceIndex[dimensionNdx]; 1234e5c31af7Sopenharmony_ci dimensionSize *= block.dimensions[dimensionNdx]; 1235e5c31af7Sopenharmony_ci } 1236e5c31af7Sopenharmony_ci 1237e5c31af7Sopenharmony_ci const int expected = (block.dimensions.empty()) ? (block.layout.binding) : (block.layout.binding + flatIndex); 1238e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying block binding, expecting " << expected << tcu::TestLog::EndMessage; 1239e5c31af7Sopenharmony_ci 1240e5c31af7Sopenharmony_ci if (propValue != expected) 1241e5c31af7Sopenharmony_ci { 1242e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid buffer binding, got " << propValue << tcu::TestLog::EndMessage; 1243e5c31af7Sopenharmony_ci setError("buffer binding invalid"); 1244e5c31af7Sopenharmony_ci } 1245e5c31af7Sopenharmony_ci } 1246e5c31af7Sopenharmony_ci else 1247e5c31af7Sopenharmony_ci { 1248e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying buffer binding, expecting a valid binding" << tcu::TestLog::EndMessage; 1249e5c31af7Sopenharmony_ci 1250e5c31af7Sopenharmony_ci if (propValue < 0) 1251e5c31af7Sopenharmony_ci { 1252e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid buffer binding, got " << propValue << tcu::TestLog::EndMessage; 1253e5c31af7Sopenharmony_ci setError("buffer binding invalid"); 1254e5c31af7Sopenharmony_ci } 1255e5c31af7Sopenharmony_ci } 1256e5c31af7Sopenharmony_ci} 1257e5c31af7Sopenharmony_ci 1258e5c31af7Sopenharmony_ciclass BlockReferencedByShaderValidator : public PropValidator 1259e5c31af7Sopenharmony_ci{ 1260e5c31af7Sopenharmony_cipublic: 1261e5c31af7Sopenharmony_ci BlockReferencedByShaderValidator (Context& context, glu::ShaderType shaderType, const VariableSearchFilter& searchFilter); 1262e5c31af7Sopenharmony_ci 1263e5c31af7Sopenharmony_ci std::string getHumanReadablePropertyString (glw::GLint propVal) const; 1264e5c31af7Sopenharmony_ci void validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1265e5c31af7Sopenharmony_ci 1266e5c31af7Sopenharmony_ciprivate: 1267e5c31af7Sopenharmony_ci const VariableSearchFilter m_filter; 1268e5c31af7Sopenharmony_ci const glu::ShaderType m_shaderType; 1269e5c31af7Sopenharmony_ci}; 1270e5c31af7Sopenharmony_ci 1271e5c31af7Sopenharmony_ciBlockReferencedByShaderValidator::BlockReferencedByShaderValidator (Context& context, glu::ShaderType shaderType, const VariableSearchFilter& searchFilter) 1272e5c31af7Sopenharmony_ci : PropValidator (context, PROGRAMRESOURCEPROP_REFERENCED_BY_SHADER, getRequiredExtensionForStage(shaderType)) 1273e5c31af7Sopenharmony_ci , m_filter (VariableSearchFilter::logicalAnd(VariableSearchFilter::createShaderTypeFilter(shaderType), searchFilter)) 1274e5c31af7Sopenharmony_ci , m_shaderType (shaderType) 1275e5c31af7Sopenharmony_ci{ 1276e5c31af7Sopenharmony_ci DE_ASSERT(m_shaderType < glu::SHADERTYPE_LAST); 1277e5c31af7Sopenharmony_ci} 1278e5c31af7Sopenharmony_ci 1279e5c31af7Sopenharmony_cistd::string BlockReferencedByShaderValidator::getHumanReadablePropertyString (glw::GLint propVal) const 1280e5c31af7Sopenharmony_ci{ 1281e5c31af7Sopenharmony_ci return de::toString(glu::getBooleanStr(propVal)); 1282e5c31af7Sopenharmony_ci} 1283e5c31af7Sopenharmony_ci 1284e5c31af7Sopenharmony_civoid BlockReferencedByShaderValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1285e5c31af7Sopenharmony_ci{ 1286e5c31af7Sopenharmony_ci const std::string blockName = glu::parseVariableName(resource.c_str()); 1287e5c31af7Sopenharmony_ci bool referencedByShader = false; 1288e5c31af7Sopenharmony_ci 1289e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1290e5c31af7Sopenharmony_ci 1291e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 1292e5c31af7Sopenharmony_ci { 1293e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx]; 1294e5c31af7Sopenharmony_ci if (!m_filter.matchesFilter(shader)) 1295e5c31af7Sopenharmony_ci continue; 1296e5c31af7Sopenharmony_ci 1297e5c31af7Sopenharmony_ci for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx) 1298e5c31af7Sopenharmony_ci { 1299e5c31af7Sopenharmony_ci const glu::InterfaceBlock& block = shader->getDefaultBlock().interfaceBlocks[blockNdx]; 1300e5c31af7Sopenharmony_ci 1301e5c31af7Sopenharmony_ci if (m_filter.matchesFilter(block) && block.interfaceName == blockName) 1302e5c31af7Sopenharmony_ci referencedByShader = true; 1303e5c31af7Sopenharmony_ci } 1304e5c31af7Sopenharmony_ci } 1305e5c31af7Sopenharmony_ci 1306e5c31af7Sopenharmony_ci m_testCtx.getLog() 1307e5c31af7Sopenharmony_ci << tcu::TestLog::Message 1308e5c31af7Sopenharmony_ci << "Verifying referenced by " << glu::getShaderTypeName(m_shaderType) << " shader, expecting " 1309e5c31af7Sopenharmony_ci << ((referencedByShader) ? ("GL_TRUE") : ("GL_FALSE")) 1310e5c31af7Sopenharmony_ci << tcu::TestLog::EndMessage; 1311e5c31af7Sopenharmony_ci 1312e5c31af7Sopenharmony_ci if (propValue != ((referencedByShader) ? (1) : (0))) 1313e5c31af7Sopenharmony_ci { 1314e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid referenced_by_" << glu::getShaderTypeName(m_shaderType) << ", got " << propValue << tcu::TestLog::EndMessage; 1315e5c31af7Sopenharmony_ci setError("referenced_by_" + std::string(glu::getShaderTypeName(m_shaderType)) + " invalid"); 1316e5c31af7Sopenharmony_ci } 1317e5c31af7Sopenharmony_ci} 1318e5c31af7Sopenharmony_ci 1319e5c31af7Sopenharmony_ciclass TopLevelArraySizeValidator : public SingleVariableValidator 1320e5c31af7Sopenharmony_ci{ 1321e5c31af7Sopenharmony_cipublic: 1322e5c31af7Sopenharmony_ci TopLevelArraySizeValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 1323e5c31af7Sopenharmony_ci 1324e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1325e5c31af7Sopenharmony_ci}; 1326e5c31af7Sopenharmony_ci 1327e5c31af7Sopenharmony_ciTopLevelArraySizeValidator::TopLevelArraySizeValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 1328e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_SIZE, programID, filter, DE_NULL) 1329e5c31af7Sopenharmony_ci{ 1330e5c31af7Sopenharmony_ci} 1331e5c31af7Sopenharmony_ci 1332e5c31af7Sopenharmony_civoid TopLevelArraySizeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1333e5c31af7Sopenharmony_ci{ 1334e5c31af7Sopenharmony_ci int expected; 1335e5c31af7Sopenharmony_ci std::string reason; 1336e5c31af7Sopenharmony_ci 1337e5c31af7Sopenharmony_ci DE_ASSERT(path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_BUFFER); 1338e5c31af7Sopenharmony_ci DE_UNREF(resource); 1339e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1340e5c31af7Sopenharmony_ci 1341e5c31af7Sopenharmony_ci if (!path[1].getDeclaration()->varType.isArrayType()) 1342e5c31af7Sopenharmony_ci { 1343e5c31af7Sopenharmony_ci expected = 1; 1344e5c31af7Sopenharmony_ci reason = "Top-level block member is not an array"; 1345e5c31af7Sopenharmony_ci } 1346e5c31af7Sopenharmony_ci else if (path[1].getDeclaration()->varType.getElementType().isBasicType()) 1347e5c31af7Sopenharmony_ci { 1348e5c31af7Sopenharmony_ci expected = 1; 1349e5c31af7Sopenharmony_ci reason = "Top-level block member is not an array of an aggregate type"; 1350e5c31af7Sopenharmony_ci } 1351e5c31af7Sopenharmony_ci else if (path[1].getDeclaration()->varType.getArraySize() == glu::VarType::UNSIZED_ARRAY) 1352e5c31af7Sopenharmony_ci { 1353e5c31af7Sopenharmony_ci expected = 0; 1354e5c31af7Sopenharmony_ci reason = "Top-level block member is an unsized top-level array"; 1355e5c31af7Sopenharmony_ci } 1356e5c31af7Sopenharmony_ci else 1357e5c31af7Sopenharmony_ci { 1358e5c31af7Sopenharmony_ci expected = path[1].getDeclaration()->varType.getArraySize(); 1359e5c31af7Sopenharmony_ci reason = "Top-level block member is a sized top-level array"; 1360e5c31af7Sopenharmony_ci } 1361e5c31af7Sopenharmony_ci 1362e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying top level array size, expecting " << expected << ". (" << reason << ")." << tcu::TestLog::EndMessage; 1363e5c31af7Sopenharmony_ci 1364e5c31af7Sopenharmony_ci if (propValue != expected) 1365e5c31af7Sopenharmony_ci { 1366e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid top level array size, got " << propValue << tcu::TestLog::EndMessage; 1367e5c31af7Sopenharmony_ci setError("top level array size invalid"); 1368e5c31af7Sopenharmony_ci } 1369e5c31af7Sopenharmony_ci} 1370e5c31af7Sopenharmony_ci 1371e5c31af7Sopenharmony_ciclass TopLevelArrayStrideValidator : public SingleVariableValidator 1372e5c31af7Sopenharmony_ci{ 1373e5c31af7Sopenharmony_cipublic: 1374e5c31af7Sopenharmony_ci TopLevelArrayStrideValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 1375e5c31af7Sopenharmony_ci 1376e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1377e5c31af7Sopenharmony_ci}; 1378e5c31af7Sopenharmony_ci 1379e5c31af7Sopenharmony_ciTopLevelArrayStrideValidator::TopLevelArrayStrideValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 1380e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_TOP_LEVEL_ARRAY_STRIDE, programID, filter, DE_NULL) 1381e5c31af7Sopenharmony_ci{ 1382e5c31af7Sopenharmony_ci} 1383e5c31af7Sopenharmony_ci 1384e5c31af7Sopenharmony_civoid TopLevelArrayStrideValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1385e5c31af7Sopenharmony_ci{ 1386e5c31af7Sopenharmony_ci DE_ASSERT(path.front().isInterfaceBlock() && path.front().getInterfaceBlock()->storage == glu::STORAGE_BUFFER); 1387e5c31af7Sopenharmony_ci DE_UNREF(resource); 1388e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1389e5c31af7Sopenharmony_ci 1390e5c31af7Sopenharmony_ci if (!path[1].getDeclaration()->varType.isArrayType()) 1391e5c31af7Sopenharmony_ci { 1392e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying top level array stride, expecting 0. (Top-level block member is not an array)." << tcu::TestLog::EndMessage; 1393e5c31af7Sopenharmony_ci 1394e5c31af7Sopenharmony_ci if (propValue != 0) 1395e5c31af7Sopenharmony_ci { 1396e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, top level array stride, got " << propValue << tcu::TestLog::EndMessage; 1397e5c31af7Sopenharmony_ci setError("top level array stride invalid"); 1398e5c31af7Sopenharmony_ci } 1399e5c31af7Sopenharmony_ci } 1400e5c31af7Sopenharmony_ci else if (path[1].getDeclaration()->varType.getElementType().isBasicType()) 1401e5c31af7Sopenharmony_ci { 1402e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying top level array stride, expecting 0. (Top-level block member is not an array of an aggregate type)." << tcu::TestLog::EndMessage; 1403e5c31af7Sopenharmony_ci 1404e5c31af7Sopenharmony_ci if (propValue != 0) 1405e5c31af7Sopenharmony_ci { 1406e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, top level array stride, got " << propValue << tcu::TestLog::EndMessage; 1407e5c31af7Sopenharmony_ci setError("top level array stride invalid"); 1408e5c31af7Sopenharmony_ci } 1409e5c31af7Sopenharmony_ci } 1410e5c31af7Sopenharmony_ci else 1411e5c31af7Sopenharmony_ci { 1412e5c31af7Sopenharmony_ci const int minimumStride = getVarTypeSize(path[1].getDeclaration()->varType.getElementType()); 1413e5c31af7Sopenharmony_ci 1414e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying top level array stride, expecting greater or equal to " << minimumStride << "." << tcu::TestLog::EndMessage; 1415e5c31af7Sopenharmony_ci 1416e5c31af7Sopenharmony_ci if (propValue < minimumStride) 1417e5c31af7Sopenharmony_ci { 1418e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid top level array stride, got " << propValue << tcu::TestLog::EndMessage; 1419e5c31af7Sopenharmony_ci setError("top level array stride invalid"); 1420e5c31af7Sopenharmony_ci } 1421e5c31af7Sopenharmony_ci } 1422e5c31af7Sopenharmony_ci} 1423e5c31af7Sopenharmony_ci 1424e5c31af7Sopenharmony_ciclass TransformFeedbackResourceValidator : public PropValidator 1425e5c31af7Sopenharmony_ci{ 1426e5c31af7Sopenharmony_cipublic: 1427e5c31af7Sopenharmony_ci TransformFeedbackResourceValidator (Context& context, ProgramResourcePropFlags validationProp); 1428e5c31af7Sopenharmony_ci 1429e5c31af7Sopenharmony_ci void validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1430e5c31af7Sopenharmony_ci 1431e5c31af7Sopenharmony_ciprivate: 1432e5c31af7Sopenharmony_ci virtual void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const = 0; 1433e5c31af7Sopenharmony_ci virtual void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const = 0; 1434e5c31af7Sopenharmony_ci}; 1435e5c31af7Sopenharmony_ci 1436e5c31af7Sopenharmony_ci 1437e5c31af7Sopenharmony_ciTransformFeedbackResourceValidator::TransformFeedbackResourceValidator (Context& context, ProgramResourcePropFlags validationProp) 1438e5c31af7Sopenharmony_ci : PropValidator(context, validationProp, DE_NULL) 1439e5c31af7Sopenharmony_ci{ 1440e5c31af7Sopenharmony_ci} 1441e5c31af7Sopenharmony_ci 1442e5c31af7Sopenharmony_civoid TransformFeedbackResourceValidator::validate (const ProgramInterfaceDefinition::Program* program, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1443e5c31af7Sopenharmony_ci{ 1444e5c31af7Sopenharmony_ci if (deStringBeginsWith(resource.c_str(), "gl_")) 1445e5c31af7Sopenharmony_ci { 1446e5c31af7Sopenharmony_ci validateBuiltinVariable(resource, propValue, implementationName); 1447e5c31af7Sopenharmony_ci } 1448e5c31af7Sopenharmony_ci else 1449e5c31af7Sopenharmony_ci { 1450e5c31af7Sopenharmony_ci // Check resource name is a xfb output. (quick check) 1451e5c31af7Sopenharmony_ci#if defined(DE_DEBUG) 1452e5c31af7Sopenharmony_ci bool generatorFound = false; 1453e5c31af7Sopenharmony_ci 1454e5c31af7Sopenharmony_ci // Check the resource name is a valid transform feedback resource and find the name generating resource 1455e5c31af7Sopenharmony_ci for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx) 1456e5c31af7Sopenharmony_ci { 1457e5c31af7Sopenharmony_ci const std::string varyingName = program->getTransformFeedbackVaryings()[varyingNdx]; 1458e5c31af7Sopenharmony_ci std::vector<VariablePathComponent> path; 1459e5c31af7Sopenharmony_ci std::vector<std::string> resources; 1460e5c31af7Sopenharmony_ci 1461e5c31af7Sopenharmony_ci if (!findProgramVariablePathByPathName(path, program, varyingName, VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(program), glu::STORAGE_OUT))) 1462e5c31af7Sopenharmony_ci { 1463e5c31af7Sopenharmony_ci // program does not contain feedback varying, not valid program 1464e5c31af7Sopenharmony_ci DE_ASSERT(false); 1465e5c31af7Sopenharmony_ci return; 1466e5c31af7Sopenharmony_ci } 1467e5c31af7Sopenharmony_ci 1468e5c31af7Sopenharmony_ci generateVariableTypeResourceNames(resources, varyingName, *path.back().getVariableType(), RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE); 1469e5c31af7Sopenharmony_ci 1470e5c31af7Sopenharmony_ci if (de::contains(resources.begin(), resources.end(), resource)) 1471e5c31af7Sopenharmony_ci { 1472e5c31af7Sopenharmony_ci generatorFound = true; 1473e5c31af7Sopenharmony_ci break; 1474e5c31af7Sopenharmony_ci } 1475e5c31af7Sopenharmony_ci } 1476e5c31af7Sopenharmony_ci 1477e5c31af7Sopenharmony_ci // resource name was not found, should never happen 1478e5c31af7Sopenharmony_ci DE_ASSERT(generatorFound); 1479e5c31af7Sopenharmony_ci DE_UNREF(generatorFound); 1480e5c31af7Sopenharmony_ci#endif 1481e5c31af7Sopenharmony_ci 1482e5c31af7Sopenharmony_ci // verify resource 1483e5c31af7Sopenharmony_ci { 1484e5c31af7Sopenharmony_ci std::vector<VariablePathComponent> path; 1485e5c31af7Sopenharmony_ci 1486e5c31af7Sopenharmony_ci if (!findProgramVariablePathByPathName(path, program, resource, VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(program), glu::STORAGE_OUT))) 1487e5c31af7Sopenharmony_ci DE_ASSERT(false); 1488e5c31af7Sopenharmony_ci 1489e5c31af7Sopenharmony_ci validateSingleVariable(path, resource, propValue, implementationName); 1490e5c31af7Sopenharmony_ci } 1491e5c31af7Sopenharmony_ci } 1492e5c31af7Sopenharmony_ci} 1493e5c31af7Sopenharmony_ci 1494e5c31af7Sopenharmony_ciclass TransformFeedbackArraySizeValidator : public TransformFeedbackResourceValidator 1495e5c31af7Sopenharmony_ci{ 1496e5c31af7Sopenharmony_cipublic: 1497e5c31af7Sopenharmony_ci TransformFeedbackArraySizeValidator (Context& context); 1498e5c31af7Sopenharmony_ci 1499e5c31af7Sopenharmony_ci void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1500e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1501e5c31af7Sopenharmony_ci}; 1502e5c31af7Sopenharmony_ci 1503e5c31af7Sopenharmony_ciTransformFeedbackArraySizeValidator::TransformFeedbackArraySizeValidator (Context& context) 1504e5c31af7Sopenharmony_ci : TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_ARRAY_SIZE) 1505e5c31af7Sopenharmony_ci{ 1506e5c31af7Sopenharmony_ci} 1507e5c31af7Sopenharmony_ci 1508e5c31af7Sopenharmony_civoid TransformFeedbackArraySizeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1509e5c31af7Sopenharmony_ci{ 1510e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1511e5c31af7Sopenharmony_ci 1512e5c31af7Sopenharmony_ci int arraySize = 0; 1513e5c31af7Sopenharmony_ci 1514e5c31af7Sopenharmony_ci if (resource == "gl_Position") 1515e5c31af7Sopenharmony_ci arraySize = 1; 1516e5c31af7Sopenharmony_ci else 1517e5c31af7Sopenharmony_ci DE_ASSERT(false); 1518e5c31af7Sopenharmony_ci 1519e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize << tcu::TestLog::EndMessage; 1520e5c31af7Sopenharmony_ci if (arraySize != propValue) 1521e5c31af7Sopenharmony_ci { 1522e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 1523e5c31af7Sopenharmony_ci setError("resource array size invalid"); 1524e5c31af7Sopenharmony_ci } 1525e5c31af7Sopenharmony_ci} 1526e5c31af7Sopenharmony_ci 1527e5c31af7Sopenharmony_civoid TransformFeedbackArraySizeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1528e5c31af7Sopenharmony_ci{ 1529e5c31af7Sopenharmony_ci DE_UNREF(resource); 1530e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1531e5c31af7Sopenharmony_ci 1532e5c31af7Sopenharmony_ci const int arraySize = (path.back().getVariableType()->isArrayType()) ? (path.back().getVariableType()->getArraySize()) : (1); 1533e5c31af7Sopenharmony_ci 1534e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying array size, expecting " << arraySize << tcu::TestLog::EndMessage; 1535e5c31af7Sopenharmony_ci if (arraySize != propValue) 1536e5c31af7Sopenharmony_ci { 1537e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 1538e5c31af7Sopenharmony_ci setError("resource array size invalid"); 1539e5c31af7Sopenharmony_ci } 1540e5c31af7Sopenharmony_ci} 1541e5c31af7Sopenharmony_ci 1542e5c31af7Sopenharmony_ciclass TransformFeedbackNameLengthValidator : public TransformFeedbackResourceValidator 1543e5c31af7Sopenharmony_ci{ 1544e5c31af7Sopenharmony_cipublic: 1545e5c31af7Sopenharmony_ci TransformFeedbackNameLengthValidator (Context& context); 1546e5c31af7Sopenharmony_ci 1547e5c31af7Sopenharmony_ciprivate: 1548e5c31af7Sopenharmony_ci void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1549e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1550e5c31af7Sopenharmony_ci void validateVariable (const std::string& implementationName, glw::GLint propValue) const; 1551e5c31af7Sopenharmony_ci}; 1552e5c31af7Sopenharmony_ci 1553e5c31af7Sopenharmony_ciTransformFeedbackNameLengthValidator::TransformFeedbackNameLengthValidator (Context& context) 1554e5c31af7Sopenharmony_ci : TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_NAME_LENGTH) 1555e5c31af7Sopenharmony_ci{ 1556e5c31af7Sopenharmony_ci} 1557e5c31af7Sopenharmony_ci 1558e5c31af7Sopenharmony_civoid TransformFeedbackNameLengthValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1559e5c31af7Sopenharmony_ci{ 1560e5c31af7Sopenharmony_ci DE_UNREF(resource); 1561e5c31af7Sopenharmony_ci validateVariable(implementationName, propValue); 1562e5c31af7Sopenharmony_ci} 1563e5c31af7Sopenharmony_ci 1564e5c31af7Sopenharmony_civoid TransformFeedbackNameLengthValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1565e5c31af7Sopenharmony_ci{ 1566e5c31af7Sopenharmony_ci DE_UNREF(path); 1567e5c31af7Sopenharmony_ci DE_UNREF(resource); 1568e5c31af7Sopenharmony_ci validateVariable(implementationName, propValue); 1569e5c31af7Sopenharmony_ci} 1570e5c31af7Sopenharmony_ci 1571e5c31af7Sopenharmony_civoid TransformFeedbackNameLengthValidator::validateVariable (const std::string& implementationName, glw::GLint propValue) const 1572e5c31af7Sopenharmony_ci{ 1573e5c31af7Sopenharmony_ci const int expected = (int)implementationName.length() + 1; // includes null byte 1574e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying name length, expecting " << expected << " (" << (int)implementationName.length() << " for \"" << implementationName << "\" + 1 byte for terminating null character)" << tcu::TestLog::EndMessage; 1575e5c31af7Sopenharmony_ci 1576e5c31af7Sopenharmony_ci if (propValue != expected) 1577e5c31af7Sopenharmony_ci { 1578e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, invalid name length, got " << propValue << tcu::TestLog::EndMessage; 1579e5c31af7Sopenharmony_ci setError("name length invalid"); 1580e5c31af7Sopenharmony_ci } 1581e5c31af7Sopenharmony_ci} 1582e5c31af7Sopenharmony_ci 1583e5c31af7Sopenharmony_ciclass TransformFeedbackTypeValidator : public TransformFeedbackResourceValidator 1584e5c31af7Sopenharmony_ci{ 1585e5c31af7Sopenharmony_cipublic: 1586e5c31af7Sopenharmony_ci TransformFeedbackTypeValidator (Context& context); 1587e5c31af7Sopenharmony_ci 1588e5c31af7Sopenharmony_ci void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1589e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1590e5c31af7Sopenharmony_ci}; 1591e5c31af7Sopenharmony_ci 1592e5c31af7Sopenharmony_ciTransformFeedbackTypeValidator::TransformFeedbackTypeValidator (Context& context) 1593e5c31af7Sopenharmony_ci : TransformFeedbackResourceValidator(context, PROGRAMRESOURCEPROP_TYPE) 1594e5c31af7Sopenharmony_ci{ 1595e5c31af7Sopenharmony_ci} 1596e5c31af7Sopenharmony_ci 1597e5c31af7Sopenharmony_civoid TransformFeedbackTypeValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1598e5c31af7Sopenharmony_ci{ 1599e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1600e5c31af7Sopenharmony_ci 1601e5c31af7Sopenharmony_ci glu::DataType varType = glu::TYPE_INVALID; 1602e5c31af7Sopenharmony_ci 1603e5c31af7Sopenharmony_ci if (resource == "gl_Position") 1604e5c31af7Sopenharmony_ci varType = glu::TYPE_FLOAT_VEC4; 1605e5c31af7Sopenharmony_ci else 1606e5c31af7Sopenharmony_ci DE_ASSERT(false); 1607e5c31af7Sopenharmony_ci 1608e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(varType) << tcu::TestLog::EndMessage; 1609e5c31af7Sopenharmony_ci if (glu::getDataTypeFromGLType(propValue) != varType) 1610e5c31af7Sopenharmony_ci { 1611e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage; 1612e5c31af7Sopenharmony_ci setError("resource type invalid"); 1613e5c31af7Sopenharmony_ci } 1614e5c31af7Sopenharmony_ci return; 1615e5c31af7Sopenharmony_ci} 1616e5c31af7Sopenharmony_ci 1617e5c31af7Sopenharmony_civoid TransformFeedbackTypeValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1618e5c31af7Sopenharmony_ci{ 1619e5c31af7Sopenharmony_ci DE_UNREF(resource); 1620e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1621e5c31af7Sopenharmony_ci 1622e5c31af7Sopenharmony_ci // Unlike other interfaces, xfb program interface uses just variable name to refer to arrays of basic types. (Others use "variable[0]") 1623e5c31af7Sopenharmony_ci // Thus we might end up querying a type for an array. In this case, return the type of an array element. 1624e5c31af7Sopenharmony_ci const glu::VarType& variable = *path.back().getVariableType(); 1625e5c31af7Sopenharmony_ci const glu::VarType& elementType = (variable.isArrayType()) ? (variable.getElementType()) : (variable); 1626e5c31af7Sopenharmony_ci 1627e5c31af7Sopenharmony_ci DE_ASSERT(elementType.isBasicType()); 1628e5c31af7Sopenharmony_ci 1629e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying type, expecting " << glu::getDataTypeName(elementType.getBasicType()) << tcu::TestLog::EndMessage; 1630e5c31af7Sopenharmony_ci if (elementType.getBasicType() != glu::getDataTypeFromGLType(propValue)) 1631e5c31af7Sopenharmony_ci { 1632e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << glu::getDataTypeName(glu::getDataTypeFromGLType(propValue)) << tcu::TestLog::EndMessage; 1633e5c31af7Sopenharmony_ci setError("resource type invalid"); 1634e5c31af7Sopenharmony_ci } 1635e5c31af7Sopenharmony_ci} 1636e5c31af7Sopenharmony_ci 1637e5c31af7Sopenharmony_ciclass PerPatchValidator : public SingleVariableValidator 1638e5c31af7Sopenharmony_ci{ 1639e5c31af7Sopenharmony_cipublic: 1640e5c31af7Sopenharmony_ci PerPatchValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter); 1641e5c31af7Sopenharmony_ci 1642e5c31af7Sopenharmony_ci std::string getHumanReadablePropertyString (glw::GLint propVal) const; 1643e5c31af7Sopenharmony_ci void validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1644e5c31af7Sopenharmony_ci void validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const; 1645e5c31af7Sopenharmony_ci}; 1646e5c31af7Sopenharmony_ci 1647e5c31af7Sopenharmony_ciPerPatchValidator::PerPatchValidator (Context& context, glw::GLuint programID, const VariableSearchFilter& filter) 1648e5c31af7Sopenharmony_ci : SingleVariableValidator(context, PROGRAMRESOURCEPROP_IS_PER_PATCH, programID, filter, "GL_EXT_tessellation_shader") 1649e5c31af7Sopenharmony_ci{ 1650e5c31af7Sopenharmony_ci} 1651e5c31af7Sopenharmony_ci 1652e5c31af7Sopenharmony_cistd::string PerPatchValidator::getHumanReadablePropertyString (glw::GLint propVal) const 1653e5c31af7Sopenharmony_ci{ 1654e5c31af7Sopenharmony_ci return de::toString(glu::getBooleanStr(propVal)); 1655e5c31af7Sopenharmony_ci} 1656e5c31af7Sopenharmony_ci 1657e5c31af7Sopenharmony_civoid PerPatchValidator::validateSingleVariable (const std::vector<VariablePathComponent>& path, const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1658e5c31af7Sopenharmony_ci{ 1659e5c31af7Sopenharmony_ci const glu::Storage storage = (path.front().isInterfaceBlock()) ? (path.front().getInterfaceBlock()->storage) : (path.front().getDeclaration()->storage); 1660e5c31af7Sopenharmony_ci const int expected = (storage == glu::STORAGE_PATCH_IN || storage == glu::STORAGE_PATCH_OUT) ? (1) : (0); 1661e5c31af7Sopenharmony_ci 1662e5c31af7Sopenharmony_ci DE_UNREF(resource); 1663e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1664e5c31af7Sopenharmony_ci 1665e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying if is per patch, expecting IS_PER_PATCH = " << expected << tcu::TestLog::EndMessage; 1666e5c31af7Sopenharmony_ci 1667e5c31af7Sopenharmony_ci if (propValue != expected) 1668e5c31af7Sopenharmony_ci { 1669e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 1670e5c31af7Sopenharmony_ci setError("resource is per patch invalid"); 1671e5c31af7Sopenharmony_ci } 1672e5c31af7Sopenharmony_ci} 1673e5c31af7Sopenharmony_ci 1674e5c31af7Sopenharmony_civoid PerPatchValidator::validateBuiltinVariable (const std::string& resource, glw::GLint propValue, const std::string& implementationName) const 1675e5c31af7Sopenharmony_ci{ 1676e5c31af7Sopenharmony_ci DE_UNREF(implementationName); 1677e5c31af7Sopenharmony_ci 1678e5c31af7Sopenharmony_ci static const struct 1679e5c31af7Sopenharmony_ci { 1680e5c31af7Sopenharmony_ci const char* name; 1681e5c31af7Sopenharmony_ci int isPerPatch; 1682e5c31af7Sopenharmony_ci } builtins[] = 1683e5c31af7Sopenharmony_ci { 1684e5c31af7Sopenharmony_ci { "gl_Position", 0 }, 1685e5c31af7Sopenharmony_ci { "gl_PerVertex.gl_Position", 0 }, 1686e5c31af7Sopenharmony_ci { "gl_InvocationID", 0 }, 1687e5c31af7Sopenharmony_ci { "gl_TessLevelOuter[0]", 1 }, 1688e5c31af7Sopenharmony_ci { "gl_TessLevelInner[0]", 1 }, 1689e5c31af7Sopenharmony_ci }; 1690e5c31af7Sopenharmony_ci 1691e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtins); ++ndx) 1692e5c31af7Sopenharmony_ci { 1693e5c31af7Sopenharmony_ci if (resource == builtins[ndx].name) 1694e5c31af7Sopenharmony_ci { 1695e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Verifying if is per patch, expecting IS_PER_PATCH = " << builtins[ndx].isPerPatch << tcu::TestLog::EndMessage; 1696e5c31af7Sopenharmony_ci 1697e5c31af7Sopenharmony_ci if (propValue != builtins[ndx].isPerPatch) 1698e5c31af7Sopenharmony_ci { 1699e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "\tError, got " << propValue << tcu::TestLog::EndMessage; 1700e5c31af7Sopenharmony_ci setError("resource is per patch invalid"); 1701e5c31af7Sopenharmony_ci } 1702e5c31af7Sopenharmony_ci return; 1703e5c31af7Sopenharmony_ci } 1704e5c31af7Sopenharmony_ci } 1705e5c31af7Sopenharmony_ci 1706e5c31af7Sopenharmony_ci DE_ASSERT(false); 1707e5c31af7Sopenharmony_ci} 1708e5c31af7Sopenharmony_ci 1709e5c31af7Sopenharmony_ci} // anonymous 1710e5c31af7Sopenharmony_ci 1711e5c31af7Sopenharmony_ciProgramResourceQueryTestTarget::ProgramResourceQueryTestTarget (ProgramInterface interface_, deUint32 propFlags_) 1712e5c31af7Sopenharmony_ci : interface(interface_) 1713e5c31af7Sopenharmony_ci , propFlags(propFlags_) 1714e5c31af7Sopenharmony_ci{ 1715e5c31af7Sopenharmony_ci switch (interface) 1716e5c31af7Sopenharmony_ci { 1717e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM: DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_UNIFORM_INTERFACE_MASK) == propFlags); break; 1718e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM_BLOCK: DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_UNIFORM_BLOCK_INTERFACE_MASK) == propFlags); break; 1719e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK: DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_SHADER_STORAGE_BLOCK_MASK) == propFlags); break; 1720e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_INPUT: DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_PROGRAM_INPUT_MASK) == propFlags); break; 1721e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_OUTPUT: DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_PROGRAM_OUTPUT_MASK) == propFlags); break; 1722e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_BUFFER_VARIABLE: DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_BUFFER_VARIABLE_MASK) == propFlags); break; 1723e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING: DE_ASSERT((propFlags & PROGRAMRESOURCEPROP_TRANSFORM_FEEDBACK_VARYING_MASK) == propFlags); break; 1724e5c31af7Sopenharmony_ci 1725e5c31af7Sopenharmony_ci default: 1726e5c31af7Sopenharmony_ci DE_ASSERT(false); 1727e5c31af7Sopenharmony_ci } 1728e5c31af7Sopenharmony_ci} 1729e5c31af7Sopenharmony_ci 1730e5c31af7Sopenharmony_ciProgramInterfaceQueryTestCase::ProgramInterfaceQueryTestCase (Context& context, const char* name, const char* description, ProgramResourceQueryTestTarget queryTarget) 1731e5c31af7Sopenharmony_ci : TestCase (context, name, description) 1732e5c31af7Sopenharmony_ci , m_queryTarget (queryTarget) 1733e5c31af7Sopenharmony_ci{ 1734e5c31af7Sopenharmony_ci} 1735e5c31af7Sopenharmony_ci 1736e5c31af7Sopenharmony_ciProgramInterfaceQueryTestCase::~ProgramInterfaceQueryTestCase (void) 1737e5c31af7Sopenharmony_ci{ 1738e5c31af7Sopenharmony_ci} 1739e5c31af7Sopenharmony_ci 1740e5c31af7Sopenharmony_ciProgramInterface ProgramInterfaceQueryTestCase::getTargetInterface (void) const 1741e5c31af7Sopenharmony_ci{ 1742e5c31af7Sopenharmony_ci return m_queryTarget.interface; 1743e5c31af7Sopenharmony_ci} 1744e5c31af7Sopenharmony_ci 1745e5c31af7Sopenharmony_cistatic glw::GLenum getGLInterfaceEnumValue (ProgramInterface interface) 1746e5c31af7Sopenharmony_ci{ 1747e5c31af7Sopenharmony_ci switch (interface) 1748e5c31af7Sopenharmony_ci { 1749e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM: return GL_UNIFORM; 1750e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM_BLOCK: return GL_UNIFORM_BLOCK; 1751e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER: return GL_ATOMIC_COUNTER_BUFFER; 1752e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_INPUT: return GL_PROGRAM_INPUT; 1753e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_OUTPUT: return GL_PROGRAM_OUTPUT; 1754e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING: return GL_TRANSFORM_FEEDBACK_VARYING; 1755e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_BUFFER_VARIABLE: return GL_BUFFER_VARIABLE; 1756e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK: return GL_SHADER_STORAGE_BLOCK; 1757e5c31af7Sopenharmony_ci default: 1758e5c31af7Sopenharmony_ci DE_ASSERT(false); 1759e5c31af7Sopenharmony_ci return 0; 1760e5c31af7Sopenharmony_ci } 1761e5c31af7Sopenharmony_ci} 1762e5c31af7Sopenharmony_ci 1763e5c31af7Sopenharmony_cistatic bool isInterfaceBlockInterfaceName (const ProgramInterfaceDefinition::Program* program, ProgramInterface interface, const std::string& blockInterfaceName) 1764e5c31af7Sopenharmony_ci{ 1765e5c31af7Sopenharmony_ci deUint32 validStorageBits; 1766e5c31af7Sopenharmony_ci deUint32 searchStageBits; 1767e5c31af7Sopenharmony_ci 1768e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(glu::STORAGE_LAST < 32); 1769e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(glu::SHADERTYPE_LAST < 32); 1770e5c31af7Sopenharmony_ci 1771e5c31af7Sopenharmony_ci switch (interface) 1772e5c31af7Sopenharmony_ci { 1773e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM_BLOCK: 1774e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK: 1775e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER: 1776e5c31af7Sopenharmony_ci return false; 1777e5c31af7Sopenharmony_ci 1778e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_INPUT: 1779e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_IN) | (1u << glu::STORAGE_PATCH_IN); 1780e5c31af7Sopenharmony_ci searchStageBits = (1u << program->getFirstStage()); 1781e5c31af7Sopenharmony_ci break; 1782e5c31af7Sopenharmony_ci 1783e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_OUTPUT: 1784e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_OUT) | (1u << glu::STORAGE_PATCH_OUT); 1785e5c31af7Sopenharmony_ci searchStageBits = (1u << program->getLastStage()); 1786e5c31af7Sopenharmony_ci break; 1787e5c31af7Sopenharmony_ci 1788e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING: 1789e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_OUT); 1790e5c31af7Sopenharmony_ci searchStageBits = (1u << getProgramTransformFeedbackStage(program)); 1791e5c31af7Sopenharmony_ci break; 1792e5c31af7Sopenharmony_ci 1793e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM: 1794e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_UNIFORM); 1795e5c31af7Sopenharmony_ci searchStageBits = 0xFFFFFFFFu; 1796e5c31af7Sopenharmony_ci break; 1797e5c31af7Sopenharmony_ci 1798e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_BUFFER_VARIABLE: 1799e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_BUFFER); 1800e5c31af7Sopenharmony_ci searchStageBits = 0xFFFFFFFFu; 1801e5c31af7Sopenharmony_ci break; 1802e5c31af7Sopenharmony_ci 1803e5c31af7Sopenharmony_ci default: 1804e5c31af7Sopenharmony_ci DE_ASSERT(false); 1805e5c31af7Sopenharmony_ci return false; 1806e5c31af7Sopenharmony_ci } 1807e5c31af7Sopenharmony_ci 1808e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 1809e5c31af7Sopenharmony_ci { 1810e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx]; 1811e5c31af7Sopenharmony_ci if (((1u << shader->getType()) & searchStageBits) == 0) 1812e5c31af7Sopenharmony_ci continue; 1813e5c31af7Sopenharmony_ci 1814e5c31af7Sopenharmony_ci for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx) 1815e5c31af7Sopenharmony_ci { 1816e5c31af7Sopenharmony_ci const glu::InterfaceBlock& block = shader->getDefaultBlock().interfaceBlocks[blockNdx]; 1817e5c31af7Sopenharmony_ci 1818e5c31af7Sopenharmony_ci if (((1u << block.storage) & validStorageBits) == 0) 1819e5c31af7Sopenharmony_ci continue; 1820e5c31af7Sopenharmony_ci 1821e5c31af7Sopenharmony_ci if (block.interfaceName == blockInterfaceName) 1822e5c31af7Sopenharmony_ci return true; 1823e5c31af7Sopenharmony_ci } 1824e5c31af7Sopenharmony_ci } 1825e5c31af7Sopenharmony_ci return false; 1826e5c31af7Sopenharmony_ci} 1827e5c31af7Sopenharmony_ci 1828e5c31af7Sopenharmony_cistatic std::string getInterfaceBlockInteraceNameByMember (const ProgramInterfaceDefinition::Program* program, ProgramInterface interface, const std::string& memberName) 1829e5c31af7Sopenharmony_ci{ 1830e5c31af7Sopenharmony_ci deUint32 validStorageBits; 1831e5c31af7Sopenharmony_ci deUint32 searchStageBits; 1832e5c31af7Sopenharmony_ci 1833e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(glu::STORAGE_LAST < 32); 1834e5c31af7Sopenharmony_ci DE_STATIC_ASSERT(glu::SHADERTYPE_LAST < 32); 1835e5c31af7Sopenharmony_ci 1836e5c31af7Sopenharmony_ci switch (interface) 1837e5c31af7Sopenharmony_ci { 1838e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM_BLOCK: 1839e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK: 1840e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_ATOMIC_COUNTER_BUFFER: 1841e5c31af7Sopenharmony_ci return ""; 1842e5c31af7Sopenharmony_ci 1843e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_INPUT: 1844e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_IN) | (1u << glu::STORAGE_PATCH_IN); 1845e5c31af7Sopenharmony_ci searchStageBits = (1u << program->getFirstStage()); 1846e5c31af7Sopenharmony_ci break; 1847e5c31af7Sopenharmony_ci 1848e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_OUTPUT: 1849e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_OUT) | (1u << glu::STORAGE_PATCH_OUT); 1850e5c31af7Sopenharmony_ci searchStageBits = (1u << program->getLastStage()); 1851e5c31af7Sopenharmony_ci break; 1852e5c31af7Sopenharmony_ci 1853e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING: 1854e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_OUT); 1855e5c31af7Sopenharmony_ci searchStageBits = (1u << getProgramTransformFeedbackStage(program)); 1856e5c31af7Sopenharmony_ci break; 1857e5c31af7Sopenharmony_ci 1858e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM: 1859e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_UNIFORM); 1860e5c31af7Sopenharmony_ci searchStageBits = 0xFFFFFFFFu; 1861e5c31af7Sopenharmony_ci break; 1862e5c31af7Sopenharmony_ci 1863e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_BUFFER_VARIABLE: 1864e5c31af7Sopenharmony_ci validStorageBits = (1u << glu::STORAGE_BUFFER); 1865e5c31af7Sopenharmony_ci searchStageBits = 0xFFFFFFFFu; 1866e5c31af7Sopenharmony_ci break; 1867e5c31af7Sopenharmony_ci 1868e5c31af7Sopenharmony_ci default: 1869e5c31af7Sopenharmony_ci DE_ASSERT(false); 1870e5c31af7Sopenharmony_ci return ""; 1871e5c31af7Sopenharmony_ci } 1872e5c31af7Sopenharmony_ci 1873e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 1874e5c31af7Sopenharmony_ci { 1875e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx]; 1876e5c31af7Sopenharmony_ci if (((1u << shader->getType()) & searchStageBits) == 0) 1877e5c31af7Sopenharmony_ci continue; 1878e5c31af7Sopenharmony_ci 1879e5c31af7Sopenharmony_ci for (int blockNdx = 0; blockNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++blockNdx) 1880e5c31af7Sopenharmony_ci { 1881e5c31af7Sopenharmony_ci const glu::InterfaceBlock& block = shader->getDefaultBlock().interfaceBlocks[blockNdx]; 1882e5c31af7Sopenharmony_ci 1883e5c31af7Sopenharmony_ci if (((1u << block.storage) & validStorageBits) == 0) 1884e5c31af7Sopenharmony_ci continue; 1885e5c31af7Sopenharmony_ci 1886e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)block.variables.size(); ++varNdx) 1887e5c31af7Sopenharmony_ci { 1888e5c31af7Sopenharmony_ci if (block.variables[varNdx].name == memberName) 1889e5c31af7Sopenharmony_ci return block.interfaceName; 1890e5c31af7Sopenharmony_ci } 1891e5c31af7Sopenharmony_ci } 1892e5c31af7Sopenharmony_ci } 1893e5c31af7Sopenharmony_ci return ""; 1894e5c31af7Sopenharmony_ci} 1895e5c31af7Sopenharmony_ci 1896e5c31af7Sopenharmony_cistatic void queryAndValidateProps (tcu::TestContext& testCtx, 1897e5c31af7Sopenharmony_ci const glw::Functions& gl, 1898e5c31af7Sopenharmony_ci glw::GLuint programID, 1899e5c31af7Sopenharmony_ci ProgramInterface interface, 1900e5c31af7Sopenharmony_ci const char* targetResourceName, 1901e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Program* programDefinition, 1902e5c31af7Sopenharmony_ci const std::vector<glw::GLenum>& props, 1903e5c31af7Sopenharmony_ci const std::vector<const PropValidator*>& validators) 1904e5c31af7Sopenharmony_ci{ 1905e5c31af7Sopenharmony_ci const glw::GLenum glInterface = getGLInterfaceEnumValue(interface); 1906e5c31af7Sopenharmony_ci std::string implementationResourceName = targetResourceName; 1907e5c31af7Sopenharmony_ci glw::GLuint resourceNdx; 1908e5c31af7Sopenharmony_ci glw::GLint written = -1; 1909e5c31af7Sopenharmony_ci 1910e5c31af7Sopenharmony_ci // prefill result buffer with an invalid value. -1 might be valid sometimes, avoid it. Make buffer one larger 1911e5c31af7Sopenharmony_ci // to allow detection of too many return values 1912e5c31af7Sopenharmony_ci std::vector<glw::GLint> propValues (props.size() + 1, -2); 1913e5c31af7Sopenharmony_ci 1914e5c31af7Sopenharmony_ci DE_ASSERT(props.size() == validators.size()); 1915e5c31af7Sopenharmony_ci 1916e5c31af7Sopenharmony_ci // query 1917e5c31af7Sopenharmony_ci 1918e5c31af7Sopenharmony_ci resourceNdx = gl.getProgramResourceIndex(programID, glInterface, targetResourceName); 1919e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "get resource index"); 1920e5c31af7Sopenharmony_ci 1921e5c31af7Sopenharmony_ci if (resourceNdx == GL_INVALID_INDEX) 1922e5c31af7Sopenharmony_ci { 1923e5c31af7Sopenharmony_ci static const struct 1924e5c31af7Sopenharmony_ci { 1925e5c31af7Sopenharmony_ci bool removeTrailingArray; // convert from "target[0]" -> "target" 1926e5c31af7Sopenharmony_ci bool removeTrailingMember; // convert from "target.member" -> "target" 1927e5c31af7Sopenharmony_ci bool removeIOBlock; // convert from "InterfaceName.target" -> "target" 1928e5c31af7Sopenharmony_ci bool addIOBlock; // convert from "target" -> "InterfaceName.target" 1929e5c31af7Sopenharmony_ci bool addIOBlockArray; // convert from "target" -> "InterfaceName[0].target" 1930e5c31af7Sopenharmony_ci } recoveryStrategies[] = 1931e5c31af7Sopenharmony_ci { 1932e5c31af7Sopenharmony_ci // try one patch 1933e5c31af7Sopenharmony_ci { true, false, false, false, false }, 1934e5c31af7Sopenharmony_ci { false, true, false, false, false }, 1935e5c31af7Sopenharmony_ci { false, false, true, false, false }, 1936e5c31af7Sopenharmony_ci { false, false, false, true, false }, 1937e5c31af7Sopenharmony_ci { false, false, false, false, true }, 1938e5c31af7Sopenharmony_ci // patch both ends 1939e5c31af7Sopenharmony_ci { true, false, true, false, false }, 1940e5c31af7Sopenharmony_ci { true, false, false, true, false }, 1941e5c31af7Sopenharmony_ci { true, false, false, false, true }, 1942e5c31af7Sopenharmony_ci { false, true, true, false, false }, 1943e5c31af7Sopenharmony_ci { false, true, false, true, false }, 1944e5c31af7Sopenharmony_ci { false, true, false, false, true }, 1945e5c31af7Sopenharmony_ci }; 1946e5c31af7Sopenharmony_ci 1947e5c31af7Sopenharmony_ci // The resource name generation in the GL implementations is very commonly broken. Try to 1948e5c31af7Sopenharmony_ci // keep the tests producing useful data even in these cases by attempting to recover from 1949e5c31af7Sopenharmony_ci // common naming bugs. Set test result to failure even if recovery succeeded to signal 1950e5c31af7Sopenharmony_ci // incorrect name generation. 1951e5c31af7Sopenharmony_ci 1952e5c31af7Sopenharmony_ci testCtx.getLog() << tcu::TestLog::Message << "getProgramResourceIndex returned GL_INVALID_INDEX for \"" << targetResourceName << "\"" << tcu::TestLog::EndMessage; 1953e5c31af7Sopenharmony_ci testCtx.setTestResult(QP_TEST_RESULT_FAIL, "could not find target resource"); 1954e5c31af7Sopenharmony_ci 1955e5c31af7Sopenharmony_ci for (int strategyNdx = 0; strategyNdx < DE_LENGTH_OF_ARRAY(recoveryStrategies); ++strategyNdx) 1956e5c31af7Sopenharmony_ci { 1957e5c31af7Sopenharmony_ci const std::string resourceName = std::string(targetResourceName); 1958e5c31af7Sopenharmony_ci const size_t rootNameEnd = resourceName.find_first_of(".["); 1959e5c31af7Sopenharmony_ci const std::string rootName = resourceName.substr(0, rootNameEnd); 1960e5c31af7Sopenharmony_ci std::string simplifiedResourceName; 1961e5c31af7Sopenharmony_ci 1962e5c31af7Sopenharmony_ci if (recoveryStrategies[strategyNdx].removeTrailingArray) 1963e5c31af7Sopenharmony_ci { 1964e5c31af7Sopenharmony_ci if (de::endsWith(resourceName, "[0]")) 1965e5c31af7Sopenharmony_ci simplifiedResourceName = resourceName.substr(0, resourceName.length() - 3); 1966e5c31af7Sopenharmony_ci else 1967e5c31af7Sopenharmony_ci continue; 1968e5c31af7Sopenharmony_ci } 1969e5c31af7Sopenharmony_ci 1970e5c31af7Sopenharmony_ci if (recoveryStrategies[strategyNdx].removeTrailingMember) 1971e5c31af7Sopenharmony_ci { 1972e5c31af7Sopenharmony_ci const size_t lastMember = resourceName.find_last_of('.'); 1973e5c31af7Sopenharmony_ci if (lastMember != std::string::npos) 1974e5c31af7Sopenharmony_ci simplifiedResourceName = resourceName.substr(0, lastMember); 1975e5c31af7Sopenharmony_ci else 1976e5c31af7Sopenharmony_ci continue; 1977e5c31af7Sopenharmony_ci } 1978e5c31af7Sopenharmony_ci 1979e5c31af7Sopenharmony_ci if (recoveryStrategies[strategyNdx].removeIOBlock) 1980e5c31af7Sopenharmony_ci { 1981e5c31af7Sopenharmony_ci if (deStringBeginsWith(resourceName.c_str(), "gl_PerVertex.")) 1982e5c31af7Sopenharmony_ci { 1983e5c31af7Sopenharmony_ci // builtin interface bock, remove block name 1984e5c31af7Sopenharmony_ci simplifiedResourceName = resourceName.substr(13); 1985e5c31af7Sopenharmony_ci } 1986e5c31af7Sopenharmony_ci else if (isInterfaceBlockInterfaceName(programDefinition, interface, rootName)) 1987e5c31af7Sopenharmony_ci { 1988e5c31af7Sopenharmony_ci // user-defined inteface block, remove name 1989e5c31af7Sopenharmony_ci const size_t accessorEnd = resourceName.find('.'); // includes potential array accessor 1990e5c31af7Sopenharmony_ci 1991e5c31af7Sopenharmony_ci if (accessorEnd != std::string::npos) 1992e5c31af7Sopenharmony_ci simplifiedResourceName = resourceName.substr(0, accessorEnd+1); 1993e5c31af7Sopenharmony_ci else 1994e5c31af7Sopenharmony_ci continue; 1995e5c31af7Sopenharmony_ci } 1996e5c31af7Sopenharmony_ci else 1997e5c31af7Sopenharmony_ci { 1998e5c31af7Sopenharmony_ci // recovery not applicable 1999e5c31af7Sopenharmony_ci continue; 2000e5c31af7Sopenharmony_ci } 2001e5c31af7Sopenharmony_ci } 2002e5c31af7Sopenharmony_ci 2003e5c31af7Sopenharmony_ci if (recoveryStrategies[strategyNdx].addIOBlock || recoveryStrategies[strategyNdx].addIOBlockArray) 2004e5c31af7Sopenharmony_ci { 2005e5c31af7Sopenharmony_ci const std::string arrayAccessor = (recoveryStrategies[strategyNdx].addIOBlockArray) ? ("[0]") : (""); 2006e5c31af7Sopenharmony_ci 2007e5c31af7Sopenharmony_ci if (deStringBeginsWith(resourceName.c_str(), "gl_") && resourceName.find('.') == std::string::npos) 2008e5c31af7Sopenharmony_ci { 2009e5c31af7Sopenharmony_ci // free builtin variable, add block name 2010e5c31af7Sopenharmony_ci simplifiedResourceName = "gl_PerVertex" + arrayAccessor + "." + resourceName; 2011e5c31af7Sopenharmony_ci } 2012e5c31af7Sopenharmony_ci else 2013e5c31af7Sopenharmony_ci { 2014e5c31af7Sopenharmony_ci const std::string interafaceName = getInterfaceBlockInteraceNameByMember(programDefinition, interface, rootName); 2015e5c31af7Sopenharmony_ci 2016e5c31af7Sopenharmony_ci if (!interafaceName.empty()) 2017e5c31af7Sopenharmony_ci { 2018e5c31af7Sopenharmony_ci // free user variable, add block name 2019e5c31af7Sopenharmony_ci simplifiedResourceName = interafaceName + arrayAccessor + "." + resourceName; 2020e5c31af7Sopenharmony_ci } 2021e5c31af7Sopenharmony_ci else 2022e5c31af7Sopenharmony_ci { 2023e5c31af7Sopenharmony_ci // recovery not applicable 2024e5c31af7Sopenharmony_ci continue; 2025e5c31af7Sopenharmony_ci } 2026e5c31af7Sopenharmony_ci } 2027e5c31af7Sopenharmony_ci } 2028e5c31af7Sopenharmony_ci 2029e5c31af7Sopenharmony_ci if (simplifiedResourceName.empty()) 2030e5c31af7Sopenharmony_ci continue; 2031e5c31af7Sopenharmony_ci 2032e5c31af7Sopenharmony_ci resourceNdx = gl.getProgramResourceIndex(programID, glInterface, simplifiedResourceName.c_str()); 2033e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "get resource index"); 2034e5c31af7Sopenharmony_ci 2035e5c31af7Sopenharmony_ci // recovery succeeded 2036e5c31af7Sopenharmony_ci if (resourceNdx != GL_INVALID_INDEX) 2037e5c31af7Sopenharmony_ci { 2038e5c31af7Sopenharmony_ci implementationResourceName = simplifiedResourceName; 2039e5c31af7Sopenharmony_ci testCtx.getLog() << tcu::TestLog::Message << "\tResource not found, continuing anyway using index obtained for resource \"" << simplifiedResourceName << "\"" << tcu::TestLog::EndMessage; 2040e5c31af7Sopenharmony_ci break; 2041e5c31af7Sopenharmony_ci } 2042e5c31af7Sopenharmony_ci } 2043e5c31af7Sopenharmony_ci 2044e5c31af7Sopenharmony_ci if (resourceNdx == GL_INVALID_INDEX) 2045e5c31af7Sopenharmony_ci return; 2046e5c31af7Sopenharmony_ci } 2047e5c31af7Sopenharmony_ci 2048e5c31af7Sopenharmony_ci gl.getProgramResourceiv(programID, glInterface, resourceNdx, (int)props.size(), &props[0], (int)propValues.size(), &written, &propValues[0]); 2049e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "get props"); 2050e5c31af7Sopenharmony_ci 2051e5c31af7Sopenharmony_ci if (written != (int)props.size()) 2052e5c31af7Sopenharmony_ci { 2053e5c31af7Sopenharmony_ci testCtx.getLog() << tcu::TestLog::Message << "getProgramResourceiv returned unexpected number of values, expected " << (int)props.size() << ", got " << written << tcu::TestLog::EndMessage; 2054e5c31af7Sopenharmony_ci testCtx.setTestResult(QP_TEST_RESULT_FAIL, "getProgramResourceiv returned unexpected number of values"); 2055e5c31af7Sopenharmony_ci return; 2056e5c31af7Sopenharmony_ci } 2057e5c31af7Sopenharmony_ci 2058e5c31af7Sopenharmony_ci if (propValues.back() != -2) 2059e5c31af7Sopenharmony_ci { 2060e5c31af7Sopenharmony_ci testCtx.getLog() << tcu::TestLog::Message << "getProgramResourceiv post write buffer guard value was modified, too many return values" << tcu::TestLog::EndMessage; 2061e5c31af7Sopenharmony_ci testCtx.setTestResult(QP_TEST_RESULT_FAIL, "getProgramResourceiv returned unexpected number of values"); 2062e5c31af7Sopenharmony_ci return; 2063e5c31af7Sopenharmony_ci } 2064e5c31af7Sopenharmony_ci propValues.pop_back(); 2065e5c31af7Sopenharmony_ci DE_ASSERT(validators.size() == propValues.size()); 2066e5c31af7Sopenharmony_ci 2067e5c31af7Sopenharmony_ci // log 2068e5c31af7Sopenharmony_ci 2069e5c31af7Sopenharmony_ci { 2070e5c31af7Sopenharmony_ci tcu::MessageBuilder message(&testCtx.getLog()); 2071e5c31af7Sopenharmony_ci message << "For resource index " << resourceNdx << " (\"" << targetResourceName << "\") got following properties:\n"; 2072e5c31af7Sopenharmony_ci 2073e5c31af7Sopenharmony_ci for (int propNdx = 0; propNdx < (int)propValues.size(); ++propNdx) 2074e5c31af7Sopenharmony_ci message << "\t" << glu::getProgramResourcePropertyName(props[propNdx]) << ":\t" << validators[propNdx]->getHumanReadablePropertyString(propValues[propNdx]) << "\n"; 2075e5c31af7Sopenharmony_ci 2076e5c31af7Sopenharmony_ci message << tcu::TestLog::EndMessage; 2077e5c31af7Sopenharmony_ci } 2078e5c31af7Sopenharmony_ci 2079e5c31af7Sopenharmony_ci // validate 2080e5c31af7Sopenharmony_ci 2081e5c31af7Sopenharmony_ci for (int propNdx = 0; propNdx < (int)propValues.size(); ++propNdx) 2082e5c31af7Sopenharmony_ci validators[propNdx]->validate(programDefinition, targetResourceName, propValues[propNdx], implementationResourceName); 2083e5c31af7Sopenharmony_ci} 2084e5c31af7Sopenharmony_ci 2085e5c31af7Sopenharmony_ciconst ProgramInterfaceDefinition::Program* ProgramInterfaceQueryTestCase::getAndCheckProgramDefinition (void) 2086e5c31af7Sopenharmony_ci{ 2087e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Program* programDefinition = getProgramDefinition(); 2088e5c31af7Sopenharmony_ci DE_ASSERT(programDefinition->isValid()); 2089e5c31af7Sopenharmony_ci 2090e5c31af7Sopenharmony_ci auto type = m_context.getRenderContext().getType(); 2091e5c31af7Sopenharmony_ci if (glu::contextSupports(type, glu::ApiType::es(3, 2)) || 2092e5c31af7Sopenharmony_ci glu::contextSupports(type, glu::ApiType::core(4, 5))) 2093e5c31af7Sopenharmony_ci { 2094e5c31af7Sopenharmony_ci return programDefinition; 2095e5c31af7Sopenharmony_ci } 2096e5c31af7Sopenharmony_ci 2097e5c31af7Sopenharmony_ci if (programDefinition->hasStage(glu::SHADERTYPE_TESSELLATION_CONTROL) || 2098e5c31af7Sopenharmony_ci programDefinition->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION)) 2099e5c31af7Sopenharmony_ci { 2100e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader")) 2101e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension"); 2102e5c31af7Sopenharmony_ci } 2103e5c31af7Sopenharmony_ci 2104e5c31af7Sopenharmony_ci // Testing IS_PER_PATCH as a part of a larger set is ok, since the extension is checked 2105e5c31af7Sopenharmony_ci // before query. However, we don't want IS_PER_PATCH-specific tests to become noop and pass. 2106e5c31af7Sopenharmony_ci if (m_queryTarget.propFlags == PROGRAMRESOURCEPROP_IS_PER_PATCH) 2107e5c31af7Sopenharmony_ci { 2108e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader")) 2109e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader extension"); 2110e5c31af7Sopenharmony_ci } 2111e5c31af7Sopenharmony_ci 2112e5c31af7Sopenharmony_ci if (programDefinition->hasStage(glu::SHADERTYPE_GEOMETRY)) 2113e5c31af7Sopenharmony_ci { 2114e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 2115e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Test requires GL_EXT_geometry_shader extension"); 2116e5c31af7Sopenharmony_ci } 2117e5c31af7Sopenharmony_ci 2118e5c31af7Sopenharmony_ci if (programContainsIOBlocks(programDefinition)) 2119e5c31af7Sopenharmony_ci { 2120e5c31af7Sopenharmony_ci if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_shader_io_blocks")) 2121e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("Test requires GL_EXT_shader_io_blocks extension"); 2122e5c31af7Sopenharmony_ci } 2123e5c31af7Sopenharmony_ci 2124e5c31af7Sopenharmony_ci return programDefinition; 2125e5c31af7Sopenharmony_ci} 2126e5c31af7Sopenharmony_ci 2127e5c31af7Sopenharmony_ciint ProgramInterfaceQueryTestCase::getMaxPatchVertices (void) 2128e5c31af7Sopenharmony_ci{ 2129e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2130e5c31af7Sopenharmony_ci glw::GLint maxPatchVertices = 0; 2131e5c31af7Sopenharmony_ci 2132e5c31af7Sopenharmony_ci gl.getIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices); 2133e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_MAX_PATCH_VERTICES)"); 2134e5c31af7Sopenharmony_ci return maxPatchVertices; 2135e5c31af7Sopenharmony_ci} 2136e5c31af7Sopenharmony_ci 2137e5c31af7Sopenharmony_ciProgramInterfaceQueryTestCase::IterateResult ProgramInterfaceQueryTestCase::iterate (void) 2138e5c31af7Sopenharmony_ci{ 2139e5c31af7Sopenharmony_ci struct TestProperty 2140e5c31af7Sopenharmony_ci { 2141e5c31af7Sopenharmony_ci glw::GLenum prop; 2142e5c31af7Sopenharmony_ci const PropValidator* validator; 2143e5c31af7Sopenharmony_ci }; 2144e5c31af7Sopenharmony_ci 2145e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Program* programDefinition = getAndCheckProgramDefinition(); 2146e5c31af7Sopenharmony_ci const std::vector<std::string> targetResources = getQueryTargetResources(); 2147e5c31af7Sopenharmony_ci glu::ShaderProgram program (m_context.getRenderContext(), generateProgramInterfaceProgramSources(programDefinition)); 2148e5c31af7Sopenharmony_ci 2149e5c31af7Sopenharmony_ci m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2150e5c31af7Sopenharmony_ci 2151e5c31af7Sopenharmony_ci // Log program 2152e5c31af7Sopenharmony_ci { 2153e5c31af7Sopenharmony_ci const tcu::ScopedLogSection section(m_testCtx.getLog(), "Program", "Program"); 2154e5c31af7Sopenharmony_ci 2155e5c31af7Sopenharmony_ci // Feedback varyings 2156e5c31af7Sopenharmony_ci if (!programDefinition->getTransformFeedbackVaryings().empty()) 2157e5c31af7Sopenharmony_ci { 2158e5c31af7Sopenharmony_ci tcu::MessageBuilder builder(&m_testCtx.getLog()); 2159e5c31af7Sopenharmony_ci builder << "Transform feedback varyings: {"; 2160e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)programDefinition->getTransformFeedbackVaryings().size(); ++ndx) 2161e5c31af7Sopenharmony_ci { 2162e5c31af7Sopenharmony_ci if (ndx) 2163e5c31af7Sopenharmony_ci builder << ", "; 2164e5c31af7Sopenharmony_ci builder << "\"" << programDefinition->getTransformFeedbackVaryings()[ndx] << "\""; 2165e5c31af7Sopenharmony_ci } 2166e5c31af7Sopenharmony_ci builder << "}" << tcu::TestLog::EndMessage; 2167e5c31af7Sopenharmony_ci } 2168e5c31af7Sopenharmony_ci 2169e5c31af7Sopenharmony_ci m_testCtx.getLog() << program; 2170e5c31af7Sopenharmony_ci if (!program.isOk()) 2171e5c31af7Sopenharmony_ci { 2172e5c31af7Sopenharmony_ci m_testCtx.getLog() << tcu::TestLog::Message << "Program build failed, checking if program exceeded implementation limits" << tcu::TestLog::EndMessage; 2173e5c31af7Sopenharmony_ci checkProgramResourceUsage(programDefinition, m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 2174e5c31af7Sopenharmony_ci 2175e5c31af7Sopenharmony_ci // within limits 2176e5c31af7Sopenharmony_ci throw tcu::TestError("could not build program"); 2177e5c31af7Sopenharmony_ci } 2178e5c31af7Sopenharmony_ci } 2179e5c31af7Sopenharmony_ci 2180e5c31af7Sopenharmony_ci // Check interface props 2181e5c31af7Sopenharmony_ci 2182e5c31af7Sopenharmony_ci switch (m_queryTarget.interface) 2183e5c31af7Sopenharmony_ci { 2184e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM: 2185e5c31af7Sopenharmony_ci { 2186e5c31af7Sopenharmony_ci const VariableSearchFilter uniformFilter = VariableSearchFilter::createStorageFilter(glu::STORAGE_UNIFORM); 2187e5c31af7Sopenharmony_ci 2188e5c31af7Sopenharmony_ci const TypeValidator typeValidator (m_context, program.getProgram(), uniformFilter); 2189e5c31af7Sopenharmony_ci const ArraySizeValidator arraySizeValidator (m_context, program.getProgram(), -1, uniformFilter); 2190e5c31af7Sopenharmony_ci const ArrayStrideValidator arrayStrideValidator (m_context, program.getProgram(), uniformFilter); 2191e5c31af7Sopenharmony_ci const BlockIndexValidator blockIndexValidator (m_context, program.getProgram(), uniformFilter); 2192e5c31af7Sopenharmony_ci const IsRowMajorValidator isRowMajorValidator (m_context, program.getProgram(), uniformFilter); 2193e5c31af7Sopenharmony_ci const MatrixStrideValidator matrixStrideValidator (m_context, program.getProgram(), uniformFilter); 2194e5c31af7Sopenharmony_ci const AtomicCounterBufferIndexVerifier atomicCounterBufferIndexVerifier (m_context, program.getProgram(), uniformFilter); 2195e5c31af7Sopenharmony_ci const LocationValidator locationValidator (m_context, program.getProgram(), uniformFilter); 2196e5c31af7Sopenharmony_ci const VariableNameLengthValidator nameLengthValidator (m_context, program.getProgram(), uniformFilter); 2197e5c31af7Sopenharmony_ci const OffsetValidator offsetVerifier (m_context, program.getProgram(), uniformFilter); 2198e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByVertexVerifier (m_context, glu::SHADERTYPE_VERTEX, uniformFilter); 2199e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByFragmentVerifier (m_context, glu::SHADERTYPE_FRAGMENT, uniformFilter); 2200e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByComputeVerifier (m_context, glu::SHADERTYPE_COMPUTE, uniformFilter); 2201e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByGeometryVerifier (m_context, glu::SHADERTYPE_GEOMETRY, uniformFilter); 2202e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByTessControlVerifier (m_context, glu::SHADERTYPE_TESSELLATION_CONTROL, uniformFilter); 2203e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByTessEvaluationVerifier (m_context, glu::SHADERTYPE_TESSELLATION_EVALUATION, uniformFilter); 2204e5c31af7Sopenharmony_ci 2205e5c31af7Sopenharmony_ci const TestProperty allProperties[] = 2206e5c31af7Sopenharmony_ci { 2207e5c31af7Sopenharmony_ci { GL_ARRAY_SIZE, &arraySizeValidator }, 2208e5c31af7Sopenharmony_ci { GL_ARRAY_STRIDE, &arrayStrideValidator }, 2209e5c31af7Sopenharmony_ci { GL_ATOMIC_COUNTER_BUFFER_INDEX, &atomicCounterBufferIndexVerifier }, 2210e5c31af7Sopenharmony_ci { GL_BLOCK_INDEX, &blockIndexValidator }, 2211e5c31af7Sopenharmony_ci { GL_IS_ROW_MAJOR, &isRowMajorValidator }, 2212e5c31af7Sopenharmony_ci { GL_LOCATION, &locationValidator }, 2213e5c31af7Sopenharmony_ci { GL_MATRIX_STRIDE, &matrixStrideValidator }, 2214e5c31af7Sopenharmony_ci { GL_NAME_LENGTH, &nameLengthValidator }, 2215e5c31af7Sopenharmony_ci { GL_OFFSET, &offsetVerifier }, 2216e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_VERTEX_SHADER, &referencedByVertexVerifier }, 2217e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_FRAGMENT_SHADER, &referencedByFragmentVerifier }, 2218e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_COMPUTE_SHADER, &referencedByComputeVerifier }, 2219e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_GEOMETRY_SHADER, &referencedByGeometryVerifier }, 2220e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_TESS_CONTROL_SHADER, &referencedByTessControlVerifier }, 2221e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_TESS_EVALUATION_SHADER, &referencedByTessEvaluationVerifier }, 2222e5c31af7Sopenharmony_ci { GL_TYPE, &typeValidator }, 2223e5c31af7Sopenharmony_ci }; 2224e5c31af7Sopenharmony_ci 2225e5c31af7Sopenharmony_ci for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx) 2226e5c31af7Sopenharmony_ci { 2227e5c31af7Sopenharmony_ci const tcu::ScopedLogSection section (m_testCtx.getLog(), "UniformResource", "Uniform resource \"" + targetResources[targetResourceNdx] + "\""); 2228e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2229e5c31af7Sopenharmony_ci std::vector<glw::GLenum> props; 2230e5c31af7Sopenharmony_ci std::vector<const PropValidator*> validators; 2231e5c31af7Sopenharmony_ci 2232e5c31af7Sopenharmony_ci for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx) 2233e5c31af7Sopenharmony_ci { 2234e5c31af7Sopenharmony_ci if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) && 2235e5c31af7Sopenharmony_ci allProperties[propNdx].validator->isSupported()) 2236e5c31af7Sopenharmony_ci { 2237e5c31af7Sopenharmony_ci props.push_back(allProperties[propNdx].prop); 2238e5c31af7Sopenharmony_ci validators.push_back(allProperties[propNdx].validator); 2239e5c31af7Sopenharmony_ci } 2240e5c31af7Sopenharmony_ci } 2241e5c31af7Sopenharmony_ci 2242e5c31af7Sopenharmony_ci DE_ASSERT(!props.empty()); 2243e5c31af7Sopenharmony_ci 2244e5c31af7Sopenharmony_ci queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators); 2245e5c31af7Sopenharmony_ci } 2246e5c31af7Sopenharmony_ci 2247e5c31af7Sopenharmony_ci break; 2248e5c31af7Sopenharmony_ci } 2249e5c31af7Sopenharmony_ci 2250e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM_BLOCK: 2251e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK: 2252e5c31af7Sopenharmony_ci { 2253e5c31af7Sopenharmony_ci const glu::Storage storage = (m_queryTarget.interface == PROGRAMINTERFACE_UNIFORM_BLOCK) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER); 2254e5c31af7Sopenharmony_ci const VariableSearchFilter blockFilter = VariableSearchFilter::createStorageFilter(storage); 2255e5c31af7Sopenharmony_ci 2256e5c31af7Sopenharmony_ci const BlockNameLengthValidator nameLengthValidator (m_context, program.getProgram(), blockFilter); 2257e5c31af7Sopenharmony_ci const BlockReferencedByShaderValidator referencedByVertexVerifier (m_context, glu::SHADERTYPE_VERTEX, blockFilter); 2258e5c31af7Sopenharmony_ci const BlockReferencedByShaderValidator referencedByFragmentVerifier (m_context, glu::SHADERTYPE_FRAGMENT, blockFilter); 2259e5c31af7Sopenharmony_ci const BlockReferencedByShaderValidator referencedByComputeVerifier (m_context, glu::SHADERTYPE_COMPUTE, blockFilter); 2260e5c31af7Sopenharmony_ci const BlockReferencedByShaderValidator referencedByGeometryVerifier (m_context, glu::SHADERTYPE_GEOMETRY, blockFilter); 2261e5c31af7Sopenharmony_ci const BlockReferencedByShaderValidator referencedByTessControlVerifier (m_context, glu::SHADERTYPE_TESSELLATION_CONTROL, blockFilter); 2262e5c31af7Sopenharmony_ci const BlockReferencedByShaderValidator referencedByTessEvaluationVerifier (m_context, glu::SHADERTYPE_TESSELLATION_EVALUATION, blockFilter); 2263e5c31af7Sopenharmony_ci const BufferBindingValidator bufferBindingValidator (m_context, program.getProgram(), blockFilter); 2264e5c31af7Sopenharmony_ci 2265e5c31af7Sopenharmony_ci const TestProperty allProperties[] = 2266e5c31af7Sopenharmony_ci { 2267e5c31af7Sopenharmony_ci { GL_NAME_LENGTH, &nameLengthValidator }, 2268e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_VERTEX_SHADER, &referencedByVertexVerifier }, 2269e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_FRAGMENT_SHADER, &referencedByFragmentVerifier }, 2270e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_COMPUTE_SHADER, &referencedByComputeVerifier }, 2271e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_GEOMETRY_SHADER, &referencedByGeometryVerifier }, 2272e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_TESS_CONTROL_SHADER, &referencedByTessControlVerifier }, 2273e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_TESS_EVALUATION_SHADER, &referencedByTessEvaluationVerifier }, 2274e5c31af7Sopenharmony_ci { GL_BUFFER_BINDING, &bufferBindingValidator }, 2275e5c31af7Sopenharmony_ci }; 2276e5c31af7Sopenharmony_ci 2277e5c31af7Sopenharmony_ci for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx) 2278e5c31af7Sopenharmony_ci { 2279e5c31af7Sopenharmony_ci const tcu::ScopedLogSection section (m_testCtx.getLog(), "BlockResource", "Interface block \"" + targetResources[targetResourceNdx] + "\""); 2280e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2281e5c31af7Sopenharmony_ci std::vector<glw::GLenum> props; 2282e5c31af7Sopenharmony_ci std::vector<const PropValidator*> validators; 2283e5c31af7Sopenharmony_ci 2284e5c31af7Sopenharmony_ci for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx) 2285e5c31af7Sopenharmony_ci { 2286e5c31af7Sopenharmony_ci if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) && 2287e5c31af7Sopenharmony_ci allProperties[propNdx].validator->isSupported()) 2288e5c31af7Sopenharmony_ci { 2289e5c31af7Sopenharmony_ci props.push_back(allProperties[propNdx].prop); 2290e5c31af7Sopenharmony_ci validators.push_back(allProperties[propNdx].validator); 2291e5c31af7Sopenharmony_ci } 2292e5c31af7Sopenharmony_ci } 2293e5c31af7Sopenharmony_ci 2294e5c31af7Sopenharmony_ci DE_ASSERT(!props.empty()); 2295e5c31af7Sopenharmony_ci 2296e5c31af7Sopenharmony_ci queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators); 2297e5c31af7Sopenharmony_ci } 2298e5c31af7Sopenharmony_ci 2299e5c31af7Sopenharmony_ci break; 2300e5c31af7Sopenharmony_ci } 2301e5c31af7Sopenharmony_ci 2302e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_INPUT: 2303e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_OUTPUT: 2304e5c31af7Sopenharmony_ci { 2305e5c31af7Sopenharmony_ci const bool isInputCase = (m_queryTarget.interface == PROGRAMINTERFACE_PROGRAM_INPUT); 2306e5c31af7Sopenharmony_ci const glu::Storage varyingStorage = (isInputCase) ? (glu::STORAGE_IN) : (glu::STORAGE_OUT); 2307e5c31af7Sopenharmony_ci const glu::Storage patchStorage = (isInputCase) ? (glu::STORAGE_PATCH_IN) : (glu::STORAGE_PATCH_OUT); 2308e5c31af7Sopenharmony_ci const glu::ShaderType shaderType = (isInputCase) ? (programDefinition->getFirstStage()) : (programDefinition->getLastStage()); 2309e5c31af7Sopenharmony_ci const int unsizedArraySize = (isInputCase && shaderType == glu::SHADERTYPE_GEOMETRY) ? (1) // input points 2310e5c31af7Sopenharmony_ci : (isInputCase && shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) ? (getMaxPatchVertices()) // input batch size 2311e5c31af7Sopenharmony_ci : (!isInputCase && shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) ? (programDefinition->getTessellationNumOutputPatchVertices()) // output batch size 2312e5c31af7Sopenharmony_ci : (isInputCase && shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION) ? (getMaxPatchVertices()) // input batch size 2313e5c31af7Sopenharmony_ci : (-1); 2314e5c31af7Sopenharmony_ci const VariableSearchFilter variableFilter = VariableSearchFilter::logicalAnd(VariableSearchFilter::createShaderTypeFilter(shaderType), 2315e5c31af7Sopenharmony_ci VariableSearchFilter::logicalOr(VariableSearchFilter::createStorageFilter(varyingStorage), 2316e5c31af7Sopenharmony_ci VariableSearchFilter::createStorageFilter(patchStorage))); 2317e5c31af7Sopenharmony_ci 2318e5c31af7Sopenharmony_ci const TypeValidator typeValidator (m_context, program.getProgram(), variableFilter); 2319e5c31af7Sopenharmony_ci const ArraySizeValidator arraySizeValidator (m_context, program.getProgram(), unsizedArraySize, variableFilter); 2320e5c31af7Sopenharmony_ci const LocationValidator locationValidator (m_context, program.getProgram(), variableFilter); 2321e5c31af7Sopenharmony_ci const VariableNameLengthValidator nameLengthValidator (m_context, program.getProgram(), variableFilter); 2322e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByVertexVerifier (m_context, glu::SHADERTYPE_VERTEX, variableFilter); 2323e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByFragmentVerifier (m_context, glu::SHADERTYPE_FRAGMENT, variableFilter); 2324e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByComputeVerifier (m_context, glu::SHADERTYPE_COMPUTE, variableFilter); 2325e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByGeometryVerifier (m_context, glu::SHADERTYPE_GEOMETRY, variableFilter); 2326e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByTessControlVerifier (m_context, glu::SHADERTYPE_TESSELLATION_CONTROL, variableFilter); 2327e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByTessEvaluationVerifier (m_context, glu::SHADERTYPE_TESSELLATION_EVALUATION, variableFilter); 2328e5c31af7Sopenharmony_ci const PerPatchValidator perPatchValidator (m_context, program.getProgram(), variableFilter); 2329e5c31af7Sopenharmony_ci 2330e5c31af7Sopenharmony_ci const TestProperty allProperties[] = 2331e5c31af7Sopenharmony_ci { 2332e5c31af7Sopenharmony_ci { GL_ARRAY_SIZE, &arraySizeValidator }, 2333e5c31af7Sopenharmony_ci { GL_LOCATION, &locationValidator }, 2334e5c31af7Sopenharmony_ci { GL_NAME_LENGTH, &nameLengthValidator }, 2335e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_VERTEX_SHADER, &referencedByVertexVerifier }, 2336e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_FRAGMENT_SHADER, &referencedByFragmentVerifier }, 2337e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_COMPUTE_SHADER, &referencedByComputeVerifier }, 2338e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_GEOMETRY_SHADER, &referencedByGeometryVerifier }, 2339e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_TESS_CONTROL_SHADER, &referencedByTessControlVerifier }, 2340e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_TESS_EVALUATION_SHADER, &referencedByTessEvaluationVerifier }, 2341e5c31af7Sopenharmony_ci { GL_TYPE, &typeValidator }, 2342e5c31af7Sopenharmony_ci { GL_IS_PER_PATCH, &perPatchValidator }, 2343e5c31af7Sopenharmony_ci }; 2344e5c31af7Sopenharmony_ci 2345e5c31af7Sopenharmony_ci for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx) 2346e5c31af7Sopenharmony_ci { 2347e5c31af7Sopenharmony_ci const std::string resourceInterfaceName = (m_queryTarget.interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? ("Input") : ("Output"); 2348e5c31af7Sopenharmony_ci const tcu::ScopedLogSection section (m_testCtx.getLog(), "BlockResource", resourceInterfaceName + " resource \"" + targetResources[targetResourceNdx] + "\""); 2349e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2350e5c31af7Sopenharmony_ci std::vector<glw::GLenum> props; 2351e5c31af7Sopenharmony_ci std::vector<const PropValidator*> validators; 2352e5c31af7Sopenharmony_ci 2353e5c31af7Sopenharmony_ci for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx) 2354e5c31af7Sopenharmony_ci { 2355e5c31af7Sopenharmony_ci if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) && 2356e5c31af7Sopenharmony_ci allProperties[propNdx].validator->isSupported()) 2357e5c31af7Sopenharmony_ci { 2358e5c31af7Sopenharmony_ci props.push_back(allProperties[propNdx].prop); 2359e5c31af7Sopenharmony_ci validators.push_back(allProperties[propNdx].validator); 2360e5c31af7Sopenharmony_ci } 2361e5c31af7Sopenharmony_ci } 2362e5c31af7Sopenharmony_ci 2363e5c31af7Sopenharmony_ci DE_ASSERT(!props.empty()); 2364e5c31af7Sopenharmony_ci 2365e5c31af7Sopenharmony_ci queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators); 2366e5c31af7Sopenharmony_ci } 2367e5c31af7Sopenharmony_ci 2368e5c31af7Sopenharmony_ci break; 2369e5c31af7Sopenharmony_ci } 2370e5c31af7Sopenharmony_ci 2371e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_BUFFER_VARIABLE: 2372e5c31af7Sopenharmony_ci { 2373e5c31af7Sopenharmony_ci const VariableSearchFilter variableFilter = VariableSearchFilter::createStorageFilter(glu::STORAGE_BUFFER); 2374e5c31af7Sopenharmony_ci 2375e5c31af7Sopenharmony_ci const TypeValidator typeValidator (m_context, program.getProgram(), variableFilter); 2376e5c31af7Sopenharmony_ci const ArraySizeValidator arraySizeValidator (m_context, program.getProgram(), 0, variableFilter); 2377e5c31af7Sopenharmony_ci const ArrayStrideValidator arrayStrideValidator (m_context, program.getProgram(), variableFilter); 2378e5c31af7Sopenharmony_ci const BlockIndexValidator blockIndexValidator (m_context, program.getProgram(), variableFilter); 2379e5c31af7Sopenharmony_ci const IsRowMajorValidator isRowMajorValidator (m_context, program.getProgram(), variableFilter); 2380e5c31af7Sopenharmony_ci const MatrixStrideValidator matrixStrideValidator (m_context, program.getProgram(), variableFilter); 2381e5c31af7Sopenharmony_ci const OffsetValidator offsetValidator (m_context, program.getProgram(), variableFilter); 2382e5c31af7Sopenharmony_ci const VariableNameLengthValidator nameLengthValidator (m_context, program.getProgram(), variableFilter); 2383e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByVertexVerifier (m_context, glu::SHADERTYPE_VERTEX, variableFilter); 2384e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByFragmentVerifier (m_context, glu::SHADERTYPE_FRAGMENT, variableFilter); 2385e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByComputeVerifier (m_context, glu::SHADERTYPE_COMPUTE, variableFilter); 2386e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByGeometryVerifier (m_context, glu::SHADERTYPE_GEOMETRY, variableFilter); 2387e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByTessControlVerifier (m_context, glu::SHADERTYPE_TESSELLATION_CONTROL, variableFilter); 2388e5c31af7Sopenharmony_ci const VariableReferencedByShaderValidator referencedByTessEvaluationVerifier (m_context, glu::SHADERTYPE_TESSELLATION_EVALUATION, variableFilter); 2389e5c31af7Sopenharmony_ci const TopLevelArraySizeValidator topLevelArraySizeValidator (m_context, program.getProgram(), variableFilter); 2390e5c31af7Sopenharmony_ci const TopLevelArrayStrideValidator topLevelArrayStrideValidator (m_context, program.getProgram(), variableFilter); 2391e5c31af7Sopenharmony_ci 2392e5c31af7Sopenharmony_ci const TestProperty allProperties[] = 2393e5c31af7Sopenharmony_ci { 2394e5c31af7Sopenharmony_ci { GL_ARRAY_SIZE, &arraySizeValidator }, 2395e5c31af7Sopenharmony_ci { GL_ARRAY_STRIDE, &arrayStrideValidator }, 2396e5c31af7Sopenharmony_ci { GL_BLOCK_INDEX, &blockIndexValidator }, 2397e5c31af7Sopenharmony_ci { GL_IS_ROW_MAJOR, &isRowMajorValidator }, 2398e5c31af7Sopenharmony_ci { GL_MATRIX_STRIDE, &matrixStrideValidator }, 2399e5c31af7Sopenharmony_ci { GL_NAME_LENGTH, &nameLengthValidator }, 2400e5c31af7Sopenharmony_ci { GL_OFFSET, &offsetValidator }, 2401e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_VERTEX_SHADER, &referencedByVertexVerifier }, 2402e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_FRAGMENT_SHADER, &referencedByFragmentVerifier }, 2403e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_COMPUTE_SHADER, &referencedByComputeVerifier }, 2404e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_GEOMETRY_SHADER, &referencedByGeometryVerifier }, 2405e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_TESS_CONTROL_SHADER, &referencedByTessControlVerifier }, 2406e5c31af7Sopenharmony_ci { GL_REFERENCED_BY_TESS_EVALUATION_SHADER, &referencedByTessEvaluationVerifier }, 2407e5c31af7Sopenharmony_ci { GL_TOP_LEVEL_ARRAY_SIZE, &topLevelArraySizeValidator }, 2408e5c31af7Sopenharmony_ci { GL_TOP_LEVEL_ARRAY_STRIDE, &topLevelArrayStrideValidator }, 2409e5c31af7Sopenharmony_ci { GL_TYPE, &typeValidator }, 2410e5c31af7Sopenharmony_ci }; 2411e5c31af7Sopenharmony_ci 2412e5c31af7Sopenharmony_ci for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx) 2413e5c31af7Sopenharmony_ci { 2414e5c31af7Sopenharmony_ci const tcu::ScopedLogSection section (m_testCtx.getLog(), "BufferVariableResource", "Buffer variable \"" + targetResources[targetResourceNdx] + "\""); 2415e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2416e5c31af7Sopenharmony_ci std::vector<glw::GLenum> props; 2417e5c31af7Sopenharmony_ci std::vector<const PropValidator*> validators; 2418e5c31af7Sopenharmony_ci 2419e5c31af7Sopenharmony_ci for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx) 2420e5c31af7Sopenharmony_ci { 2421e5c31af7Sopenharmony_ci if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) && 2422e5c31af7Sopenharmony_ci allProperties[propNdx].validator->isSupported()) 2423e5c31af7Sopenharmony_ci { 2424e5c31af7Sopenharmony_ci props.push_back(allProperties[propNdx].prop); 2425e5c31af7Sopenharmony_ci validators.push_back(allProperties[propNdx].validator); 2426e5c31af7Sopenharmony_ci } 2427e5c31af7Sopenharmony_ci } 2428e5c31af7Sopenharmony_ci 2429e5c31af7Sopenharmony_ci DE_ASSERT(!props.empty()); 2430e5c31af7Sopenharmony_ci 2431e5c31af7Sopenharmony_ci queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators); 2432e5c31af7Sopenharmony_ci } 2433e5c31af7Sopenharmony_ci 2434e5c31af7Sopenharmony_ci break; 2435e5c31af7Sopenharmony_ci } 2436e5c31af7Sopenharmony_ci 2437e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING: 2438e5c31af7Sopenharmony_ci { 2439e5c31af7Sopenharmony_ci const TransformFeedbackTypeValidator typeValidator (m_context); 2440e5c31af7Sopenharmony_ci const TransformFeedbackArraySizeValidator arraySizeValidator (m_context); 2441e5c31af7Sopenharmony_ci const TransformFeedbackNameLengthValidator nameLengthValidator (m_context); 2442e5c31af7Sopenharmony_ci 2443e5c31af7Sopenharmony_ci const TestProperty allProperties[] = 2444e5c31af7Sopenharmony_ci { 2445e5c31af7Sopenharmony_ci { GL_ARRAY_SIZE, &arraySizeValidator }, 2446e5c31af7Sopenharmony_ci { GL_NAME_LENGTH, &nameLengthValidator }, 2447e5c31af7Sopenharmony_ci { GL_TYPE, &typeValidator }, 2448e5c31af7Sopenharmony_ci }; 2449e5c31af7Sopenharmony_ci 2450e5c31af7Sopenharmony_ci for (int targetResourceNdx = 0; targetResourceNdx < (int)targetResources.size(); ++targetResourceNdx) 2451e5c31af7Sopenharmony_ci { 2452e5c31af7Sopenharmony_ci const tcu::ScopedLogSection section (m_testCtx.getLog(), "XFBVariableResource", "Transform feedback varying \"" + targetResources[targetResourceNdx] + "\""); 2453e5c31af7Sopenharmony_ci const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2454e5c31af7Sopenharmony_ci std::vector<glw::GLenum> props; 2455e5c31af7Sopenharmony_ci std::vector<const PropValidator*> validators; 2456e5c31af7Sopenharmony_ci 2457e5c31af7Sopenharmony_ci for (int propNdx = 0; propNdx < DE_LENGTH_OF_ARRAY(allProperties); ++propNdx) 2458e5c31af7Sopenharmony_ci { 2459e5c31af7Sopenharmony_ci if (allProperties[propNdx].validator->isSelected(m_queryTarget.propFlags) && 2460e5c31af7Sopenharmony_ci allProperties[propNdx].validator->isSupported()) 2461e5c31af7Sopenharmony_ci { 2462e5c31af7Sopenharmony_ci props.push_back(allProperties[propNdx].prop); 2463e5c31af7Sopenharmony_ci validators.push_back(allProperties[propNdx].validator); 2464e5c31af7Sopenharmony_ci } 2465e5c31af7Sopenharmony_ci } 2466e5c31af7Sopenharmony_ci 2467e5c31af7Sopenharmony_ci DE_ASSERT(!props.empty()); 2468e5c31af7Sopenharmony_ci 2469e5c31af7Sopenharmony_ci queryAndValidateProps(m_testCtx, gl, program.getProgram(), m_queryTarget.interface, targetResources[targetResourceNdx].c_str(), programDefinition, props, validators); 2470e5c31af7Sopenharmony_ci } 2471e5c31af7Sopenharmony_ci 2472e5c31af7Sopenharmony_ci break; 2473e5c31af7Sopenharmony_ci } 2474e5c31af7Sopenharmony_ci 2475e5c31af7Sopenharmony_ci default: 2476e5c31af7Sopenharmony_ci DE_ASSERT(false); 2477e5c31af7Sopenharmony_ci } 2478e5c31af7Sopenharmony_ci 2479e5c31af7Sopenharmony_ci return STOP; 2480e5c31af7Sopenharmony_ci} 2481e5c31af7Sopenharmony_ci 2482e5c31af7Sopenharmony_cistatic bool checkLimit (glw::GLenum pname, int usage, const glw::Functions& gl, tcu::TestLog& log) 2483e5c31af7Sopenharmony_ci{ 2484e5c31af7Sopenharmony_ci if (usage > 0) 2485e5c31af7Sopenharmony_ci { 2486e5c31af7Sopenharmony_ci glw::GLint limit = 0; 2487e5c31af7Sopenharmony_ci gl.getIntegerv(pname, &limit); 2488e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "query limits"); 2489e5c31af7Sopenharmony_ci 2490e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "\t" << glu::getGettableStateStr(pname) << " = " << limit << ", test requires " << usage << tcu::TestLog::EndMessage; 2491e5c31af7Sopenharmony_ci 2492e5c31af7Sopenharmony_ci if (limit < usage) 2493e5c31af7Sopenharmony_ci { 2494e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "\t\tLimit exceeded" << tcu::TestLog::EndMessage; 2495e5c31af7Sopenharmony_ci return false; 2496e5c31af7Sopenharmony_ci } 2497e5c31af7Sopenharmony_ci } 2498e5c31af7Sopenharmony_ci 2499e5c31af7Sopenharmony_ci return true; 2500e5c31af7Sopenharmony_ci} 2501e5c31af7Sopenharmony_ci 2502e5c31af7Sopenharmony_cistatic bool checkShaderResourceUsage (const ProgramInterfaceDefinition::Program* program, const ProgramInterfaceDefinition::Shader* shader, const glw::Functions& gl, tcu::TestLog& log) 2503e5c31af7Sopenharmony_ci{ 2504e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::ShaderResourceUsage usage = getShaderResourceUsage(program, shader); 2505e5c31af7Sopenharmony_ci 2506e5c31af7Sopenharmony_ci switch (shader->getType()) 2507e5c31af7Sopenharmony_ci { 2508e5c31af7Sopenharmony_ci case glu::SHADERTYPE_VERTEX: 2509e5c31af7Sopenharmony_ci { 2510e5c31af7Sopenharmony_ci const struct 2511e5c31af7Sopenharmony_ci { 2512e5c31af7Sopenharmony_ci glw::GLenum pname; 2513e5c31af7Sopenharmony_ci int usage; 2514e5c31af7Sopenharmony_ci } restrictions[] = 2515e5c31af7Sopenharmony_ci { 2516e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_ATTRIBS, usage.numInputVectors }, 2517e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents }, 2518e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_UNIFORM_VECTORS, usage.numUniformVectors }, 2519e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_UNIFORM_BLOCKS, usage.numUniformBlocks }, 2520e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_OUTPUT_COMPONENTS, usage.numOutputComponents }, 2521e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, usage.numSamplers }, 2522e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers }, 2523e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_ATOMIC_COUNTERS, usage.numAtomicCounters }, 2524e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_IMAGE_UNIFORMS, usage.numImages }, 2525e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, usage.numCombinedUniformComponents }, 2526e5c31af7Sopenharmony_ci { GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks }, 2527e5c31af7Sopenharmony_ci }; 2528e5c31af7Sopenharmony_ci 2529e5c31af7Sopenharmony_ci bool allOk = true; 2530e5c31af7Sopenharmony_ci 2531e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Vertex shader:" << tcu::TestLog::EndMessage; 2532e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx) 2533e5c31af7Sopenharmony_ci allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log); 2534e5c31af7Sopenharmony_ci 2535e5c31af7Sopenharmony_ci return allOk; 2536e5c31af7Sopenharmony_ci } 2537e5c31af7Sopenharmony_ci 2538e5c31af7Sopenharmony_ci case glu::SHADERTYPE_FRAGMENT: 2539e5c31af7Sopenharmony_ci { 2540e5c31af7Sopenharmony_ci const struct 2541e5c31af7Sopenharmony_ci { 2542e5c31af7Sopenharmony_ci glw::GLenum pname; 2543e5c31af7Sopenharmony_ci int usage; 2544e5c31af7Sopenharmony_ci } restrictions[] = 2545e5c31af7Sopenharmony_ci { 2546e5c31af7Sopenharmony_ci { GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents }, 2547e5c31af7Sopenharmony_ci { GL_MAX_FRAGMENT_UNIFORM_VECTORS, usage.numUniformVectors }, 2548e5c31af7Sopenharmony_ci { GL_MAX_FRAGMENT_UNIFORM_BLOCKS, usage.numUniformBlocks }, 2549e5c31af7Sopenharmony_ci { GL_MAX_FRAGMENT_INPUT_COMPONENTS, usage.numInputComponents }, 2550e5c31af7Sopenharmony_ci { GL_MAX_TEXTURE_IMAGE_UNITS, usage.numSamplers }, 2551e5c31af7Sopenharmony_ci { GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers }, 2552e5c31af7Sopenharmony_ci { GL_MAX_FRAGMENT_ATOMIC_COUNTERS, usage.numAtomicCounters }, 2553e5c31af7Sopenharmony_ci { GL_MAX_FRAGMENT_IMAGE_UNIFORMS, usage.numImages }, 2554e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, usage.numCombinedUniformComponents }, 2555e5c31af7Sopenharmony_ci { GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks }, 2556e5c31af7Sopenharmony_ci }; 2557e5c31af7Sopenharmony_ci 2558e5c31af7Sopenharmony_ci bool allOk = true; 2559e5c31af7Sopenharmony_ci 2560e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Fragment shader:" << tcu::TestLog::EndMessage; 2561e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx) 2562e5c31af7Sopenharmony_ci allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log); 2563e5c31af7Sopenharmony_ci 2564e5c31af7Sopenharmony_ci return allOk; 2565e5c31af7Sopenharmony_ci } 2566e5c31af7Sopenharmony_ci 2567e5c31af7Sopenharmony_ci case glu::SHADERTYPE_COMPUTE: 2568e5c31af7Sopenharmony_ci { 2569e5c31af7Sopenharmony_ci const struct 2570e5c31af7Sopenharmony_ci { 2571e5c31af7Sopenharmony_ci glw::GLenum pname; 2572e5c31af7Sopenharmony_ci int usage; 2573e5c31af7Sopenharmony_ci } restrictions[] = 2574e5c31af7Sopenharmony_ci { 2575e5c31af7Sopenharmony_ci { GL_MAX_COMPUTE_UNIFORM_BLOCKS, usage.numUniformBlocks }, 2576e5c31af7Sopenharmony_ci { GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, usage.numSamplers }, 2577e5c31af7Sopenharmony_ci { GL_MAX_COMPUTE_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents }, 2578e5c31af7Sopenharmony_ci { GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers }, 2579e5c31af7Sopenharmony_ci { GL_MAX_COMPUTE_ATOMIC_COUNTERS, usage.numAtomicCounters }, 2580e5c31af7Sopenharmony_ci { GL_MAX_COMPUTE_IMAGE_UNIFORMS, usage.numImages }, 2581e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS, usage.numCombinedUniformComponents }, 2582e5c31af7Sopenharmony_ci { GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks }, 2583e5c31af7Sopenharmony_ci }; 2584e5c31af7Sopenharmony_ci 2585e5c31af7Sopenharmony_ci bool allOk = true; 2586e5c31af7Sopenharmony_ci 2587e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Compute shader:" << tcu::TestLog::EndMessage; 2588e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx) 2589e5c31af7Sopenharmony_ci allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log); 2590e5c31af7Sopenharmony_ci 2591e5c31af7Sopenharmony_ci return allOk; 2592e5c31af7Sopenharmony_ci } 2593e5c31af7Sopenharmony_ci 2594e5c31af7Sopenharmony_ci case glu::SHADERTYPE_GEOMETRY: 2595e5c31af7Sopenharmony_ci { 2596e5c31af7Sopenharmony_ci const int totalOutputComponents = program->getGeometryNumOutputVertices() * usage.numOutputComponents; 2597e5c31af7Sopenharmony_ci const struct 2598e5c31af7Sopenharmony_ci { 2599e5c31af7Sopenharmony_ci glw::GLenum pname; 2600e5c31af7Sopenharmony_ci int usage; 2601e5c31af7Sopenharmony_ci } restrictions[] = 2602e5c31af7Sopenharmony_ci { 2603e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents }, 2604e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_UNIFORM_BLOCKS, usage.numUniformBlocks }, 2605e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_INPUT_COMPONENTS, usage.numInputComponents }, 2606e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, usage.numOutputComponents }, 2607e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_OUTPUT_VERTICES, (int)program->getGeometryNumOutputVertices() }, 2608e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, totalOutputComponents }, 2609e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, usage.numSamplers }, 2610e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers }, 2611e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_ATOMIC_COUNTERS, usage.numAtomicCounters }, 2612e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_IMAGE_UNIFORMS, usage.numImages }, 2613e5c31af7Sopenharmony_ci { GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks }, 2614e5c31af7Sopenharmony_ci }; 2615e5c31af7Sopenharmony_ci 2616e5c31af7Sopenharmony_ci bool allOk = true; 2617e5c31af7Sopenharmony_ci 2618e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Geometry shader:" << tcu::TestLog::EndMessage; 2619e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx) 2620e5c31af7Sopenharmony_ci allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log); 2621e5c31af7Sopenharmony_ci 2622e5c31af7Sopenharmony_ci return allOk; 2623e5c31af7Sopenharmony_ci } 2624e5c31af7Sopenharmony_ci 2625e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_CONTROL: 2626e5c31af7Sopenharmony_ci { 2627e5c31af7Sopenharmony_ci const int totalOutputComponents = program->getTessellationNumOutputPatchVertices() * usage.numOutputComponents + usage.numPatchOutputComponents; 2628e5c31af7Sopenharmony_ci const struct 2629e5c31af7Sopenharmony_ci { 2630e5c31af7Sopenharmony_ci glw::GLenum pname; 2631e5c31af7Sopenharmony_ci int usage; 2632e5c31af7Sopenharmony_ci } restrictions[] = 2633e5c31af7Sopenharmony_ci { 2634e5c31af7Sopenharmony_ci { GL_MAX_PATCH_VERTICES, (int)program->getTessellationNumOutputPatchVertices() }, 2635e5c31af7Sopenharmony_ci { GL_MAX_TESS_PATCH_COMPONENTS, usage.numPatchOutputComponents }, 2636e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents }, 2637e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS, usage.numUniformBlocks }, 2638e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, usage.numInputComponents }, 2639e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, usage.numOutputComponents }, 2640e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS, totalOutputComponents }, 2641e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS, usage.numSamplers }, 2642e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers }, 2643e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, usage.numAtomicCounters }, 2644e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, usage.numImages }, 2645e5c31af7Sopenharmony_ci { GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks }, 2646e5c31af7Sopenharmony_ci }; 2647e5c31af7Sopenharmony_ci 2648e5c31af7Sopenharmony_ci bool allOk = true; 2649e5c31af7Sopenharmony_ci 2650e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Tessellation control shader:" << tcu::TestLog::EndMessage; 2651e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx) 2652e5c31af7Sopenharmony_ci allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log); 2653e5c31af7Sopenharmony_ci 2654e5c31af7Sopenharmony_ci return allOk; 2655e5c31af7Sopenharmony_ci } 2656e5c31af7Sopenharmony_ci 2657e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_EVALUATION: 2658e5c31af7Sopenharmony_ci { 2659e5c31af7Sopenharmony_ci const struct 2660e5c31af7Sopenharmony_ci { 2661e5c31af7Sopenharmony_ci glw::GLenum pname; 2662e5c31af7Sopenharmony_ci int usage; 2663e5c31af7Sopenharmony_ci } restrictions[] = 2664e5c31af7Sopenharmony_ci { 2665e5c31af7Sopenharmony_ci { GL_MAX_PATCH_VERTICES, (int)program->getTessellationNumOutputPatchVertices() }, 2666e5c31af7Sopenharmony_ci { GL_MAX_TESS_PATCH_COMPONENTS, usage.numPatchInputComponents }, 2667e5c31af7Sopenharmony_ci { GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS, usage.numDefaultBlockUniformComponents }, 2668e5c31af7Sopenharmony_ci { GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, usage.numUniformBlocks }, 2669e5c31af7Sopenharmony_ci { GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, usage.numInputComponents }, 2670e5c31af7Sopenharmony_ci { GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, usage.numOutputComponents }, 2671e5c31af7Sopenharmony_ci { GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS, usage.numSamplers }, 2672e5c31af7Sopenharmony_ci { GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers }, 2673e5c31af7Sopenharmony_ci { GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, usage.numAtomicCounters }, 2674e5c31af7Sopenharmony_ci { GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, usage.numImages }, 2675e5c31af7Sopenharmony_ci { GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks }, 2676e5c31af7Sopenharmony_ci }; 2677e5c31af7Sopenharmony_ci 2678e5c31af7Sopenharmony_ci bool allOk = true; 2679e5c31af7Sopenharmony_ci 2680e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Tessellation evaluation shader:" << tcu::TestLog::EndMessage; 2681e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx) 2682e5c31af7Sopenharmony_ci allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log); 2683e5c31af7Sopenharmony_ci 2684e5c31af7Sopenharmony_ci return allOk; 2685e5c31af7Sopenharmony_ci } 2686e5c31af7Sopenharmony_ci 2687e5c31af7Sopenharmony_ci default: 2688e5c31af7Sopenharmony_ci DE_ASSERT(false); 2689e5c31af7Sopenharmony_ci return false; 2690e5c31af7Sopenharmony_ci } 2691e5c31af7Sopenharmony_ci} 2692e5c31af7Sopenharmony_ci 2693e5c31af7Sopenharmony_cistatic bool checkProgramCombinedResourceUsage (const ProgramInterfaceDefinition::Program* program, const glw::Functions& gl, tcu::TestLog& log) 2694e5c31af7Sopenharmony_ci{ 2695e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::ProgramResourceUsage usage = getCombinedProgramResourceUsage(program); 2696e5c31af7Sopenharmony_ci 2697e5c31af7Sopenharmony_ci const struct 2698e5c31af7Sopenharmony_ci { 2699e5c31af7Sopenharmony_ci glw::GLenum pname; 2700e5c31af7Sopenharmony_ci int usage; 2701e5c31af7Sopenharmony_ci } restrictions[] = 2702e5c31af7Sopenharmony_ci { 2703e5c31af7Sopenharmony_ci { GL_MAX_UNIFORM_BUFFER_BINDINGS, usage.uniformBufferMaxBinding+1 }, 2704e5c31af7Sopenharmony_ci { GL_MAX_UNIFORM_BLOCK_SIZE, usage.uniformBufferMaxSize }, 2705e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_UNIFORM_BLOCKS, usage.numUniformBlocks }, 2706e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, usage.numCombinedVertexUniformComponents }, 2707e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, usage.numCombinedFragmentUniformComponents }, 2708e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS, usage.numCombinedGeometryUniformComponents }, 2709e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS, usage.numCombinedTessControlUniformComponents }, 2710e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS, usage.numCombinedTessEvalUniformComponents }, 2711e5c31af7Sopenharmony_ci { GL_MAX_VARYING_COMPONENTS, usage.numVaryingComponents }, 2712e5c31af7Sopenharmony_ci { GL_MAX_VARYING_VECTORS, usage.numVaryingVectors }, 2713e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, usage.numCombinedSamplers }, 2714e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, usage.numCombinedOutputResources }, 2715e5c31af7Sopenharmony_ci { GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, usage.atomicCounterBufferMaxBinding+1 }, 2716e5c31af7Sopenharmony_ci { GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, usage.atomicCounterBufferMaxSize }, 2717e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS, usage.numAtomicCounterBuffers }, 2718e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_ATOMIC_COUNTERS, usage.numAtomicCounters }, 2719e5c31af7Sopenharmony_ci { GL_MAX_IMAGE_UNITS, usage.maxImageBinding+1 }, 2720e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_IMAGE_UNIFORMS, usage.numCombinedImages }, 2721e5c31af7Sopenharmony_ci { GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, usage.shaderStorageBufferMaxBinding+1 }, 2722e5c31af7Sopenharmony_ci { GL_MAX_SHADER_STORAGE_BLOCK_SIZE, usage.shaderStorageBufferMaxSize }, 2723e5c31af7Sopenharmony_ci { GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, usage.numShaderStorageBlocks }, 2724e5c31af7Sopenharmony_ci { GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, usage.numXFBInterleavedComponents }, 2725e5c31af7Sopenharmony_ci { GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, usage.numXFBSeparateAttribs }, 2726e5c31af7Sopenharmony_ci { GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, usage.numXFBSeparateComponents }, 2727e5c31af7Sopenharmony_ci { GL_MAX_DRAW_BUFFERS, usage.fragmentOutputMaxBinding+1 }, 2728e5c31af7Sopenharmony_ci }; 2729e5c31af7Sopenharmony_ci 2730e5c31af7Sopenharmony_ci bool allOk = true; 2731e5c31af7Sopenharmony_ci 2732e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "Program combined:" << tcu::TestLog::EndMessage; 2733e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(restrictions); ++ndx) 2734e5c31af7Sopenharmony_ci allOk &= checkLimit(restrictions[ndx].pname, restrictions[ndx].usage, gl, log); 2735e5c31af7Sopenharmony_ci 2736e5c31af7Sopenharmony_ci return allOk; 2737e5c31af7Sopenharmony_ci} 2738e5c31af7Sopenharmony_ci 2739e5c31af7Sopenharmony_civoid checkProgramResourceUsage (const ProgramInterfaceDefinition::Program* program, const glw::Functions& gl, tcu::TestLog& log) 2740e5c31af7Sopenharmony_ci{ 2741e5c31af7Sopenharmony_ci bool limitExceeded = false; 2742e5c31af7Sopenharmony_ci 2743e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 2744e5c31af7Sopenharmony_ci limitExceeded |= !checkShaderResourceUsage(program, program->getShaders()[shaderNdx], gl, log); 2745e5c31af7Sopenharmony_ci 2746e5c31af7Sopenharmony_ci limitExceeded |= !checkProgramCombinedResourceUsage(program, gl, log); 2747e5c31af7Sopenharmony_ci 2748e5c31af7Sopenharmony_ci if (limitExceeded) 2749e5c31af7Sopenharmony_ci { 2750e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << "One or more resource limits exceeded" << tcu::TestLog::EndMessage; 2751e5c31af7Sopenharmony_ci throw tcu::NotSupportedError("one or more resource limits exceeded"); 2752e5c31af7Sopenharmony_ci } 2753e5c31af7Sopenharmony_ci} 2754e5c31af7Sopenharmony_ci 2755e5c31af7Sopenharmony_ci} // Functional 2756e5c31af7Sopenharmony_ci} // gles31 2757e5c31af7Sopenharmony_ci} // deqp 2758