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 utilities 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "es31fProgramInterfaceDefinitionUtil.hpp" 25e5c31af7Sopenharmony_ci#include "es31fProgramInterfaceDefinition.hpp" 26e5c31af7Sopenharmony_ci#include "gluVarType.hpp" 27e5c31af7Sopenharmony_ci#include "gluVarTypeUtil.hpp" 28e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp" 29e5c31af7Sopenharmony_ci#include "deString.h" 30e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 31e5c31af7Sopenharmony_ci#include "glwEnums.hpp" 32e5c31af7Sopenharmony_ci 33e5c31af7Sopenharmony_ci#include <set> 34e5c31af7Sopenharmony_ci#include <map> 35e5c31af7Sopenharmony_ci#include <sstream> 36e5c31af7Sopenharmony_ci#include <vector> 37e5c31af7Sopenharmony_ci#include <algorithm> 38e5c31af7Sopenharmony_ci 39e5c31af7Sopenharmony_cinamespace deqp 40e5c31af7Sopenharmony_ci{ 41e5c31af7Sopenharmony_cinamespace gles31 42e5c31af7Sopenharmony_ci{ 43e5c31af7Sopenharmony_cinamespace Functional 44e5c31af7Sopenharmony_ci{ 45e5c31af7Sopenharmony_cinamespace ProgramInterfaceDefinition 46e5c31af7Sopenharmony_ci{ 47e5c31af7Sopenharmony_ci 48e5c31af7Sopenharmony_ciVariableSearchFilter::VariableSearchFilter (void) 49e5c31af7Sopenharmony_ci : m_shaderTypeBits (0xFFFFFFFFul) 50e5c31af7Sopenharmony_ci , m_storageBits (0xFFFFFFFFul) 51e5c31af7Sopenharmony_ci{ 52e5c31af7Sopenharmony_ci} 53e5c31af7Sopenharmony_ci 54e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::createShaderTypeFilter (glu::ShaderType type) 55e5c31af7Sopenharmony_ci{ 56e5c31af7Sopenharmony_ci DE_ASSERT(type < glu::SHADERTYPE_LAST); 57e5c31af7Sopenharmony_ci 58e5c31af7Sopenharmony_ci VariableSearchFilter filter; 59e5c31af7Sopenharmony_ci filter.m_shaderTypeBits = (1u << type); 60e5c31af7Sopenharmony_ci return filter; 61e5c31af7Sopenharmony_ci} 62e5c31af7Sopenharmony_ci 63e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::createStorageFilter (glu::Storage storage) 64e5c31af7Sopenharmony_ci{ 65e5c31af7Sopenharmony_ci DE_ASSERT(storage < glu::STORAGE_LAST); 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ci VariableSearchFilter filter; 68e5c31af7Sopenharmony_ci filter.m_storageBits = (1u << storage); 69e5c31af7Sopenharmony_ci return filter; 70e5c31af7Sopenharmony_ci} 71e5c31af7Sopenharmony_ci 72e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::createShaderTypeStorageFilter (glu::ShaderType type, glu::Storage storage) 73e5c31af7Sopenharmony_ci{ 74e5c31af7Sopenharmony_ci return logicalAnd(createShaderTypeFilter(type), createStorageFilter(storage)); 75e5c31af7Sopenharmony_ci} 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::logicalOr (const VariableSearchFilter& a, const VariableSearchFilter& b) 78e5c31af7Sopenharmony_ci{ 79e5c31af7Sopenharmony_ci VariableSearchFilter filter; 80e5c31af7Sopenharmony_ci filter.m_shaderTypeBits = a.m_shaderTypeBits | b.m_shaderTypeBits; 81e5c31af7Sopenharmony_ci filter.m_storageBits = a.m_storageBits | b.m_storageBits; 82e5c31af7Sopenharmony_ci return filter; 83e5c31af7Sopenharmony_ci} 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::logicalAnd (const VariableSearchFilter& a, const VariableSearchFilter& b) 86e5c31af7Sopenharmony_ci{ 87e5c31af7Sopenharmony_ci VariableSearchFilter filter; 88e5c31af7Sopenharmony_ci filter.m_shaderTypeBits = a.m_shaderTypeBits & b.m_shaderTypeBits; 89e5c31af7Sopenharmony_ci filter.m_storageBits = a.m_storageBits & b.m_storageBits; 90e5c31af7Sopenharmony_ci return filter; 91e5c31af7Sopenharmony_ci} 92e5c31af7Sopenharmony_ci 93e5c31af7Sopenharmony_cibool VariableSearchFilter::matchesFilter (const ProgramInterfaceDefinition::Shader* shader) const 94e5c31af7Sopenharmony_ci{ 95e5c31af7Sopenharmony_ci DE_ASSERT(shader->getType() < glu::SHADERTYPE_LAST); 96e5c31af7Sopenharmony_ci return (m_shaderTypeBits & (1u << shader->getType())) != 0; 97e5c31af7Sopenharmony_ci} 98e5c31af7Sopenharmony_ci 99e5c31af7Sopenharmony_cibool VariableSearchFilter::matchesFilter (const glu::VariableDeclaration& variable) const 100e5c31af7Sopenharmony_ci{ 101e5c31af7Sopenharmony_ci DE_ASSERT(variable.storage < glu::STORAGE_LAST); 102e5c31af7Sopenharmony_ci return (m_storageBits & (1u << variable.storage)) != 0; 103e5c31af7Sopenharmony_ci} 104e5c31af7Sopenharmony_ci 105e5c31af7Sopenharmony_cibool VariableSearchFilter::matchesFilter (const glu::InterfaceBlock& block) const 106e5c31af7Sopenharmony_ci{ 107e5c31af7Sopenharmony_ci DE_ASSERT(block.storage < glu::STORAGE_LAST); 108e5c31af7Sopenharmony_ci return (m_storageBits & (1u << block.storage)) != 0; 109e5c31af7Sopenharmony_ci} 110e5c31af7Sopenharmony_ci 111e5c31af7Sopenharmony_ci} // ProgramInterfaceDefinition 112e5c31af7Sopenharmony_ci 113e5c31af7Sopenharmony_cistatic bool incrementMultiDimensionIndex (std::vector<int>& index, const std::vector<int>& dimensions) 114e5c31af7Sopenharmony_ci{ 115e5c31af7Sopenharmony_ci int incrementDimensionNdx = (int)(index.size() - 1); 116e5c31af7Sopenharmony_ci 117e5c31af7Sopenharmony_ci while (incrementDimensionNdx >= 0) 118e5c31af7Sopenharmony_ci { 119e5c31af7Sopenharmony_ci if (++index[incrementDimensionNdx] == dimensions[incrementDimensionNdx]) 120e5c31af7Sopenharmony_ci index[incrementDimensionNdx--] = 0; 121e5c31af7Sopenharmony_ci else 122e5c31af7Sopenharmony_ci break; 123e5c31af7Sopenharmony_ci } 124e5c31af7Sopenharmony_ci 125e5c31af7Sopenharmony_ci return (incrementDimensionNdx != -1); 126e5c31af7Sopenharmony_ci} 127e5c31af7Sopenharmony_ci 128e5c31af7Sopenharmony_cibool programContainsIOBlocks (const ProgramInterfaceDefinition::Program* program) 129e5c31af7Sopenharmony_ci{ 130e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 131e5c31af7Sopenharmony_ci { 132e5c31af7Sopenharmony_ci if (shaderContainsIOBlocks(program->getShaders()[shaderNdx])) 133e5c31af7Sopenharmony_ci return true; 134e5c31af7Sopenharmony_ci } 135e5c31af7Sopenharmony_ci 136e5c31af7Sopenharmony_ci return false; 137e5c31af7Sopenharmony_ci} 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_cibool shaderContainsIOBlocks (const ProgramInterfaceDefinition::Shader* shader) 140e5c31af7Sopenharmony_ci{ 141e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx) 142e5c31af7Sopenharmony_ci { 143e5c31af7Sopenharmony_ci const glu::Storage storage = shader->getDefaultBlock().interfaceBlocks[ndx].storage; 144e5c31af7Sopenharmony_ci if (storage == glu::STORAGE_IN || 145e5c31af7Sopenharmony_ci storage == glu::STORAGE_OUT || 146e5c31af7Sopenharmony_ci storage == glu::STORAGE_PATCH_IN || 147e5c31af7Sopenharmony_ci storage == glu::STORAGE_PATCH_OUT) 148e5c31af7Sopenharmony_ci { 149e5c31af7Sopenharmony_ci return true; 150e5c31af7Sopenharmony_ci } 151e5c31af7Sopenharmony_ci } 152e5c31af7Sopenharmony_ci return false; 153e5c31af7Sopenharmony_ci} 154e5c31af7Sopenharmony_ci 155e5c31af7Sopenharmony_ciglu::ShaderType getProgramTransformFeedbackStage (const ProgramInterfaceDefinition::Program* program) 156e5c31af7Sopenharmony_ci{ 157e5c31af7Sopenharmony_ci if (program->hasStage(glu::SHADERTYPE_GEOMETRY)) 158e5c31af7Sopenharmony_ci return glu::SHADERTYPE_GEOMETRY; 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ci if (program->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION)) 161e5c31af7Sopenharmony_ci return glu::SHADERTYPE_TESSELLATION_EVALUATION; 162e5c31af7Sopenharmony_ci 163e5c31af7Sopenharmony_ci if (program->hasStage(glu::SHADERTYPE_VERTEX)) 164e5c31af7Sopenharmony_ci return glu::SHADERTYPE_VERTEX; 165e5c31af7Sopenharmony_ci 166e5c31af7Sopenharmony_ci DE_ASSERT(false); 167e5c31af7Sopenharmony_ci return glu::SHADERTYPE_LAST; 168e5c31af7Sopenharmony_ci} 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_civoid generateVariableTypeResourceNames (std::vector<std::string>& resources, const std::string& name, const glu::VarType& type, deUint32 resourceNameGenerationFlags) 171e5c31af7Sopenharmony_ci{ 172e5c31af7Sopenharmony_ci DE_ASSERT((resourceNameGenerationFlags & (~RESOURCE_NAME_GENERATION_FLAG_MASK)) == 0); 173e5c31af7Sopenharmony_ci 174e5c31af7Sopenharmony_ci // remove top-level flag from children 175e5c31af7Sopenharmony_ci const deUint32 childFlags = resourceNameGenerationFlags & ~((deUint32)RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE); 176e5c31af7Sopenharmony_ci 177e5c31af7Sopenharmony_ci if (type.isBasicType()) 178e5c31af7Sopenharmony_ci resources.push_back(name); 179e5c31af7Sopenharmony_ci else if (type.isStructType()) 180e5c31af7Sopenharmony_ci { 181e5c31af7Sopenharmony_ci const glu::StructType* structType = type.getStructPtr(); 182e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < structType->getNumMembers(); ++ndx) 183e5c31af7Sopenharmony_ci generateVariableTypeResourceNames(resources, name + "." + structType->getMember(ndx).getName(), structType->getMember(ndx).getType(), childFlags); 184e5c31af7Sopenharmony_ci } 185e5c31af7Sopenharmony_ci else if (type.isArrayType()) 186e5c31af7Sopenharmony_ci { 187e5c31af7Sopenharmony_ci // Bottom-level arrays of basic types of a transform feedback variable will produce only the first 188e5c31af7Sopenharmony_ci // element but without the trailing "[0]" 189e5c31af7Sopenharmony_ci if (type.getElementType().isBasicType() && 190e5c31af7Sopenharmony_ci (resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE) != 0) 191e5c31af7Sopenharmony_ci { 192e5c31af7Sopenharmony_ci resources.push_back(name); 193e5c31af7Sopenharmony_ci } 194e5c31af7Sopenharmony_ci // Bottom-level arrays of basic types and SSBO top-level arrays of any type procude only first element 195e5c31af7Sopenharmony_ci else if (type.getElementType().isBasicType() || 196e5c31af7Sopenharmony_ci (resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) != 0) 197e5c31af7Sopenharmony_ci { 198e5c31af7Sopenharmony_ci generateVariableTypeResourceNames(resources, name + "[0]", type.getElementType(), childFlags); 199e5c31af7Sopenharmony_ci } 200e5c31af7Sopenharmony_ci // Other arrays of aggregate types are expanded 201e5c31af7Sopenharmony_ci else 202e5c31af7Sopenharmony_ci { 203e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < type.getArraySize(); ++ndx) 204e5c31af7Sopenharmony_ci generateVariableTypeResourceNames(resources, name + "[" + de::toString(ndx) + "]", type.getElementType(), childFlags); 205e5c31af7Sopenharmony_ci } 206e5c31af7Sopenharmony_ci } 207e5c31af7Sopenharmony_ci else 208e5c31af7Sopenharmony_ci DE_ASSERT(false); 209e5c31af7Sopenharmony_ci} 210e5c31af7Sopenharmony_ci 211e5c31af7Sopenharmony_ci// Program source generation 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_cinamespace 214e5c31af7Sopenharmony_ci{ 215e5c31af7Sopenharmony_ci 216e5c31af7Sopenharmony_ciusing ProgramInterfaceDefinition::VariablePathComponent; 217e5c31af7Sopenharmony_ciusing ProgramInterfaceDefinition::VariableSearchFilter; 218e5c31af7Sopenharmony_ci 219e5c31af7Sopenharmony_cistatic std::string getShaderExtensionDeclarations (const ProgramInterfaceDefinition::Shader* shader) 220e5c31af7Sopenharmony_ci{ 221e5c31af7Sopenharmony_ci if (shader->getVersion() > glu::GLSL_VERSION_440) 222e5c31af7Sopenharmony_ci return ""; 223e5c31af7Sopenharmony_ci 224e5c31af7Sopenharmony_ci std::vector<std::string> extensions; 225e5c31af7Sopenharmony_ci std::ostringstream buf; 226e5c31af7Sopenharmony_ci 227e5c31af7Sopenharmony_ci if (shader->getType() == glu::SHADERTYPE_GEOMETRY) 228e5c31af7Sopenharmony_ci { 229e5c31af7Sopenharmony_ci extensions.push_back("GL_EXT_geometry_shader"); 230e5c31af7Sopenharmony_ci } 231e5c31af7Sopenharmony_ci else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL || 232e5c31af7Sopenharmony_ci shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION) 233e5c31af7Sopenharmony_ci { 234e5c31af7Sopenharmony_ci extensions.push_back("GL_EXT_tessellation_shader"); 235e5c31af7Sopenharmony_ci } 236e5c31af7Sopenharmony_ci 237e5c31af7Sopenharmony_ci if (shaderContainsIOBlocks(shader)) 238e5c31af7Sopenharmony_ci extensions.push_back("GL_EXT_shader_io_blocks"); 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)extensions.size(); ++ndx) 241e5c31af7Sopenharmony_ci buf << "#extension " << extensions[ndx] << " : require\n"; 242e5c31af7Sopenharmony_ci return buf.str(); 243e5c31af7Sopenharmony_ci} 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_cistatic std::string getShaderTypeDeclarations (const ProgramInterfaceDefinition::Program* program, const ProgramInterfaceDefinition::Shader* shader) 246e5c31af7Sopenharmony_ci{ 247e5c31af7Sopenharmony_ci glu::ShaderType type = shader->getType(); 248e5c31af7Sopenharmony_ci auto isCoreGL = (shader->getVersion() > glu::GLSL_VERSION_440); 249e5c31af7Sopenharmony_ci 250e5c31af7Sopenharmony_ci switch (type) 251e5c31af7Sopenharmony_ci { 252e5c31af7Sopenharmony_ci case glu::SHADERTYPE_VERTEX: 253e5c31af7Sopenharmony_ci if (isCoreGL) 254e5c31af7Sopenharmony_ci return "out gl_PerVertex { vec4 gl_Position; };\n"; 255e5c31af7Sopenharmony_ci return ""; 256e5c31af7Sopenharmony_ci 257e5c31af7Sopenharmony_ci case glu::SHADERTYPE_FRAGMENT: 258e5c31af7Sopenharmony_ci return ""; 259e5c31af7Sopenharmony_ci 260e5c31af7Sopenharmony_ci case glu::SHADERTYPE_GEOMETRY: 261e5c31af7Sopenharmony_ci { 262e5c31af7Sopenharmony_ci std::ostringstream buf; 263e5c31af7Sopenharmony_ci buf << "layout(points) in;\n" 264e5c31af7Sopenharmony_ci "layout(points, max_vertices=" << program->getGeometryNumOutputVertices() << ") out;\n"; 265e5c31af7Sopenharmony_ci if (isCoreGL) 266e5c31af7Sopenharmony_ci { 267e5c31af7Sopenharmony_ci buf << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n" 268e5c31af7Sopenharmony_ci "out gl_PerVertex { vec4 gl_Position; };\n"; 269e5c31af7Sopenharmony_ci } 270e5c31af7Sopenharmony_ci return buf.str(); 271e5c31af7Sopenharmony_ci } 272e5c31af7Sopenharmony_ci 273e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_CONTROL: 274e5c31af7Sopenharmony_ci { 275e5c31af7Sopenharmony_ci std::ostringstream buf; 276e5c31af7Sopenharmony_ci buf << "layout(vertices=" << program->getTessellationNumOutputPatchVertices() << ") out;\n"; 277e5c31af7Sopenharmony_ci if (isCoreGL) 278e5c31af7Sopenharmony_ci { 279e5c31af7Sopenharmony_ci buf << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n" 280e5c31af7Sopenharmony_ci "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"; 281e5c31af7Sopenharmony_ci } 282e5c31af7Sopenharmony_ci return buf.str(); 283e5c31af7Sopenharmony_ci } 284e5c31af7Sopenharmony_ci 285e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_EVALUATION: 286e5c31af7Sopenharmony_ci { 287e5c31af7Sopenharmony_ci std::ostringstream buf; 288e5c31af7Sopenharmony_ci if (isCoreGL) 289e5c31af7Sopenharmony_ci { 290e5c31af7Sopenharmony_ci buf << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n" 291e5c31af7Sopenharmony_ci "out gl_PerVertex { vec4 gl_Position; };\n"; 292e5c31af7Sopenharmony_ci } 293e5c31af7Sopenharmony_ci buf << "layout(triangles, point_mode) in;\n"; 294e5c31af7Sopenharmony_ci return buf.str(); 295e5c31af7Sopenharmony_ci } 296e5c31af7Sopenharmony_ci 297e5c31af7Sopenharmony_ci case glu::SHADERTYPE_COMPUTE: 298e5c31af7Sopenharmony_ci return "layout(local_size_x=1) in;\n"; 299e5c31af7Sopenharmony_ci 300e5c31af7Sopenharmony_ci default: 301e5c31af7Sopenharmony_ci DE_ASSERT(false); 302e5c31af7Sopenharmony_ci return ""; 303e5c31af7Sopenharmony_ci } 304e5c31af7Sopenharmony_ci} 305e5c31af7Sopenharmony_ci 306e5c31af7Sopenharmony_ciclass StructNameEqualPredicate 307e5c31af7Sopenharmony_ci{ 308e5c31af7Sopenharmony_cipublic: 309e5c31af7Sopenharmony_ci StructNameEqualPredicate (const char* name) : m_name(name) { } 310e5c31af7Sopenharmony_ci bool operator() (const glu::StructType* type) { return type->hasTypeName() && (deStringEqual(m_name, type->getTypeName()) == DE_TRUE); } 311e5c31af7Sopenharmony_ciprivate: 312e5c31af7Sopenharmony_ci const char* m_name; 313e5c31af7Sopenharmony_ci}; 314e5c31af7Sopenharmony_ci 315e5c31af7Sopenharmony_cistatic void collectNamedStructureDefinitions (std::vector<const glu::StructType*>& dst, const glu::VarType& type) 316e5c31af7Sopenharmony_ci{ 317e5c31af7Sopenharmony_ci if (type.isBasicType()) 318e5c31af7Sopenharmony_ci return; 319e5c31af7Sopenharmony_ci else if (type.isArrayType()) 320e5c31af7Sopenharmony_ci return collectNamedStructureDefinitions(dst, type.getElementType()); 321e5c31af7Sopenharmony_ci else if (type.isStructType()) 322e5c31af7Sopenharmony_ci { 323e5c31af7Sopenharmony_ci if (type.getStructPtr()->hasTypeName()) 324e5c31af7Sopenharmony_ci { 325e5c31af7Sopenharmony_ci // must be unique (may share the the same struct) 326e5c31af7Sopenharmony_ci std::vector<const glu::StructType*>::iterator where = std::find_if(dst.begin(), dst.end(), StructNameEqualPredicate(type.getStructPtr()->getTypeName())); 327e5c31af7Sopenharmony_ci if (where != dst.end()) 328e5c31af7Sopenharmony_ci { 329e5c31af7Sopenharmony_ci DE_ASSERT(**where == *type.getStructPtr()); 330e5c31af7Sopenharmony_ci 331e5c31af7Sopenharmony_ci // identical type has been added already, types of members must be added too 332e5c31af7Sopenharmony_ci return; 333e5c31af7Sopenharmony_ci } 334e5c31af7Sopenharmony_ci } 335e5c31af7Sopenharmony_ci 336e5c31af7Sopenharmony_ci // Add types of members first 337e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx) 338e5c31af7Sopenharmony_ci collectNamedStructureDefinitions(dst, type.getStructPtr()->getMember(ndx).getType()); 339e5c31af7Sopenharmony_ci 340e5c31af7Sopenharmony_ci dst.push_back(type.getStructPtr()); 341e5c31af7Sopenharmony_ci } 342e5c31af7Sopenharmony_ci else 343e5c31af7Sopenharmony_ci DE_ASSERT(false); 344e5c31af7Sopenharmony_ci} 345e5c31af7Sopenharmony_ci 346e5c31af7Sopenharmony_cistatic void writeStructureDefinitions (std::ostringstream& buf, const ProgramInterfaceDefinition::DefaultBlock& defaultBlock) 347e5c31af7Sopenharmony_ci{ 348e5c31af7Sopenharmony_ci std::vector<const glu::StructType*> namedStructs; 349e5c31af7Sopenharmony_ci 350e5c31af7Sopenharmony_ci // Collect all structs in post order 351e5c31af7Sopenharmony_ci 352e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)defaultBlock.variables.size(); ++ndx) 353e5c31af7Sopenharmony_ci collectNamedStructureDefinitions(namedStructs, defaultBlock.variables[ndx].varType); 354e5c31af7Sopenharmony_ci 355e5c31af7Sopenharmony_ci for (int blockNdx = 0; blockNdx < (int)defaultBlock.interfaceBlocks.size(); ++blockNdx) 356e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)defaultBlock.interfaceBlocks[blockNdx].variables.size(); ++ndx) 357e5c31af7Sopenharmony_ci collectNamedStructureDefinitions(namedStructs, defaultBlock.interfaceBlocks[blockNdx].variables[ndx].varType); 358e5c31af7Sopenharmony_ci 359e5c31af7Sopenharmony_ci // Write 360e5c31af7Sopenharmony_ci 361e5c31af7Sopenharmony_ci for (int structNdx = 0; structNdx < (int)namedStructs.size(); ++structNdx) 362e5c31af7Sopenharmony_ci { 363e5c31af7Sopenharmony_ci buf << "struct " << namedStructs[structNdx]->getTypeName() << "\n" 364e5c31af7Sopenharmony_ci "{\n"; 365e5c31af7Sopenharmony_ci 366e5c31af7Sopenharmony_ci for (int memberNdx = 0; memberNdx < namedStructs[structNdx]->getNumMembers(); ++memberNdx) 367e5c31af7Sopenharmony_ci buf << glu::indent(1) << glu::declare(namedStructs[structNdx]->getMember(memberNdx).getType(), namedStructs[structNdx]->getMember(memberNdx).getName(), 1) << ";\n"; 368e5c31af7Sopenharmony_ci 369e5c31af7Sopenharmony_ci buf << "};\n"; 370e5c31af7Sopenharmony_ci } 371e5c31af7Sopenharmony_ci 372e5c31af7Sopenharmony_ci if (!namedStructs.empty()) 373e5c31af7Sopenharmony_ci buf << "\n"; 374e5c31af7Sopenharmony_ci} 375e5c31af7Sopenharmony_ci 376e5c31af7Sopenharmony_cistatic void writeInterfaceBlock (std::ostringstream& buf, const glu::InterfaceBlock& interfaceBlock) 377e5c31af7Sopenharmony_ci{ 378e5c31af7Sopenharmony_ci buf << interfaceBlock.layout; 379e5c31af7Sopenharmony_ci 380e5c31af7Sopenharmony_ci if (interfaceBlock.layout != glu::Layout()) 381e5c31af7Sopenharmony_ci buf << " "; 382e5c31af7Sopenharmony_ci 383e5c31af7Sopenharmony_ci buf << glu::getStorageName(interfaceBlock.storage) << " " << interfaceBlock.interfaceName << "\n" 384e5c31af7Sopenharmony_ci << "{\n"; 385e5c31af7Sopenharmony_ci 386e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)interfaceBlock.variables.size(); ++ndx) 387e5c31af7Sopenharmony_ci buf << glu::indent(1) << interfaceBlock.variables[ndx] << ";\n"; 388e5c31af7Sopenharmony_ci 389e5c31af7Sopenharmony_ci buf << "}"; 390e5c31af7Sopenharmony_ci 391e5c31af7Sopenharmony_ci if (!interfaceBlock.instanceName.empty()) 392e5c31af7Sopenharmony_ci buf << " " << interfaceBlock.instanceName; 393e5c31af7Sopenharmony_ci 394e5c31af7Sopenharmony_ci for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx) 395e5c31af7Sopenharmony_ci buf << "[" << interfaceBlock.dimensions[dimensionNdx] << "]"; 396e5c31af7Sopenharmony_ci 397e5c31af7Sopenharmony_ci buf << ";\n\n"; 398e5c31af7Sopenharmony_ci} 399e5c31af7Sopenharmony_ci 400e5c31af7Sopenharmony_cistatic bool isReadableInterface (const glu::InterfaceBlock& interface) 401e5c31af7Sopenharmony_ci{ 402e5c31af7Sopenharmony_ci return interface.storage == glu::STORAGE_UNIFORM || 403e5c31af7Sopenharmony_ci interface.storage == glu::STORAGE_IN || 404e5c31af7Sopenharmony_ci interface.storage == glu::STORAGE_PATCH_IN || 405e5c31af7Sopenharmony_ci (interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_WRITEONLY_BIT) == 0); 406e5c31af7Sopenharmony_ci} 407e5c31af7Sopenharmony_ci 408e5c31af7Sopenharmony_cistatic bool isWritableInterface (const glu::InterfaceBlock& interface) 409e5c31af7Sopenharmony_ci{ 410e5c31af7Sopenharmony_ci return interface.storage == glu::STORAGE_OUT || 411e5c31af7Sopenharmony_ci interface.storage == glu::STORAGE_PATCH_OUT || 412e5c31af7Sopenharmony_ci (interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_READONLY_BIT) == 0); 413e5c31af7Sopenharmony_ci} 414e5c31af7Sopenharmony_ci 415e5c31af7Sopenharmony_ci 416e5c31af7Sopenharmony_cistatic void writeVariableReadAccumulateExpression (std::ostringstream& buf, 417e5c31af7Sopenharmony_ci const std::string& accumulatorName, 418e5c31af7Sopenharmony_ci const std::string& name, 419e5c31af7Sopenharmony_ci glu::ShaderType shaderType, 420e5c31af7Sopenharmony_ci glu::Storage storage, 421e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Program* program, 422e5c31af7Sopenharmony_ci const glu::VarType& varType) 423e5c31af7Sopenharmony_ci{ 424e5c31af7Sopenharmony_ci if (varType.isBasicType()) 425e5c31af7Sopenharmony_ci { 426e5c31af7Sopenharmony_ci buf << "\t" << accumulatorName << " += "; 427e5c31af7Sopenharmony_ci 428e5c31af7Sopenharmony_ci if (glu::isDataTypeScalar(varType.getBasicType())) 429e5c31af7Sopenharmony_ci buf << "vec4(float(" << name << "))"; 430e5c31af7Sopenharmony_ci else if (glu::isDataTypeVector(varType.getBasicType())) 431e5c31af7Sopenharmony_ci buf << "vec4(" << name << ".xyxy)"; 432e5c31af7Sopenharmony_ci else if (glu::isDataTypeMatrix(varType.getBasicType())) 433e5c31af7Sopenharmony_ci buf << "vec4(float(" << name << "[0][0]))"; 434e5c31af7Sopenharmony_ci else if (glu::isDataTypeSamplerMultisample(varType.getBasicType())) 435e5c31af7Sopenharmony_ci buf << "vec4(float(textureSize(" << name << ").x))"; 436e5c31af7Sopenharmony_ci else if (glu::isDataTypeSampler(varType.getBasicType())) 437e5c31af7Sopenharmony_ci buf << "vec4(float(textureSize(" << name << ", 0).x))"; 438e5c31af7Sopenharmony_ci else if (glu::isDataTypeImage(varType.getBasicType())) 439e5c31af7Sopenharmony_ci buf << "vec4(float(imageSize(" << name << ").x))"; 440e5c31af7Sopenharmony_ci else if (varType.getBasicType() == glu::TYPE_UINT_ATOMIC_COUNTER) 441e5c31af7Sopenharmony_ci buf << "vec4(float(atomicCounterIncrement(" << name << ")))"; 442e5c31af7Sopenharmony_ci else 443e5c31af7Sopenharmony_ci DE_ASSERT(false); 444e5c31af7Sopenharmony_ci 445e5c31af7Sopenharmony_ci buf << ";\n"; 446e5c31af7Sopenharmony_ci } 447e5c31af7Sopenharmony_ci else if (varType.isStructType()) 448e5c31af7Sopenharmony_ci { 449e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx) 450e5c31af7Sopenharmony_ci writeVariableReadAccumulateExpression(buf, 451e5c31af7Sopenharmony_ci accumulatorName, 452e5c31af7Sopenharmony_ci name + "." + varType.getStructPtr()->getMember(ndx).getName(), 453e5c31af7Sopenharmony_ci shaderType, 454e5c31af7Sopenharmony_ci storage, 455e5c31af7Sopenharmony_ci program, 456e5c31af7Sopenharmony_ci varType.getStructPtr()->getMember(ndx).getType()); 457e5c31af7Sopenharmony_ci } 458e5c31af7Sopenharmony_ci else if (varType.isArrayType()) 459e5c31af7Sopenharmony_ci { 460e5c31af7Sopenharmony_ci if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY) 461e5c31af7Sopenharmony_ci { 462e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < varType.getArraySize(); ++ndx) 463e5c31af7Sopenharmony_ci writeVariableReadAccumulateExpression(buf, 464e5c31af7Sopenharmony_ci accumulatorName, 465e5c31af7Sopenharmony_ci name + "[" + de::toString(ndx) + "]", 466e5c31af7Sopenharmony_ci shaderType, 467e5c31af7Sopenharmony_ci storage, 468e5c31af7Sopenharmony_ci program, 469e5c31af7Sopenharmony_ci varType.getElementType()); 470e5c31af7Sopenharmony_ci } 471e5c31af7Sopenharmony_ci else if (storage == glu::STORAGE_BUFFER) 472e5c31af7Sopenharmony_ci { 473e5c31af7Sopenharmony_ci // run-time sized array, read arbitrary 474e5c31af7Sopenharmony_ci writeVariableReadAccumulateExpression(buf, 475e5c31af7Sopenharmony_ci accumulatorName, 476e5c31af7Sopenharmony_ci name + "[8]", 477e5c31af7Sopenharmony_ci shaderType, 478e5c31af7Sopenharmony_ci storage, 479e5c31af7Sopenharmony_ci program, 480e5c31af7Sopenharmony_ci varType.getElementType()); 481e5c31af7Sopenharmony_ci } 482e5c31af7Sopenharmony_ci else 483e5c31af7Sopenharmony_ci { 484e5c31af7Sopenharmony_ci DE_ASSERT(storage == glu::STORAGE_IN); 485e5c31af7Sopenharmony_ci 486e5c31af7Sopenharmony_ci if (shaderType == glu::SHADERTYPE_GEOMETRY) 487e5c31af7Sopenharmony_ci { 488e5c31af7Sopenharmony_ci // implicit sized geometry input array, size = primitive size. Just reading first is enough 489e5c31af7Sopenharmony_ci writeVariableReadAccumulateExpression(buf, 490e5c31af7Sopenharmony_ci accumulatorName, 491e5c31af7Sopenharmony_ci name + "[0]", 492e5c31af7Sopenharmony_ci shaderType, 493e5c31af7Sopenharmony_ci storage, 494e5c31af7Sopenharmony_ci program, 495e5c31af7Sopenharmony_ci varType.getElementType()); 496e5c31af7Sopenharmony_ci } 497e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) 498e5c31af7Sopenharmony_ci { 499e5c31af7Sopenharmony_ci // implicit sized tessellation input array, size = input patch max size. Just reading current is enough 500e5c31af7Sopenharmony_ci writeVariableReadAccumulateExpression(buf, 501e5c31af7Sopenharmony_ci accumulatorName, 502e5c31af7Sopenharmony_ci name + "[gl_InvocationID]", 503e5c31af7Sopenharmony_ci shaderType, 504e5c31af7Sopenharmony_ci storage, 505e5c31af7Sopenharmony_ci program, 506e5c31af7Sopenharmony_ci varType.getElementType()); 507e5c31af7Sopenharmony_ci } 508e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION) 509e5c31af7Sopenharmony_ci { 510e5c31af7Sopenharmony_ci // implicit sized tessellation input array, size = output patch max size. Read all to prevent optimizations 511e5c31af7Sopenharmony_ci DE_ASSERT(program->getTessellationNumOutputPatchVertices() > 0); 512e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)program->getTessellationNumOutputPatchVertices(); ++ndx) 513e5c31af7Sopenharmony_ci { 514e5c31af7Sopenharmony_ci writeVariableReadAccumulateExpression(buf, 515e5c31af7Sopenharmony_ci accumulatorName, 516e5c31af7Sopenharmony_ci name + "[" + de::toString(ndx) + "]", 517e5c31af7Sopenharmony_ci shaderType, 518e5c31af7Sopenharmony_ci storage, 519e5c31af7Sopenharmony_ci program, 520e5c31af7Sopenharmony_ci varType.getElementType()); 521e5c31af7Sopenharmony_ci } 522e5c31af7Sopenharmony_ci } 523e5c31af7Sopenharmony_ci else 524e5c31af7Sopenharmony_ci DE_ASSERT(false); 525e5c31af7Sopenharmony_ci } 526e5c31af7Sopenharmony_ci } 527e5c31af7Sopenharmony_ci else 528e5c31af7Sopenharmony_ci DE_ASSERT(false); 529e5c31af7Sopenharmony_ci} 530e5c31af7Sopenharmony_ci 531e5c31af7Sopenharmony_cistatic void writeInterfaceReadAccumulateExpression (std::ostringstream& buf, 532e5c31af7Sopenharmony_ci const std::string& accumulatorName, 533e5c31af7Sopenharmony_ci const glu::InterfaceBlock& block, 534e5c31af7Sopenharmony_ci glu::ShaderType shaderType, 535e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Program* program) 536e5c31af7Sopenharmony_ci{ 537e5c31af7Sopenharmony_ci if (block.dimensions.empty()) 538e5c31af7Sopenharmony_ci { 539e5c31af7Sopenharmony_ci const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + "."); 540e5c31af7Sopenharmony_ci 541e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx) 542e5c31af7Sopenharmony_ci { 543e5c31af7Sopenharmony_ci writeVariableReadAccumulateExpression(buf, 544e5c31af7Sopenharmony_ci accumulatorName, 545e5c31af7Sopenharmony_ci prefix + block.variables[ndx].name, 546e5c31af7Sopenharmony_ci shaderType, 547e5c31af7Sopenharmony_ci block.storage, 548e5c31af7Sopenharmony_ci program, 549e5c31af7Sopenharmony_ci block.variables[ndx].varType); 550e5c31af7Sopenharmony_ci } 551e5c31af7Sopenharmony_ci } 552e5c31af7Sopenharmony_ci else 553e5c31af7Sopenharmony_ci { 554e5c31af7Sopenharmony_ci std::vector<int> index(block.dimensions.size(), 0); 555e5c31af7Sopenharmony_ci 556e5c31af7Sopenharmony_ci for (;;) 557e5c31af7Sopenharmony_ci { 558e5c31af7Sopenharmony_ci // access element 559e5c31af7Sopenharmony_ci { 560e5c31af7Sopenharmony_ci std::ostringstream name; 561e5c31af7Sopenharmony_ci name << block.instanceName; 562e5c31af7Sopenharmony_ci 563e5c31af7Sopenharmony_ci for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx) 564e5c31af7Sopenharmony_ci name << "[" << index[dimensionNdx] << "]"; 565e5c31af7Sopenharmony_ci 566e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx) 567e5c31af7Sopenharmony_ci { 568e5c31af7Sopenharmony_ci writeVariableReadAccumulateExpression(buf, 569e5c31af7Sopenharmony_ci accumulatorName, 570e5c31af7Sopenharmony_ci name.str() + "." + block.variables[ndx].name, 571e5c31af7Sopenharmony_ci shaderType, 572e5c31af7Sopenharmony_ci block.storage, 573e5c31af7Sopenharmony_ci program, 574e5c31af7Sopenharmony_ci block.variables[ndx].varType); 575e5c31af7Sopenharmony_ci } 576e5c31af7Sopenharmony_ci } 577e5c31af7Sopenharmony_ci 578e5c31af7Sopenharmony_ci // increment index 579e5c31af7Sopenharmony_ci if (!incrementMultiDimensionIndex(index, block.dimensions)) 580e5c31af7Sopenharmony_ci break; 581e5c31af7Sopenharmony_ci } 582e5c31af7Sopenharmony_ci } 583e5c31af7Sopenharmony_ci} 584e5c31af7Sopenharmony_ci 585e5c31af7Sopenharmony_cistatic void writeVariableWriteExpression (std::ostringstream& buf, 586e5c31af7Sopenharmony_ci const std::string& sourceVec4Name, 587e5c31af7Sopenharmony_ci const std::string& name, 588e5c31af7Sopenharmony_ci glu::ShaderType shaderType, 589e5c31af7Sopenharmony_ci glu::Storage storage, 590e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Program* program, 591e5c31af7Sopenharmony_ci const glu::VarType& varType) 592e5c31af7Sopenharmony_ci{ 593e5c31af7Sopenharmony_ci if (varType.isBasicType()) 594e5c31af7Sopenharmony_ci { 595e5c31af7Sopenharmony_ci buf << "\t" << name << " = "; 596e5c31af7Sopenharmony_ci 597e5c31af7Sopenharmony_ci if (glu::isDataTypeScalar(varType.getBasicType())) 598e5c31af7Sopenharmony_ci buf << glu::getDataTypeName(varType.getBasicType()) << "(" << sourceVec4Name << ".y)"; 599e5c31af7Sopenharmony_ci else if (glu::isDataTypeVector(varType.getBasicType()) || glu::isDataTypeMatrix(varType.getBasicType())) 600e5c31af7Sopenharmony_ci buf << glu::getDataTypeName(varType.getBasicType()) << "(" << glu::getDataTypeName(glu::getDataTypeScalarType(varType.getBasicType())) << "(" << sourceVec4Name << ".y))"; 601e5c31af7Sopenharmony_ci else 602e5c31af7Sopenharmony_ci DE_ASSERT(false); 603e5c31af7Sopenharmony_ci 604e5c31af7Sopenharmony_ci buf << ";\n"; 605e5c31af7Sopenharmony_ci } 606e5c31af7Sopenharmony_ci else if (varType.isStructType()) 607e5c31af7Sopenharmony_ci { 608e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx) 609e5c31af7Sopenharmony_ci writeVariableWriteExpression(buf, 610e5c31af7Sopenharmony_ci sourceVec4Name, 611e5c31af7Sopenharmony_ci name + "." + varType.getStructPtr()->getMember(ndx).getName(), 612e5c31af7Sopenharmony_ci shaderType, 613e5c31af7Sopenharmony_ci storage, 614e5c31af7Sopenharmony_ci program, 615e5c31af7Sopenharmony_ci varType.getStructPtr()->getMember(ndx).getType()); 616e5c31af7Sopenharmony_ci } 617e5c31af7Sopenharmony_ci else if (varType.isArrayType()) 618e5c31af7Sopenharmony_ci { 619e5c31af7Sopenharmony_ci if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY) 620e5c31af7Sopenharmony_ci { 621e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < varType.getArraySize(); ++ndx) 622e5c31af7Sopenharmony_ci writeVariableWriteExpression(buf, 623e5c31af7Sopenharmony_ci sourceVec4Name, 624e5c31af7Sopenharmony_ci name + "[" + de::toString(ndx) + "]", 625e5c31af7Sopenharmony_ci shaderType, 626e5c31af7Sopenharmony_ci storage, 627e5c31af7Sopenharmony_ci program, 628e5c31af7Sopenharmony_ci varType.getElementType()); 629e5c31af7Sopenharmony_ci } 630e5c31af7Sopenharmony_ci else if (storage == glu::STORAGE_BUFFER) 631e5c31af7Sopenharmony_ci { 632e5c31af7Sopenharmony_ci // run-time sized array, write arbitrary 633e5c31af7Sopenharmony_ci writeVariableWriteExpression(buf, 634e5c31af7Sopenharmony_ci sourceVec4Name, 635e5c31af7Sopenharmony_ci name + "[9]", 636e5c31af7Sopenharmony_ci shaderType, 637e5c31af7Sopenharmony_ci storage, 638e5c31af7Sopenharmony_ci program, 639e5c31af7Sopenharmony_ci varType.getElementType()); 640e5c31af7Sopenharmony_ci } 641e5c31af7Sopenharmony_ci else 642e5c31af7Sopenharmony_ci { 643e5c31af7Sopenharmony_ci DE_ASSERT(storage == glu::STORAGE_OUT); 644e5c31af7Sopenharmony_ci 645e5c31af7Sopenharmony_ci if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) 646e5c31af7Sopenharmony_ci { 647e5c31af7Sopenharmony_ci // implicit sized tessellation onput array, size = output patch max size. Can only write to gl_InvocationID 648e5c31af7Sopenharmony_ci writeVariableWriteExpression(buf, 649e5c31af7Sopenharmony_ci sourceVec4Name, 650e5c31af7Sopenharmony_ci name + "[gl_InvocationID]", 651e5c31af7Sopenharmony_ci shaderType, 652e5c31af7Sopenharmony_ci storage, 653e5c31af7Sopenharmony_ci program, 654e5c31af7Sopenharmony_ci varType.getElementType()); 655e5c31af7Sopenharmony_ci } 656e5c31af7Sopenharmony_ci else 657e5c31af7Sopenharmony_ci DE_ASSERT(false); 658e5c31af7Sopenharmony_ci } 659e5c31af7Sopenharmony_ci } 660e5c31af7Sopenharmony_ci else 661e5c31af7Sopenharmony_ci DE_ASSERT(false); 662e5c31af7Sopenharmony_ci} 663e5c31af7Sopenharmony_ci 664e5c31af7Sopenharmony_cistatic void writeInterfaceWriteExpression (std::ostringstream& buf, 665e5c31af7Sopenharmony_ci const std::string& sourceVec4Name, 666e5c31af7Sopenharmony_ci const glu::InterfaceBlock& block, 667e5c31af7Sopenharmony_ci glu::ShaderType shaderType, 668e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Program* program) 669e5c31af7Sopenharmony_ci{ 670e5c31af7Sopenharmony_ci if (block.dimensions.empty()) 671e5c31af7Sopenharmony_ci { 672e5c31af7Sopenharmony_ci const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + "."); 673e5c31af7Sopenharmony_ci 674e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx) 675e5c31af7Sopenharmony_ci { 676e5c31af7Sopenharmony_ci writeVariableWriteExpression(buf, 677e5c31af7Sopenharmony_ci sourceVec4Name, 678e5c31af7Sopenharmony_ci prefix + block.variables[ndx].name, 679e5c31af7Sopenharmony_ci shaderType, 680e5c31af7Sopenharmony_ci block.storage, 681e5c31af7Sopenharmony_ci program, 682e5c31af7Sopenharmony_ci block.variables[ndx].varType); 683e5c31af7Sopenharmony_ci } 684e5c31af7Sopenharmony_ci } 685e5c31af7Sopenharmony_ci else 686e5c31af7Sopenharmony_ci { 687e5c31af7Sopenharmony_ci std::vector<int> index(block.dimensions.size(), 0); 688e5c31af7Sopenharmony_ci 689e5c31af7Sopenharmony_ci for (;;) 690e5c31af7Sopenharmony_ci { 691e5c31af7Sopenharmony_ci // access element 692e5c31af7Sopenharmony_ci { 693e5c31af7Sopenharmony_ci std::ostringstream name; 694e5c31af7Sopenharmony_ci name << block.instanceName; 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx) 697e5c31af7Sopenharmony_ci name << "[" << index[dimensionNdx] << "]"; 698e5c31af7Sopenharmony_ci 699e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx) 700e5c31af7Sopenharmony_ci { 701e5c31af7Sopenharmony_ci writeVariableWriteExpression(buf, 702e5c31af7Sopenharmony_ci sourceVec4Name, 703e5c31af7Sopenharmony_ci name.str() + "." + block.variables[ndx].name, 704e5c31af7Sopenharmony_ci shaderType, 705e5c31af7Sopenharmony_ci block.storage, 706e5c31af7Sopenharmony_ci program, 707e5c31af7Sopenharmony_ci block.variables[ndx].varType); 708e5c31af7Sopenharmony_ci } 709e5c31af7Sopenharmony_ci } 710e5c31af7Sopenharmony_ci 711e5c31af7Sopenharmony_ci // increment index 712e5c31af7Sopenharmony_ci if (!incrementMultiDimensionIndex(index, block.dimensions)) 713e5c31af7Sopenharmony_ci break; 714e5c31af7Sopenharmony_ci } 715e5c31af7Sopenharmony_ci } 716e5c31af7Sopenharmony_ci} 717e5c31af7Sopenharmony_ci 718e5c31af7Sopenharmony_cistatic bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const char* subPath, const glu::VarType& type) 719e5c31af7Sopenharmony_ci{ 720e5c31af7Sopenharmony_ci glu::VarTokenizer tokenizer(subPath); 721e5c31af7Sopenharmony_ci 722e5c31af7Sopenharmony_ci typePath.push_back(VariablePathComponent(&type)); 723e5c31af7Sopenharmony_ci 724e5c31af7Sopenharmony_ci if (tokenizer.getToken() == glu::VarTokenizer::TOKEN_END) 725e5c31af7Sopenharmony_ci return true; 726e5c31af7Sopenharmony_ci 727e5c31af7Sopenharmony_ci if (type.isStructType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_PERIOD) 728e5c31af7Sopenharmony_ci { 729e5c31af7Sopenharmony_ci tokenizer.advance(); 730e5c31af7Sopenharmony_ci 731e5c31af7Sopenharmony_ci // malformed path 732e5c31af7Sopenharmony_ci if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_IDENTIFIER) 733e5c31af7Sopenharmony_ci return false; 734e5c31af7Sopenharmony_ci 735e5c31af7Sopenharmony_ci for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx) 736e5c31af7Sopenharmony_ci if (type.getStructPtr()->getMember(memberNdx).getName() == tokenizer.getIdentifier()) 737e5c31af7Sopenharmony_ci return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getStructPtr()->getMember(memberNdx).getType()); 738e5c31af7Sopenharmony_ci 739e5c31af7Sopenharmony_ci // malformed path, no such member 740e5c31af7Sopenharmony_ci return false; 741e5c31af7Sopenharmony_ci } 742e5c31af7Sopenharmony_ci else if (type.isArrayType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_LEFT_BRACKET) 743e5c31af7Sopenharmony_ci { 744e5c31af7Sopenharmony_ci tokenizer.advance(); 745e5c31af7Sopenharmony_ci 746e5c31af7Sopenharmony_ci // malformed path 747e5c31af7Sopenharmony_ci if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_NUMBER) 748e5c31af7Sopenharmony_ci return false; 749e5c31af7Sopenharmony_ci 750e5c31af7Sopenharmony_ci tokenizer.advance(); 751e5c31af7Sopenharmony_ci if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_RIGHT_BRACKET) 752e5c31af7Sopenharmony_ci return false; 753e5c31af7Sopenharmony_ci 754e5c31af7Sopenharmony_ci return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getElementType()); 755e5c31af7Sopenharmony_ci } 756e5c31af7Sopenharmony_ci 757e5c31af7Sopenharmony_ci return false; 758e5c31af7Sopenharmony_ci} 759e5c31af7Sopenharmony_ci 760e5c31af7Sopenharmony_cistatic bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const std::string& path, const glu::VariableDeclaration& var) 761e5c31af7Sopenharmony_ci{ 762e5c31af7Sopenharmony_ci if (glu::parseVariableName(path.c_str()) != var.name) 763e5c31af7Sopenharmony_ci return false; 764e5c31af7Sopenharmony_ci 765e5c31af7Sopenharmony_ci typePath.push_back(VariablePathComponent(&var)); 766e5c31af7Sopenharmony_ci return traverseVariablePath(typePath, path.c_str() + var.name.length(), var.varType); 767e5c31af7Sopenharmony_ci} 768e5c31af7Sopenharmony_ci 769e5c31af7Sopenharmony_cistatic bool traverseShaderVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Shader* shader, const std::string& path, const VariableSearchFilter& filter) 770e5c31af7Sopenharmony_ci{ 771e5c31af7Sopenharmony_ci // Default block variable? 772e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx) 773e5c31af7Sopenharmony_ci if (filter.matchesFilter(shader->getDefaultBlock().variables[varNdx])) 774e5c31af7Sopenharmony_ci if (traverseVariablePath(typePath, path, shader->getDefaultBlock().variables[varNdx])) 775e5c31af7Sopenharmony_ci return true; 776e5c31af7Sopenharmony_ci 777e5c31af7Sopenharmony_ci // is variable an interface block variable? 778e5c31af7Sopenharmony_ci { 779e5c31af7Sopenharmony_ci const std::string blockName = glu::parseVariableName(path.c_str()); 780e5c31af7Sopenharmony_ci 781e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx) 782e5c31af7Sopenharmony_ci { 783e5c31af7Sopenharmony_ci if (!filter.matchesFilter(shader->getDefaultBlock().interfaceBlocks[interfaceNdx])) 784e5c31af7Sopenharmony_ci continue; 785e5c31af7Sopenharmony_ci 786e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName) 787e5c31af7Sopenharmony_ci { 788e5c31af7Sopenharmony_ci // resource is a member of a named interface block 789e5c31af7Sopenharmony_ci // \note there is no array index specifier even if the interface is declared as an array of instances 790e5c31af7Sopenharmony_ci const std::string blockMemberPath = path.substr(blockName.size() + 1); 791e5c31af7Sopenharmony_ci const std::string blockMemeberName = glu::parseVariableName(blockMemberPath.c_str()); 792e5c31af7Sopenharmony_ci 793e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx) 794e5c31af7Sopenharmony_ci { 795e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName) 796e5c31af7Sopenharmony_ci { 797e5c31af7Sopenharmony_ci typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx])); 798e5c31af7Sopenharmony_ci return traverseVariablePath(typePath, blockMemberPath, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]); 799e5c31af7Sopenharmony_ci } 800e5c31af7Sopenharmony_ci } 801e5c31af7Sopenharmony_ci 802e5c31af7Sopenharmony_ci // terminate search 803e5c31af7Sopenharmony_ci return false; 804e5c31af7Sopenharmony_ci } 805e5c31af7Sopenharmony_ci else if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].instanceName.empty()) 806e5c31af7Sopenharmony_ci { 807e5c31af7Sopenharmony_ci const std::string blockMemeberName = glu::parseVariableName(path.c_str()); 808e5c31af7Sopenharmony_ci 809e5c31af7Sopenharmony_ci // unnamed block contains such variable? 810e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx) 811e5c31af7Sopenharmony_ci { 812e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName) 813e5c31af7Sopenharmony_ci { 814e5c31af7Sopenharmony_ci typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx])); 815e5c31af7Sopenharmony_ci return traverseVariablePath(typePath, path, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]); 816e5c31af7Sopenharmony_ci } 817e5c31af7Sopenharmony_ci } 818e5c31af7Sopenharmony_ci 819e5c31af7Sopenharmony_ci // continue search 820e5c31af7Sopenharmony_ci } 821e5c31af7Sopenharmony_ci } 822e5c31af7Sopenharmony_ci } 823e5c31af7Sopenharmony_ci 824e5c31af7Sopenharmony_ci return false; 825e5c31af7Sopenharmony_ci} 826e5c31af7Sopenharmony_ci 827e5c31af7Sopenharmony_cistatic bool traverseProgramVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& path, const VariableSearchFilter& filter) 828e5c31af7Sopenharmony_ci{ 829e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 830e5c31af7Sopenharmony_ci { 831e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx]; 832e5c31af7Sopenharmony_ci 833e5c31af7Sopenharmony_ci if (filter.matchesFilter(shader)) 834e5c31af7Sopenharmony_ci { 835e5c31af7Sopenharmony_ci // \note modifying output variable even when returning false 836e5c31af7Sopenharmony_ci typePath.clear(); 837e5c31af7Sopenharmony_ci if (traverseShaderVariablePath(typePath, shader, path, filter)) 838e5c31af7Sopenharmony_ci return true; 839e5c31af7Sopenharmony_ci } 840e5c31af7Sopenharmony_ci } 841e5c31af7Sopenharmony_ci 842e5c31af7Sopenharmony_ci return false; 843e5c31af7Sopenharmony_ci} 844e5c31af7Sopenharmony_ci 845e5c31af7Sopenharmony_cistatic bool containsSubType (const glu::VarType& complexType, glu::DataType basicType) 846e5c31af7Sopenharmony_ci{ 847e5c31af7Sopenharmony_ci if (complexType.isBasicType()) 848e5c31af7Sopenharmony_ci { 849e5c31af7Sopenharmony_ci return complexType.getBasicType() == basicType; 850e5c31af7Sopenharmony_ci } 851e5c31af7Sopenharmony_ci else if (complexType.isArrayType()) 852e5c31af7Sopenharmony_ci { 853e5c31af7Sopenharmony_ci return containsSubType(complexType.getElementType(), basicType); 854e5c31af7Sopenharmony_ci } 855e5c31af7Sopenharmony_ci else if (complexType.isStructType()) 856e5c31af7Sopenharmony_ci { 857e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx) 858e5c31af7Sopenharmony_ci if (containsSubType(complexType.getStructPtr()->getMember(ndx).getType(), basicType)) 859e5c31af7Sopenharmony_ci return true; 860e5c31af7Sopenharmony_ci return false; 861e5c31af7Sopenharmony_ci } 862e5c31af7Sopenharmony_ci else 863e5c31af7Sopenharmony_ci { 864e5c31af7Sopenharmony_ci DE_ASSERT(false); 865e5c31af7Sopenharmony_ci return false; 866e5c31af7Sopenharmony_ci } 867e5c31af7Sopenharmony_ci} 868e5c31af7Sopenharmony_ci 869e5c31af7Sopenharmony_cistatic int getNumShaderBlocks (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage) 870e5c31af7Sopenharmony_ci{ 871e5c31af7Sopenharmony_ci int retVal = 0; 872e5c31af7Sopenharmony_ci 873e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx) 874e5c31af7Sopenharmony_ci { 875e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage) 876e5c31af7Sopenharmony_ci { 877e5c31af7Sopenharmony_ci int numInstances = 1; 878e5c31af7Sopenharmony_ci 879e5c31af7Sopenharmony_ci for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx) 880e5c31af7Sopenharmony_ci numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx]; 881e5c31af7Sopenharmony_ci 882e5c31af7Sopenharmony_ci retVal += numInstances; 883e5c31af7Sopenharmony_ci } 884e5c31af7Sopenharmony_ci } 885e5c31af7Sopenharmony_ci 886e5c31af7Sopenharmony_ci return retVal; 887e5c31af7Sopenharmony_ci} 888e5c31af7Sopenharmony_ci 889e5c31af7Sopenharmony_cistatic int getNumAtomicCounterBuffers (const ProgramInterfaceDefinition::Shader* shader) 890e5c31af7Sopenharmony_ci{ 891e5c31af7Sopenharmony_ci std::set<int> buffers; 892e5c31af7Sopenharmony_ci 893e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx) 894e5c31af7Sopenharmony_ci { 895e5c31af7Sopenharmony_ci if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER)) 896e5c31af7Sopenharmony_ci { 897e5c31af7Sopenharmony_ci DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1); 898e5c31af7Sopenharmony_ci buffers.insert(shader->getDefaultBlock().variables[ndx].layout.binding); 899e5c31af7Sopenharmony_ci } 900e5c31af7Sopenharmony_ci } 901e5c31af7Sopenharmony_ci 902e5c31af7Sopenharmony_ci return (int)buffers.size(); 903e5c31af7Sopenharmony_ci} 904e5c31af7Sopenharmony_ci 905e5c31af7Sopenharmony_citemplate <typename DataTypeMap> 906e5c31af7Sopenharmony_cistatic int accumulateComplexType (const glu::VarType& complexType, const DataTypeMap& dTypeMap) 907e5c31af7Sopenharmony_ci{ 908e5c31af7Sopenharmony_ci if (complexType.isBasicType()) 909e5c31af7Sopenharmony_ci return dTypeMap(complexType.getBasicType()); 910e5c31af7Sopenharmony_ci else if (complexType.isArrayType()) 911e5c31af7Sopenharmony_ci { 912e5c31af7Sopenharmony_ci const int arraySize = (complexType.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (complexType.getArraySize()); 913e5c31af7Sopenharmony_ci return arraySize * accumulateComplexType(complexType.getElementType(), dTypeMap); 914e5c31af7Sopenharmony_ci } 915e5c31af7Sopenharmony_ci else if (complexType.isStructType()) 916e5c31af7Sopenharmony_ci { 917e5c31af7Sopenharmony_ci int sum = 0; 918e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx) 919e5c31af7Sopenharmony_ci sum += accumulateComplexType(complexType.getStructPtr()->getMember(ndx).getType(), dTypeMap); 920e5c31af7Sopenharmony_ci return sum; 921e5c31af7Sopenharmony_ci } 922e5c31af7Sopenharmony_ci else 923e5c31af7Sopenharmony_ci { 924e5c31af7Sopenharmony_ci DE_ASSERT(false); 925e5c31af7Sopenharmony_ci return false; 926e5c31af7Sopenharmony_ci } 927e5c31af7Sopenharmony_ci} 928e5c31af7Sopenharmony_ci 929e5c31af7Sopenharmony_citemplate <typename InterfaceBlockFilter, typename VarDeclFilter, typename DataTypeMap> 930e5c31af7Sopenharmony_cistatic int accumulateShader (const ProgramInterfaceDefinition::Shader* shader, 931e5c31af7Sopenharmony_ci const InterfaceBlockFilter& ibFilter, 932e5c31af7Sopenharmony_ci const VarDeclFilter& vdFilter, 933e5c31af7Sopenharmony_ci const DataTypeMap& dMap) 934e5c31af7Sopenharmony_ci{ 935e5c31af7Sopenharmony_ci int retVal = 0; 936e5c31af7Sopenharmony_ci 937e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx) 938e5c31af7Sopenharmony_ci { 939e5c31af7Sopenharmony_ci if (ibFilter(shader->getDefaultBlock().interfaceBlocks[ndx])) 940e5c31af7Sopenharmony_ci { 941e5c31af7Sopenharmony_ci int numInstances = 1; 942e5c31af7Sopenharmony_ci 943e5c31af7Sopenharmony_ci for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx) 944e5c31af7Sopenharmony_ci numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx]; 945e5c31af7Sopenharmony_ci 946e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].variables.size(); ++varNdx) 947e5c31af7Sopenharmony_ci retVal += numInstances * accumulateComplexType(shader->getDefaultBlock().interfaceBlocks[ndx].variables[varNdx].varType, dMap); 948e5c31af7Sopenharmony_ci } 949e5c31af7Sopenharmony_ci } 950e5c31af7Sopenharmony_ci 951e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx) 952e5c31af7Sopenharmony_ci if (vdFilter(shader->getDefaultBlock().variables[varNdx])) 953e5c31af7Sopenharmony_ci retVal += accumulateComplexType(shader->getDefaultBlock().variables[varNdx].varType, dMap); 954e5c31af7Sopenharmony_ci 955e5c31af7Sopenharmony_ci return retVal; 956e5c31af7Sopenharmony_ci} 957e5c31af7Sopenharmony_ci 958e5c31af7Sopenharmony_cistatic bool unusedTrueConstantTypeFilter (glu::DataType d) 959e5c31af7Sopenharmony_ci{ 960e5c31af7Sopenharmony_ci DE_UNREF(d); 961e5c31af7Sopenharmony_ci return true; 962e5c31af7Sopenharmony_ci} 963e5c31af7Sopenharmony_ci 964e5c31af7Sopenharmony_ciclass InstanceCounter 965e5c31af7Sopenharmony_ci{ 966e5c31af7Sopenharmony_cipublic: 967e5c31af7Sopenharmony_ci InstanceCounter (bool (*predicate)(glu::DataType)) 968e5c31af7Sopenharmony_ci : m_predicate(predicate) 969e5c31af7Sopenharmony_ci { 970e5c31af7Sopenharmony_ci } 971e5c31af7Sopenharmony_ci 972e5c31af7Sopenharmony_ci int operator() (glu::DataType t) const 973e5c31af7Sopenharmony_ci { 974e5c31af7Sopenharmony_ci return (m_predicate(t)) ? (1) : (0); 975e5c31af7Sopenharmony_ci } 976e5c31af7Sopenharmony_ci 977e5c31af7Sopenharmony_ciprivate: 978e5c31af7Sopenharmony_ci bool (*const m_predicate)(glu::DataType); 979e5c31af7Sopenharmony_ci}; 980e5c31af7Sopenharmony_ci 981e5c31af7Sopenharmony_ciclass InterfaceBlockStorageFilter 982e5c31af7Sopenharmony_ci{ 983e5c31af7Sopenharmony_cipublic: 984e5c31af7Sopenharmony_ci InterfaceBlockStorageFilter (glu::Storage storage) 985e5c31af7Sopenharmony_ci : m_storage(storage) 986e5c31af7Sopenharmony_ci { 987e5c31af7Sopenharmony_ci } 988e5c31af7Sopenharmony_ci 989e5c31af7Sopenharmony_ci bool operator() (const glu::InterfaceBlock& b) const 990e5c31af7Sopenharmony_ci { 991e5c31af7Sopenharmony_ci return m_storage == b.storage; 992e5c31af7Sopenharmony_ci } 993e5c31af7Sopenharmony_ci 994e5c31af7Sopenharmony_ciprivate: 995e5c31af7Sopenharmony_ci const glu::Storage m_storage; 996e5c31af7Sopenharmony_ci}; 997e5c31af7Sopenharmony_ci 998e5c31af7Sopenharmony_ciclass VariableDeclarationStorageFilter 999e5c31af7Sopenharmony_ci{ 1000e5c31af7Sopenharmony_cipublic: 1001e5c31af7Sopenharmony_ci VariableDeclarationStorageFilter (glu::Storage storage) 1002e5c31af7Sopenharmony_ci : m_storage(storage) 1003e5c31af7Sopenharmony_ci { 1004e5c31af7Sopenharmony_ci } 1005e5c31af7Sopenharmony_ci 1006e5c31af7Sopenharmony_ci bool operator() (const glu::VariableDeclaration& d) const 1007e5c31af7Sopenharmony_ci { 1008e5c31af7Sopenharmony_ci return m_storage == d.storage; 1009e5c31af7Sopenharmony_ci } 1010e5c31af7Sopenharmony_ci 1011e5c31af7Sopenharmony_ciprivate: 1012e5c31af7Sopenharmony_ci const glu::Storage m_storage; 1013e5c31af7Sopenharmony_ci}; 1014e5c31af7Sopenharmony_ci 1015e5c31af7Sopenharmony_cistatic int getNumTypeInstances (const glu::VarType& complexType, bool (*predicate)(glu::DataType)) 1016e5c31af7Sopenharmony_ci{ 1017e5c31af7Sopenharmony_ci return accumulateComplexType(complexType, InstanceCounter(predicate)); 1018e5c31af7Sopenharmony_ci} 1019e5c31af7Sopenharmony_ci 1020e5c31af7Sopenharmony_cistatic int getNumTypeInstances (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, bool (*predicate)(glu::DataType)) 1021e5c31af7Sopenharmony_ci{ 1022e5c31af7Sopenharmony_ci return accumulateShader(shader, InterfaceBlockStorageFilter(storage), VariableDeclarationStorageFilter(storage), InstanceCounter(predicate)); 1023e5c31af7Sopenharmony_ci} 1024e5c31af7Sopenharmony_ci 1025e5c31af7Sopenharmony_cistatic int getNumTypeInstances (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage) 1026e5c31af7Sopenharmony_ci{ 1027e5c31af7Sopenharmony_ci return getNumTypeInstances(shader, storage, unusedTrueConstantTypeFilter); 1028e5c31af7Sopenharmony_ci} 1029e5c31af7Sopenharmony_ci 1030e5c31af7Sopenharmony_cistatic int accumulateShaderStorage (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, int (*typeMap)(glu::DataType)) 1031e5c31af7Sopenharmony_ci{ 1032e5c31af7Sopenharmony_ci return accumulateShader(shader, InterfaceBlockStorageFilter(storage), VariableDeclarationStorageFilter(storage), typeMap); 1033e5c31af7Sopenharmony_ci} 1034e5c31af7Sopenharmony_ci 1035e5c31af7Sopenharmony_cistatic int getNumDataTypeComponents (glu::DataType type) 1036e5c31af7Sopenharmony_ci{ 1037e5c31af7Sopenharmony_ci if (glu::isDataTypeScalarOrVector(type) || glu::isDataTypeMatrix(type)) 1038e5c31af7Sopenharmony_ci return glu::getDataTypeScalarSize(type); 1039e5c31af7Sopenharmony_ci else 1040e5c31af7Sopenharmony_ci return 0; 1041e5c31af7Sopenharmony_ci} 1042e5c31af7Sopenharmony_ci 1043e5c31af7Sopenharmony_cistatic int getNumDataTypeVectors (glu::DataType type) 1044e5c31af7Sopenharmony_ci{ 1045e5c31af7Sopenharmony_ci if (glu::isDataTypeScalar(type)) 1046e5c31af7Sopenharmony_ci return 1; 1047e5c31af7Sopenharmony_ci else if (glu::isDataTypeVector(type)) 1048e5c31af7Sopenharmony_ci return 1; 1049e5c31af7Sopenharmony_ci else if (glu::isDataTypeMatrix(type)) 1050e5c31af7Sopenharmony_ci return glu::getDataTypeMatrixNumColumns(type); 1051e5c31af7Sopenharmony_ci else 1052e5c31af7Sopenharmony_ci return 0; 1053e5c31af7Sopenharmony_ci} 1054e5c31af7Sopenharmony_ci 1055e5c31af7Sopenharmony_cistatic int getNumComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage) 1056e5c31af7Sopenharmony_ci{ 1057e5c31af7Sopenharmony_ci return accumulateShaderStorage(shader, storage, getNumDataTypeComponents); 1058e5c31af7Sopenharmony_ci} 1059e5c31af7Sopenharmony_ci 1060e5c31af7Sopenharmony_cistatic int getNumVectors (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage) 1061e5c31af7Sopenharmony_ci{ 1062e5c31af7Sopenharmony_ci return accumulateShaderStorage(shader, storage, getNumDataTypeVectors); 1063e5c31af7Sopenharmony_ci} 1064e5c31af7Sopenharmony_ci 1065e5c31af7Sopenharmony_cistatic int getNumDefaultBlockComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage) 1066e5c31af7Sopenharmony_ci{ 1067e5c31af7Sopenharmony_ci int retVal = 0; 1068e5c31af7Sopenharmony_ci 1069e5c31af7Sopenharmony_ci for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx) 1070e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().variables[varNdx].storage == storage) 1071e5c31af7Sopenharmony_ci retVal += accumulateComplexType(shader->getDefaultBlock().variables[varNdx].varType, getNumDataTypeComponents); 1072e5c31af7Sopenharmony_ci 1073e5c31af7Sopenharmony_ci return retVal; 1074e5c31af7Sopenharmony_ci} 1075e5c31af7Sopenharmony_ci 1076e5c31af7Sopenharmony_cistatic int getMaxBufferBinding (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage) 1077e5c31af7Sopenharmony_ci{ 1078e5c31af7Sopenharmony_ci int maxBinding = -1; 1079e5c31af7Sopenharmony_ci 1080e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx) 1081e5c31af7Sopenharmony_ci { 1082e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage) 1083e5c31af7Sopenharmony_ci { 1084e5c31af7Sopenharmony_ci const int binding = (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding == -1) ? (0) : (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding); 1085e5c31af7Sopenharmony_ci int numInstances = 1; 1086e5c31af7Sopenharmony_ci 1087e5c31af7Sopenharmony_ci for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx) 1088e5c31af7Sopenharmony_ci numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx]; 1089e5c31af7Sopenharmony_ci 1090e5c31af7Sopenharmony_ci maxBinding = de::max(maxBinding, binding + numInstances - 1); 1091e5c31af7Sopenharmony_ci } 1092e5c31af7Sopenharmony_ci } 1093e5c31af7Sopenharmony_ci 1094e5c31af7Sopenharmony_ci return (int)maxBinding; 1095e5c31af7Sopenharmony_ci} 1096e5c31af7Sopenharmony_ci 1097e5c31af7Sopenharmony_cistatic int getBufferTypeSize (glu::DataType type, glu::MatrixOrder order) 1098e5c31af7Sopenharmony_ci{ 1099e5c31af7Sopenharmony_ci // assume vec4 alignments, should produce values greater than or equal to the actual resource usage 1100e5c31af7Sopenharmony_ci int numVectors = 0; 1101e5c31af7Sopenharmony_ci 1102e5c31af7Sopenharmony_ci if (glu::isDataTypeScalarOrVector(type)) 1103e5c31af7Sopenharmony_ci numVectors = 1; 1104e5c31af7Sopenharmony_ci else if (glu::isDataTypeMatrix(type) && order == glu::MATRIXORDER_ROW_MAJOR) 1105e5c31af7Sopenharmony_ci numVectors = glu::getDataTypeMatrixNumRows(type); 1106e5c31af7Sopenharmony_ci else if (glu::isDataTypeMatrix(type) && order != glu::MATRIXORDER_ROW_MAJOR) 1107e5c31af7Sopenharmony_ci numVectors = glu::getDataTypeMatrixNumColumns(type); 1108e5c31af7Sopenharmony_ci else 1109e5c31af7Sopenharmony_ci DE_ASSERT(false); 1110e5c31af7Sopenharmony_ci 1111e5c31af7Sopenharmony_ci return 4 * numVectors; 1112e5c31af7Sopenharmony_ci} 1113e5c31af7Sopenharmony_ci 1114e5c31af7Sopenharmony_cistatic int getBufferVariableSize (const glu::VarType& type, glu::MatrixOrder order) 1115e5c31af7Sopenharmony_ci{ 1116e5c31af7Sopenharmony_ci if (type.isBasicType()) 1117e5c31af7Sopenharmony_ci return getBufferTypeSize(type.getBasicType(), order); 1118e5c31af7Sopenharmony_ci else if (type.isArrayType()) 1119e5c31af7Sopenharmony_ci { 1120e5c31af7Sopenharmony_ci const int arraySize = (type.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (type.getArraySize()); 1121e5c31af7Sopenharmony_ci return arraySize * getBufferVariableSize(type.getElementType(), order); 1122e5c31af7Sopenharmony_ci } 1123e5c31af7Sopenharmony_ci else if (type.isStructType()) 1124e5c31af7Sopenharmony_ci { 1125e5c31af7Sopenharmony_ci int sum = 0; 1126e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx) 1127e5c31af7Sopenharmony_ci sum += getBufferVariableSize(type.getStructPtr()->getMember(ndx).getType(), order); 1128e5c31af7Sopenharmony_ci return sum; 1129e5c31af7Sopenharmony_ci } 1130e5c31af7Sopenharmony_ci else 1131e5c31af7Sopenharmony_ci { 1132e5c31af7Sopenharmony_ci DE_ASSERT(false); 1133e5c31af7Sopenharmony_ci return false; 1134e5c31af7Sopenharmony_ci } 1135e5c31af7Sopenharmony_ci} 1136e5c31af7Sopenharmony_ci 1137e5c31af7Sopenharmony_cistatic int getBufferSize (const glu::InterfaceBlock& block, glu::MatrixOrder blockOrder) 1138e5c31af7Sopenharmony_ci{ 1139e5c31af7Sopenharmony_ci int size = 0; 1140e5c31af7Sopenharmony_ci 1141e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx) 1142e5c31af7Sopenharmony_ci size += getBufferVariableSize(block.variables[ndx].varType, (block.variables[ndx].layout.matrixOrder == glu::MATRIXORDER_LAST) ? (blockOrder) : (block.variables[ndx].layout.matrixOrder)); 1143e5c31af7Sopenharmony_ci 1144e5c31af7Sopenharmony_ci return size; 1145e5c31af7Sopenharmony_ci} 1146e5c31af7Sopenharmony_ci 1147e5c31af7Sopenharmony_cistatic int getBufferMaxSize (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage) 1148e5c31af7Sopenharmony_ci{ 1149e5c31af7Sopenharmony_ci int maxSize = 0; 1150e5c31af7Sopenharmony_ci 1151e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx) 1152e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage) 1153e5c31af7Sopenharmony_ci maxSize = de::max(maxSize, getBufferSize(shader->getDefaultBlock().interfaceBlocks[ndx], shader->getDefaultBlock().interfaceBlocks[ndx].layout.matrixOrder)); 1154e5c31af7Sopenharmony_ci 1155e5c31af7Sopenharmony_ci return (int)maxSize; 1156e5c31af7Sopenharmony_ci} 1157e5c31af7Sopenharmony_ci 1158e5c31af7Sopenharmony_cistatic int getAtomicCounterMaxBinding (const ProgramInterfaceDefinition::Shader* shader) 1159e5c31af7Sopenharmony_ci{ 1160e5c31af7Sopenharmony_ci int maxBinding = -1; 1161e5c31af7Sopenharmony_ci 1162e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx) 1163e5c31af7Sopenharmony_ci { 1164e5c31af7Sopenharmony_ci if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER)) 1165e5c31af7Sopenharmony_ci { 1166e5c31af7Sopenharmony_ci DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1); 1167e5c31af7Sopenharmony_ci maxBinding = de::max(maxBinding, shader->getDefaultBlock().variables[ndx].layout.binding); 1168e5c31af7Sopenharmony_ci } 1169e5c31af7Sopenharmony_ci } 1170e5c31af7Sopenharmony_ci 1171e5c31af7Sopenharmony_ci return (int)maxBinding; 1172e5c31af7Sopenharmony_ci} 1173e5c31af7Sopenharmony_ci 1174e5c31af7Sopenharmony_cistatic int getUniformMaxBinding (const ProgramInterfaceDefinition::Shader* shader, bool (*predicate)(glu::DataType)) 1175e5c31af7Sopenharmony_ci{ 1176e5c31af7Sopenharmony_ci int maxBinding = -1; 1177e5c31af7Sopenharmony_ci 1178e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx) 1179e5c31af7Sopenharmony_ci { 1180e5c31af7Sopenharmony_ci const int binding = (shader->getDefaultBlock().variables[ndx].layout.binding == -1) ? (0) : (shader->getDefaultBlock().variables[ndx].layout.binding); 1181e5c31af7Sopenharmony_ci const int numInstances = getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, predicate); 1182e5c31af7Sopenharmony_ci 1183e5c31af7Sopenharmony_ci maxBinding = de::max(maxBinding, binding + numInstances - 1); 1184e5c31af7Sopenharmony_ci } 1185e5c31af7Sopenharmony_ci 1186e5c31af7Sopenharmony_ci return maxBinding; 1187e5c31af7Sopenharmony_ci} 1188e5c31af7Sopenharmony_ci 1189e5c31af7Sopenharmony_cistatic int getAtomicCounterMaxBufferSize (const ProgramInterfaceDefinition::Shader* shader) 1190e5c31af7Sopenharmony_ci{ 1191e5c31af7Sopenharmony_ci std::map<int, int> bufferSizes; 1192e5c31af7Sopenharmony_ci int maxSize = 0; 1193e5c31af7Sopenharmony_ci 1194e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx) 1195e5c31af7Sopenharmony_ci { 1196e5c31af7Sopenharmony_ci if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER)) 1197e5c31af7Sopenharmony_ci { 1198e5c31af7Sopenharmony_ci const int bufferBinding = shader->getDefaultBlock().variables[ndx].layout.binding; 1199e5c31af7Sopenharmony_ci const int offset = (shader->getDefaultBlock().variables[ndx].layout.offset == -1) ? (0) : (shader->getDefaultBlock().variables[ndx].layout.offset); 1200e5c31af7Sopenharmony_ci const int size = offset + 4 * getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, glu::isDataTypeAtomicCounter); 1201e5c31af7Sopenharmony_ci 1202e5c31af7Sopenharmony_ci DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1); 1203e5c31af7Sopenharmony_ci 1204e5c31af7Sopenharmony_ci if (bufferSizes.find(bufferBinding) == bufferSizes.end()) 1205e5c31af7Sopenharmony_ci bufferSizes[bufferBinding] = size; 1206e5c31af7Sopenharmony_ci else 1207e5c31af7Sopenharmony_ci bufferSizes[bufferBinding] = de::max<int>(bufferSizes[bufferBinding], size); 1208e5c31af7Sopenharmony_ci } 1209e5c31af7Sopenharmony_ci } 1210e5c31af7Sopenharmony_ci 1211e5c31af7Sopenharmony_ci for (std::map<int, int>::iterator it = bufferSizes.begin(); it != bufferSizes.end(); ++it) 1212e5c31af7Sopenharmony_ci maxSize = de::max<int>(maxSize, it->second); 1213e5c31af7Sopenharmony_ci 1214e5c31af7Sopenharmony_ci return maxSize; 1215e5c31af7Sopenharmony_ci} 1216e5c31af7Sopenharmony_ci 1217e5c31af7Sopenharmony_cistatic int getNumFeedbackVaryingComponents (const ProgramInterfaceDefinition::Program* program, const std::string& name) 1218e5c31af7Sopenharmony_ci{ 1219e5c31af7Sopenharmony_ci std::vector<VariablePathComponent> path; 1220e5c31af7Sopenharmony_ci 1221e5c31af7Sopenharmony_ci if (name == "gl_Position") 1222e5c31af7Sopenharmony_ci return 4; 1223e5c31af7Sopenharmony_ci 1224e5c31af7Sopenharmony_ci DE_ASSERT(deStringBeginsWith(name.c_str(), "gl_") == DE_FALSE); 1225e5c31af7Sopenharmony_ci 1226e5c31af7Sopenharmony_ci if (!traverseProgramVariablePath(path, program, name, VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(program), glu::STORAGE_OUT))) 1227e5c31af7Sopenharmony_ci DE_ASSERT(false); // Program failed validate, invalid operation 1228e5c31af7Sopenharmony_ci 1229e5c31af7Sopenharmony_ci return accumulateComplexType(*path.back().getVariableType(), getNumDataTypeComponents); 1230e5c31af7Sopenharmony_ci} 1231e5c31af7Sopenharmony_ci 1232e5c31af7Sopenharmony_cistatic int getNumXFBComponents (const ProgramInterfaceDefinition::Program* program) 1233e5c31af7Sopenharmony_ci{ 1234e5c31af7Sopenharmony_ci int numComponents = 0; 1235e5c31af7Sopenharmony_ci 1236e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx) 1237e5c31af7Sopenharmony_ci numComponents += getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx]); 1238e5c31af7Sopenharmony_ci 1239e5c31af7Sopenharmony_ci return numComponents; 1240e5c31af7Sopenharmony_ci} 1241e5c31af7Sopenharmony_ci 1242e5c31af7Sopenharmony_cistatic int getNumMaxXFBOutputComponents (const ProgramInterfaceDefinition::Program* program) 1243e5c31af7Sopenharmony_ci{ 1244e5c31af7Sopenharmony_ci int numComponents = 0; 1245e5c31af7Sopenharmony_ci 1246e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx) 1247e5c31af7Sopenharmony_ci numComponents = de::max(numComponents, getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx])); 1248e5c31af7Sopenharmony_ci 1249e5c31af7Sopenharmony_ci return numComponents; 1250e5c31af7Sopenharmony_ci} 1251e5c31af7Sopenharmony_ci 1252e5c31af7Sopenharmony_cistatic int getFragmentOutputMaxLocation (const ProgramInterfaceDefinition::Shader* shader) 1253e5c31af7Sopenharmony_ci{ 1254e5c31af7Sopenharmony_ci DE_ASSERT(shader->getType() == glu::SHADERTYPE_FRAGMENT); 1255e5c31af7Sopenharmony_ci 1256e5c31af7Sopenharmony_ci int maxOutputLocation = -1; 1257e5c31af7Sopenharmony_ci 1258e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx) 1259e5c31af7Sopenharmony_ci { 1260e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT) 1261e5c31af7Sopenharmony_ci { 1262e5c31af7Sopenharmony_ci // missing location qualifier means location == 0 1263e5c31af7Sopenharmony_ci const int outputLocation = (shader->getDefaultBlock().variables[ndx].layout.location == -1) 1264e5c31af7Sopenharmony_ci ? (0) 1265e5c31af7Sopenharmony_ci : (shader->getDefaultBlock().variables[ndx].layout.location); 1266e5c31af7Sopenharmony_ci 1267e5c31af7Sopenharmony_ci // only basic types or arrays of basic types possible 1268e5c31af7Sopenharmony_ci DE_ASSERT(!shader->getDefaultBlock().variables[ndx].varType.isStructType()); 1269e5c31af7Sopenharmony_ci 1270e5c31af7Sopenharmony_ci const int locationSlotsTaken = (shader->getDefaultBlock().variables[ndx].varType.isArrayType()) 1271e5c31af7Sopenharmony_ci ? (shader->getDefaultBlock().variables[ndx].varType.getArraySize()) 1272e5c31af7Sopenharmony_ci : (1); 1273e5c31af7Sopenharmony_ci 1274e5c31af7Sopenharmony_ci maxOutputLocation = de::max(maxOutputLocation, outputLocation + locationSlotsTaken - 1); 1275e5c31af7Sopenharmony_ci } 1276e5c31af7Sopenharmony_ci } 1277e5c31af7Sopenharmony_ci 1278e5c31af7Sopenharmony_ci return maxOutputLocation; 1279e5c31af7Sopenharmony_ci} 1280e5c31af7Sopenharmony_ci 1281e5c31af7Sopenharmony_ci} // anonymous 1282e5c31af7Sopenharmony_ci 1283e5c31af7Sopenharmony_cistd::vector<std::string> getProgramInterfaceBlockMemberResourceList (const glu::InterfaceBlock& interfaceBlock) 1284e5c31af7Sopenharmony_ci{ 1285e5c31af7Sopenharmony_ci const std::string namePrefix = (!interfaceBlock.instanceName.empty()) ? (interfaceBlock.interfaceName + ".") : (""); 1286e5c31af7Sopenharmony_ci const bool isTopLevelBufferVariable = (interfaceBlock.storage == glu::STORAGE_BUFFER); 1287e5c31af7Sopenharmony_ci std::vector<std::string> resources; 1288e5c31af7Sopenharmony_ci 1289e5c31af7Sopenharmony_ci // \note this is defined in the GLSL spec, not in the GL spec 1290e5c31af7Sopenharmony_ci for (int variableNdx = 0; variableNdx < (int)interfaceBlock.variables.size(); ++variableNdx) 1291e5c31af7Sopenharmony_ci generateVariableTypeResourceNames(resources, 1292e5c31af7Sopenharmony_ci namePrefix + interfaceBlock.variables[variableNdx].name, 1293e5c31af7Sopenharmony_ci interfaceBlock.variables[variableNdx].varType, 1294e5c31af7Sopenharmony_ci (isTopLevelBufferVariable) ? 1295e5c31af7Sopenharmony_ci (RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) : 1296e5c31af7Sopenharmony_ci (RESOURCE_NAME_GENERATION_FLAG_DEFAULT)); 1297e5c31af7Sopenharmony_ci 1298e5c31af7Sopenharmony_ci return resources; 1299e5c31af7Sopenharmony_ci} 1300e5c31af7Sopenharmony_ci 1301e5c31af7Sopenharmony_cistd::vector<std::string> getProgramInterfaceResourceList (const ProgramInterfaceDefinition::Program* program, ProgramInterface interface) 1302e5c31af7Sopenharmony_ci{ 1303e5c31af7Sopenharmony_ci // The same {uniform (block), buffer (variable)} can exist in multiple shaders, remove duplicates but keep order 1304e5c31af7Sopenharmony_ci const bool removeDuplicated = (interface == PROGRAMINTERFACE_UNIFORM) || 1305e5c31af7Sopenharmony_ci (interface == PROGRAMINTERFACE_UNIFORM_BLOCK) || 1306e5c31af7Sopenharmony_ci (interface == PROGRAMINTERFACE_BUFFER_VARIABLE) || 1307e5c31af7Sopenharmony_ci (interface == PROGRAMINTERFACE_SHADER_STORAGE_BLOCK); 1308e5c31af7Sopenharmony_ci std::vector<std::string> resources; 1309e5c31af7Sopenharmony_ci 1310e5c31af7Sopenharmony_ci switch (interface) 1311e5c31af7Sopenharmony_ci { 1312e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM: 1313e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_BUFFER_VARIABLE: 1314e5c31af7Sopenharmony_ci { 1315e5c31af7Sopenharmony_ci const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER); 1316e5c31af7Sopenharmony_ci 1317e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 1318e5c31af7Sopenharmony_ci { 1319e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx]; 1320e5c31af7Sopenharmony_ci 1321e5c31af7Sopenharmony_ci for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx) 1322e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().variables[variableNdx].storage == storage) 1323e5c31af7Sopenharmony_ci generateVariableTypeResourceNames(resources, 1324e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[variableNdx].name, 1325e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[variableNdx].varType, 1326e5c31af7Sopenharmony_ci RESOURCE_NAME_GENERATION_FLAG_DEFAULT); 1327e5c31af7Sopenharmony_ci 1328e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx) 1329e5c31af7Sopenharmony_ci { 1330e5c31af7Sopenharmony_ci const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx]; 1331e5c31af7Sopenharmony_ci if (interfaceBlock.storage == storage) 1332e5c31af7Sopenharmony_ci { 1333e5c31af7Sopenharmony_ci const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock); 1334e5c31af7Sopenharmony_ci resources.insert(resources.end(), blockResources.begin(), blockResources.end()); 1335e5c31af7Sopenharmony_ci } 1336e5c31af7Sopenharmony_ci } 1337e5c31af7Sopenharmony_ci } 1338e5c31af7Sopenharmony_ci break; 1339e5c31af7Sopenharmony_ci } 1340e5c31af7Sopenharmony_ci 1341e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_UNIFORM_BLOCK: 1342e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK: 1343e5c31af7Sopenharmony_ci { 1344e5c31af7Sopenharmony_ci const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM_BLOCK) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER); 1345e5c31af7Sopenharmony_ci 1346e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 1347e5c31af7Sopenharmony_ci { 1348e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx]; 1349e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx) 1350e5c31af7Sopenharmony_ci { 1351e5c31af7Sopenharmony_ci const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx]; 1352e5c31af7Sopenharmony_ci if (interfaceBlock.storage == storage) 1353e5c31af7Sopenharmony_ci { 1354e5c31af7Sopenharmony_ci std::vector<int> index(interfaceBlock.dimensions.size(), 0); 1355e5c31af7Sopenharmony_ci 1356e5c31af7Sopenharmony_ci for (;;) 1357e5c31af7Sopenharmony_ci { 1358e5c31af7Sopenharmony_ci // add resource string for each element 1359e5c31af7Sopenharmony_ci { 1360e5c31af7Sopenharmony_ci std::ostringstream name; 1361e5c31af7Sopenharmony_ci name << interfaceBlock.interfaceName; 1362e5c31af7Sopenharmony_ci 1363e5c31af7Sopenharmony_ci for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx) 1364e5c31af7Sopenharmony_ci name << "[" << index[dimensionNdx] << "]"; 1365e5c31af7Sopenharmony_ci 1366e5c31af7Sopenharmony_ci resources.push_back(name.str()); 1367e5c31af7Sopenharmony_ci } 1368e5c31af7Sopenharmony_ci 1369e5c31af7Sopenharmony_ci // increment index 1370e5c31af7Sopenharmony_ci if (!incrementMultiDimensionIndex(index, interfaceBlock.dimensions)) 1371e5c31af7Sopenharmony_ci break; 1372e5c31af7Sopenharmony_ci } 1373e5c31af7Sopenharmony_ci } 1374e5c31af7Sopenharmony_ci } 1375e5c31af7Sopenharmony_ci } 1376e5c31af7Sopenharmony_ci break; 1377e5c31af7Sopenharmony_ci } 1378e5c31af7Sopenharmony_ci 1379e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_INPUT: 1380e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_PROGRAM_OUTPUT: 1381e5c31af7Sopenharmony_ci { 1382e5c31af7Sopenharmony_ci const glu::Storage queryStorage = (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_IN) : (glu::STORAGE_OUT); 1383e5c31af7Sopenharmony_ci const glu::Storage queryPatchStorage = (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_PATCH_IN) : (glu::STORAGE_PATCH_OUT); 1384e5c31af7Sopenharmony_ci const glu::ShaderType shaderType = (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (program->getFirstStage()) : (program->getLastStage()); 1385e5c31af7Sopenharmony_ci 1386e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 1387e5c31af7Sopenharmony_ci { 1388e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx]; 1389e5c31af7Sopenharmony_ci 1390e5c31af7Sopenharmony_ci if (shader->getType() != shaderType) 1391e5c31af7Sopenharmony_ci continue; 1392e5c31af7Sopenharmony_ci 1393e5c31af7Sopenharmony_ci for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx) 1394e5c31af7Sopenharmony_ci { 1395e5c31af7Sopenharmony_ci const glu::Storage variableStorage = shader->getDefaultBlock().variables[variableNdx].storage; 1396e5c31af7Sopenharmony_ci if (variableStorage == queryStorage || variableStorage == queryPatchStorage) 1397e5c31af7Sopenharmony_ci generateVariableTypeResourceNames(resources, 1398e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[variableNdx].name, 1399e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[variableNdx].varType, 1400e5c31af7Sopenharmony_ci RESOURCE_NAME_GENERATION_FLAG_DEFAULT); 1401e5c31af7Sopenharmony_ci } 1402e5c31af7Sopenharmony_ci 1403e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx) 1404e5c31af7Sopenharmony_ci { 1405e5c31af7Sopenharmony_ci const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx]; 1406e5c31af7Sopenharmony_ci if (interfaceBlock.storage == queryStorage || interfaceBlock.storage == queryPatchStorage) 1407e5c31af7Sopenharmony_ci { 1408e5c31af7Sopenharmony_ci const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock); 1409e5c31af7Sopenharmony_ci resources.insert(resources.end(), blockResources.begin(), blockResources.end()); 1410e5c31af7Sopenharmony_ci } 1411e5c31af7Sopenharmony_ci } 1412e5c31af7Sopenharmony_ci } 1413e5c31af7Sopenharmony_ci 1414e5c31af7Sopenharmony_ci // built-ins 1415e5c31af7Sopenharmony_ci if (interface == PROGRAMINTERFACE_PROGRAM_INPUT) 1416e5c31af7Sopenharmony_ci { 1417e5c31af7Sopenharmony_ci if (shaderType == glu::SHADERTYPE_VERTEX && resources.empty()) 1418e5c31af7Sopenharmony_ci resources.push_back("gl_VertexID"); // only read from when there are no other inputs 1419e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty()) 1420e5c31af7Sopenharmony_ci resources.push_back("gl_FragCoord"); // only read from when there are no other inputs 1421e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_GEOMETRY) 1422e5c31af7Sopenharmony_ci resources.push_back("gl_PerVertex.gl_Position"); 1423e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) 1424e5c31af7Sopenharmony_ci { 1425e5c31af7Sopenharmony_ci resources.push_back("gl_InvocationID"); 1426e5c31af7Sopenharmony_ci resources.push_back("gl_PerVertex.gl_Position"); 1427e5c31af7Sopenharmony_ci } 1428e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION) 1429e5c31af7Sopenharmony_ci resources.push_back("gl_PerVertex.gl_Position"); 1430e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_COMPUTE && resources.empty()) 1431e5c31af7Sopenharmony_ci resources.push_back("gl_NumWorkGroups"); // only read from when there are no other inputs 1432e5c31af7Sopenharmony_ci } 1433e5c31af7Sopenharmony_ci else if (interface == PROGRAMINTERFACE_PROGRAM_OUTPUT) 1434e5c31af7Sopenharmony_ci { 1435e5c31af7Sopenharmony_ci if (shaderType == glu::SHADERTYPE_VERTEX) 1436e5c31af7Sopenharmony_ci resources.push_back("gl_Position"); 1437e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty()) 1438e5c31af7Sopenharmony_ci resources.push_back("gl_FragDepth"); // only written to when there are no other outputs 1439e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_GEOMETRY) 1440e5c31af7Sopenharmony_ci resources.push_back("gl_Position"); 1441e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL) 1442e5c31af7Sopenharmony_ci { 1443e5c31af7Sopenharmony_ci resources.push_back("gl_PerVertex.gl_Position"); 1444e5c31af7Sopenharmony_ci resources.push_back("gl_TessLevelOuter[0]"); 1445e5c31af7Sopenharmony_ci resources.push_back("gl_TessLevelInner[0]"); 1446e5c31af7Sopenharmony_ci } 1447e5c31af7Sopenharmony_ci else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION) 1448e5c31af7Sopenharmony_ci resources.push_back("gl_Position"); 1449e5c31af7Sopenharmony_ci } 1450e5c31af7Sopenharmony_ci 1451e5c31af7Sopenharmony_ci break; 1452e5c31af7Sopenharmony_ci } 1453e5c31af7Sopenharmony_ci 1454e5c31af7Sopenharmony_ci case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING: 1455e5c31af7Sopenharmony_ci { 1456e5c31af7Sopenharmony_ci const glu::ShaderType xfbStage = getProgramTransformFeedbackStage(program); 1457e5c31af7Sopenharmony_ci 1458e5c31af7Sopenharmony_ci for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx) 1459e5c31af7Sopenharmony_ci { 1460e5c31af7Sopenharmony_ci const std::string& varyingName = program->getTransformFeedbackVaryings()[varyingNdx]; 1461e5c31af7Sopenharmony_ci 1462e5c31af7Sopenharmony_ci if (deStringBeginsWith(varyingName.c_str(), "gl_")) 1463e5c31af7Sopenharmony_ci resources.push_back(varyingName); // builtin 1464e5c31af7Sopenharmony_ci else 1465e5c31af7Sopenharmony_ci { 1466e5c31af7Sopenharmony_ci std::vector<VariablePathComponent> path; 1467e5c31af7Sopenharmony_ci 1468e5c31af7Sopenharmony_ci if (!traverseProgramVariablePath(path, program, varyingName, VariableSearchFilter::createShaderTypeStorageFilter(xfbStage, glu::STORAGE_OUT))) 1469e5c31af7Sopenharmony_ci DE_ASSERT(false); // Program failed validate, invalid operation 1470e5c31af7Sopenharmony_ci 1471e5c31af7Sopenharmony_ci generateVariableTypeResourceNames(resources, 1472e5c31af7Sopenharmony_ci varyingName, 1473e5c31af7Sopenharmony_ci *path.back().getVariableType(), 1474e5c31af7Sopenharmony_ci RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE); 1475e5c31af7Sopenharmony_ci } 1476e5c31af7Sopenharmony_ci } 1477e5c31af7Sopenharmony_ci 1478e5c31af7Sopenharmony_ci break; 1479e5c31af7Sopenharmony_ci } 1480e5c31af7Sopenharmony_ci 1481e5c31af7Sopenharmony_ci default: 1482e5c31af7Sopenharmony_ci DE_ASSERT(false); 1483e5c31af7Sopenharmony_ci } 1484e5c31af7Sopenharmony_ci 1485e5c31af7Sopenharmony_ci if (removeDuplicated) 1486e5c31af7Sopenharmony_ci { 1487e5c31af7Sopenharmony_ci std::set<std::string> addedVariables; 1488e5c31af7Sopenharmony_ci std::vector<std::string> uniqueResouces; 1489e5c31af7Sopenharmony_ci 1490e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)resources.size(); ++ndx) 1491e5c31af7Sopenharmony_ci { 1492e5c31af7Sopenharmony_ci if (addedVariables.find(resources[ndx]) == addedVariables.end()) 1493e5c31af7Sopenharmony_ci { 1494e5c31af7Sopenharmony_ci addedVariables.insert(resources[ndx]); 1495e5c31af7Sopenharmony_ci uniqueResouces.push_back(resources[ndx]); 1496e5c31af7Sopenharmony_ci } 1497e5c31af7Sopenharmony_ci } 1498e5c31af7Sopenharmony_ci 1499e5c31af7Sopenharmony_ci uniqueResouces.swap(resources); 1500e5c31af7Sopenharmony_ci } 1501e5c31af7Sopenharmony_ci 1502e5c31af7Sopenharmony_ci return resources; 1503e5c31af7Sopenharmony_ci} 1504e5c31af7Sopenharmony_ci 1505e5c31af7Sopenharmony_ci/** 1506e5c31af7Sopenharmony_ci * Name of the unused uniform added by generateProgramInterfaceProgramSources 1507e5c31af7Sopenharmony_ci * 1508e5c31af7Sopenharmony_ci * A uniform named "unusedZero" is added by 1509e5c31af7Sopenharmony_ci * generateProgramInterfaceProgramSources. It is used in expressions to 1510e5c31af7Sopenharmony_ci * prevent various program resources from being eliminated by the GLSL 1511e5c31af7Sopenharmony_ci * compiler's optimizer. 1512e5c31af7Sopenharmony_ci * 1513e5c31af7Sopenharmony_ci * \sa deqp::gles31::Functional::ProgramInterfaceDefinition::generateProgramInterfaceProgramSources 1514e5c31af7Sopenharmony_ci */ 1515e5c31af7Sopenharmony_ciconst char* getUnusedZeroUniformName() 1516e5c31af7Sopenharmony_ci{ 1517e5c31af7Sopenharmony_ci return "unusedZero"; 1518e5c31af7Sopenharmony_ci} 1519e5c31af7Sopenharmony_ci 1520e5c31af7Sopenharmony_ciglu::ProgramSources generateProgramInterfaceProgramSources (const ProgramInterfaceDefinition::Program* program) 1521e5c31af7Sopenharmony_ci{ 1522e5c31af7Sopenharmony_ci glu::ProgramSources sources; 1523e5c31af7Sopenharmony_ci 1524e5c31af7Sopenharmony_ci DE_ASSERT(program->isValid()); 1525e5c31af7Sopenharmony_ci 1526e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 1527e5c31af7Sopenharmony_ci { 1528e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx]; 1529e5c31af7Sopenharmony_ci bool containsUserDefinedOutputs = false; 1530e5c31af7Sopenharmony_ci bool containsUserDefinedInputs = false; 1531e5c31af7Sopenharmony_ci std::ostringstream sourceBuf; 1532e5c31af7Sopenharmony_ci std::ostringstream usageBuf; 1533e5c31af7Sopenharmony_ci 1534e5c31af7Sopenharmony_ci sourceBuf << glu::getGLSLVersionDeclaration(shader->getVersion()) << "\n" 1535e5c31af7Sopenharmony_ci << getShaderExtensionDeclarations(shader) 1536e5c31af7Sopenharmony_ci << getShaderTypeDeclarations(program, shader) 1537e5c31af7Sopenharmony_ci << "\n"; 1538e5c31af7Sopenharmony_ci 1539e5c31af7Sopenharmony_ci // Struct definitions 1540e5c31af7Sopenharmony_ci 1541e5c31af7Sopenharmony_ci writeStructureDefinitions(sourceBuf, shader->getDefaultBlock()); 1542e5c31af7Sopenharmony_ci 1543e5c31af7Sopenharmony_ci // variables in the default scope 1544e5c31af7Sopenharmony_ci 1545e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx) 1546e5c31af7Sopenharmony_ci sourceBuf << shader->getDefaultBlock().variables[ndx] << ";\n"; 1547e5c31af7Sopenharmony_ci 1548e5c31af7Sopenharmony_ci if (!shader->getDefaultBlock().variables.empty()) 1549e5c31af7Sopenharmony_ci sourceBuf << "\n"; 1550e5c31af7Sopenharmony_ci 1551e5c31af7Sopenharmony_ci // Interface blocks 1552e5c31af7Sopenharmony_ci 1553e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx) 1554e5c31af7Sopenharmony_ci writeInterfaceBlock(sourceBuf, shader->getDefaultBlock().interfaceBlocks[ndx]); 1555e5c31af7Sopenharmony_ci 1556e5c31af7Sopenharmony_ci // Use inputs and outputs so that they won't be removed by the optimizer 1557e5c31af7Sopenharmony_ci 1558e5c31af7Sopenharmony_ci usageBuf << "highp uniform vec4 " << getUnusedZeroUniformName() << "; // Default value is vec4(0.0).\n" 1559e5c31af7Sopenharmony_ci "highp vec4 readInputs()\n" 1560e5c31af7Sopenharmony_ci "{\n" 1561e5c31af7Sopenharmony_ci " highp vec4 retValue = " << getUnusedZeroUniformName() << ";\n"; 1562e5c31af7Sopenharmony_ci 1563e5c31af7Sopenharmony_ci // User-defined inputs 1564e5c31af7Sopenharmony_ci 1565e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx) 1566e5c31af7Sopenharmony_ci { 1567e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_IN || 1568e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_PATCH_IN || 1569e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_UNIFORM) 1570e5c31af7Sopenharmony_ci { 1571e5c31af7Sopenharmony_ci writeVariableReadAccumulateExpression(usageBuf, 1572e5c31af7Sopenharmony_ci "retValue", 1573e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[ndx].name, 1574e5c31af7Sopenharmony_ci shader->getType(), 1575e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[ndx].storage, 1576e5c31af7Sopenharmony_ci program, 1577e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[ndx].varType); 1578e5c31af7Sopenharmony_ci containsUserDefinedInputs = true; 1579e5c31af7Sopenharmony_ci } 1580e5c31af7Sopenharmony_ci } 1581e5c31af7Sopenharmony_ci 1582e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx) 1583e5c31af7Sopenharmony_ci { 1584e5c31af7Sopenharmony_ci const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx]; 1585e5c31af7Sopenharmony_ci if (isReadableInterface(interface)) 1586e5c31af7Sopenharmony_ci { 1587e5c31af7Sopenharmony_ci writeInterfaceReadAccumulateExpression(usageBuf, 1588e5c31af7Sopenharmony_ci "retValue", 1589e5c31af7Sopenharmony_ci interface, 1590e5c31af7Sopenharmony_ci shader->getType(), 1591e5c31af7Sopenharmony_ci program); 1592e5c31af7Sopenharmony_ci containsUserDefinedInputs = true; 1593e5c31af7Sopenharmony_ci } 1594e5c31af7Sopenharmony_ci } 1595e5c31af7Sopenharmony_ci 1596e5c31af7Sopenharmony_ci // Built-in-inputs 1597e5c31af7Sopenharmony_ci 1598e5c31af7Sopenharmony_ci switch (shader->getType()) 1599e5c31af7Sopenharmony_ci { 1600e5c31af7Sopenharmony_ci case glu::SHADERTYPE_VERTEX: 1601e5c31af7Sopenharmony_ci // make readInputs to never be compile time constant 1602e5c31af7Sopenharmony_ci if (!containsUserDefinedInputs) 1603e5c31af7Sopenharmony_ci usageBuf << " retValue += vec4(float(gl_VertexID));\n"; 1604e5c31af7Sopenharmony_ci break; 1605e5c31af7Sopenharmony_ci 1606e5c31af7Sopenharmony_ci case glu::SHADERTYPE_FRAGMENT: 1607e5c31af7Sopenharmony_ci // make readInputs to never be compile time constant 1608e5c31af7Sopenharmony_ci if (!containsUserDefinedInputs) 1609e5c31af7Sopenharmony_ci usageBuf << " retValue += gl_FragCoord;\n"; 1610e5c31af7Sopenharmony_ci break; 1611e5c31af7Sopenharmony_ci case glu::SHADERTYPE_GEOMETRY: 1612e5c31af7Sopenharmony_ci // always use previous stage's output values so that previous stage won't be optimized out 1613e5c31af7Sopenharmony_ci usageBuf << " retValue += gl_in[0].gl_Position;\n"; 1614e5c31af7Sopenharmony_ci break; 1615e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_CONTROL: 1616e5c31af7Sopenharmony_ci // always use previous stage's output values so that previous stage won't be optimized out 1617e5c31af7Sopenharmony_ci usageBuf << " retValue += gl_in[0].gl_Position;\n"; 1618e5c31af7Sopenharmony_ci break; 1619e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_EVALUATION: 1620e5c31af7Sopenharmony_ci // always use previous stage's output values so that previous stage won't be optimized out 1621e5c31af7Sopenharmony_ci usageBuf << " retValue += gl_in[0].gl_Position;\n"; 1622e5c31af7Sopenharmony_ci break; 1623e5c31af7Sopenharmony_ci 1624e5c31af7Sopenharmony_ci case glu::SHADERTYPE_COMPUTE: 1625e5c31af7Sopenharmony_ci // make readInputs to never be compile time constant 1626e5c31af7Sopenharmony_ci if (!containsUserDefinedInputs) 1627e5c31af7Sopenharmony_ci usageBuf << " retValue += vec4(float(gl_NumWorkGroups.x));\n"; 1628e5c31af7Sopenharmony_ci break; 1629e5c31af7Sopenharmony_ci default: 1630e5c31af7Sopenharmony_ci DE_ASSERT(false); 1631e5c31af7Sopenharmony_ci } 1632e5c31af7Sopenharmony_ci 1633e5c31af7Sopenharmony_ci usageBuf << " return retValue;\n" 1634e5c31af7Sopenharmony_ci "}\n\n"; 1635e5c31af7Sopenharmony_ci 1636e5c31af7Sopenharmony_ci usageBuf << "void writeOutputs(in highp vec4 unusedValue)\n" 1637e5c31af7Sopenharmony_ci "{\n"; 1638e5c31af7Sopenharmony_ci 1639e5c31af7Sopenharmony_ci // User-defined outputs 1640e5c31af7Sopenharmony_ci 1641e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx) 1642e5c31af7Sopenharmony_ci { 1643e5c31af7Sopenharmony_ci if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT || 1644e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_PATCH_OUT) 1645e5c31af7Sopenharmony_ci { 1646e5c31af7Sopenharmony_ci writeVariableWriteExpression(usageBuf, 1647e5c31af7Sopenharmony_ci "unusedValue", 1648e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[ndx].name, 1649e5c31af7Sopenharmony_ci shader->getType(), 1650e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[ndx].storage, 1651e5c31af7Sopenharmony_ci program, 1652e5c31af7Sopenharmony_ci shader->getDefaultBlock().variables[ndx].varType); 1653e5c31af7Sopenharmony_ci containsUserDefinedOutputs = true; 1654e5c31af7Sopenharmony_ci } 1655e5c31af7Sopenharmony_ci } 1656e5c31af7Sopenharmony_ci 1657e5c31af7Sopenharmony_ci for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx) 1658e5c31af7Sopenharmony_ci { 1659e5c31af7Sopenharmony_ci const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx]; 1660e5c31af7Sopenharmony_ci if (isWritableInterface(interface)) 1661e5c31af7Sopenharmony_ci { 1662e5c31af7Sopenharmony_ci writeInterfaceWriteExpression(usageBuf, "unusedValue", interface, shader->getType(), program); 1663e5c31af7Sopenharmony_ci containsUserDefinedOutputs = true; 1664e5c31af7Sopenharmony_ci } 1665e5c31af7Sopenharmony_ci } 1666e5c31af7Sopenharmony_ci 1667e5c31af7Sopenharmony_ci // Builtin-outputs that must be written to 1668e5c31af7Sopenharmony_ci 1669e5c31af7Sopenharmony_ci if (shader->getType() == glu::SHADERTYPE_VERTEX) 1670e5c31af7Sopenharmony_ci usageBuf << " gl_Position = unusedValue;\n"; 1671e5c31af7Sopenharmony_ci else if (shader->getType() == glu::SHADERTYPE_GEOMETRY) 1672e5c31af7Sopenharmony_ci usageBuf << " gl_Position = unusedValue;\n" 1673e5c31af7Sopenharmony_ci " EmitVertex();\n"; 1674e5c31af7Sopenharmony_ci else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL) 1675e5c31af7Sopenharmony_ci usageBuf << " gl_out[gl_InvocationID].gl_Position = unusedValue;\n" 1676e5c31af7Sopenharmony_ci " gl_TessLevelOuter[0] = 2.8;\n" 1677e5c31af7Sopenharmony_ci " gl_TessLevelOuter[1] = 2.8;\n" 1678e5c31af7Sopenharmony_ci " gl_TessLevelOuter[2] = 2.8;\n" 1679e5c31af7Sopenharmony_ci " gl_TessLevelOuter[3] = 2.8;\n" 1680e5c31af7Sopenharmony_ci " gl_TessLevelInner[0] = 2.8;\n" 1681e5c31af7Sopenharmony_ci " gl_TessLevelInner[1] = 2.8;\n"; 1682e5c31af7Sopenharmony_ci else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION) 1683e5c31af7Sopenharmony_ci usageBuf << " gl_Position = unusedValue;\n"; 1684e5c31af7Sopenharmony_ci 1685e5c31af7Sopenharmony_ci // Output to sink input data to 1686e5c31af7Sopenharmony_ci 1687e5c31af7Sopenharmony_ci if (!containsUserDefinedOutputs) 1688e5c31af7Sopenharmony_ci { 1689e5c31af7Sopenharmony_ci if (shader->getType() == glu::SHADERTYPE_FRAGMENT) 1690e5c31af7Sopenharmony_ci usageBuf << " gl_FragDepth = dot(unusedValue.xy, unusedValue.xw);\n"; 1691e5c31af7Sopenharmony_ci else if (shader->getType() == glu::SHADERTYPE_COMPUTE) 1692e5c31af7Sopenharmony_ci usageBuf << " unusedOutputBlock.unusedValue = unusedValue;\n"; 1693e5c31af7Sopenharmony_ci } 1694e5c31af7Sopenharmony_ci 1695e5c31af7Sopenharmony_ci usageBuf << "}\n\n" 1696e5c31af7Sopenharmony_ci "void main()\n" 1697e5c31af7Sopenharmony_ci "{\n" 1698e5c31af7Sopenharmony_ci " writeOutputs(readInputs());\n" 1699e5c31af7Sopenharmony_ci "}\n"; 1700e5c31af7Sopenharmony_ci 1701e5c31af7Sopenharmony_ci // Interface for unused output 1702e5c31af7Sopenharmony_ci 1703e5c31af7Sopenharmony_ci if (shader->getType() == glu::SHADERTYPE_COMPUTE && !containsUserDefinedOutputs) 1704e5c31af7Sopenharmony_ci { 1705e5c31af7Sopenharmony_ci sourceBuf << "writeonly buffer UnusedOutputInterface\n" 1706e5c31af7Sopenharmony_ci << "{\n" 1707e5c31af7Sopenharmony_ci << " highp vec4 unusedValue;\n" 1708e5c31af7Sopenharmony_ci << "} unusedOutputBlock;\n\n"; 1709e5c31af7Sopenharmony_ci } 1710e5c31af7Sopenharmony_ci 1711e5c31af7Sopenharmony_ci sources << glu::ShaderSource(shader->getType(), sourceBuf.str() + usageBuf.str()); 1712e5c31af7Sopenharmony_ci } 1713e5c31af7Sopenharmony_ci 1714e5c31af7Sopenharmony_ci if (program->isSeparable()) 1715e5c31af7Sopenharmony_ci sources << glu::ProgramSeparable(true); 1716e5c31af7Sopenharmony_ci 1717e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx) 1718e5c31af7Sopenharmony_ci sources << glu::TransformFeedbackVarying(program->getTransformFeedbackVaryings()[ndx]); 1719e5c31af7Sopenharmony_ci 1720e5c31af7Sopenharmony_ci if (program->getTransformFeedbackMode()) 1721e5c31af7Sopenharmony_ci sources << glu::TransformFeedbackMode(program->getTransformFeedbackMode()); 1722e5c31af7Sopenharmony_ci 1723e5c31af7Sopenharmony_ci return sources; 1724e5c31af7Sopenharmony_ci} 1725e5c31af7Sopenharmony_ci 1726e5c31af7Sopenharmony_cibool findProgramVariablePathByPathName (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& pathName, const VariableSearchFilter& filter) 1727e5c31af7Sopenharmony_ci{ 1728e5c31af7Sopenharmony_ci std::vector<VariablePathComponent> modifiedPath; 1729e5c31af7Sopenharmony_ci 1730e5c31af7Sopenharmony_ci if (!traverseProgramVariablePath(modifiedPath, program, pathName, filter)) 1731e5c31af7Sopenharmony_ci return false; 1732e5c31af7Sopenharmony_ci 1733e5c31af7Sopenharmony_ci // modify param only on success 1734e5c31af7Sopenharmony_ci typePath.swap(modifiedPath); 1735e5c31af7Sopenharmony_ci return true; 1736e5c31af7Sopenharmony_ci} 1737e5c31af7Sopenharmony_ci 1738e5c31af7Sopenharmony_ciProgramInterfaceDefinition::ShaderResourceUsage getShaderResourceUsage (const ProgramInterfaceDefinition::Program* program, const ProgramInterfaceDefinition::Shader* shader) 1739e5c31af7Sopenharmony_ci{ 1740e5c31af7Sopenharmony_ci ProgramInterfaceDefinition::ShaderResourceUsage retVal; 1741e5c31af7Sopenharmony_ci 1742e5c31af7Sopenharmony_ci retVal.numInputs = getNumTypeInstances(shader, glu::STORAGE_IN); 1743e5c31af7Sopenharmony_ci retVal.numInputVectors = getNumVectors(shader, glu::STORAGE_IN); 1744e5c31af7Sopenharmony_ci retVal.numInputComponents = getNumComponents(shader, glu::STORAGE_IN); 1745e5c31af7Sopenharmony_ci 1746e5c31af7Sopenharmony_ci retVal.numOutputs = getNumTypeInstances(shader, glu::STORAGE_OUT); 1747e5c31af7Sopenharmony_ci retVal.numOutputVectors = getNumVectors(shader, glu::STORAGE_OUT); 1748e5c31af7Sopenharmony_ci retVal.numOutputComponents = getNumComponents(shader, glu::STORAGE_OUT); 1749e5c31af7Sopenharmony_ci 1750e5c31af7Sopenharmony_ci retVal.numPatchInputComponents = getNumComponents(shader, glu::STORAGE_PATCH_IN); 1751e5c31af7Sopenharmony_ci retVal.numPatchOutputComponents = getNumComponents(shader, glu::STORAGE_PATCH_OUT); 1752e5c31af7Sopenharmony_ci 1753e5c31af7Sopenharmony_ci retVal.numDefaultBlockUniformComponents = getNumDefaultBlockComponents(shader, glu::STORAGE_UNIFORM); 1754e5c31af7Sopenharmony_ci retVal.numCombinedUniformComponents = getNumComponents(shader, glu::STORAGE_UNIFORM); 1755e5c31af7Sopenharmony_ci retVal.numUniformVectors = getNumVectors(shader, glu::STORAGE_UNIFORM); 1756e5c31af7Sopenharmony_ci 1757e5c31af7Sopenharmony_ci retVal.numSamplers = getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler); 1758e5c31af7Sopenharmony_ci retVal.numImages = getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage); 1759e5c31af7Sopenharmony_ci 1760e5c31af7Sopenharmony_ci retVal.numAtomicCounterBuffers = getNumAtomicCounterBuffers(shader); 1761e5c31af7Sopenharmony_ci retVal.numAtomicCounters = getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter); 1762e5c31af7Sopenharmony_ci 1763e5c31af7Sopenharmony_ci retVal.numUniformBlocks = getNumShaderBlocks(shader, glu::STORAGE_UNIFORM); 1764e5c31af7Sopenharmony_ci retVal.numShaderStorageBlocks = getNumShaderBlocks(shader, glu::STORAGE_BUFFER); 1765e5c31af7Sopenharmony_ci 1766e5c31af7Sopenharmony_ci // add builtins 1767e5c31af7Sopenharmony_ci switch (shader->getType()) 1768e5c31af7Sopenharmony_ci { 1769e5c31af7Sopenharmony_ci case glu::SHADERTYPE_VERTEX: 1770e5c31af7Sopenharmony_ci // gl_Position is not counted 1771e5c31af7Sopenharmony_ci break; 1772e5c31af7Sopenharmony_ci 1773e5c31af7Sopenharmony_ci case glu::SHADERTYPE_FRAGMENT: 1774e5c31af7Sopenharmony_ci // nada 1775e5c31af7Sopenharmony_ci break; 1776e5c31af7Sopenharmony_ci 1777e5c31af7Sopenharmony_ci case glu::SHADERTYPE_GEOMETRY: 1778e5c31af7Sopenharmony_ci // gl_Position in (point mode => size 1) 1779e5c31af7Sopenharmony_ci retVal.numInputs += 1; 1780e5c31af7Sopenharmony_ci retVal.numInputVectors += 1; 1781e5c31af7Sopenharmony_ci retVal.numInputComponents += 4; 1782e5c31af7Sopenharmony_ci 1783e5c31af7Sopenharmony_ci // gl_Position out 1784e5c31af7Sopenharmony_ci retVal.numOutputs += 1; 1785e5c31af7Sopenharmony_ci retVal.numOutputVectors += 1; 1786e5c31af7Sopenharmony_ci retVal.numOutputComponents += 4; 1787e5c31af7Sopenharmony_ci break; 1788e5c31af7Sopenharmony_ci 1789e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_CONTROL: 1790e5c31af7Sopenharmony_ci // gl_Position in is read up to gl_InstanceID 1791e5c31af7Sopenharmony_ci retVal.numInputs += 1 * program->getTessellationNumOutputPatchVertices(); 1792e5c31af7Sopenharmony_ci retVal.numInputVectors += 1 * program->getTessellationNumOutputPatchVertices(); 1793e5c31af7Sopenharmony_ci retVal.numInputComponents += 4 * program->getTessellationNumOutputPatchVertices(); 1794e5c31af7Sopenharmony_ci 1795e5c31af7Sopenharmony_ci // gl_Position out, size = num patch out vertices 1796e5c31af7Sopenharmony_ci retVal.numOutputs += 1 * program->getTessellationNumOutputPatchVertices(); 1797e5c31af7Sopenharmony_ci retVal.numOutputVectors += 1 * program->getTessellationNumOutputPatchVertices(); 1798e5c31af7Sopenharmony_ci retVal.numOutputComponents += 4 * program->getTessellationNumOutputPatchVertices(); 1799e5c31af7Sopenharmony_ci break; 1800e5c31af7Sopenharmony_ci 1801e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_EVALUATION: 1802e5c31af7Sopenharmony_ci // gl_Position in is read up to gl_InstanceID 1803e5c31af7Sopenharmony_ci retVal.numInputs += 1 * program->getTessellationNumOutputPatchVertices(); 1804e5c31af7Sopenharmony_ci retVal.numInputVectors += 1 * program->getTessellationNumOutputPatchVertices(); 1805e5c31af7Sopenharmony_ci retVal.numInputComponents += 4 * program->getTessellationNumOutputPatchVertices(); 1806e5c31af7Sopenharmony_ci 1807e5c31af7Sopenharmony_ci // gl_Position out 1808e5c31af7Sopenharmony_ci retVal.numOutputs += 1; 1809e5c31af7Sopenharmony_ci retVal.numOutputVectors += 1; 1810e5c31af7Sopenharmony_ci retVal.numOutputComponents += 4; 1811e5c31af7Sopenharmony_ci break; 1812e5c31af7Sopenharmony_ci 1813e5c31af7Sopenharmony_ci case glu::SHADERTYPE_COMPUTE: 1814e5c31af7Sopenharmony_ci // nada 1815e5c31af7Sopenharmony_ci break; 1816e5c31af7Sopenharmony_ci 1817e5c31af7Sopenharmony_ci default: 1818e5c31af7Sopenharmony_ci DE_ASSERT(false); 1819e5c31af7Sopenharmony_ci break; 1820e5c31af7Sopenharmony_ci } 1821e5c31af7Sopenharmony_ci return retVal; 1822e5c31af7Sopenharmony_ci} 1823e5c31af7Sopenharmony_ci 1824e5c31af7Sopenharmony_ciProgramInterfaceDefinition::ProgramResourceUsage getCombinedProgramResourceUsage (const ProgramInterfaceDefinition::Program* program) 1825e5c31af7Sopenharmony_ci{ 1826e5c31af7Sopenharmony_ci ProgramInterfaceDefinition::ProgramResourceUsage retVal; 1827e5c31af7Sopenharmony_ci int numVertexOutputComponents = 0; 1828e5c31af7Sopenharmony_ci int numFragmentInputComponents = 0; 1829e5c31af7Sopenharmony_ci int numVertexOutputVectors = 0; 1830e5c31af7Sopenharmony_ci int numFragmentInputVectors = 0; 1831e5c31af7Sopenharmony_ci 1832e5c31af7Sopenharmony_ci retVal.uniformBufferMaxBinding = -1; // max binding is inclusive upper bound. Allow 0 bindings by using negative value 1833e5c31af7Sopenharmony_ci retVal.uniformBufferMaxSize = 0; 1834e5c31af7Sopenharmony_ci retVal.numUniformBlocks = 0; 1835e5c31af7Sopenharmony_ci retVal.numCombinedVertexUniformComponents = 0; 1836e5c31af7Sopenharmony_ci retVal.numCombinedFragmentUniformComponents = 0; 1837e5c31af7Sopenharmony_ci retVal.numCombinedGeometryUniformComponents = 0; 1838e5c31af7Sopenharmony_ci retVal.numCombinedTessControlUniformComponents = 0; 1839e5c31af7Sopenharmony_ci retVal.numCombinedTessEvalUniformComponents = 0; 1840e5c31af7Sopenharmony_ci retVal.shaderStorageBufferMaxBinding = -1; // see above 1841e5c31af7Sopenharmony_ci retVal.shaderStorageBufferMaxSize = 0; 1842e5c31af7Sopenharmony_ci retVal.numShaderStorageBlocks = 0; 1843e5c31af7Sopenharmony_ci retVal.numVaryingComponents = 0; 1844e5c31af7Sopenharmony_ci retVal.numVaryingVectors = 0; 1845e5c31af7Sopenharmony_ci retVal.numCombinedSamplers = 0; 1846e5c31af7Sopenharmony_ci retVal.atomicCounterBufferMaxBinding = -1; // see above 1847e5c31af7Sopenharmony_ci retVal.atomicCounterBufferMaxSize = 0; 1848e5c31af7Sopenharmony_ci retVal.numAtomicCounterBuffers = 0; 1849e5c31af7Sopenharmony_ci retVal.numAtomicCounters = 0; 1850e5c31af7Sopenharmony_ci retVal.maxImageBinding = -1; // see above 1851e5c31af7Sopenharmony_ci retVal.numCombinedImages = 0; 1852e5c31af7Sopenharmony_ci retVal.numCombinedOutputResources = 0; 1853e5c31af7Sopenharmony_ci retVal.numXFBInterleavedComponents = 0; 1854e5c31af7Sopenharmony_ci retVal.numXFBSeparateAttribs = 0; 1855e5c31af7Sopenharmony_ci retVal.numXFBSeparateComponents = 0; 1856e5c31af7Sopenharmony_ci retVal.fragmentOutputMaxBinding = -1; // see above 1857e5c31af7Sopenharmony_ci 1858e5c31af7Sopenharmony_ci for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx) 1859e5c31af7Sopenharmony_ci { 1860e5c31af7Sopenharmony_ci const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx]; 1861e5c31af7Sopenharmony_ci 1862e5c31af7Sopenharmony_ci retVal.uniformBufferMaxBinding = de::max(retVal.uniformBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_UNIFORM)); 1863e5c31af7Sopenharmony_ci retVal.uniformBufferMaxSize = de::max(retVal.uniformBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_UNIFORM)); 1864e5c31af7Sopenharmony_ci retVal.numUniformBlocks += getNumShaderBlocks(shader, glu::STORAGE_UNIFORM); 1865e5c31af7Sopenharmony_ci 1866e5c31af7Sopenharmony_ci switch (shader->getType()) 1867e5c31af7Sopenharmony_ci { 1868e5c31af7Sopenharmony_ci case glu::SHADERTYPE_VERTEX: retVal.numCombinedVertexUniformComponents += getNumComponents(shader, glu::STORAGE_UNIFORM); break; 1869e5c31af7Sopenharmony_ci case glu::SHADERTYPE_FRAGMENT: retVal.numCombinedFragmentUniformComponents += getNumComponents(shader, glu::STORAGE_UNIFORM); break; 1870e5c31af7Sopenharmony_ci case glu::SHADERTYPE_GEOMETRY: retVal.numCombinedGeometryUniformComponents += getNumComponents(shader, glu::STORAGE_UNIFORM); break; 1871e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_CONTROL: retVal.numCombinedTessControlUniformComponents += getNumComponents(shader, glu::STORAGE_UNIFORM); break; 1872e5c31af7Sopenharmony_ci case glu::SHADERTYPE_TESSELLATION_EVALUATION: retVal.numCombinedTessEvalUniformComponents += getNumComponents(shader, glu::STORAGE_UNIFORM); break; 1873e5c31af7Sopenharmony_ci default: break; 1874e5c31af7Sopenharmony_ci } 1875e5c31af7Sopenharmony_ci 1876e5c31af7Sopenharmony_ci retVal.shaderStorageBufferMaxBinding = de::max(retVal.shaderStorageBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_BUFFER)); 1877e5c31af7Sopenharmony_ci retVal.shaderStorageBufferMaxSize = de::max(retVal.shaderStorageBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_BUFFER)); 1878e5c31af7Sopenharmony_ci retVal.numShaderStorageBlocks += getNumShaderBlocks(shader, glu::STORAGE_BUFFER); 1879e5c31af7Sopenharmony_ci 1880e5c31af7Sopenharmony_ci if (shader->getType() == glu::SHADERTYPE_VERTEX) 1881e5c31af7Sopenharmony_ci { 1882e5c31af7Sopenharmony_ci numVertexOutputComponents += getNumComponents(shader, glu::STORAGE_OUT); 1883e5c31af7Sopenharmony_ci numVertexOutputVectors += getNumVectors(shader, glu::STORAGE_OUT); 1884e5c31af7Sopenharmony_ci } 1885e5c31af7Sopenharmony_ci else if (shader->getType() == glu::SHADERTYPE_FRAGMENT) 1886e5c31af7Sopenharmony_ci { 1887e5c31af7Sopenharmony_ci numFragmentInputComponents += getNumComponents(shader, glu::STORAGE_IN); 1888e5c31af7Sopenharmony_ci numFragmentInputVectors += getNumVectors(shader, glu::STORAGE_IN); 1889e5c31af7Sopenharmony_ci } 1890e5c31af7Sopenharmony_ci 1891e5c31af7Sopenharmony_ci retVal.numCombinedSamplers += getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler); 1892e5c31af7Sopenharmony_ci 1893e5c31af7Sopenharmony_ci retVal.atomicCounterBufferMaxBinding = de::max(retVal.atomicCounterBufferMaxBinding, getAtomicCounterMaxBinding(shader)); 1894e5c31af7Sopenharmony_ci retVal.atomicCounterBufferMaxSize = de::max(retVal.atomicCounterBufferMaxSize, getAtomicCounterMaxBufferSize(shader)); 1895e5c31af7Sopenharmony_ci retVal.numAtomicCounterBuffers += getNumAtomicCounterBuffers(shader); 1896e5c31af7Sopenharmony_ci retVal.numAtomicCounters += getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter); 1897e5c31af7Sopenharmony_ci retVal.maxImageBinding = de::max(retVal.maxImageBinding, getUniformMaxBinding(shader, glu::isDataTypeImage)); 1898e5c31af7Sopenharmony_ci retVal.numCombinedImages += getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage); 1899e5c31af7Sopenharmony_ci 1900e5c31af7Sopenharmony_ci retVal.numCombinedOutputResources += getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage); 1901e5c31af7Sopenharmony_ci retVal.numCombinedOutputResources += getNumShaderBlocks(shader, glu::STORAGE_BUFFER); 1902e5c31af7Sopenharmony_ci 1903e5c31af7Sopenharmony_ci if (shader->getType() == glu::SHADERTYPE_FRAGMENT) 1904e5c31af7Sopenharmony_ci { 1905e5c31af7Sopenharmony_ci retVal.numCombinedOutputResources += getNumVectors(shader, glu::STORAGE_OUT); 1906e5c31af7Sopenharmony_ci retVal.fragmentOutputMaxBinding = de::max(retVal.fragmentOutputMaxBinding, getFragmentOutputMaxLocation(shader)); 1907e5c31af7Sopenharmony_ci } 1908e5c31af7Sopenharmony_ci } 1909e5c31af7Sopenharmony_ci 1910e5c31af7Sopenharmony_ci if (program->getTransformFeedbackMode() == GL_INTERLEAVED_ATTRIBS) 1911e5c31af7Sopenharmony_ci retVal.numXFBInterleavedComponents = getNumXFBComponents(program); 1912e5c31af7Sopenharmony_ci else if (program->getTransformFeedbackMode() == GL_SEPARATE_ATTRIBS) 1913e5c31af7Sopenharmony_ci { 1914e5c31af7Sopenharmony_ci retVal.numXFBSeparateAttribs = (int)program->getTransformFeedbackVaryings().size(); 1915e5c31af7Sopenharmony_ci retVal.numXFBSeparateComponents = getNumMaxXFBOutputComponents(program); 1916e5c31af7Sopenharmony_ci } 1917e5c31af7Sopenharmony_ci 1918e5c31af7Sopenharmony_ci // legacy limits 1919e5c31af7Sopenharmony_ci retVal.numVaryingComponents = de::max(numVertexOutputComponents, numFragmentInputComponents); 1920e5c31af7Sopenharmony_ci retVal.numVaryingVectors = de::max(numVertexOutputVectors, numFragmentInputVectors); 1921e5c31af7Sopenharmony_ci 1922e5c31af7Sopenharmony_ci return retVal; 1923e5c31af7Sopenharmony_ci} 1924e5c31af7Sopenharmony_ci 1925e5c31af7Sopenharmony_ci} // Functional 1926e5c31af7Sopenharmony_ci} // gles31 1927e5c31af7Sopenharmony_ci} // deqp 1928