1617a3babSopenharmony_ci// 2617a3babSopenharmony_ci// Copyright (C) 2016-2017 Google, Inc. 3617a3babSopenharmony_ci// Copyright (C) 2020 The Khronos Group Inc. 4617a3babSopenharmony_ci// 5617a3babSopenharmony_ci// All rights reserved. 6617a3babSopenharmony_ci// 7617a3babSopenharmony_ci// Redistribution and use in source and binary forms, with or without 8617a3babSopenharmony_ci// modification, are permitted provided that the following conditions 9617a3babSopenharmony_ci// are met: 10617a3babSopenharmony_ci// 11617a3babSopenharmony_ci// Redistributions of source code must retain the above copyright 12617a3babSopenharmony_ci// notice, this list of conditions and the following disclaimer. 13617a3babSopenharmony_ci// 14617a3babSopenharmony_ci// Redistributions in binary form must reproduce the above 15617a3babSopenharmony_ci// copyright notice, this list of conditions and the following 16617a3babSopenharmony_ci// disclaimer in the documentation and/or other materials provided 17617a3babSopenharmony_ci// with the distribution. 18617a3babSopenharmony_ci// 19617a3babSopenharmony_ci// Neither the name of 3Dlabs Inc. Ltd. nor the names of its 20617a3babSopenharmony_ci// contributors may be used to endorse or promote products derived 21617a3babSopenharmony_ci// from this software without specific prior written permission. 22617a3babSopenharmony_ci// 23617a3babSopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24617a3babSopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25617a3babSopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26617a3babSopenharmony_ci// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27617a3babSopenharmony_ci// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28617a3babSopenharmony_ci// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29617a3babSopenharmony_ci// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30617a3babSopenharmony_ci// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31617a3babSopenharmony_ci// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32617a3babSopenharmony_ci// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33617a3babSopenharmony_ci// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34617a3babSopenharmony_ci// POSSIBILITY OF SUCH DAMAGE. 35617a3babSopenharmony_ci// 36617a3babSopenharmony_ci#include <algorithm> 37617a3babSopenharmony_ci 38617a3babSopenharmony_ci#include <gtest/gtest.h> 39617a3babSopenharmony_ci 40617a3babSopenharmony_ci#include "TestFixture.h" 41617a3babSopenharmony_ci 42617a3babSopenharmony_ci#include "glslang/MachineIndependent/iomapper.h" 43617a3babSopenharmony_ci#include "glslang/MachineIndependent/reflection.h" 44617a3babSopenharmony_ci 45617a3babSopenharmony_cinamespace glslangtest { 46617a3babSopenharmony_cinamespace { 47617a3babSopenharmony_ci 48617a3babSopenharmony_cistruct IoMapData { 49617a3babSopenharmony_ci std::vector<std::string> fileNames; 50617a3babSopenharmony_ci Semantics semantics; 51617a3babSopenharmony_ci}; 52617a3babSopenharmony_ci 53617a3babSopenharmony_ciusing GlslMapIOTest = GlslangTest <::testing::TestWithParam<IoMapData>>; 54617a3babSopenharmony_ci 55617a3babSopenharmony_citemplate<class T> 56617a3babSopenharmony_cistd::string interfaceName(T symbol) { 57617a3babSopenharmony_ci return symbol.getType()->getBasicType() == glslang::EbtBlock ? std::string(symbol.getType()->getTypeName().c_str()) : symbol.name; 58617a3babSopenharmony_ci} 59617a3babSopenharmony_ci 60617a3babSopenharmony_cibool verifyIOMapping(std::string& linkingError, glslang::TProgram& program) { 61617a3babSopenharmony_ci bool success = true; 62617a3babSopenharmony_ci 63617a3babSopenharmony_ci // Verify IO Mapping by generating reflection for each stage individually 64617a3babSopenharmony_ci // and comparing layout qualifiers on the results 65617a3babSopenharmony_ci 66617a3babSopenharmony_ci 67617a3babSopenharmony_ci int reflectionOptions = EShReflectionDefault; 68617a3babSopenharmony_ci //reflectionOptions |= EShReflectionStrictArraySuffix; 69617a3babSopenharmony_ci //reflectionOptions |= EShReflectionBasicArraySuffix; 70617a3babSopenharmony_ci reflectionOptions |= EShReflectionIntermediateIO; 71617a3babSopenharmony_ci reflectionOptions |= EShReflectionSeparateBuffers; 72617a3babSopenharmony_ci reflectionOptions |= EShReflectionAllBlockVariables; 73617a3babSopenharmony_ci //reflectionOptions |= EShReflectionUnwrapIOBlocks; 74617a3babSopenharmony_ci 75617a3babSopenharmony_ci success &= program.buildReflection(reflectionOptions); 76617a3babSopenharmony_ci 77617a3babSopenharmony_ci // check that the reflection output from the individual stages all makes sense.. 78617a3babSopenharmony_ci std::vector<glslang::TReflection> stageReflections; 79617a3babSopenharmony_ci for (int s = 0; s < EShLangCount; ++s) { 80617a3babSopenharmony_ci if (program.getIntermediate((EShLanguage)s)) { 81617a3babSopenharmony_ci stageReflections.emplace_back((EShReflectionOptions)reflectionOptions, (EShLanguage)s, (EShLanguage)s); 82617a3babSopenharmony_ci success &= stageReflections.back().addStage((EShLanguage)s, *program.getIntermediate((EShLanguage)s)); 83617a3babSopenharmony_ci } 84617a3babSopenharmony_ci } 85617a3babSopenharmony_ci 86617a3babSopenharmony_ci // check that input/output locations match between stages 87617a3babSopenharmony_ci auto it = stageReflections.begin(); 88617a3babSopenharmony_ci auto nextIt = it + 1; 89617a3babSopenharmony_ci for (; nextIt != stageReflections.end(); it++, nextIt++) { 90617a3babSopenharmony_ci int numOut = it->getNumPipeOutputs(); 91617a3babSopenharmony_ci std::map<std::string, const glslang::TObjectReflection*> pipeOut; 92617a3babSopenharmony_ci 93617a3babSopenharmony_ci for (int i = 0; i < numOut; i++) { 94617a3babSopenharmony_ci const glslang::TObjectReflection& out = it->getPipeOutput(i); 95617a3babSopenharmony_ci std::string name = interfaceName(out); 96617a3babSopenharmony_ci pipeOut[name] = &out; 97617a3babSopenharmony_ci } 98617a3babSopenharmony_ci 99617a3babSopenharmony_ci int numIn = nextIt->getNumPipeInputs(); 100617a3babSopenharmony_ci for (int i = 0; i < numIn; i++) { 101617a3babSopenharmony_ci auto in = nextIt->getPipeInput(i); 102617a3babSopenharmony_ci std::string name = interfaceName(in); 103617a3babSopenharmony_ci auto out = pipeOut.find(name); 104617a3babSopenharmony_ci 105617a3babSopenharmony_ci if (out != pipeOut.end()) { 106617a3babSopenharmony_ci auto inQualifier = in.getType()->getQualifier(); 107617a3babSopenharmony_ci auto outQualifier = out->second->getType()->getQualifier(); 108617a3babSopenharmony_ci success &= outQualifier.layoutLocation == inQualifier.layoutLocation; 109617a3babSopenharmony_ci } 110617a3babSopenharmony_ci else { 111617a3babSopenharmony_ci if (!in.getType()->isStruct()) { 112617a3babSopenharmony_ci bool found = false; 113617a3babSopenharmony_ci for (auto outIt : pipeOut) { 114617a3babSopenharmony_ci if (outIt.second->getType()->isStruct()) { 115617a3babSopenharmony_ci unsigned int baseLoc = outIt.second->getType()->getQualifier().hasLocation() ? 116617a3babSopenharmony_ci outIt.second->getType()->getQualifier().layoutLocation : 117617a3babSopenharmony_ci std::numeric_limits<unsigned int>::max(); 118617a3babSopenharmony_ci for (size_t j = 0; j < outIt.second->getType()->getStruct()->size(); j++) { 119617a3babSopenharmony_ci baseLoc = (*outIt.second->getType()->getStruct())[j].type->getQualifier().hasLocation() ? 120617a3babSopenharmony_ci (*outIt.second->getType()->getStruct())[j].type->getQualifier().layoutLocation : baseLoc; 121617a3babSopenharmony_ci if (baseLoc != std::numeric_limits<unsigned int>::max()) { 122617a3babSopenharmony_ci if (baseLoc == in.getType()->getQualifier().layoutLocation) { 123617a3babSopenharmony_ci found = true; 124617a3babSopenharmony_ci break; 125617a3babSopenharmony_ci } 126617a3babSopenharmony_ci baseLoc += glslang::TIntermediate::computeTypeLocationSize(*(*outIt.second->getType()->getStruct())[j].type, EShLangVertex); 127617a3babSopenharmony_ci } 128617a3babSopenharmony_ci } 129617a3babSopenharmony_ci if (found) { 130617a3babSopenharmony_ci break; 131617a3babSopenharmony_ci } 132617a3babSopenharmony_ci } 133617a3babSopenharmony_ci } 134617a3babSopenharmony_ci success &= found; 135617a3babSopenharmony_ci } 136617a3babSopenharmony_ci else { 137617a3babSopenharmony_ci unsigned int baseLoc = in.getType()->getQualifier().hasLocation() ? in.getType()->getQualifier().layoutLocation : -1; 138617a3babSopenharmony_ci for (size_t j = 0; j < in.getType()->getStruct()->size(); j++) { 139617a3babSopenharmony_ci baseLoc = (*in.getType()->getStruct())[j].type->getQualifier().hasLocation() ? 140617a3babSopenharmony_ci (*in.getType()->getStruct())[j].type->getQualifier().layoutLocation : baseLoc; 141617a3babSopenharmony_ci if (baseLoc != std::numeric_limits<unsigned int>::max()) { 142617a3babSopenharmony_ci bool isMemberFound = false; 143617a3babSopenharmony_ci for (auto outIt : pipeOut) { 144617a3babSopenharmony_ci if (baseLoc == outIt.second->getType()->getQualifier().layoutLocation) { 145617a3babSopenharmony_ci isMemberFound = true; 146617a3babSopenharmony_ci break; 147617a3babSopenharmony_ci } 148617a3babSopenharmony_ci } 149617a3babSopenharmony_ci if (!isMemberFound) { 150617a3babSopenharmony_ci success &= false; 151617a3babSopenharmony_ci break; 152617a3babSopenharmony_ci } 153617a3babSopenharmony_ci baseLoc += glslang::TIntermediate::computeTypeLocationSize(*(*in.getType()->getStruct())[j].type, EShLangVertex); 154617a3babSopenharmony_ci } 155617a3babSopenharmony_ci } 156617a3babSopenharmony_ci } 157617a3babSopenharmony_ci } 158617a3babSopenharmony_ci } 159617a3babSopenharmony_ci } 160617a3babSopenharmony_ci 161617a3babSopenharmony_ci // compare uniforms in each stage to the program 162617a3babSopenharmony_ci { 163617a3babSopenharmony_ci int totalUniforms = program.getNumUniformVariables(); 164617a3babSopenharmony_ci std::map<std::string, const glslang::TObjectReflection*> programUniforms; 165617a3babSopenharmony_ci for (int i = 0; i < totalUniforms; i++) { 166617a3babSopenharmony_ci const glslang::TObjectReflection& uniform = program.getUniform(i); 167617a3babSopenharmony_ci std::string name = interfaceName(uniform); 168617a3babSopenharmony_ci programUniforms[name] = &uniform; 169617a3babSopenharmony_ci } 170617a3babSopenharmony_ci it = stageReflections.begin(); 171617a3babSopenharmony_ci for (; it != stageReflections.end(); it++) { 172617a3babSopenharmony_ci int numUniform = it->getNumUniforms(); 173617a3babSopenharmony_ci std::map<std::string, glslang::TObjectReflection> uniforms; 174617a3babSopenharmony_ci 175617a3babSopenharmony_ci for (int i = 0; i < numUniform; i++) { 176617a3babSopenharmony_ci glslang::TObjectReflection uniform = it->getUniform(i); 177617a3babSopenharmony_ci std::string name = interfaceName(uniform); 178617a3babSopenharmony_ci auto programUniform = programUniforms.find(name); 179617a3babSopenharmony_ci 180617a3babSopenharmony_ci if (programUniform != programUniforms.end()) { 181617a3babSopenharmony_ci auto stageQualifier = uniform.getType()->getQualifier(); 182617a3babSopenharmony_ci auto programQualifier = programUniform->second->getType()->getQualifier(); 183617a3babSopenharmony_ci 184617a3babSopenharmony_ci success &= stageQualifier.layoutLocation == programQualifier.layoutLocation; 185617a3babSopenharmony_ci success &= stageQualifier.layoutBinding == programQualifier.layoutBinding; 186617a3babSopenharmony_ci success &= stageQualifier.layoutSet == programQualifier.layoutSet; 187617a3babSopenharmony_ci } 188617a3babSopenharmony_ci else { 189617a3babSopenharmony_ci success &= false; 190617a3babSopenharmony_ci } 191617a3babSopenharmony_ci } 192617a3babSopenharmony_ci } 193617a3babSopenharmony_ci } 194617a3babSopenharmony_ci 195617a3babSopenharmony_ci // compare uniform blocks in each stage to the program table 196617a3babSopenharmony_ci { 197617a3babSopenharmony_ci int totalUniforms = program.getNumUniformBlocks(); 198617a3babSopenharmony_ci std::map<std::string, const glslang::TObjectReflection*> programUniforms; 199617a3babSopenharmony_ci for (int i = 0; i < totalUniforms; i++) { 200617a3babSopenharmony_ci const glslang::TObjectReflection& uniform = program.getUniformBlock(i); 201617a3babSopenharmony_ci std::string name = interfaceName(uniform); 202617a3babSopenharmony_ci programUniforms[name] = &uniform; 203617a3babSopenharmony_ci } 204617a3babSopenharmony_ci it = stageReflections.begin(); 205617a3babSopenharmony_ci for (; it != stageReflections.end(); it++) { 206617a3babSopenharmony_ci int numUniform = it->getNumUniformBlocks(); 207617a3babSopenharmony_ci std::map<std::string, glslang::TObjectReflection> uniforms; 208617a3babSopenharmony_ci 209617a3babSopenharmony_ci for (int i = 0; i < numUniform; i++) { 210617a3babSopenharmony_ci glslang::TObjectReflection uniform = it->getUniformBlock(i); 211617a3babSopenharmony_ci std::string name = interfaceName(uniform); 212617a3babSopenharmony_ci auto programUniform = programUniforms.find(name); 213617a3babSopenharmony_ci 214617a3babSopenharmony_ci if (programUniform != programUniforms.end()) { 215617a3babSopenharmony_ci auto stageQualifier = uniform.getType()->getQualifier(); 216617a3babSopenharmony_ci auto programQualifier = programUniform->second->getType()->getQualifier(); 217617a3babSopenharmony_ci 218617a3babSopenharmony_ci success &= stageQualifier.layoutLocation == programQualifier.layoutLocation; 219617a3babSopenharmony_ci success &= stageQualifier.layoutBinding == programQualifier.layoutBinding; 220617a3babSopenharmony_ci success &= stageQualifier.layoutSet == programQualifier.layoutSet; 221617a3babSopenharmony_ci } 222617a3babSopenharmony_ci else { 223617a3babSopenharmony_ci success &= false; 224617a3babSopenharmony_ci } 225617a3babSopenharmony_ci } 226617a3babSopenharmony_ci } 227617a3babSopenharmony_ci } 228617a3babSopenharmony_ci 229617a3babSopenharmony_ci if (!success) { 230617a3babSopenharmony_ci linkingError += "Mismatched cross-stage IO\n"; 231617a3babSopenharmony_ci } 232617a3babSopenharmony_ci 233617a3babSopenharmony_ci return success; 234617a3babSopenharmony_ci} 235617a3babSopenharmony_ci 236617a3babSopenharmony_ciTEST_P(GlslMapIOTest, FromFile) 237617a3babSopenharmony_ci{ 238617a3babSopenharmony_ci const auto& fileNames = GetParam().fileNames; 239617a3babSopenharmony_ci Semantics semantics = GetParam().semantics; 240617a3babSopenharmony_ci const size_t fileCount = fileNames.size(); 241617a3babSopenharmony_ci const EShMessages controls = DeriveOptions(Source::GLSL, semantics, Target::BothASTAndSpv); 242617a3babSopenharmony_ci GlslangResult result; 243617a3babSopenharmony_ci 244617a3babSopenharmony_ci // Compile each input shader file. 245617a3babSopenharmony_ci bool success = true; 246617a3babSopenharmony_ci std::vector<std::unique_ptr<glslang::TShader>> shaders; 247617a3babSopenharmony_ci for (size_t i = 0; i < fileCount; ++i) { 248617a3babSopenharmony_ci std::string contents; 249617a3babSopenharmony_ci tryLoadFile(GlobalTestSettings.testRoot + "/" + fileNames[i], 250617a3babSopenharmony_ci "input", &contents); 251617a3babSopenharmony_ci shaders.emplace_back( 252617a3babSopenharmony_ci new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i])))); 253617a3babSopenharmony_ci auto* shader = shaders.back().get(); 254617a3babSopenharmony_ci 255617a3babSopenharmony_ci shader->setAutoMapLocations(true); 256617a3babSopenharmony_ci shader->setAutoMapBindings(true); 257617a3babSopenharmony_ci 258617a3babSopenharmony_ci if (controls & EShMsgSpvRules) { 259617a3babSopenharmony_ci if (controls & EShMsgVulkanRules) { 260617a3babSopenharmony_ci shader->setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl 261617a3babSopenharmony_ci : glslang::EShSourceGlsl, 262617a3babSopenharmony_ci shader->getStage(), glslang::EShClientVulkan, 100); 263617a3babSopenharmony_ci shader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_1); 264617a3babSopenharmony_ci shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0); 265617a3babSopenharmony_ci } else { 266617a3babSopenharmony_ci shader->setEnvInput((controls & EShMsgReadHlsl) ? glslang::EShSourceHlsl 267617a3babSopenharmony_ci : glslang::EShSourceGlsl, 268617a3babSopenharmony_ci shader->getStage(), glslang::EShClientOpenGL, 100); 269617a3babSopenharmony_ci shader->setEnvClient(glslang::EShClientOpenGL, glslang::EShTargetOpenGL_450); 270617a3babSopenharmony_ci shader->setEnvTarget(glslang::EshTargetSpv, glslang::EShTargetSpv_1_0); 271617a3babSopenharmony_ci } 272617a3babSopenharmony_ci } 273617a3babSopenharmony_ci 274617a3babSopenharmony_ci success &= compile(shader, contents, "", controls); 275617a3babSopenharmony_ci 276617a3babSopenharmony_ci result.shaderResults.push_back( 277617a3babSopenharmony_ci { fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog() }); 278617a3babSopenharmony_ci } 279617a3babSopenharmony_ci 280617a3babSopenharmony_ci // Link all of them. 281617a3babSopenharmony_ci glslang::TProgram program; 282617a3babSopenharmony_ci for (const auto& shader : shaders) program.addShader(shader.get()); 283617a3babSopenharmony_ci success &= program.link(controls); 284617a3babSopenharmony_ci result.linkingOutput = program.getInfoLog(); 285617a3babSopenharmony_ci result.linkingError = program.getInfoDebugLog(); 286617a3babSopenharmony_ci 287617a3babSopenharmony_ci unsigned int stage = 0; 288617a3babSopenharmony_ci glslang::TIntermediate* firstIntermediate = nullptr; 289617a3babSopenharmony_ci while (!program.getIntermediate((EShLanguage)stage) && stage < EShLangCount) { stage++; } 290617a3babSopenharmony_ci firstIntermediate = program.getIntermediate((EShLanguage)stage); 291617a3babSopenharmony_ci 292617a3babSopenharmony_ci glslang::TDefaultGlslIoResolver resolver(*firstIntermediate); 293617a3babSopenharmony_ci glslang::TGlslIoMapper ioMapper; 294617a3babSopenharmony_ci 295617a3babSopenharmony_ci if (success) { 296617a3babSopenharmony_ci success &= program.mapIO(&resolver, &ioMapper); 297617a3babSopenharmony_ci result.linkingOutput = program.getInfoLog(); 298617a3babSopenharmony_ci result.linkingError = program.getInfoDebugLog(); 299617a3babSopenharmony_ci } 300617a3babSopenharmony_ci 301617a3babSopenharmony_ci success &= verifyIOMapping(result.linkingError, program); 302617a3babSopenharmony_ci result.validationResult = success; 303617a3babSopenharmony_ci 304617a3babSopenharmony_ci if (success && (controls & EShMsgSpvRules)) { 305617a3babSopenharmony_ci for (int stage = 0; stage < EShLangCount; ++stage) { 306617a3babSopenharmony_ci if (program.getIntermediate((EShLanguage)stage)) { 307617a3babSopenharmony_ci spv::SpvBuildLogger logger; 308617a3babSopenharmony_ci std::vector<uint32_t> spirv_binary; 309617a3babSopenharmony_ci options().disableOptimizer = false; 310617a3babSopenharmony_ci glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), 311617a3babSopenharmony_ci spirv_binary, &logger, &options()); 312617a3babSopenharmony_ci 313617a3babSopenharmony_ci std::ostringstream disassembly_stream; 314617a3babSopenharmony_ci spv::Parameterize(); 315617a3babSopenharmony_ci spv::Disassemble(disassembly_stream, spirv_binary); 316617a3babSopenharmony_ci result.spirvWarningsErrors += logger.getAllMessages(); 317617a3babSopenharmony_ci result.spirv += disassembly_stream.str(); 318617a3babSopenharmony_ci result.validationResult &= !options().validate || logger.getAllMessages().empty(); 319617a3babSopenharmony_ci } 320617a3babSopenharmony_ci } 321617a3babSopenharmony_ci } 322617a3babSopenharmony_ci 323617a3babSopenharmony_ci std::ostringstream stream; 324617a3babSopenharmony_ci outputResultToStream(&stream, result, controls); 325617a3babSopenharmony_ci 326617a3babSopenharmony_ci // Check with expected results. 327617a3babSopenharmony_ci const std::string expectedOutputFname = 328617a3babSopenharmony_ci GlobalTestSettings.testRoot + "/baseResults/" + fileNames.front() + ".out"; 329617a3babSopenharmony_ci std::string expectedOutput; 330617a3babSopenharmony_ci tryLoadFile(expectedOutputFname, "expected output", &expectedOutput); 331617a3babSopenharmony_ci 332617a3babSopenharmony_ci checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname, 333617a3babSopenharmony_ci result.spirvWarningsErrors); 334617a3babSopenharmony_ci} 335617a3babSopenharmony_ci 336617a3babSopenharmony_ci// clang-format off 337617a3babSopenharmony_ciINSTANTIATE_TEST_SUITE_P( 338617a3babSopenharmony_ci Glsl, GlslMapIOTest, 339617a3babSopenharmony_ci ::testing::ValuesIn(std::vector<IoMapData>({ 340617a3babSopenharmony_ci {{"iomap.crossStage.vert", "iomap.crossStage.frag" }, Semantics::OpenGL}, 341617a3babSopenharmony_ci {{"iomap.crossStage.2.vert", "iomap.crossStage.2.geom", "iomap.crossStage.2.frag" }, Semantics::OpenGL}, 342617a3babSopenharmony_ci {{"iomap.blockOutVariableIn.vert", "iomap.blockOutVariableIn.frag"}, Semantics::OpenGL}, 343617a3babSopenharmony_ci {{"iomap.variableOutBlockIn.vert", "iomap.variableOutBlockIn.frag"}, Semantics::OpenGL}, 344617a3babSopenharmony_ci {{"iomap.blockOutVariableIn.2.vert", "iomap.blockOutVariableIn.geom"}, Semantics::OpenGL}, 345617a3babSopenharmony_ci {{"iomap.variableOutBlockIn.2.vert", "iomap.variableOutBlockIn.geom"}, Semantics::OpenGL}, 346617a3babSopenharmony_ci // vulkan semantics 347617a3babSopenharmony_ci {{"iomap.crossStage.vk.vert", "iomap.crossStage.vk.geom", "iomap.crossStage.vk.frag" }, Semantics::Vulkan}, 348617a3babSopenharmony_ci })) 349617a3babSopenharmony_ci); 350617a3babSopenharmony_ci// clang-format on 351617a3babSopenharmony_ci 352617a3babSopenharmony_ci} // anonymous namespace 353617a3babSopenharmony_ci} // namespace glslangtest 354