Home | History | Annotate | Download | only in sksl
      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