/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SKSL_PROGRAMSETTINGS
#define SKSL_PROGRAMSETTINGS

#include "include/private/SkSLDefines.h"
#include "include/private/SkSLProgramKind.h"
#include "include/sksl/SkSLVersion.h"

#include <vector>

namespace SkSL {

/**
 * Holds the compiler settings for a program.
 */
struct ProgramSettings {
    // If true, the destination fragment color can be read from sk_FragColor. It must be declared
    // inout. This is only supported in GLSL, when framebuffer-fetch is used.
    bool fFragColorIsInOut = false;
    // if true, all halfs are forced to be floats
    bool fForceHighPrecision = false;
    // if true, add -0.5 bias to LOD of all texture lookups
    bool fSharpenTextures = false;
    // If true, sk_FragCoord, the dFdy gradient, and sk_Clockwise won't be modified by the
    // rtFlip. Additionally, the 'fUseFlipRTUniform' boolean will be forced to false so no rtFlip
    // uniform will be emitted.
    bool fForceNoRTFlip = false;
    // if the program needs to create an RTFlip uniform, this is its offset in the uniform buffer
    int fRTFlipOffset = -1;
    // if the program needs to create an RTFlip uniform and is creating SPIR-V, this is the binding
    // and set number of the uniform buffer.
    int fRTFlipBinding = -1;
    int fRTFlipSet = -1;
    // If layout(set=S, binding=B) is not specified for a uniform, these values will be used.
    // At present, zero is always used by our backends.
    int fDefaultUniformSet = 0;
    int fDefaultUniformBinding = 0;
    // Enables the SkSL optimizer. Note that we never disable optimizations which are needed to
    // fully evaluate constant-expressions, like constant folding or constant-intrinsic evaluation.
    bool fOptimize = true;
    // (Requires fOptimize = true) Removes any uncalled functions other than main(). Note that a
    // function which starts out being used may end up being uncalled after optimization.
    bool fRemoveDeadFunctions = true;
    // (Requires fOptimize = true) Removes variables which are never used.
    bool fRemoveDeadVariables = true;
    // (Requires fOptimize = true) When greater than zero, enables the inliner. The threshold value
    // sets an upper limit on the acceptable amount of code growth from inlining.
    int fInlineThreshold = SkSL::kDefaultInlineThreshold;
    // If true, every function in the generated program will be given the `noinline` modifier.
    bool fForceNoInline = false;
    // If true, implicit conversions to lower precision numeric types are allowed (e.g., float to
    // half). These are always allowed when compiling Runtime Effects.
    bool fAllowNarrowingConversions = false;
    // If true, then Debug code will run SPIR-V output through the validator to ensure its
    // correctness
    bool fValidateSPIRV = true;
    // If true, any synthetic uniforms must use push constant syntax
    bool fUsePushConstants = false;
    // TODO(skia:11209) - Replace this with a "promised" capabilities?
    // Sets a maximum SkSL version. Compilation will fail if the program uses features that aren't
    // allowed at the requested version. For instance, a valid program must have fully-unrollable
    // `for` loops at version 100, but any loop structure is allowed at version 300.
    SkSL::Version fMaxVersionAllowed = SkSL::Version::k100;
    // If true, SkVM debug traces will contain the `trace_var` opcode. This opcode can cause the
    // generated code to contain a lot of extra computations, because we need to explicitly compute
    // every temporary value, even ones that would otherwise be optimized away entirely. The other
    // debug opcodes are much less invasive on the generated code.
    bool fAllowTraceVarInSkVMDebugTrace = true;
    // If true, SkSL will use a memory pool for all IR nodes when compiling a program. This is
    // usually a significant speed increase, but uses more memory, so it is a good idea for programs
    // that will be freed shortly after compilation. It can also be useful to disable this flag when
    // investigating memory corruption. (This controls behavior of the SkSL compiler, not the code
    // we generate.)
    bool fUseMemoryPool = true;
    // If true, VarDeclaration can be cloned for testing purposes. See VarDeclaration::clone for
    // more information.
    bool fAllowVarDeclarationCloneForTesting = false;
    // If true, SPIR-V codegen restricted to a subset supported by Dawn.
    // TODO(skia:13840, skia:14023): Remove this setting when Skia can use WGSL on Dawn.
    bool fSPIRVDawnCompatMode = false;
};

/**
 * All the configuration data for a given program.
 */
struct ProgramConfig {
    /** True if we are currently processing one of the built-in SkSL include modules. */
    bool fIsBuiltinCode;
    ProgramKind fKind;
    ProgramSettings fSettings;

    // When enforcesSkSLVersion() is true, this determines the available feature set that will be
    // enforced. This is set automatically when the `#version` directive is parsed.
    SkSL::Version fRequiredSkSLVersion = SkSL::Version::k100;

    bool enforcesSkSLVersion() const {
        return IsRuntimeEffect(fKind);
    }

    bool strictES2Mode() const {
        // TODO(skia:11209): Remove the first condition - so this is just based on #version.
        //                   Make it more generic (eg, isVersionLT) checking.
        return fSettings.fMaxVersionAllowed == Version::k100 &&
               fRequiredSkSLVersion == Version::k100 &&
               this->enforcesSkSLVersion();
    }

    const char* versionDescription() const {
        if (this->enforcesSkSLVersion()) {
            switch (fRequiredSkSLVersion) {
                case Version::k100: return "#version 100\n";
                case Version::k300: return "#version 300\n";
            }
        }
        return "";
    }

    static bool IsFragment(ProgramKind kind) {
        return kind == ProgramKind::kFragment ||
               kind == ProgramKind::kGraphiteFragment;
    }

    static bool IsVertex(ProgramKind kind) {
        return kind == ProgramKind::kVertex ||
               kind == ProgramKind::kGraphiteVertex;
    }

    static bool IsCompute(ProgramKind kind) {
        return kind == ProgramKind::kCompute;
    }

    static bool IsRuntimeEffect(ProgramKind kind) {
        return (kind == ProgramKind::kRuntimeColorFilter ||
                kind == ProgramKind::kRuntimeShader ||
                kind == ProgramKind::kRuntimeBlender ||
                kind == ProgramKind::kPrivateRuntimeColorFilter ||
                kind == ProgramKind::kPrivateRuntimeShader ||
                kind == ProgramKind::kPrivateRuntimeBlender ||
                kind == ProgramKind::kMeshVertex ||
                kind == ProgramKind::kMeshFragment);
    }

    static bool AllowsPrivateIdentifiers(ProgramKind kind) {
        return (kind != ProgramKind::kRuntimeColorFilter &&
                kind != ProgramKind::kRuntimeShader &&
                kind != ProgramKind::kRuntimeBlender &&
                kind != ProgramKind::kMeshVertex &&
                kind != ProgramKind::kMeshFragment);
    }
};

}  // namespace SkSL

#endif
