1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include <fstream> 9 #include "SkSLCompiler.h" 10 #include "SkSLFileOutputStream.h" 11 12 // Given the path to a file (e.g. src/gpu/effects/GrFooFragmentProcessor.fp) and the expected 13 // filename prefix and suffix (e.g. "Gr" and ".fp"), returns the "base name" of the 14 // file (in this case, 'FooFragmentProcessor'). If no match, returns the empty string. 15 static SkSL::String base_name(const char* fpPath, const char* prefix, const char* suffix) { 16 SkSL::String result; 17 const char* end = fpPath + strlen(fpPath); 18 const char* fileName = end; 19 // back up until we find a slash 20 while (fileName != fpPath && '/' != *(fileName - 1) && '\\' != *(fileName - 1)) { 21 --fileName; 22 } 23 if (!strncmp(fileName, prefix, strlen(prefix)) && 24 !strncmp(end - strlen(suffix), suffix, strlen(suffix))) { 25 result.append(fileName + strlen(prefix), end - fileName - strlen(prefix) - strlen(suffix)); 26 } 27 return result; 28 } 29 30 /** 31 * Very simple standalone executable to facilitate testing. 32 */ 33 int main(int argc, const char** argv) { 34 if (argc != 3) { 35 printf("usage: skslc <input> <output>\n"); 36 exit(1); 37 } 38 SkSL::Program::Kind kind; 39 SkSL::String input(argv[1]); 40 if (input.endsWith(".vert")) { 41 kind = SkSL::Program::kVertex_Kind; 42 } else if (input.endsWith(".frag")) { 43 kind = SkSL::Program::kFragment_Kind; 44 } else if (input.endsWith(".geom")) { 45 kind = SkSL::Program::kGeometry_Kind; 46 } else if (input.endsWith(".fp")) { 47 kind = SkSL::Program::kFragmentProcessor_Kind; 48 } else { 49 printf("input filename must end in '.vert', '.frag', '.geom', or '.fp'\n"); 50 exit(1); 51 } 52 53 std::ifstream in(argv[1]); 54 std::string stdText((std::istreambuf_iterator<char>(in)), 55 std::istreambuf_iterator<char>()); 56 SkSL::String text(stdText.c_str()); 57 if (in.rdstate()) { 58 printf("error reading '%s'\n", argv[1]); 59 exit(2); 60 } 61 SkSL::Program::Settings settings; 62 settings.fArgs.insert(std::make_pair("gpImplementsDistanceVector", 1)); 63 SkSL::String name(argv[2]); 64 if (name.endsWith(".spirv")) { 65 SkSL::FileOutputStream out(argv[2]); 66 SkSL::Compiler compiler; 67 if (!out.isValid()) { 68 printf("error writing '%s'\n", argv[2]); 69 exit(4); 70 } 71 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 72 if (!program || !compiler.toSPIRV(*program, out)) { 73 printf("%s", compiler.errorText().c_str()); 74 exit(3); 75 } 76 if (!out.close()) { 77 printf("error writing '%s'\n", argv[2]); 78 exit(4); 79 } 80 } else if (name.endsWith(".glsl")) { 81 SkSL::FileOutputStream out(argv[2]); 82 SkSL::Compiler compiler; 83 if (!out.isValid()) { 84 printf("error writing '%s'\n", argv[2]); 85 exit(4); 86 } 87 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 88 if (!program || !compiler.toGLSL(*program, out)) { 89 printf("%s", compiler.errorText().c_str()); 90 exit(3); 91 } 92 if (!out.close()) { 93 printf("error writing '%s'\n", argv[2]); 94 exit(4); 95 } 96 } else if (name.endsWith(".metal")) { 97 SkSL::FileOutputStream out(argv[2]); 98 SkSL::Compiler compiler; 99 if (!out.isValid()) { 100 printf("error writing '%s'\n", argv[2]); 101 exit(4); 102 } 103 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 104 if (!program || !compiler.toMetal(*program, out)) { 105 printf("%s", compiler.errorText().c_str()); 106 exit(3); 107 } 108 if (!out.close()) { 109 printf("error writing '%s'\n", argv[2]); 110 exit(4); 111 } 112 } else if (name.endsWith(".h")) { 113 SkSL::FileOutputStream out(argv[2]); 114 SkSL::Compiler compiler(SkSL::Compiler::kPermitInvalidStaticTests_Flag); 115 if (!out.isValid()) { 116 printf("error writing '%s'\n", argv[2]); 117 exit(4); 118 } 119 settings.fReplaceSettings = false; 120 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 121 if (!program || !compiler.toH(*program, base_name(argv[1], "Gr", ".fp"), out)) { 122 printf("%s", compiler.errorText().c_str()); 123 exit(3); 124 } 125 if (!out.close()) { 126 printf("error writing '%s'\n", argv[2]); 127 exit(4); 128 } 129 } else if (name.endsWith(".cpp")) { 130 SkSL::FileOutputStream out(argv[2]); 131 SkSL::Compiler compiler(SkSL::Compiler::kPermitInvalidStaticTests_Flag); 132 if (!out.isValid()) { 133 printf("error writing '%s'\n", argv[2]); 134 exit(4); 135 } 136 settings.fReplaceSettings = false; 137 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 138 if (!program || !compiler.toCPP(*program, base_name(argv[1], "Gr", ".fp"), out)) { 139 printf("%s", compiler.errorText().c_str()); 140 exit(3); 141 } 142 if (!out.close()) { 143 printf("error writing '%s'\n", argv[2]); 144 exit(4); 145 } 146 } else { 147 printf("expected output filename to end with '.spirv', '.glsl', '.cpp', '.h', or '.metal'"); 148 exit(1); 149 } 150 } 151