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 if (input.endsWith(".stage")) { 49 kind = SkSL::Program::kPipelineStage_Kind; 50 } else { 51 printf("input filename must end in '.vert', '.frag', '.geom', '.fp', or '.stage'\n"); 52 exit(1); 53 } 54 55 std::ifstream in(argv[1]); 56 std::string stdText((std::istreambuf_iterator<char>(in)), 57 std::istreambuf_iterator<char>()); 58 SkSL::String text(stdText.c_str()); 59 if (in.rdstate()) { 60 printf("error reading '%s'\n", argv[1]); 61 exit(2); 62 } 63 SkSL::Program::Settings settings; 64 settings.fArgs.insert(std::make_pair("gpImplementsDistanceVector", 1)); 65 SkSL::String name(argv[2]); 66 if (name.endsWith(".spirv")) { 67 SkSL::FileOutputStream out(argv[2]); 68 SkSL::Compiler compiler; 69 if (!out.isValid()) { 70 printf("error writing '%s'\n", argv[2]); 71 exit(4); 72 } 73 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 74 if (!program || !compiler.toSPIRV(*program, out)) { 75 printf("%s", compiler.errorText().c_str()); 76 exit(3); 77 } 78 if (!out.close()) { 79 printf("error writing '%s'\n", argv[2]); 80 exit(4); 81 } 82 } else if (name.endsWith(".glsl")) { 83 SkSL::FileOutputStream out(argv[2]); 84 SkSL::Compiler compiler; 85 if (!out.isValid()) { 86 printf("error writing '%s'\n", argv[2]); 87 exit(4); 88 } 89 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 90 if (!program || !compiler.toGLSL(*program, out)) { 91 printf("%s", compiler.errorText().c_str()); 92 exit(3); 93 } 94 if (!out.close()) { 95 printf("error writing '%s'\n", argv[2]); 96 exit(4); 97 } 98 } else if (name.endsWith(".metal")) { 99 SkSL::FileOutputStream out(argv[2]); 100 SkSL::Compiler compiler; 101 if (!out.isValid()) { 102 printf("error writing '%s'\n", argv[2]); 103 exit(4); 104 } 105 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 106 if (!program || !compiler.toMetal(*program, out)) { 107 printf("%s", compiler.errorText().c_str()); 108 exit(3); 109 } 110 if (!out.close()) { 111 printf("error writing '%s'\n", argv[2]); 112 exit(4); 113 } 114 } else if (name.endsWith(".h")) { 115 SkSL::FileOutputStream out(argv[2]); 116 SkSL::Compiler compiler(SkSL::Compiler::kPermitInvalidStaticTests_Flag); 117 if (!out.isValid()) { 118 printf("error writing '%s'\n", argv[2]); 119 exit(4); 120 } 121 settings.fReplaceSettings = false; 122 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 123 if (!program || !compiler.toH(*program, base_name(argv[1], "Gr", ".fp"), out)) { 124 printf("%s", compiler.errorText().c_str()); 125 exit(3); 126 } 127 if (!out.close()) { 128 printf("error writing '%s'\n", argv[2]); 129 exit(4); 130 } 131 } else if (name.endsWith(".cpp")) { 132 SkSL::FileOutputStream out(argv[2]); 133 SkSL::Compiler compiler(SkSL::Compiler::kPermitInvalidStaticTests_Flag); 134 if (!out.isValid()) { 135 printf("error writing '%s'\n", argv[2]); 136 exit(4); 137 } 138 settings.fReplaceSettings = false; 139 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings); 140 if (!program || !compiler.toCPP(*program, base_name(argv[1], "Gr", ".fp"), out)) { 141 printf("%s", compiler.errorText().c_str()); 142 exit(3); 143 } 144 if (!out.close()) { 145 printf("error writing '%s'\n", argv[2]); 146 exit(4); 147 } 148 } else { 149 printf("expected output filename to end with '.spirv', '.glsl', '.cpp', '.h', or '.metal'"); 150 exit(1); 151 } 152 } 153