1 // 2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #include "GLSLANG/ShaderLang.h" 8 9 #include <assert.h> 10 #include <math.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <vector> 15 #include "angle_gl.h" 16 17 // 18 // Return codes from main. 19 // 20 enum TFailCode { 21 ESuccess = 0, 22 EFailUsage, 23 EFailCompile, 24 EFailCompilerCreate, 25 }; 26 27 static void usage(); 28 static sh::GLenum FindShaderType(const char* fileName); 29 static bool CompileFile(char* fileName, ShHandle compiler, int compileOptions); 30 static void LogMsg(const char* msg, const char* name, const int num, const char* logName); 31 static void PrintActiveVariables(ShHandle compiler, ShShaderInfo varType); 32 33 // If NUM_SOURCE_STRINGS is set to a value > 1, the input file data is 34 // broken into that many chunks. 35 const unsigned int NUM_SOURCE_STRINGS = 2; 36 typedef std::vector<char*> ShaderSource; 37 static bool ReadShaderSource(const char* fileName, ShaderSource& source); 38 static void FreeShaderSource(ShaderSource& source); 39 40 // 41 // Set up the per compile resources 42 // 43 void GenerateResources(ShBuiltInResources* resources) 44 { 45 ShInitBuiltInResources(resources); 46 47 resources->MaxVertexAttribs = 8; 48 resources->MaxVertexUniformVectors = 128; 49 resources->MaxVaryingVectors = 8; 50 resources->MaxVertexTextureImageUnits = 0; 51 resources->MaxCombinedTextureImageUnits = 8; 52 resources->MaxTextureImageUnits = 8; 53 resources->MaxFragmentUniformVectors = 16; 54 resources->MaxDrawBuffers = 1; 55 56 resources->OES_standard_derivatives = 0; 57 resources->OES_EGL_image_external = 0; 58 } 59 60 int main(int argc, char* argv[]) 61 { 62 TFailCode failCode = ESuccess; 63 64 int compileOptions = 0; 65 int numCompiles = 0; 66 ShHandle vertexCompiler = 0; 67 ShHandle fragmentCompiler = 0; 68 char* buffer = 0; 69 size_t bufferLen = 0; 70 ShShaderSpec spec = SH_GLES2_SPEC; 71 ShShaderOutput output = SH_ESSL_OUTPUT; 72 73 ShInitialize(); 74 75 ShBuiltInResources resources; 76 GenerateResources(&resources); 77 78 argc--; 79 argv++; 80 for (; (argc >= 1) && (failCode == ESuccess); argc--, argv++) { 81 if (argv[0][0] == '-') { 82 switch (argv[0][1]) { 83 case 'i': compileOptions |= SH_INTERMEDIATE_TREE; break; 84 case 'o': compileOptions |= SH_OBJECT_CODE; break; 85 case 'u': compileOptions |= SH_VARIABLES; break; 86 case 'l': compileOptions |= SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX; break; 87 case 'e': compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; break; 88 case 'd': compileOptions |= SH_DEPENDENCY_GRAPH; break; 89 case 't': compileOptions |= SH_TIMING_RESTRICTIONS; break; 90 case 's': 91 if (argv[0][2] == '=') { 92 switch (argv[0][3]) { 93 case 'e': spec = SH_GLES2_SPEC; break; 94 case 'w': spec = SH_WEBGL_SPEC; break; 95 case 'c': spec = SH_CSS_SHADERS_SPEC; break; 96 default: failCode = EFailUsage; 97 } 98 } else { 99 failCode = EFailUsage; 100 } 101 break; 102 case 'b': 103 if (argv[0][2] == '=') { 104 switch (argv[0][3]) { 105 case 'e': output = SH_ESSL_OUTPUT; break; 106 case 'g': output = SH_GLSL_OUTPUT; break; 107 case 'h': 108 if (argv[0][4] == '1' && argv[0][5] == '1') 109 { 110 output = SH_HLSL11_OUTPUT; 111 } 112 else 113 { 114 output = SH_HLSL9_OUTPUT; 115 } 116 break; 117 default: failCode = EFailUsage; 118 } 119 } else { 120 failCode = EFailUsage; 121 } 122 break; 123 case 'x': 124 if (argv[0][2] == '=') { 125 switch (argv[0][3]) { 126 case 'i': resources.OES_EGL_image_external = 1; break; 127 case 'd': resources.OES_standard_derivatives = 1; break; 128 case 'r': resources.ARB_texture_rectangle = 1; break; 129 case 'l': resources.EXT_shader_texture_lod = 1; break; 130 default: failCode = EFailUsage; 131 } 132 } else { 133 failCode = EFailUsage; 134 } 135 break; 136 default: failCode = EFailUsage; 137 } 138 } else { 139 ShHandle compiler = 0; 140 switch (FindShaderType(argv[0])) { 141 case GL_VERTEX_SHADER: 142 if (vertexCompiler == 0) 143 vertexCompiler = ShConstructCompiler( 144 GL_VERTEX_SHADER, spec, output, &resources); 145 compiler = vertexCompiler; 146 break; 147 case GL_FRAGMENT_SHADER: 148 if (fragmentCompiler == 0) 149 fragmentCompiler = ShConstructCompiler( 150 GL_FRAGMENT_SHADER, spec, output, &resources); 151 compiler = fragmentCompiler; 152 break; 153 default: break; 154 } 155 if (compiler) { 156 bool compiled = CompileFile(argv[0], compiler, compileOptions); 157 158 LogMsg("BEGIN", "COMPILER", numCompiles, "INFO LOG"); 159 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &bufferLen); 160 buffer = (char*) realloc(buffer, bufferLen * sizeof(char)); 161 ShGetInfoLog(compiler, buffer); 162 puts(buffer); 163 LogMsg("END", "COMPILER", numCompiles, "INFO LOG"); 164 printf("\n\n"); 165 166 if (compiled && (compileOptions & SH_OBJECT_CODE)) { 167 LogMsg("BEGIN", "COMPILER", numCompiles, "OBJ CODE"); 168 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &bufferLen); 169 buffer = (char*) realloc(buffer, bufferLen * sizeof(char)); 170 ShGetObjectCode(compiler, buffer); 171 puts(buffer); 172 LogMsg("END", "COMPILER", numCompiles, "OBJ CODE"); 173 printf("\n\n"); 174 } 175 if (compiled && (compileOptions & SH_VARIABLES)) { 176 LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE ATTRIBS"); 177 PrintActiveVariables(compiler, SH_ACTIVE_ATTRIBUTES); 178 LogMsg("END", "COMPILER", numCompiles, "ACTIVE ATTRIBS"); 179 printf("\n\n"); 180 181 LogMsg("BEGIN", "COMPILER", numCompiles, "ACTIVE UNIFORMS"); 182 PrintActiveVariables(compiler, SH_ACTIVE_UNIFORMS); 183 LogMsg("END", "COMPILER", numCompiles, "ACTIVE UNIFORMS"); 184 printf("\n\n"); 185 } 186 if (!compiled) 187 failCode = EFailCompile; 188 ++numCompiles; 189 } else { 190 failCode = EFailCompilerCreate; 191 } 192 } 193 } 194 195 if ((vertexCompiler == 0) && (fragmentCompiler == 0)) 196 failCode = EFailUsage; 197 if (failCode == EFailUsage) 198 usage(); 199 200 if (vertexCompiler) 201 ShDestruct(vertexCompiler); 202 if (fragmentCompiler) 203 ShDestruct(fragmentCompiler); 204 if (buffer) 205 free(buffer); 206 ShFinalize(); 207 208 return failCode; 209 } 210 211 // 212 // print usage to stdout 213 // 214 void usage() 215 { 216 printf("Usage: translate [-i -m -o -u -l -e -b=e -b=g -b=h -x=i -x=d] file1 file2 ...\n" 217 "Where: filename : filename ending in .frag or .vert\n" 218 " -i : print intermediate tree\n" 219 " -m : map long variable names\n" 220 " -o : print translated code\n" 221 " -u : print active attribs and uniforms\n" 222 " -l : unroll for-loops with integer indices\n" 223 " -e : emulate certain built-in functions (workaround for driver bugs)\n" 224 " -t : enforce experimental timing restrictions\n" 225 " -d : print dependency graph used to enforce timing restrictions\n" 226 " -s=e : use GLES2 spec (this is by default)\n" 227 " -s=w : use WebGL spec\n" 228 " -s=c : use CSS Shaders spec\n" 229 " -b=e : output GLSL ES code (this is by default)\n" 230 " -b=g : output GLSL code\n" 231 " -b=h9 : output HLSL9 code\n" 232 " -b=h11 : output HLSL11 code\n" 233 " -x=i : enable GL_OES_EGL_image_external\n" 234 " -x=d : enable GL_OES_EGL_standard_derivatives\n" 235 " -x=r : enable ARB_texture_rectangle\n" 236 " -x=l : enable EXT_shader_texture_lod\n"); 237 } 238 239 // 240 // Deduce the shader type from the filename. Files must end in one of the 241 // following extensions: 242 // 243 // .frag* = fragment shader 244 // .vert* = vertex shader 245 // 246 sh::GLenum FindShaderType(const char* fileName) 247 { 248 assert(fileName); 249 250 const char* ext = strrchr(fileName, '.'); 251 252 if (ext && strcmp(ext, ".sl") == 0) 253 for (; ext > fileName && ext[0] != '.'; ext--); 254 255 ext = strrchr(fileName, '.'); 256 if (ext) { 257 if (strncmp(ext, ".frag", 4) == 0) return GL_FRAGMENT_SHADER; 258 if (strncmp(ext, ".vert", 4) == 0) return GL_VERTEX_SHADER; 259 } 260 261 return GL_FRAGMENT_SHADER; 262 } 263 264 // 265 // Read a file's data into a string, and compile it using ShCompile 266 // 267 bool CompileFile(char* fileName, ShHandle compiler, int compileOptions) 268 { 269 ShaderSource source; 270 if (!ReadShaderSource(fileName, source)) 271 return false; 272 273 int ret = ShCompile(compiler, &source[0], source.size(), compileOptions); 274 275 FreeShaderSource(source); 276 return ret ? true : false; 277 } 278 279 void LogMsg(const char* msg, const char* name, const int num, const char* logName) 280 { 281 printf("#### %s %s %d %s ####\n", msg, name, num, logName); 282 } 283 284 void PrintActiveVariables(ShHandle compiler, ShShaderInfo varType) 285 { 286 size_t nameSize = 0; 287 switch (varType) { 288 case SH_ACTIVE_ATTRIBUTES: 289 ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &nameSize); 290 break; 291 case SH_ACTIVE_UNIFORMS: 292 ShGetInfo(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH, &nameSize); 293 break; 294 default: assert(0); 295 } 296 if (nameSize <= 1) return; 297 char* name = new char[nameSize]; 298 299 size_t activeVars = 0; 300 int size = 0; 301 sh::GLenum type = GL_NONE; 302 ShPrecisionType precision = SH_PRECISION_UNDEFINED; 303 int staticUse = 0; 304 const char* typeName = NULL; 305 ShGetInfo(compiler, varType, &activeVars); 306 for (size_t i = 0; i < activeVars; ++i) { 307 switch (varType) { 308 case SH_ACTIVE_ATTRIBUTES: 309 ShGetVariableInfo(compiler, SH_ACTIVE_ATTRIBUTES, static_cast<int>(i), NULL, &size, &type, &precision, &staticUse, name, NULL); 310 break; 311 case SH_ACTIVE_UNIFORMS: 312 ShGetVariableInfo(compiler, SH_ACTIVE_UNIFORMS, static_cast<int>(i), NULL, &size, &type, &precision, &staticUse, name, NULL); 313 break; 314 default: assert(0); 315 } 316 switch (type) { 317 case GL_FLOAT: typeName = "GL_FLOAT"; break; 318 case GL_FLOAT_VEC2: typeName = "GL_FLOAT_VEC2"; break; 319 case GL_FLOAT_VEC3: typeName = "GL_FLOAT_VEC3"; break; 320 case GL_FLOAT_VEC4: typeName = "GL_FLOAT_VEC4"; break; 321 case GL_INT: typeName = "GL_INT"; break; 322 case GL_INT_VEC2: typeName = "GL_INT_VEC2"; break; 323 case GL_INT_VEC3: typeName = "GL_INT_VEC3"; break; 324 case GL_INT_VEC4: typeName = "GL_INT_VEC4"; break; 325 case GL_UNSIGNED_INT: typeName = "GL_UNSIGNED_INT"; break; 326 case GL_UNSIGNED_INT_VEC2: typeName = "GL_UNSIGNED_INT_VEC2"; break; 327 case GL_UNSIGNED_INT_VEC3: typeName = "GL_UNSIGNED_INT_VEC3"; break; 328 case GL_UNSIGNED_INT_VEC4: typeName = "GL_UNSIGNED_INT_VEC4"; break; 329 case GL_BOOL: typeName = "GL_BOOL"; break; 330 case GL_BOOL_VEC2: typeName = "GL_BOOL_VEC2"; break; 331 case GL_BOOL_VEC3: typeName = "GL_BOOL_VEC3"; break; 332 case GL_BOOL_VEC4: typeName = "GL_BOOL_VEC4"; break; 333 case GL_FLOAT_MAT2: typeName = "GL_FLOAT_MAT2"; break; 334 case GL_FLOAT_MAT3: typeName = "GL_FLOAT_MAT3"; break; 335 case GL_FLOAT_MAT4: typeName = "GL_FLOAT_MAT4"; break; 336 case GL_FLOAT_MAT2x3: typeName = "GL_FLOAT_MAT2x3"; break; 337 case GL_FLOAT_MAT3x2: typeName = "GL_FLOAT_MAT3x2"; break; 338 case GL_FLOAT_MAT4x2: typeName = "GL_FLOAT_MAT4x2"; break; 339 case GL_FLOAT_MAT2x4: typeName = "GL_FLOAT_MAT2x4"; break; 340 case GL_FLOAT_MAT3x4: typeName = "GL_FLOAT_MAT3x4"; break; 341 case GL_FLOAT_MAT4x3: typeName = "GL_FLOAT_MAT4x3"; break; 342 case GL_SAMPLER_2D: typeName = "GL_SAMPLER_2D"; break; 343 case GL_SAMPLER_CUBE: typeName = "GL_SAMPLER_CUBE"; break; 344 case GL_SAMPLER_EXTERNAL_OES: typeName = "GL_SAMPLER_EXTERNAL_OES"; break; 345 default: assert(0); 346 } 347 printf("%lu: name:%s type:%s size:%d\n", i, name, typeName, size); 348 } 349 delete [] name; 350 } 351 352 static bool ReadShaderSource(const char* fileName, ShaderSource& source) { 353 FILE* in = fopen(fileName, "rb"); 354 if (!in) { 355 printf("Error: unable to open input file: %s\n", fileName); 356 return false; 357 } 358 359 // Obtain file size. 360 fseek(in, 0, SEEK_END); 361 size_t count = ftell(in); 362 rewind(in); 363 364 int len = (int)ceil((float)count / (float)NUM_SOURCE_STRINGS); 365 source.reserve(NUM_SOURCE_STRINGS); 366 // Notice the usage of do-while instead of a while loop here. 367 // It is there to handle empty files in which case a single empty 368 // string is added to vector. 369 do { 370 char* data = new char[len + 1]; 371 size_t nread = fread(data, 1, len, in); 372 data[nread] = '\0'; 373 source.push_back(data); 374 375 count -= nread; 376 } while (count > 0); 377 378 fclose(in); 379 return true; 380 } 381 382 static void FreeShaderSource(ShaderSource& source) { 383 for (ShaderSource::size_type i = 0; i < source.size(); ++i) { 384 delete [] source[i]; 385 } 386 source.clear(); 387 } 388 389