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 #ifndef SKSL_PROGRAMSETTINGS 9 #define SKSL_PROGRAMSETTINGS 10 11 #include "include/sksl/SkSLVersion.h" 12 #include "src/sksl/SkSLDefines.h" 13 #include "src/sksl/SkSLModule.h" 14 #include "src/sksl/SkSLProgramKind.h" 15 16 #include <optional> 17 #include <vector> 18 19 namespace SkSL { 20 21 enum class ModuleType : int8_t; 22 23 /** 24 * Holds the compiler settings for a program. 25 */ 26 struct ProgramSettings { 27 // If true, the destination fragment color can be read from sk_FragColor. It must be declared 28 // inout. This is only supported in GLSL, when framebuffer-fetch is used. 29 bool fFragColorIsInOut = false; 30 // if true, all halfs are forced to be floats 31 bool fForceHighPrecision = false; 32 // if true, add -0.5 bias to LOD of all texture lookups 33 bool fSharpenTextures = false; 34 // If true, sk_FragCoord, the dFdy gradient, and sk_Clockwise won't be modified by the 35 // rtFlip. Additionally, the program interface's 'fRTFlipUniform' value will be left as None, 36 // so no rtFlip uniform will be emitted. 37 bool fForceNoRTFlip = false; 38 // if the program needs to create an RTFlip uniform, this is its offset in the uniform buffer 39 int fRTFlipOffset = -1; 40 // if the program needs to create an RTFlip uniform and is creating SPIR-V, this is the binding 41 // and set number of the uniform buffer. 42 int fRTFlipBinding = -1; 43 int fRTFlipSet = -1; 44 // If layout(set=S, binding=B) is not specified for a uniform, these values will be used. 45 // At present, zero is always used by our backends. 46 int fDefaultUniformSet = 0; 47 int fDefaultUniformBinding = 0; 48 // Enables the SkSL optimizer. Note that we never disable optimizations which are needed to 49 // fully evaluate constant-expressions, like constant folding or constant-intrinsic evaluation. 50 bool fOptimize = true; 51 // (Requires fOptimize = true) Removes any uncalled functions other than main(). Note that a 52 // function which starts out being used may end up being uncalled after optimization. 53 bool fRemoveDeadFunctions = true; 54 // (Requires fOptimize = true) Removes variables which are never used. 55 bool fRemoveDeadVariables = true; 56 // (Requires fOptimize = true) When greater than zero, enables the inliner. The threshold value 57 // sets an upper limit on the acceptable amount of code growth from inlining. 58 int fInlineThreshold = SkSL::kDefaultInlineThreshold; 59 // If true, every function in the generated program will be given the `noinline` modifier. 60 bool fForceNoInline = false; 61 // If true, implicit conversions to lower precision numeric types are allowed (e.g., float to 62 // half). These are always allowed when compiling Runtime Effects. 63 bool fAllowNarrowingConversions = false; 64 // If true, then Debug code will run SPIR-V output through the validator to ensure its 65 // correctness 66 bool fValidateSPIRV = true; 67 // If true, any synthetic uniforms must use push constant syntax 68 bool fUseVulkanPushConstantsForGaneshRTAdjust = false; 69 // TODO(skia:11209) - Replace this with a "promised" capabilities? 70 // Sets a maximum SkSL version. Compilation will fail if the program uses features that aren't 71 // allowed at the requested version. For instance, a valid program must have fully-unrollable 72 // `for` loops at version 100, but any loop structure is allowed at version 300. 73 SkSL::Version fMaxVersionAllowed = SkSL::Version::k100; 74 // If true, SkSL will use a memory pool for all IR nodes when compiling a program. This is 75 // usually a significant speed increase, but uses more memory, so it is a good idea for programs 76 // that will be freed shortly after compilation. It can also be useful to disable this flag when 77 // investigating memory corruption. (This controls behavior of the SkSL compiler, not the code 78 // we generate.) 79 bool fUseMemoryPool = true; 80 // Advanced Filter: It's a flag for skia to passthrough uv coord from vert stage to frag stage 81 // It's the same value with SkRuntimeEffect::fUseAF 82 bool fUseAF = false; 83 }; 84 85 /** 86 * All the configuration data for a given program. 87 */ 88 struct ProgramConfig { 89 /** 90 * If we are compiling one of the SkSL built-in modules, this field indicates which one. 91 * Contains `ModuleType::program` when not compiling a module at all. 92 */ 93 ModuleType fModuleType; 94 ProgramKind fKind; 95 ProgramSettings fSettings; 96 isBuiltinCodeProgramConfig97 bool isBuiltinCode() { 98 return fModuleType != ModuleType::program; 99 } 100 101 // When enforcesSkSLVersion() is true, this determines the available feature set that will be 102 // enforced. This is set automatically when the `#version` directive is parsed. 103 SkSL::Version fRequiredSkSLVersion = SkSL::Version::k100; 104 enforcesSkSLVersionProgramConfig105 bool enforcesSkSLVersion() const { 106 return IsRuntimeEffect(fKind); 107 } 108 strictES2ModeProgramConfig109 bool strictES2Mode() const { 110 // TODO(skia:11209): Remove the first condition - so this is just based on #version. 111 // Make it more generic (eg, isVersionLT) checking. 112 return fSettings.fMaxVersionAllowed == Version::k100 && 113 fRequiredSkSLVersion == Version::k100 && 114 this->enforcesSkSLVersion(); 115 } 116 versionDescriptionProgramConfig117 const char* versionDescription() const { 118 if (this->enforcesSkSLVersion()) { 119 switch (fRequiredSkSLVersion) { 120 case Version::k100: return "#version 100\n"; 121 case Version::k300: return "#version 300\n"; 122 } 123 } 124 return ""; 125 } 126 IsFragmentProgramConfig127 static bool IsFragment(ProgramKind kind) { 128 return kind == ProgramKind::kFragment || 129 kind == ProgramKind::kGraphiteFragment || 130 kind == ProgramKind::kGraphiteFragmentES2; 131 } 132 IsVertexProgramConfig133 static bool IsVertex(ProgramKind kind) { 134 return kind == ProgramKind::kVertex || 135 kind == ProgramKind::kGraphiteVertex || 136 kind == ProgramKind::kGraphiteVertexES2; 137 } 138 IsComputeProgramConfig139 static bool IsCompute(ProgramKind kind) { 140 return kind == ProgramKind::kCompute; 141 } 142 IsRuntimeEffectProgramConfig143 static bool IsRuntimeEffect(ProgramKind kind) { 144 return (kind == ProgramKind::kRuntimeColorFilter || 145 kind == ProgramKind::kRuntimeShader || 146 kind == ProgramKind::kRuntimeBlender || 147 kind == ProgramKind::kPrivateRuntimeColorFilter || 148 kind == ProgramKind::kPrivateRuntimeShader || 149 kind == ProgramKind::kPrivateRuntimeBlender || 150 kind == ProgramKind::kMeshVertex || 151 kind == ProgramKind::kMeshFragment); 152 } 153 IsRuntimeShaderProgramConfig154 static bool IsRuntimeShader(ProgramKind kind) { 155 return (kind == ProgramKind::kRuntimeShader || 156 kind == ProgramKind::kPrivateRuntimeShader); 157 } 158 IsRuntimeColorFilterProgramConfig159 static bool IsRuntimeColorFilter(ProgramKind kind) { 160 return (kind == ProgramKind::kRuntimeColorFilter || 161 kind == ProgramKind::kPrivateRuntimeColorFilter); 162 } 163 IsRuntimeBlenderProgramConfig164 static bool IsRuntimeBlender(ProgramKind kind) { 165 return (kind == ProgramKind::kRuntimeBlender || 166 kind == ProgramKind::kPrivateRuntimeBlender); 167 } 168 IsMeshProgramConfig169 static bool IsMesh(ProgramKind kind) { 170 return (kind == ProgramKind::kMeshVertex || 171 kind == ProgramKind::kMeshFragment); 172 } 173 AllowsPrivateIdentifiersProgramConfig174 static bool AllowsPrivateIdentifiers(ProgramKind kind) { 175 return (kind != ProgramKind::kRuntimeColorFilter && 176 kind != ProgramKind::kRuntimeShader && 177 kind != ProgramKind::kRuntimeBlender && 178 kind != ProgramKind::kMeshVertex && 179 kind != ProgramKind::kMeshFragment); 180 } 181 }; 182 183 } // namespace SkSL 184 185 #endif 186