blob: c51ccc294a693c5c2aabdc8344bffa5c0f71d9de [file] [log] [blame]
/*
* 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 {
class ExternalFunction;
/**
* 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;
// External functions available for use in runtime effects. These values are registered in the
// symbol table of the Program, but ownership is *not* transferred. It is up to the caller to
// keep them alive.
const std::vector<std::unique_ptr<ExternalFunction>>* fExternalFunctions = nullptr;
// 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) || fKind == ProgramKind::kGeneric;
}
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