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 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "es31fProgramInterfaceDefinition.hpp" 25e5c31af7Sopenharmony_ci#include "es31fProgramInterfaceDefinitionUtil.hpp" 26e5c31af7Sopenharmony_ci#include "gluVarType.hpp" 27e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp" 28e5c31af7Sopenharmony_ci#include "deSTLUtil.hpp" 29e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 30e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 31e5c31af7Sopenharmony_ci 32e5c31af7Sopenharmony_ci#include <set> 33e5c31af7Sopenharmony_ci 34e5c31af7Sopenharmony_cinamespace deqp 35e5c31af7Sopenharmony_ci{ 36e5c31af7Sopenharmony_cinamespace gles31 37e5c31af7Sopenharmony_ci{ 38e5c31af7Sopenharmony_cinamespace Functional 39e5c31af7Sopenharmony_ci{ 40e5c31af7Sopenharmony_cinamespace ProgramInterfaceDefinition 41e5c31af7Sopenharmony_ci{ 42e5c31af7Sopenharmony_cinamespace 43e5c31af7Sopenharmony_ci{ 44e5c31af7Sopenharmony_ci 45e5c31af7Sopenharmony_cistatic const glu::ShaderType s_shaderStageOrder[] = 46e5c31af7Sopenharmony_ci{ 47e5c31af7Sopenharmony_ci glu::SHADERTYPE_COMPUTE, 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_ci glu::SHADERTYPE_VERTEX, 50e5c31af7Sopenharmony_ci glu::SHADERTYPE_TESSELLATION_CONTROL, 51e5c31af7Sopenharmony_ci glu::SHADERTYPE_TESSELLATION_EVALUATION, 52e5c31af7Sopenharmony_ci glu::SHADERTYPE_GEOMETRY, 53e5c31af7Sopenharmony_ci glu::SHADERTYPE_FRAGMENT, 54e5c31af7Sopenharmony_ci 55e5c31af7Sopenharmony_ci glu::SHADERTYPE_RAYGEN, 56e5c31af7Sopenharmony_ci glu::SHADERTYPE_ANY_HIT, 57e5c31af7Sopenharmony_ci glu::SHADERTYPE_CLOSEST_HIT, 58e5c31af7Sopenharmony_ci glu::SHADERTYPE_MISS, 59e5c31af7Sopenharmony_ci glu::SHADERTYPE_INTERSECTION, 60e5c31af7Sopenharmony_ci glu::SHADERTYPE_CALLABLE, 61e5c31af7Sopenharmony_ci 62e5c31af7Sopenharmony_ci glu::SHADERTYPE_TASK, 63e5c31af7Sopenharmony_ci glu::SHADERTYPE_MESH, 64e5c31af7Sopenharmony_ci}; 65e5c31af7Sopenharmony_ci 66e5c31af7Sopenharmony_ci// s_shaderStageOrder does not contain ShaderType_LAST 67e5c31af7Sopenharmony_ciDE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_shaderStageOrder) == glu::SHADERTYPE_LAST); 68e5c31af7Sopenharmony_ci 69e5c31af7Sopenharmony_cistatic bool containsMatchingSubtype (const glu::VarType& varType, bool (*predicate)(glu::DataType)) 70e5c31af7Sopenharmony_ci{ 71e5c31af7Sopenharmony_ci if (varType.isBasicType() && predicate(varType.getBasicType())) 72e5c31af7Sopenharmony_ci return true; 73e5c31af7Sopenharmony_ci 74e5c31af7Sopenharmony_ci if (varType.isArrayType()) 75e5c31af7Sopenharmony_ci return containsMatchingSubtype(varType.getElementType(), predicate); 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ci if (varType.isStructType()) 78e5c31af7Sopenharmony_ci for (int memberNdx = 0; memberNdx < varType.getStructPtr()->getNumMembers(); ++memberNdx) 79e5c31af7Sopenharmony_ci if (containsMatchingSubtype(varType.getStructPtr()->getMember(memberNdx).getType(), predicate)) 80e5c31af7Sopenharmony_ci return true; 81e5c31af7Sopenharmony_ci 82e5c31af7Sopenharmony_ci return false; 83e5c31af7Sopenharmony_ci} 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_cistatic bool containsMatchingSubtype (const std::vector<glu::VariableDeclaration>& decls, bool (*predicate)(glu::DataType)) 86e5c31af7Sopenharmony_ci{ 87e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)decls.size(); ++varNdx) 88e5c31af7Sopenharmony_ci if (containsMatchingSubtype(decls[varNdx].varType, predicate)) 89e5c31af7Sopenharmony_ci return true; 90e5c31af7Sopenharmony_ci return false; 91e5c31af7Sopenharmony_ci} 92e5c31af7Sopenharmony_ci 93e5c31af7Sopenharmony_cistatic bool isOpaqueType (glu::DataType type) 94e5c31af7Sopenharmony_ci{ 95e5c31af7Sopenharmony_ci return glu::isDataTypeAtomicCounter(type) || 96e5c31af7Sopenharmony_ci glu::isDataTypeImage(type) || 97e5c31af7Sopenharmony_ci glu::isDataTypeSampler(type); 98e5c31af7Sopenharmony_ci} 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_cistatic int getShaderStageIndex (glu::ShaderType stage) 101e5c31af7Sopenharmony_ci{ 102e5c31af7Sopenharmony_ci const glu::ShaderType* const it = std::find(DE_ARRAY_BEGIN(s_shaderStageOrder), DE_ARRAY_END(s_shaderStageOrder), stage); 103e5c31af7Sopenharmony_ci 104e5c31af7Sopenharmony_ci if (it == DE_ARRAY_END(s_shaderStageOrder)) 105e5c31af7Sopenharmony_ci return -1; 106e5c31af7Sopenharmony_ci else 107e5c31af7Sopenharmony_ci { 108e5c31af7Sopenharmony_ci const int index = (int)(it - DE_ARRAY_BEGIN(s_shaderStageOrder)); 109e5c31af7Sopenharmony_ci return index; 110e5c31af7Sopenharmony_ci } 111e5c31af7Sopenharmony_ci} 112e5c31af7Sopenharmony_ci 113e5c31af7Sopenharmony_ci} // anonymous 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ciShader::Shader (glu::ShaderType type, glu::GLSLVersion version) 116e5c31af7Sopenharmony_ci : m_shaderType (type) 117e5c31af7Sopenharmony_ci , m_version (version) 118e5c31af7Sopenharmony_ci{ 119e5c31af7Sopenharmony_ci} 120e5c31af7Sopenharmony_ci 121e5c31af7Sopenharmony_ciShader::~Shader (void) 122e5c31af7Sopenharmony_ci{ 123e5c31af7Sopenharmony_ci} 124e5c31af7Sopenharmony_ci 125e5c31af7Sopenharmony_cistatic bool isIllegalVertexInput (const glu::VarType& varType) 126e5c31af7Sopenharmony_ci{ 127e5c31af7Sopenharmony_ci // booleans, opaque types, arrays, structs are not allowed as inputs 128e5c31af7Sopenharmony_ci if (!varType.isBasicType()) 129e5c31af7Sopenharmony_ci return true; 130e5c31af7Sopenharmony_ci if (glu::isDataTypeBoolOrBVec(varType.getBasicType())) 131e5c31af7Sopenharmony_ci return true; 132e5c31af7Sopenharmony_ci return false; 133e5c31af7Sopenharmony_ci} 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_cistatic bool isIllegalVertexOutput (const glu::VarType& varType, bool insideAStruct = false, bool insideAnArray = false) 136e5c31af7Sopenharmony_ci{ 137e5c31af7Sopenharmony_ci // booleans, opaque types, arrays of arrays, arrays of structs, array in struct, struct struct are not allowed as vertex outputs 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci if (varType.isBasicType()) 140e5c31af7Sopenharmony_ci { 141e5c31af7Sopenharmony_ci const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) && !glu::isDataTypeVector(varType.getBasicType()) && !glu::isDataTypeMatrix(varType.getBasicType()); 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci if (glu::isDataTypeBoolOrBVec(varType.getBasicType())) 144e5c31af7Sopenharmony_ci return true; 145e5c31af7Sopenharmony_ci 146e5c31af7Sopenharmony_ci if (isOpaqueType) 147e5c31af7Sopenharmony_ci return true; 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_ci return false; 150e5c31af7Sopenharmony_ci } 151e5c31af7Sopenharmony_ci else if (varType.isArrayType()) 152e5c31af7Sopenharmony_ci { 153e5c31af7Sopenharmony_ci if (insideAnArray || insideAStruct) 154e5c31af7Sopenharmony_ci return true; 155e5c31af7Sopenharmony_ci 156e5c31af7Sopenharmony_ci return isIllegalVertexOutput(varType.getElementType(), insideAStruct, true); 157e5c31af7Sopenharmony_ci } 158e5c31af7Sopenharmony_ci else if (varType.isStructType()) 159e5c31af7Sopenharmony_ci { 160e5c31af7Sopenharmony_ci if (insideAnArray || insideAStruct) 161e5c31af7Sopenharmony_ci return true; 162e5c31af7Sopenharmony_ci 163e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx) 164e5c31af7Sopenharmony_ci if (isIllegalVertexOutput(varType.getStructPtr()->getMember(ndx).getType(), true, insideAnArray)) 165e5c31af7Sopenharmony_ci return true; 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ci return false; 168e5c31af7Sopenharmony_ci } 169e5c31af7Sopenharmony_ci else 170e5c31af7Sopenharmony_ci { 171e5c31af7Sopenharmony_ci DE_ASSERT(false); 172e5c31af7Sopenharmony_ci return true; 173e5c31af7Sopenharmony_ci } 174e5c31af7Sopenharmony_ci} 175e5c31af7Sopenharmony_ci 176e5c31af7Sopenharmony_cistatic bool isIllegalFragmentInput (const glu::VarType& varType) 177e5c31af7Sopenharmony_ci{ 178e5c31af7Sopenharmony_ci return isIllegalVertexOutput(varType); 179e5c31af7Sopenharmony_ci} 180e5c31af7Sopenharmony_ci 181e5c31af7Sopenharmony_cistatic bool isIllegalFragmentOutput (const glu::VarType& varType, bool insideAnArray = false) 182e5c31af7Sopenharmony_ci{ 183e5c31af7Sopenharmony_ci // booleans, opaque types, matrices, structs, arrays of arrays are not allowed as outputs 184e5c31af7Sopenharmony_ci 185e5c31af7Sopenharmony_ci if (varType.isBasicType()) 186e5c31af7Sopenharmony_ci { 187e5c31af7Sopenharmony_ci const bool isOpaqueType = !glu::isDataTypeScalar(varType.getBasicType()) && !glu::isDataTypeVector(varType.getBasicType()) && !glu::isDataTypeMatrix(varType.getBasicType()); 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_ci if (glu::isDataTypeBoolOrBVec(varType.getBasicType()) || isOpaqueType || glu::isDataTypeMatrix(varType.getBasicType())) 190e5c31af7Sopenharmony_ci return true; 191e5c31af7Sopenharmony_ci return false; 192e5c31af7Sopenharmony_ci } 193e5c31af7Sopenharmony_ci else if (varType.isArrayType()) 194e5c31af7Sopenharmony_ci { 195e5c31af7Sopenharmony_ci if (insideAnArray) 196e5c31af7Sopenharmony_ci return true; 197e5c31af7Sopenharmony_ci return isIllegalFragmentOutput(varType.getElementType(), true); 198e5c31af7Sopenharmony_ci } 199e5c31af7Sopenharmony_ci else if (varType.isStructType()) 200e5c31af7Sopenharmony_ci return true; 201e5c31af7Sopenharmony_ci else 202e5c31af7Sopenharmony_ci { 203e5c31af7Sopenharmony_ci DE_ASSERT(false); 204e5c31af7Sopenharmony_ci return true; 205e5c31af7Sopenharmony_ci } 206e5c31af7Sopenharmony_ci} 207e5c31af7Sopenharmony_ci 208e5c31af7Sopenharmony_cistatic bool isTypeIntegerOrContainsIntegers (const glu::VarType& varType) 209e5c31af7Sopenharmony_ci{ 210e5c31af7Sopenharmony_ci if (varType.isBasicType()) 211e5c31af7Sopenharmony_ci return glu::isDataTypeIntOrIVec(varType.getBasicType()) || glu::isDataTypeUintOrUVec(varType.getBasicType()); 212e5c31af7Sopenharmony_ci else if (varType.isArrayType()) 213e5c31af7Sopenharmony_ci return isTypeIntegerOrContainsIntegers(varType.getElementType()); 214e5c31af7Sopenharmony_ci else if (varType.isStructType()) 215e5c31af7Sopenharmony_ci { 216e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx) 217e5c31af7Sopenharmony_ci if (isTypeIntegerOrContainsIntegers(varType.getStructPtr()->getMember(ndx).getType())) 218e5c31af7Sopenharmony_ci return true; 219e5c31af7Sopenharmony_ci return false; 220e5c31af7Sopenharmony_ci } 221e5c31af7Sopenharmony_ci else 222e5c31af7Sopenharmony_ci { 223e5c31af7Sopenharmony_ci DE_ASSERT(false); 224e5c31af7Sopenharmony_ci return true; 225e5c31af7Sopenharmony_ci } 226e5c31af7Sopenharmony_ci} 227e5c31af7Sopenharmony_ci 228e5c31af7Sopenharmony_cibool Shader::isValid (void) const 229e5c31af7Sopenharmony_ci{ 230e5c31af7Sopenharmony_ci // Default block variables 231e5c31af7Sopenharmony_ci { 232e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx) 233e5c31af7Sopenharmony_ci { 234e5c31af7Sopenharmony_ci // atomic declaration in the default block without binding 235e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].layout.binding == -1 && 236e5c31af7Sopenharmony_ci containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeAtomicCounter)) 237e5c31af7Sopenharmony_ci return false; 238e5c31af7Sopenharmony_ci 239e5c31af7Sopenharmony_ci // atomic declaration in a struct 240e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].varType.isStructType() && 241e5c31af7Sopenharmony_ci containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeAtomicCounter)) 242e5c31af7Sopenharmony_ci return false; 243e5c31af7Sopenharmony_ci 244e5c31af7Sopenharmony_ci // Unsupported layout qualifiers 245e5c31af7Sopenharmony_ci 246e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].layout.matrixOrder != glu::MATRIXORDER_LAST) 247e5c31af7Sopenharmony_ci return false; 248e5c31af7Sopenharmony_ci 249e5c31af7Sopenharmony_ci if (containsMatchingSubtype(m_defaultBlock.variables[varNdx].varType, glu::isDataTypeSampler)) 250e5c31af7Sopenharmony_ci { 251e5c31af7Sopenharmony_ci const glu::Layout layoutWithLocationAndBinding(m_defaultBlock.variables[varNdx].layout.location, m_defaultBlock.variables[varNdx].layout.binding); 252e5c31af7Sopenharmony_ci 253e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].layout != layoutWithLocationAndBinding) 254e5c31af7Sopenharmony_ci return false; 255e5c31af7Sopenharmony_ci } 256e5c31af7Sopenharmony_ci } 257e5c31af7Sopenharmony_ci } 258e5c31af7Sopenharmony_ci 259e5c31af7Sopenharmony_ci // Interface blocks 260e5c31af7Sopenharmony_ci { 261e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx) 262e5c31af7Sopenharmony_ci { 263e5c31af7Sopenharmony_ci // ES31 disallows interface block array arrays 264e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.size() > 1) 265e5c31af7Sopenharmony_ci return false; 266e5c31af7Sopenharmony_ci 267e5c31af7Sopenharmony_ci // Interface block arrays must have instance name 268e5c31af7Sopenharmony_ci if (!m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty() && m_defaultBlock.interfaceBlocks[interfaceNdx].instanceName.empty()) 269e5c31af7Sopenharmony_ci return false; 270e5c31af7Sopenharmony_ci 271e5c31af7Sopenharmony_ci // Opaque types in interface block 272e5c31af7Sopenharmony_ci if (containsMatchingSubtype(m_defaultBlock.interfaceBlocks[interfaceNdx].variables, isOpaqueType)) 273e5c31af7Sopenharmony_ci return false; 274e5c31af7Sopenharmony_ci } 275e5c31af7Sopenharmony_ci } 276e5c31af7Sopenharmony_ci 277e5c31af7Sopenharmony_ci // Shader type specific 278e5c31af7Sopenharmony_ci 279e5c31af7Sopenharmony_ci if (m_shaderType == glu::SHADERTYPE_VERTEX) 280e5c31af7Sopenharmony_ci { 281e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx) 282e5c31af7Sopenharmony_ci { 283e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && isIllegalVertexInput(m_defaultBlock.variables[varNdx].varType)) 284e5c31af7Sopenharmony_ci return false; 285e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && isIllegalVertexOutput(m_defaultBlock.variables[varNdx].varType)) 286e5c31af7Sopenharmony_ci return false; 287e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT && isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType)) 288e5c31af7Sopenharmony_ci return false; 289e5c31af7Sopenharmony_ci } 290e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx) 291e5c31af7Sopenharmony_ci { 292e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN || 293e5c31af7Sopenharmony_ci m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN || 294e5c31af7Sopenharmony_ci m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT) 295e5c31af7Sopenharmony_ci { 296e5c31af7Sopenharmony_ci return false; 297e5c31af7Sopenharmony_ci } 298e5c31af7Sopenharmony_ci } 299e5c31af7Sopenharmony_ci } 300e5c31af7Sopenharmony_ci else if (m_shaderType == glu::SHADERTYPE_FRAGMENT) 301e5c31af7Sopenharmony_ci { 302e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx) 303e5c31af7Sopenharmony_ci { 304e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && isIllegalFragmentInput(m_defaultBlock.variables[varNdx].varType)) 305e5c31af7Sopenharmony_ci return false; 306e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && m_defaultBlock.variables[varNdx].interpolation != glu::INTERPOLATION_FLAT && isTypeIntegerOrContainsIntegers(m_defaultBlock.variables[varNdx].varType)) 307e5c31af7Sopenharmony_ci return false; 308e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && isIllegalFragmentOutput(m_defaultBlock.variables[varNdx].varType)) 309e5c31af7Sopenharmony_ci return false; 310e5c31af7Sopenharmony_ci } 311e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx) 312e5c31af7Sopenharmony_ci { 313e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN || 314e5c31af7Sopenharmony_ci m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT || 315e5c31af7Sopenharmony_ci m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT) 316e5c31af7Sopenharmony_ci { 317e5c31af7Sopenharmony_ci return false; 318e5c31af7Sopenharmony_ci } 319e5c31af7Sopenharmony_ci } 320e5c31af7Sopenharmony_ci } 321e5c31af7Sopenharmony_ci else if (m_shaderType == glu::SHADERTYPE_COMPUTE) 322e5c31af7Sopenharmony_ci { 323e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx) 324e5c31af7Sopenharmony_ci { 325e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN || 326e5c31af7Sopenharmony_ci m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN || 327e5c31af7Sopenharmony_ci m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT || 328e5c31af7Sopenharmony_ci m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT) 329e5c31af7Sopenharmony_ci { 330e5c31af7Sopenharmony_ci return false; 331e5c31af7Sopenharmony_ci } 332e5c31af7Sopenharmony_ci } 333e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx) 334e5c31af7Sopenharmony_ci { 335e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN || 336e5c31af7Sopenharmony_ci m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN || 337e5c31af7Sopenharmony_ci m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT || 338e5c31af7Sopenharmony_ci m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT) 339e5c31af7Sopenharmony_ci { 340e5c31af7Sopenharmony_ci return false; 341e5c31af7Sopenharmony_ci } 342e5c31af7Sopenharmony_ci } 343e5c31af7Sopenharmony_ci } 344e5c31af7Sopenharmony_ci else if (m_shaderType == glu::SHADERTYPE_GEOMETRY) 345e5c31af7Sopenharmony_ci { 346e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx) 347e5c31af7Sopenharmony_ci { 348e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN || 349e5c31af7Sopenharmony_ci m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT) 350e5c31af7Sopenharmony_ci { 351e5c31af7Sopenharmony_ci return false; 352e5c31af7Sopenharmony_ci } 353e5c31af7Sopenharmony_ci // arrayed input 354e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType()) 355e5c31af7Sopenharmony_ci return false; 356e5c31af7Sopenharmony_ci } 357e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx) 358e5c31af7Sopenharmony_ci { 359e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN || 360e5c31af7Sopenharmony_ci m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT) 361e5c31af7Sopenharmony_ci { 362e5c31af7Sopenharmony_ci return false; 363e5c31af7Sopenharmony_ci } 364e5c31af7Sopenharmony_ci // arrayed input 365e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty()) 366e5c31af7Sopenharmony_ci return false; 367e5c31af7Sopenharmony_ci } 368e5c31af7Sopenharmony_ci } 369e5c31af7Sopenharmony_ci else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) 370e5c31af7Sopenharmony_ci { 371e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx) 372e5c31af7Sopenharmony_ci { 373e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_IN) 374e5c31af7Sopenharmony_ci return false; 375e5c31af7Sopenharmony_ci // arrayed input 376e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType()) 377e5c31af7Sopenharmony_ci return false; 378e5c31af7Sopenharmony_ci // arrayed output 379e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_OUT && !m_defaultBlock.variables[varNdx].varType.isArrayType()) 380e5c31af7Sopenharmony_ci return false; 381e5c31af7Sopenharmony_ci } 382e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx) 383e5c31af7Sopenharmony_ci { 384e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_IN) 385e5c31af7Sopenharmony_ci return false; 386e5c31af7Sopenharmony_ci // arrayed input 387e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty()) 388e5c31af7Sopenharmony_ci return false; 389e5c31af7Sopenharmony_ci // arrayed output 390e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_OUT && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty()) 391e5c31af7Sopenharmony_ci return false; 392e5c31af7Sopenharmony_ci } 393e5c31af7Sopenharmony_ci } 394e5c31af7Sopenharmony_ci else if (m_shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION) 395e5c31af7Sopenharmony_ci { 396e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)m_defaultBlock.variables.size(); ++varNdx) 397e5c31af7Sopenharmony_ci { 398e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_PATCH_OUT) 399e5c31af7Sopenharmony_ci return false; 400e5c31af7Sopenharmony_ci // arrayed input 401e5c31af7Sopenharmony_ci if (m_defaultBlock.variables[varNdx].storage == glu::STORAGE_IN && !m_defaultBlock.variables[varNdx].varType.isArrayType()) 402e5c31af7Sopenharmony_ci return false; 403e5c31af7Sopenharmony_ci } 404e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx) 405e5c31af7Sopenharmony_ci { 406e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_PATCH_OUT) 407e5c31af7Sopenharmony_ci return false; 408e5c31af7Sopenharmony_ci // arrayed input 409e5c31af7Sopenharmony_ci if (m_defaultBlock.interfaceBlocks[interfaceNdx].storage == glu::STORAGE_IN && m_defaultBlock.interfaceBlocks[interfaceNdx].dimensions.empty()) 410e5c31af7Sopenharmony_ci return false; 411e5c31af7Sopenharmony_ci } 412e5c31af7Sopenharmony_ci } 413e5c31af7Sopenharmony_ci else 414e5c31af7Sopenharmony_ci DE_ASSERT(false); 415e5c31af7Sopenharmony_ci 416e5c31af7Sopenharmony_ci return true; 417e5c31af7Sopenharmony_ci} 418e5c31af7Sopenharmony_ci 419e5c31af7Sopenharmony_ciProgram::Program (void) 420e5c31af7Sopenharmony_ci : m_separable (false) 421e5c31af7Sopenharmony_ci , m_xfbMode (0) 422e5c31af7Sopenharmony_ci , m_geoNumOutputVertices (0) 423e5c31af7Sopenharmony_ci , m_tessNumOutputVertices (0) 424e5c31af7Sopenharmony_ci{ 425e5c31af7Sopenharmony_ci} 426e5c31af7Sopenharmony_ci 427e5c31af7Sopenharmony_cistatic void collectStructPtrs (std::set<const glu::StructType*>& dst, const glu::VarType& type) 428e5c31af7Sopenharmony_ci{ 429e5c31af7Sopenharmony_ci if (type.isArrayType()) 430e5c31af7Sopenharmony_ci collectStructPtrs(dst, type.getElementType()); 431e5c31af7Sopenharmony_ci else if (type.isStructType()) 432e5c31af7Sopenharmony_ci { 433e5c31af7Sopenharmony_ci dst.insert(type.getStructPtr()); 434e5c31af7Sopenharmony_ci 435e5c31af7Sopenharmony_ci for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx) 436e5c31af7Sopenharmony_ci collectStructPtrs(dst, type.getStructPtr()->getMember(memberNdx).getType()); 437e5c31af7Sopenharmony_ci } 438e5c31af7Sopenharmony_ci} 439e5c31af7Sopenharmony_ci 440e5c31af7Sopenharmony_ciProgram::~Program (void) 441e5c31af7Sopenharmony_ci{ 442e5c31af7Sopenharmony_ci // delete shader struct types, need to be done by the program since shaders might share struct types 443e5c31af7Sopenharmony_ci { 444e5c31af7Sopenharmony_ci std::set<const glu::StructType*> structTypes; 445e5c31af7Sopenharmony_ci 446e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx) 447e5c31af7Sopenharmony_ci { 448e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.variables.size(); ++varNdx) 449e5c31af7Sopenharmony_ci collectStructPtrs(structTypes, m_shaders[shaderNdx]->m_defaultBlock.variables[varNdx].varType); 450e5c31af7Sopenharmony_ci 451e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks.size(); ++interfaceNdx) 452e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks[interfaceNdx].variables.size(); ++varNdx) 453e5c31af7Sopenharmony_ci collectStructPtrs(structTypes, m_shaders[shaderNdx]->m_defaultBlock.interfaceBlocks[interfaceNdx].variables[varNdx].varType); 454e5c31af7Sopenharmony_ci } 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci for (std::set<const glu::StructType*>::iterator it = structTypes.begin(); it != structTypes.end(); ++it) 457e5c31af7Sopenharmony_ci delete *it; 458e5c31af7Sopenharmony_ci } 459e5c31af7Sopenharmony_ci 460e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx) 461e5c31af7Sopenharmony_ci delete m_shaders[shaderNdx]; 462e5c31af7Sopenharmony_ci m_shaders.clear(); 463e5c31af7Sopenharmony_ci} 464e5c31af7Sopenharmony_ci 465e5c31af7Sopenharmony_ciShader* Program::addShader (glu::ShaderType type, glu::GLSLVersion version) 466e5c31af7Sopenharmony_ci{ 467e5c31af7Sopenharmony_ci DE_ASSERT(type < glu::SHADERTYPE_LAST); 468e5c31af7Sopenharmony_ci 469e5c31af7Sopenharmony_ci Shader* shader; 470e5c31af7Sopenharmony_ci 471e5c31af7Sopenharmony_ci // make sure push_back() cannot throw 472e5c31af7Sopenharmony_ci m_shaders.reserve(m_shaders.size() + 1); 473e5c31af7Sopenharmony_ci 474e5c31af7Sopenharmony_ci shader = new Shader(type, version); 475e5c31af7Sopenharmony_ci m_shaders.push_back(shader); 476e5c31af7Sopenharmony_ci 477e5c31af7Sopenharmony_ci return shader; 478e5c31af7Sopenharmony_ci} 479e5c31af7Sopenharmony_ci 480e5c31af7Sopenharmony_civoid Program::setSeparable (bool separable) 481e5c31af7Sopenharmony_ci{ 482e5c31af7Sopenharmony_ci m_separable = separable; 483e5c31af7Sopenharmony_ci} 484e5c31af7Sopenharmony_ci 485e5c31af7Sopenharmony_cibool Program::isSeparable (void) const 486e5c31af7Sopenharmony_ci{ 487e5c31af7Sopenharmony_ci return m_separable; 488e5c31af7Sopenharmony_ci} 489e5c31af7Sopenharmony_ci 490e5c31af7Sopenharmony_ciconst std::vector<Shader*>& Program::getShaders (void) const 491e5c31af7Sopenharmony_ci{ 492e5c31af7Sopenharmony_ci return m_shaders; 493e5c31af7Sopenharmony_ci} 494e5c31af7Sopenharmony_ci 495e5c31af7Sopenharmony_ciglu::ShaderType Program::getFirstStage (void) const 496e5c31af7Sopenharmony_ci{ 497e5c31af7Sopenharmony_ci const int nullValue = DE_LENGTH_OF_ARRAY(s_shaderStageOrder); 498e5c31af7Sopenharmony_ci int firstStage = nullValue; 499e5c31af7Sopenharmony_ci 500e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx) 501e5c31af7Sopenharmony_ci { 502e5c31af7Sopenharmony_ci const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType()); 503e5c31af7Sopenharmony_ci if (index != -1) 504e5c31af7Sopenharmony_ci firstStage = de::min(firstStage, index); 505e5c31af7Sopenharmony_ci } 506e5c31af7Sopenharmony_ci 507e5c31af7Sopenharmony_ci if (firstStage == nullValue) 508e5c31af7Sopenharmony_ci return glu::SHADERTYPE_LAST; 509e5c31af7Sopenharmony_ci else 510e5c31af7Sopenharmony_ci return s_shaderStageOrder[firstStage]; 511e5c31af7Sopenharmony_ci} 512e5c31af7Sopenharmony_ci 513e5c31af7Sopenharmony_ciglu::ShaderType Program::getLastStage (void) const 514e5c31af7Sopenharmony_ci{ 515e5c31af7Sopenharmony_ci const int nullValue = -1; 516e5c31af7Sopenharmony_ci int lastStage = nullValue; 517e5c31af7Sopenharmony_ci 518e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx) 519e5c31af7Sopenharmony_ci { 520e5c31af7Sopenharmony_ci const int index = getShaderStageIndex(m_shaders[shaderNdx]->getType()); 521e5c31af7Sopenharmony_ci if (index != -1) 522e5c31af7Sopenharmony_ci lastStage = de::max(lastStage, index); 523e5c31af7Sopenharmony_ci } 524e5c31af7Sopenharmony_ci 525e5c31af7Sopenharmony_ci if (lastStage == nullValue) 526e5c31af7Sopenharmony_ci return glu::SHADERTYPE_LAST; 527e5c31af7Sopenharmony_ci else 528e5c31af7Sopenharmony_ci return s_shaderStageOrder[lastStage]; 529e5c31af7Sopenharmony_ci} 530e5c31af7Sopenharmony_ci 531e5c31af7Sopenharmony_cibool Program::hasStage (glu::ShaderType stage) const 532e5c31af7Sopenharmony_ci{ 533e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)m_shaders.size(); ++shaderNdx) 534e5c31af7Sopenharmony_ci { 535e5c31af7Sopenharmony_ci if (m_shaders[shaderNdx]->getType() == stage) 536e5c31af7Sopenharmony_ci return true; 537e5c31af7Sopenharmony_ci } 538e5c31af7Sopenharmony_ci return false; 539e5c31af7Sopenharmony_ci} 540e5c31af7Sopenharmony_ci 541e5c31af7Sopenharmony_civoid Program::addTransformFeedbackVarying (const std::string& varName) 542e5c31af7Sopenharmony_ci{ 543e5c31af7Sopenharmony_ci m_xfbVaryings.push_back(varName); 544e5c31af7Sopenharmony_ci} 545e5c31af7Sopenharmony_ci 546e5c31af7Sopenharmony_ciconst std::vector<std::string>& Program::getTransformFeedbackVaryings (void) const 547e5c31af7Sopenharmony_ci{ 548e5c31af7Sopenharmony_ci return m_xfbVaryings; 549e5c31af7Sopenharmony_ci} 550e5c31af7Sopenharmony_ci 551e5c31af7Sopenharmony_civoid Program::setTransformFeedbackMode (deUint32 mode) 552e5c31af7Sopenharmony_ci{ 553e5c31af7Sopenharmony_ci m_xfbMode = mode; 554e5c31af7Sopenharmony_ci} 555e5c31af7Sopenharmony_ci 556e5c31af7Sopenharmony_cideUint32 Program::getTransformFeedbackMode (void) const 557e5c31af7Sopenharmony_ci{ 558e5c31af7Sopenharmony_ci return m_xfbMode; 559e5c31af7Sopenharmony_ci} 560e5c31af7Sopenharmony_ci 561e5c31af7Sopenharmony_cideUint32 Program::getGeometryNumOutputVertices (void) const 562e5c31af7Sopenharmony_ci{ 563e5c31af7Sopenharmony_ci return m_geoNumOutputVertices; 564e5c31af7Sopenharmony_ci} 565e5c31af7Sopenharmony_ci 566e5c31af7Sopenharmony_civoid Program::setGeometryNumOutputVertices (deUint32 vertices) 567e5c31af7Sopenharmony_ci{ 568e5c31af7Sopenharmony_ci m_geoNumOutputVertices = vertices; 569e5c31af7Sopenharmony_ci} 570e5c31af7Sopenharmony_ci 571e5c31af7Sopenharmony_cideUint32 Program::getTessellationNumOutputPatchVertices (void) const 572e5c31af7Sopenharmony_ci{ 573e5c31af7Sopenharmony_ci return m_tessNumOutputVertices; 574e5c31af7Sopenharmony_ci} 575e5c31af7Sopenharmony_ci 576e5c31af7Sopenharmony_civoid Program::setTessellationNumOutputPatchVertices (deUint32 vertices) 577e5c31af7Sopenharmony_ci{ 578e5c31af7Sopenharmony_ci m_tessNumOutputVertices = vertices; 579e5c31af7Sopenharmony_ci} 580e5c31af7Sopenharmony_ci 581e5c31af7Sopenharmony_cibool Program::isValid (void) const 582e5c31af7Sopenharmony_ci{ 583e5c31af7Sopenharmony_ci const bool isOpenGLES = (m_shaders.empty()) ? (false) : (glu::glslVersionIsES(m_shaders[0]->getVersion())); 584e5c31af7Sopenharmony_ci bool computePresent = false; 585e5c31af7Sopenharmony_ci bool vertexPresent = false; 586e5c31af7Sopenharmony_ci bool fragmentPresent = false; 587e5c31af7Sopenharmony_ci bool tessControlPresent = false; 588e5c31af7Sopenharmony_ci bool tessEvalPresent = false; 589e5c31af7Sopenharmony_ci bool geometryPresent = false; 590e5c31af7Sopenharmony_ci 591e5c31af7Sopenharmony_ci if (m_shaders.empty()) 592e5c31af7Sopenharmony_ci return false; 593e5c31af7Sopenharmony_ci 594e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx) 595e5c31af7Sopenharmony_ci if (!m_shaders[ndx]->isValid()) 596e5c31af7Sopenharmony_ci return false; 597e5c31af7Sopenharmony_ci 598e5c31af7Sopenharmony_ci // same version 599e5c31af7Sopenharmony_ci for (int ndx = 1; ndx < (int)m_shaders.size(); ++ndx) 600e5c31af7Sopenharmony_ci if (m_shaders[0]->getVersion() != m_shaders[ndx]->getVersion()) 601e5c31af7Sopenharmony_ci return false; 602e5c31af7Sopenharmony_ci 603e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)m_shaders.size(); ++ndx) 604e5c31af7Sopenharmony_ci { 605e5c31af7Sopenharmony_ci switch (m_shaders[ndx]->getType()) 606e5c31af7Sopenharmony_ci { 607e5c31af7Sopenharmony_ci case glu::SHADERTYPE_COMPUTE: computePresent = true; break; 608e5c31af7Sopenharmony_ci case glu::SHADERTYPE_VERTEX: vertexPresent = true; break; 609e5c31af7Sopenharmony_ci case glu::SHADERTYPE_FRAGMENT: fragmentPresent = true; break; 610e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_CONTROL: tessControlPresent = true; break; 611e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_EVALUATION: tessEvalPresent = true; break; 612e5c31af7Sopenharmony_ci case glu::SHADERTYPE_GEOMETRY: geometryPresent = true; break; 613e5c31af7Sopenharmony_ci default: 614e5c31af7Sopenharmony_ci DE_ASSERT(false); 615e5c31af7Sopenharmony_ci break; 616e5c31af7Sopenharmony_ci } 617e5c31af7Sopenharmony_ci } 618e5c31af7Sopenharmony_ci // compute present -> no other stages present 619e5c31af7Sopenharmony_ci { 620e5c31af7Sopenharmony_ci const bool nonComputePresent = vertexPresent || fragmentPresent || tessControlPresent || tessEvalPresent || geometryPresent; 621e5c31af7Sopenharmony_ci if (computePresent && nonComputePresent) 622e5c31af7Sopenharmony_ci return false; 623e5c31af7Sopenharmony_ci } 624e5c31af7Sopenharmony_ci 625e5c31af7Sopenharmony_ci // must contain both vertex and fragment shaders 626e5c31af7Sopenharmony_ci if (!computePresent && !m_separable) 627e5c31af7Sopenharmony_ci { 628e5c31af7Sopenharmony_ci if (!vertexPresent || !fragmentPresent) 629e5c31af7Sopenharmony_ci return false; 630e5c31af7Sopenharmony_ci } 631e5c31af7Sopenharmony_ci 632e5c31af7Sopenharmony_ci // tess.Eval present <=> tess.Control present 633e5c31af7Sopenharmony_ci if (!m_separable) 634e5c31af7Sopenharmony_ci { 635e5c31af7Sopenharmony_ci if (tessEvalPresent != tessControlPresent) 636e5c31af7Sopenharmony_ci return false; 637e5c31af7Sopenharmony_ci } 638e5c31af7Sopenharmony_ci 639e5c31af7Sopenharmony_ci if ((m_tessNumOutputVertices != 0) != (tessControlPresent || tessEvalPresent)) 640e5c31af7Sopenharmony_ci return false; 641e5c31af7Sopenharmony_ci 642e5c31af7Sopenharmony_ci if ((m_geoNumOutputVertices != 0) != geometryPresent) 643e5c31af7Sopenharmony_ci return false; 644e5c31af7Sopenharmony_ci 645e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)m_xfbVaryings.size(); ++ndx) 646e5c31af7Sopenharmony_ci { 647e5c31af7Sopenharmony_ci // user-defined 648e5c31af7Sopenharmony_ci if (!de::beginsWith(m_xfbVaryings[ndx], "gl_")) 649e5c31af7Sopenharmony_ci { 650e5c31af7Sopenharmony_ci std::vector<ProgramInterfaceDefinition::VariablePathComponent> path; 651e5c31af7Sopenharmony_ci if (!findProgramVariablePathByPathName(path, this, m_xfbVaryings[ndx], VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(this), glu::STORAGE_OUT))) 652e5c31af7Sopenharmony_ci return false; 653e5c31af7Sopenharmony_ci if (!path.back().isVariableType()) 654e5c31af7Sopenharmony_ci return false; 655e5c31af7Sopenharmony_ci 656e5c31af7Sopenharmony_ci // Khronos bug #12787 disallowed capturing whole structs in OpenGL ES. 657e5c31af7Sopenharmony_ci if (path.back().getVariableType()->isStructType() && isOpenGLES) 658e5c31af7Sopenharmony_ci return false; 659e5c31af7Sopenharmony_ci } 660e5c31af7Sopenharmony_ci } 661e5c31af7Sopenharmony_ci 662e5c31af7Sopenharmony_ci return true; 663e5c31af7Sopenharmony_ci} 664e5c31af7Sopenharmony_ci 665e5c31af7Sopenharmony_ci} // ProgramInterfaceDefinition 666e5c31af7Sopenharmony_ci} // Functional 667e5c31af7Sopenharmony_ci} // gles31 668e5c31af7Sopenharmony_ci} // deqp 669