Path: blob/main_old/samples/shader_translator/shader_translator.cpp
1694 views
//1// Copyright 2002 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//56#include "GLSLANG/ShaderLang.h"78#include <assert.h>9#include <math.h>10#include <stdio.h>11#include <stdlib.h>12#include <string.h>13#include <sstream>14#include <vector>15#include "angle_gl.h"1617#if defined(ANGLE_ENABLE_VULKAN)18// SPIR-V tools include for disassembly.19# include <spirv-tools/libspirv.hpp>20#endif2122//23// Return codes from main.24//25enum TFailCode26{27ESuccess = 0,28EFailUsage,29EFailCompile,30EFailCompilerCreate,31};3233static void usage();34static sh::GLenum FindShaderType(const char *fileName);35static bool CompileFile(char *fileName, ShHandle compiler, ShCompileOptions compileOptions);36static void LogMsg(const char *msg, const char *name, const int num, const char *logName);37static void PrintVariable(const std::string &prefix, size_t index, const sh::ShaderVariable &var);38static void PrintActiveVariables(ShHandle compiler);3940// If NUM_SOURCE_STRINGS is set to a value > 1, the input file data is41// broken into that many chunks. This will affect file/line numbering in42// the preprocessor.43const unsigned int NUM_SOURCE_STRINGS = 1;44typedef std::vector<char *> ShaderSource;45static bool ReadShaderSource(const char *fileName, ShaderSource &source);46static void FreeShaderSource(ShaderSource &source);4748static bool ParseGLSLOutputVersion(const std::string &, ShShaderOutput *outResult);49static bool ParseIntValue(const std::string &, int emptyDefault, int *outValue);5051static void PrintSpirv(const sh::BinaryBlob &blob);5253//54// Set up the per compile resources55//56void GenerateResources(ShBuiltInResources *resources)57{58sh::InitBuiltInResources(resources);5960resources->MaxVertexAttribs = 8;61resources->MaxVertexUniformVectors = 128;62resources->MaxVaryingVectors = 8;63resources->MaxVertexTextureImageUnits = 0;64resources->MaxCombinedTextureImageUnits = 8;65resources->MaxTextureImageUnits = 8;66resources->MaxFragmentUniformVectors = 16;67resources->MaxDrawBuffers = 1;68resources->MaxDualSourceDrawBuffers = 1;6970resources->OES_standard_derivatives = 0;71resources->OES_EGL_image_external = 0;72resources->EXT_geometry_shader = 1;73resources->ANGLE_texture_multisample = 0;74resources->APPLE_clip_distance = 0;75}7677int main(int argc, char *argv[])78{79TFailCode failCode = ESuccess;8081ShCompileOptions compileOptions = 0;82int numCompiles = 0;83ShHandle vertexCompiler = 0;84ShHandle fragmentCompiler = 0;85ShHandle computeCompiler = 0;86ShHandle geometryCompiler = 0;87ShShaderSpec spec = SH_GLES2_SPEC;88ShShaderOutput output = SH_ESSL_OUTPUT;8990#if defined(ANGLE_ENABLE_VULKAN)91sh::InitializeGlslang();92#endif93sh::Initialize();9495ShBuiltInResources resources;96GenerateResources(&resources);9798argc--;99argv++;100for (; (argc >= 1) && (failCode == ESuccess); argc--, argv++)101{102if (argv[0][0] == '-')103{104switch (argv[0][1])105{106case 'i':107compileOptions |= SH_INTERMEDIATE_TREE;108break;109case 'o':110compileOptions |= SH_OBJECT_CODE;111break;112case 'u':113compileOptions |= SH_VARIABLES;114break;115case 's':116if (argv[0][2] == '=')117{118switch (argv[0][3])119{120case 'e':121if (argv[0][4] == '3')122{123if (argv[0][5] == '1')124{125spec = SH_GLES3_1_SPEC;126}127else128{129spec = SH_GLES3_SPEC;130}131}132else133{134spec = SH_GLES2_SPEC;135}136break;137case 'w':138if (argv[0][4] == '3')139{140spec = SH_WEBGL3_SPEC;141}142else if (argv[0][4] == '2')143{144spec = SH_WEBGL2_SPEC;145}146else if (argv[0][4] == 'n')147{148spec = SH_WEBGL_SPEC;149}150else151{152spec = SH_WEBGL_SPEC;153resources.FragmentPrecisionHigh = 1;154}155break;156case 'd':157if (argv[0][4] == 'c')158{159spec = SH_GL_COMPATIBILITY_SPEC;160}161else162{163spec = SH_GL_CORE_SPEC;164}165break;166default:167failCode = EFailUsage;168}169}170else171{172failCode = EFailUsage;173}174break;175case 'b':176if (argv[0][2] == '=')177{178switch (argv[0][3])179{180case 'e':181output = SH_ESSL_OUTPUT;182compileOptions |= SH_INITIALIZE_UNINITIALIZED_LOCALS;183break;184case 'g':185if (!ParseGLSLOutputVersion(&argv[0][sizeof("-b=g") - 1], &output))186{187failCode = EFailUsage;188}189compileOptions |= SH_INITIALIZE_UNINITIALIZED_LOCALS;190break;191case 'v':192output = SH_SPIRV_VULKAN_OUTPUT;193compileOptions |= SH_INITIALIZE_UNINITIALIZED_LOCALS;194break;195case 'h':196if (argv[0][4] == '1' && argv[0][5] == '1')197{198output = SH_HLSL_4_1_OUTPUT;199}200else201{202output = SH_HLSL_3_0_OUTPUT;203}204break;205default:206failCode = EFailUsage;207}208}209else210{211failCode = EFailUsage;212}213break;214case 'x':215if (argv[0][2] == '=')216{217// clang-format off218switch (argv[0][3])219{220case 'i': resources.OES_EGL_image_external = 1; break;221case 'd': resources.OES_standard_derivatives = 1; break;222case 'r': resources.ARB_texture_rectangle = 1; break;223case 'b':224if (ParseIntValue(&argv[0][sizeof("-x=b") - 1], 1,225&resources.MaxDualSourceDrawBuffers))226{227resources.EXT_blend_func_extended = 1;228}229else230{231failCode = EFailUsage;232}233break;234case 'w':235if (ParseIntValue(&argv[0][sizeof("-x=w") - 1], 1,236&resources.MaxDrawBuffers))237{238resources.EXT_draw_buffers = 1;239}240else241{242failCode = EFailUsage;243}244break;245case 'g': resources.EXT_frag_depth = 1; break;246case 'l': resources.EXT_shader_texture_lod = 1; break;247case 'f': resources.EXT_shader_framebuffer_fetch = 1; break;248case 'n': resources.NV_shader_framebuffer_fetch = 1; break;249case 'a': resources.ARM_shader_framebuffer_fetch = 1; break;250case 'm':251resources.OVR_multiview2 = 1;252resources.OVR_multiview = 1;253compileOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;254compileOptions |= SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER;255break;256case 'y': resources.EXT_YUV_target = 1; break;257case 's': resources.OES_sample_variables = 1; break;258default: failCode = EFailUsage;259}260// clang-format on261}262else263{264failCode = EFailUsage;265}266break;267default:268failCode = EFailUsage;269}270}271else272{273if (spec != SH_GLES2_SPEC && spec != SH_WEBGL_SPEC)274{275resources.MaxDrawBuffers = 8;276resources.MaxVertexTextureImageUnits = 16;277resources.MaxTextureImageUnits = 16;278}279ShHandle compiler = 0;280switch (FindShaderType(argv[0]))281{282case GL_VERTEX_SHADER:283if (vertexCompiler == 0)284{285vertexCompiler =286sh::ConstructCompiler(GL_VERTEX_SHADER, spec, output, &resources);287}288compiler = vertexCompiler;289break;290case GL_FRAGMENT_SHADER:291if (fragmentCompiler == 0)292{293fragmentCompiler =294sh::ConstructCompiler(GL_FRAGMENT_SHADER, spec, output, &resources);295}296compiler = fragmentCompiler;297break;298case GL_COMPUTE_SHADER:299if (computeCompiler == 0)300{301computeCompiler =302sh::ConstructCompiler(GL_COMPUTE_SHADER, spec, output, &resources);303}304compiler = computeCompiler;305break;306case GL_GEOMETRY_SHADER_EXT:307if (geometryCompiler == 0)308{309geometryCompiler =310sh::ConstructCompiler(GL_GEOMETRY_SHADER_EXT, spec, output, &resources);311}312compiler = geometryCompiler;313break;314default:315break;316}317if (compiler)318{319switch (output)320{321case SH_HLSL_3_0_OUTPUT:322case SH_HLSL_4_1_OUTPUT:323case SH_HLSL_4_0_FL9_3_OUTPUT:324compileOptions &= ~SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER;325break;326default:327break;328}329330bool compiled = CompileFile(argv[0], compiler, compileOptions);331332LogMsg("BEGIN", "COMPILER", numCompiles, "INFO LOG");333std::string log = sh::GetInfoLog(compiler);334puts(log.c_str());335LogMsg("END", "COMPILER", numCompiles, "INFO LOG");336printf("\n\n");337338if (compiled && (compileOptions & SH_OBJECT_CODE))339{340LogMsg("BEGIN", "COMPILER", numCompiles, "OBJ CODE");341if (output != SH_SPIRV_VULKAN_OUTPUT)342{343const std::string &code = sh::GetObjectCode(compiler);344puts(code.c_str());345}346else347{348const sh::BinaryBlob &blob = sh::GetObjectBinaryBlob(compiler);349PrintSpirv(blob);350}351LogMsg("END", "COMPILER", numCompiles, "OBJ CODE");352printf("\n\n");353}354if (compiled && (compileOptions & SH_VARIABLES))355{356LogMsg("BEGIN", "COMPILER", numCompiles, "VARIABLES");357PrintActiveVariables(compiler);358LogMsg("END", "COMPILER", numCompiles, "VARIABLES");359printf("\n\n");360}361if (!compiled)362failCode = EFailCompile;363++numCompiles;364}365else366{367failCode = EFailCompilerCreate;368}369}370}371372if ((vertexCompiler == 0) && (fragmentCompiler == 0) && (computeCompiler == 0) &&373(geometryCompiler == 0))374failCode = EFailUsage;375if (failCode == EFailUsage)376usage();377378if (vertexCompiler)379sh::Destruct(vertexCompiler);380if (fragmentCompiler)381sh::Destruct(fragmentCompiler);382if (computeCompiler)383sh::Destruct(computeCompiler);384if (geometryCompiler)385sh::Destruct(geometryCompiler);386387sh::Finalize();388#if defined(ANGLE_ENABLE_VULKAN)389sh::FinalizeGlslang();390#endif391392return failCode;393}394395//396// print usage to stdout397//398void usage()399{400// clang-format off401printf(402"Usage: translate [-i -o -u -l -b=e -b=g -b=h9 -x=i -x=d] file1 file2 ...\n"403"Where: filename : filename ending in .frag or .vert\n"404" -i : print intermediate tree\n"405" -o : print translated code\n"406" -u : print active attribs, uniforms, varyings and program outputs\n"407" -s=e2 : use GLES2 spec (this is by default)\n"408" -s=e3 : use GLES3 spec\n"409" -s=e31 : use GLES31 spec (in development)\n"410" -s=w : use WebGL 1.0 spec\n"411" -s=wn : use WebGL 1.0 spec with no highp support in fragment shaders\n"412" -s=w2 : use WebGL 2.0 spec\n"413" -s=d : use Desktop Core spec (in development)\n"414" -s=dc : use Desktop Compatibility spec (in development)\n"415" -b=e : output GLSL ES code (this is by default)\n"416" -b=g : output GLSL code (compatibility profile)\n"417" -b=g[NUM]: output GLSL code (NUM can be 130, 140, 150, 330, 400, 410, 420, 430, "418"440, 450)\n"419" -b=v : output Vulkan SPIR-V code\n"420" -b=h9 : output HLSL9 code\n"421" -b=h11 : output HLSL11 code\n"422" -x=i : enable GL_OES_EGL_image_external\n"423" -x=d : enable GL_OES_EGL_standard_derivatives\n"424" -x=r : enable ARB_texture_rectangle\n"425" -x=b[NUM]: enable EXT_blend_func_extended (NUM default 1)\n"426" -x=w[NUM]: enable EXT_draw_buffers (NUM default 1)\n"427" -x=g : enable EXT_frag_depth\n"428" -x=l : enable EXT_shader_texture_lod\n"429" -x=f : enable EXT_shader_framebuffer_fetch\n"430" -x=n : enable NV_shader_framebuffer_fetch\n"431" -x=a : enable ARM_shader_framebuffer_fetch\n"432" -x=m : enable OVR_multiview\n"433" -x=y : enable YUV_target\n"434" -x=s : enable OES_sample_variables\n");435// clang-format on436}437438//439// Deduce the shader type from the filename. Files must end in one of the440// following extensions:441//442// .frag* = fragment shader443// .vert* = vertex shader444//445sh::GLenum FindShaderType(const char *fileName)446{447assert(fileName);448449const char *ext = strrchr(fileName, '.');450451if (ext && strcmp(ext, ".sl") == 0)452for (; ext > fileName && ext[0] != '.'; ext--)453;454455ext = strrchr(fileName, '.');456if (ext)457{458if (strncmp(ext, ".frag", 5) == 0)459return GL_FRAGMENT_SHADER;460if (strncmp(ext, ".vert", 5) == 0)461return GL_VERTEX_SHADER;462if (strncmp(ext, ".comp", 5) == 0)463return GL_COMPUTE_SHADER;464if (strncmp(ext, ".geom", 5) == 0)465return GL_GEOMETRY_SHADER_EXT;466}467468return GL_FRAGMENT_SHADER;469}470471//472// Read a file's data into a string, and compile it using sh::Compile473//474bool CompileFile(char *fileName, ShHandle compiler, ShCompileOptions compileOptions)475{476ShaderSource source;477if (!ReadShaderSource(fileName, source))478return false;479480int ret = sh::Compile(compiler, &source[0], source.size(), compileOptions);481482FreeShaderSource(source);483return ret ? true : false;484}485486void LogMsg(const char *msg, const char *name, const int num, const char *logName)487{488printf("#### %s %s %d %s ####\n", msg, name, num, logName);489}490491void PrintVariable(const std::string &prefix, size_t index, const sh::ShaderVariable &var)492{493std::string typeName;494switch (var.type)495{496case GL_FLOAT:497typeName = "GL_FLOAT";498break;499case GL_FLOAT_VEC2:500typeName = "GL_FLOAT_VEC2";501break;502case GL_FLOAT_VEC3:503typeName = "GL_FLOAT_VEC3";504break;505case GL_FLOAT_VEC4:506typeName = "GL_FLOAT_VEC4";507break;508case GL_INT:509typeName = "GL_INT";510break;511case GL_INT_VEC2:512typeName = "GL_INT_VEC2";513break;514case GL_INT_VEC3:515typeName = "GL_INT_VEC3";516break;517case GL_INT_VEC4:518typeName = "GL_INT_VEC4";519break;520case GL_UNSIGNED_INT:521typeName = "GL_UNSIGNED_INT";522break;523case GL_UNSIGNED_INT_VEC2:524typeName = "GL_UNSIGNED_INT_VEC2";525break;526case GL_UNSIGNED_INT_VEC3:527typeName = "GL_UNSIGNED_INT_VEC3";528break;529case GL_UNSIGNED_INT_VEC4:530typeName = "GL_UNSIGNED_INT_VEC4";531break;532case GL_BOOL:533typeName = "GL_BOOL";534break;535case GL_BOOL_VEC2:536typeName = "GL_BOOL_VEC2";537break;538case GL_BOOL_VEC3:539typeName = "GL_BOOL_VEC3";540break;541case GL_BOOL_VEC4:542typeName = "GL_BOOL_VEC4";543break;544case GL_FLOAT_MAT2:545typeName = "GL_FLOAT_MAT2";546break;547case GL_FLOAT_MAT3:548typeName = "GL_FLOAT_MAT3";549break;550case GL_FLOAT_MAT4:551typeName = "GL_FLOAT_MAT4";552break;553case GL_FLOAT_MAT2x3:554typeName = "GL_FLOAT_MAT2x3";555break;556case GL_FLOAT_MAT3x2:557typeName = "GL_FLOAT_MAT3x2";558break;559case GL_FLOAT_MAT4x2:560typeName = "GL_FLOAT_MAT4x2";561break;562case GL_FLOAT_MAT2x4:563typeName = "GL_FLOAT_MAT2x4";564break;565case GL_FLOAT_MAT3x4:566typeName = "GL_FLOAT_MAT3x4";567break;568case GL_FLOAT_MAT4x3:569typeName = "GL_FLOAT_MAT4x3";570break;571572case GL_SAMPLER_2D:573typeName = "GL_SAMPLER_2D";574break;575case GL_SAMPLER_3D:576typeName = "GL_SAMPLER_3D";577break;578case GL_SAMPLER_CUBE:579typeName = "GL_SAMPLER_CUBE";580break;581case GL_SAMPLER_CUBE_SHADOW:582typeName = "GL_SAMPLER_CUBE_SHADOW";583break;584case GL_SAMPLER_2D_SHADOW:585typeName = "GL_SAMPLER_2D_ARRAY_SHADOW";586break;587case GL_SAMPLER_2D_ARRAY:588typeName = "GL_SAMPLER_2D_ARRAY";589break;590case GL_SAMPLER_2D_ARRAY_SHADOW:591typeName = "GL_SAMPLER_2D_ARRAY_SHADOW";592break;593case GL_SAMPLER_2D_MULTISAMPLE:594typeName = "GL_SAMPLER_2D_MULTISAMPLE";595break;596case GL_IMAGE_2D:597typeName = "GL_IMAGE_2D";598break;599case GL_IMAGE_3D:600typeName = "GL_IMAGE_3D";601break;602case GL_IMAGE_CUBE:603typeName = "GL_IMAGE_CUBE";604break;605case GL_IMAGE_2D_ARRAY:606typeName = "GL_IMAGE_2D_ARRAY";607break;608609case GL_INT_SAMPLER_2D:610typeName = "GL_INT_SAMPLER_2D";611break;612case GL_INT_SAMPLER_3D:613typeName = "GL_INT_SAMPLER_3D";614break;615case GL_INT_SAMPLER_CUBE:616typeName = "GL_INT_SAMPLER_CUBE";617break;618case GL_INT_SAMPLER_2D_ARRAY:619typeName = "GL_INT_SAMPLER_2D_ARRAY";620break;621case GL_INT_SAMPLER_2D_MULTISAMPLE:622typeName = "GL_INT_SAMPLER_2D_MULTISAMPLE";623break;624case GL_INT_IMAGE_2D:625typeName = "GL_INT_IMAGE_2D";626break;627case GL_INT_IMAGE_3D:628typeName = "GL_INT_IMAGE_3D";629break;630case GL_INT_IMAGE_CUBE:631typeName = "GL_INT_IMAGE_CUBE";632break;633case GL_INT_IMAGE_2D_ARRAY:634typeName = "GL_INT_IMAGE_2D_ARRAY";635break;636637case GL_UNSIGNED_INT_SAMPLER_2D:638typeName = "GL_UNSIGNED_INT_SAMPLER_2D";639break;640case GL_UNSIGNED_INT_SAMPLER_3D:641typeName = "GL_UNSIGNED_INT_SAMPLER_3D";642break;643case GL_UNSIGNED_INT_SAMPLER_CUBE:644typeName = "GL_UNSIGNED_INT_SAMPLER_CUBE";645break;646case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:647typeName = "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY";648break;649case GL_UNSIGNED_INT_ATOMIC_COUNTER:650typeName = "GL_UNSIGNED_INT_ATOMIC_COUNTER";651break;652case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:653typeName = "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE";654break;655case GL_UNSIGNED_INT_IMAGE_2D:656typeName = "GL_UNSIGNED_INT_IMAGE_2D";657break;658case GL_UNSIGNED_INT_IMAGE_3D:659typeName = "GL_UNSIGNED_INT_IMAGE_3D";660break;661case GL_UNSIGNED_INT_IMAGE_CUBE:662typeName = "GL_UNSIGNED_INT_IMAGE_CUBE";663break;664case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:665typeName = "GL_UNSIGNED_INT_IMAGE_2D_ARRAY";666break;667668case GL_SAMPLER_EXTERNAL_OES:669typeName = "GL_SAMPLER_EXTERNAL_OES";670break;671case GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT:672typeName = "GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT";673break;674default:675typeName = "UNKNOWN";676break;677}678679printf("%s %u : name=%s, mappedName=%s, type=%s, arraySizes=", prefix.c_str(),680static_cast<unsigned int>(index), var.name.c_str(), var.mappedName.c_str(),681typeName.c_str());682for (unsigned int arraySize : var.arraySizes)683{684printf("%u ", arraySize);685}686printf("\n");687if (var.fields.size())688{689std::string structPrefix;690for (size_t i = 0; i < prefix.size(); ++i)691structPrefix += ' ';692printf("%s struct %s\n", structPrefix.c_str(), var.structOrBlockName.c_str());693structPrefix += " field";694for (size_t i = 0; i < var.fields.size(); ++i)695PrintVariable(structPrefix, i, var.fields[i]);696}697}698699static void PrintActiveVariables(ShHandle compiler)700{701const std::vector<sh::ShaderVariable> *uniforms = sh::GetUniforms(compiler);702const std::vector<sh::ShaderVariable> *inputVaryings = sh::GetInputVaryings(compiler);703const std::vector<sh::ShaderVariable> *outputVaryings = sh::GetOutputVaryings(compiler);704const std::vector<sh::ShaderVariable> *attributes = sh::GetAttributes(compiler);705const std::vector<sh::ShaderVariable> *outputs = sh::GetOutputVariables(compiler);706for (size_t varCategory = 0; varCategory < 5; ++varCategory)707{708size_t numVars = 0;709std::string varCategoryName;710if (varCategory == 0)711{712numVars = uniforms->size();713varCategoryName = "uniform";714}715else if (varCategory == 1)716{717numVars = inputVaryings->size();718varCategoryName = "input varying";719}720else if (varCategory == 2)721{722numVars = outputVaryings->size();723varCategoryName = "output varying";724}725else if (varCategory == 3)726{727numVars = attributes->size();728varCategoryName = "attribute";729}730else731{732numVars = outputs->size();733varCategoryName = "output";734}735736for (size_t i = 0; i < numVars; ++i)737{738const sh::ShaderVariable *var;739if (varCategory == 0)740var = &((*uniforms)[i]);741else if (varCategory == 1)742var = &((*inputVaryings)[i]);743else if (varCategory == 2)744var = &((*outputVaryings)[i]);745else if (varCategory == 3)746var = &((*attributes)[i]);747else748var = &((*outputs)[i]);749750PrintVariable(varCategoryName, i, *var);751}752printf("\n");753}754}755756static bool ReadShaderSource(const char *fileName, ShaderSource &source)757{758FILE *in = fopen(fileName, "rb");759if (!in)760{761printf("Error: unable to open input file: %s\n", fileName);762return false;763}764765// Obtain file size.766fseek(in, 0, SEEK_END);767size_t count = ftell(in);768rewind(in);769770int len = (int)ceil((float)count / (float)NUM_SOURCE_STRINGS);771source.reserve(NUM_SOURCE_STRINGS);772// Notice the usage of do-while instead of a while loop here.773// It is there to handle empty files in which case a single empty774// string is added to vector.775do776{777char *data = new char[len + 1];778size_t nread = fread(data, 1, len, in);779data[nread] = '\0';780source.push_back(data);781782count -= nread;783} while (count > 0);784785fclose(in);786return true;787}788789static void FreeShaderSource(ShaderSource &source)790{791for (ShaderSource::size_type i = 0; i < source.size(); ++i)792{793delete[] source[i];794}795source.clear();796}797798static bool ParseGLSLOutputVersion(const std::string &num, ShShaderOutput *outResult)799{800if (num.length() == 0)801{802*outResult = SH_GLSL_COMPATIBILITY_OUTPUT;803return true;804}805std::istringstream input(num);806int value;807if (!(input >> value && input.eof()))808{809return false;810}811812switch (value)813{814case 130:815*outResult = SH_GLSL_130_OUTPUT;816return true;817case 140:818*outResult = SH_GLSL_140_OUTPUT;819return true;820case 150:821*outResult = SH_GLSL_150_CORE_OUTPUT;822return true;823case 330:824*outResult = SH_GLSL_330_CORE_OUTPUT;825return true;826case 400:827*outResult = SH_GLSL_400_CORE_OUTPUT;828return true;829case 410:830*outResult = SH_GLSL_410_CORE_OUTPUT;831return true;832case 420:833*outResult = SH_GLSL_420_CORE_OUTPUT;834return true;835case 430:836*outResult = SH_GLSL_430_CORE_OUTPUT;837return true;838case 440:839*outResult = SH_GLSL_440_CORE_OUTPUT;840return true;841case 450:842*outResult = SH_GLSL_450_CORE_OUTPUT;843return true;844default:845break;846}847return false;848}849850static bool ParseIntValue(const std::string &num, int emptyDefault, int *outValue)851{852if (num.length() == 0)853{854*outValue = emptyDefault;855return true;856}857858std::istringstream input(num);859int value;860if (!(input >> value && input.eof()))861{862return false;863}864*outValue = value;865return true;866}867868static void PrintSpirv(const sh::BinaryBlob &blob)869{870#if defined(ANGLE_ENABLE_VULKAN)871spvtools::SpirvTools spirvTools(SPV_ENV_VULKAN_1_1);872873std::string readableSpirv;874spirvTools.Disassemble(blob, &readableSpirv, 0);875876puts(readableSpirv.c_str());877#endif878}879880881