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 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