root/test/generator/example_generator.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. generate
  2. schedule

#include "Halide.h"

// By convention, Generators always go in a .cpp file, usually with no
// corresponding .h file. They can be enclosed in any C++ namespaces
// you like, but the anonymous namespace is often the best choice.
//
// It's normally considered Best Practice to have exactly one Generator
// per .cpp file, and to have the .cpp file name match the generator name
// with a "_generator" suffix (e.g., Generator with name "foo" should
// live in "foo_generator.cpp"), as it tends to simplify build rules,
// but neither of these are required.

namespace {

enum SomeEnum { Foo, Bar };

// Note the inheritance using the Curiously Recurring Template Pattern
class Example : public Halide::Generator<Example> {
public:
    // GeneratorParams, ScheduleParams, Inputs, and Outputs are (by convention)
    // always public and always declared at the top of the Generator,
    // in the order
    //    GeneratorParam(s)
    //    ScheduleParam(s)
    //    Input(s)
    //    Output(s)
    //
    // Note that the Inputs will appear in the C function
    // call in the order they are declared. (GeneratorParams and ScheduleParams 
    // are always referenced by name, not position, so their order is irrelevant.)
    //
    // All Input variants declared as Generator members must have explicit
    // names, and all such names must match the regex [A-Za-z_][A-Za-z_0-9]*
    // (i.e., essentially a C/C++ variable name). By convention, the name should 
    // match the member-variable name.

    // GeneratorParams can be float or ints: {default} or {default, min, max}
    // (Note that if you want to specify min and max, you must specify both.)
    GeneratorParam<float> compiletime_factor{ "compiletime_factor", 1, 0, 100 };
    GeneratorParam<int> channels{ "channels", 3 };
    // ...or enums: {default, name->value map}
    GeneratorParam<SomeEnum> enummy{ "enummy",
                                     Foo,
                                     { { "foo", Foo },
                                       { "bar", Bar } } };
    // ...or bools: {default}
    ScheduleParam<bool> vectorize{ "vectorize", true };

    // These are bad names that will produce errors at build time:
    // GeneratorParam<bool> badname{ " flag", true };
    // GeneratorParam<bool> badname{ "flag ", true };
    // GeneratorParam<bool> badname{ "0flag ", true };
    // GeneratorParam<bool> badname{ "", true };
    // GeneratorParam<bool> badname{ "\001", true };
    // GeneratorParam<bool> badname{ "a name? with! stuff*", true };

    // Note that a leading underscore is legal-but-reserved in C,
    // but it's outright forbidden here. (underscore after first char is ok.)
    // GeneratorParam<bool> badname{ "_flag", true };

    // We also forbid two underscores in a row.
    // GeneratorParam<bool> badname{ "f__lag", true };

    // Input<> are arguments passed to the filter when
    // it is executed (as opposed to the Generator, during compilation).
    // When jitting, there is effectively little difference between the
    // two (at least for scalar values). Note that we set a default value of
    // 1.0 so that invocations that don't set it explicitly use a predictable value.
    Input<float> runtime_factor{ "runtime_factor", 1.0 };

    Output<Func> output{ "output", Int(32), 3 };

    void generate() {
        Func f;
        f(x, y) = max(x, y);
        output(x, y, c) = cast(output.type(), f(x, y) * c * compiletime_factor * runtime_factor);
    }

    void schedule() {
        output
            .bound(c, 0, channels)
            .reorder(c, x, y)
            .unroll(c);
        // Note that we can use the Generator method natural_vector_size()
        // here; this produces the width of the SIMD vector being targeted
        // divided by the width of the data type.
        output
            .specialize(vectorize)
            .vectorize(x, natural_vector_size(output.type()));
    }

private:
    Var x{"x"}, y{"y"}, c{"c"};
};

}  // namespace

HALIDE_REGISTER_GENERATOR(Example, "example")

/* [<][>][^][v][top][bottom][index][help] */