| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2018 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 GrSkSLFP_DEFINED |
| 9 | #define GrSkSLFP_DEFINED |
| 10 | |
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 11 | #include "include/core/SkRefCnt.h" |
| Brian Osman | bd4f872 | 2020-03-06 15:23:54 -0500 | [diff] [blame] | 12 | #include "include/gpu/GrContextOptions.h" |
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 13 | #include "src/gpu/GrCaps.h" |
| 14 | #include "src/gpu/GrCoordTransform.h" |
| 15 | #include "src/gpu/GrFragmentProcessor.h" |
| Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 16 | #include "src/sksl/SkSLCompiler.h" |
| 17 | #include "src/sksl/SkSLPipelineStageCodeGenerator.h" |
| Mike Klein | 0ec1c57 | 2018-12-04 11:52:51 -0500 | [diff] [blame] | 18 | #include <atomic> |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 19 | |
| Ethan Nicholas | 78aceb2 | 2018-08-31 16:13:58 -0400 | [diff] [blame] | 20 | #if GR_TEST_UTILS |
| 21 | #define GR_FP_SRC_STRING const char* |
| 22 | #else |
| 23 | #define GR_FP_SRC_STRING static const char* |
| 24 | #endif |
| 25 | |
| Robert Phillips | 1efecea | 2019-02-15 16:58:40 -0500 | [diff] [blame] | 26 | class GrContext_Base; |
| Robert Phillips | 7f11fb5 | 2019-12-03 13:35:19 -0500 | [diff] [blame] | 27 | class GrShaderCaps; |
| Brian Osman | 9bfd595 | 2020-02-05 10:51:44 -0500 | [diff] [blame] | 28 | class SkData; |
| Brian Osman | 7b1678a | 2019-12-16 09:17:25 -0500 | [diff] [blame] | 29 | class SkRuntimeEffect; |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 30 | |
| 31 | class GrSkSLFP : public GrFragmentProcessor { |
| 32 | public: |
| 33 | /** |
| Brian Osman | 7b1678a | 2019-12-16 09:17:25 -0500 | [diff] [blame] | 34 | * Creates a new fragment processor from an SkRuntimeEffect and a struct of inputs to the |
| Ethan Nicholas | 31cff27 | 2019-09-26 13:04:48 -0400 | [diff] [blame] | 35 | * program. The input struct's type is derived from the 'in' and 'uniform' variables in the SkSL |
| 36 | * source, so e.g. the shader: |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 37 | * |
| 38 | * in bool dither; |
| Ethan Nicholas | 31cff27 | 2019-09-26 13:04:48 -0400 | [diff] [blame] | 39 | * uniform float x; |
| 40 | * uniform float y; |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 41 | * .... |
| 42 | * |
| 43 | * would expect a pointer to a struct set up like: |
| 44 | * |
| 45 | * struct { |
| 46 | * bool dither; |
| 47 | * float x; |
| 48 | * float y; |
| 49 | * }; |
| 50 | * |
| Ethan Nicholas | 31cff27 | 2019-09-26 13:04:48 -0400 | [diff] [blame] | 51 | * While both 'in' and 'uniform' variables go into this struct, the difference between them is |
| 52 | * that 'in' variables are statically "baked in" to the generated code, becoming literals, |
| 53 | * whereas uniform variables may be changed from invocation to invocation without having to |
| 54 | * recompile the shader. |
| 55 | * |
| 56 | * As the decision of whether to create a new shader or just upload new uniforms all happens |
| 57 | * behind the scenes, the difference between the two from an end-user perspective is primarily |
| 58 | * in performance: on the one hand, changing the value of an 'in' variable is very expensive |
| 59 | * (requiring the compiler to regenerate the code, upload a new shader to the GPU, and so |
| 60 | * forth), but on the other hand the compiler can optimize around its value because it is known |
| 61 | * at compile time. 'in' variables are therefore suitable for things like flags, where there are |
| 62 | * only a few possible values and a known-in-advance value can cause entire chunks of code to |
| 63 | * become dead (think static @ifs), while 'uniform's are used for continuous values like colors |
| 64 | * and coordinates, where it would be silly to create a separate shader for each possible set of |
| 65 | * values. Other than the (significant) performance implications, the only difference between |
| 66 | * the two is that 'in' variables can be used in static @if / @switch tests. When in doubt, use |
| 67 | * 'uniform'. |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 68 | */ |
| Brian Osman | 7b1678a | 2019-12-16 09:17:25 -0500 | [diff] [blame] | 69 | static std::unique_ptr<GrSkSLFP> Make(GrContext_Base* context, |
| 70 | sk_sp<SkRuntimeEffect> effect, |
| 71 | const char* name, |
| Ethan Nicholas | afe2c90 | 2020-04-28 13:55:02 -0400 | [diff] [blame] | 72 | sk_sp<SkData> inputs); |
| Ethan Nicholas | a70693b | 2019-03-04 13:07:36 -0500 | [diff] [blame] | 73 | |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 74 | const char* name() const override; |
| 75 | |
| Ethan Nicholas | ce00811 | 2018-08-30 09:19:50 -0400 | [diff] [blame] | 76 | void addChild(std::unique_ptr<GrFragmentProcessor> child); |
| 77 | |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 78 | std::unique_ptr<GrFragmentProcessor> clone() const override; |
| 79 | |
| 80 | private: |
| Brian Osman | bd4f872 | 2020-03-06 15:23:54 -0500 | [diff] [blame] | 81 | using ShaderErrorHandler = GrContextOptions::ShaderErrorHandler; |
| 82 | |
| 83 | GrSkSLFP(sk_sp<const GrShaderCaps> shaderCaps, ShaderErrorHandler* shaderErrorHandler, |
| Ethan Nicholas | afe2c90 | 2020-04-28 13:55:02 -0400 | [diff] [blame] | 84 | sk_sp<SkRuntimeEffect> effect, const char* name, sk_sp<SkData> inputs); |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 85 | |
| 86 | GrSkSLFP(const GrSkSLFP& other); |
| 87 | |
| 88 | GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; |
| 89 | |
| 90 | void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; |
| 91 | |
| 92 | bool onIsEqual(const GrFragmentProcessor&) const override; |
| 93 | |
| Brian Osman | 7b1678a | 2019-12-16 09:17:25 -0500 | [diff] [blame] | 94 | sk_sp<const GrShaderCaps> fShaderCaps; |
| Brian Osman | bd4f872 | 2020-03-06 15:23:54 -0500 | [diff] [blame] | 95 | ShaderErrorHandler* fShaderErrorHandler; |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 96 | |
| Brian Osman | 7b1678a | 2019-12-16 09:17:25 -0500 | [diff] [blame] | 97 | sk_sp<SkRuntimeEffect> fEffect; |
| 98 | const char* fName; |
| Brian Osman | 9bfd595 | 2020-02-05 10:51:44 -0500 | [diff] [blame] | 99 | sk_sp<SkData> fInputs; |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 100 | |
| Brian Osman | 3b1e4c2 | 2019-08-12 15:12:14 -0400 | [diff] [blame] | 101 | GrCoordTransform fCoordTransform; |
| 102 | |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 103 | GR_DECLARE_FRAGMENT_PROCESSOR_TEST |
| 104 | |
| 105 | typedef GrFragmentProcessor INHERITED; |
| 106 | |
| Ethan Nicholas | ce00811 | 2018-08-30 09:19:50 -0400 | [diff] [blame] | 107 | friend class GrGLSLSkSLFP; |
| 108 | |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 109 | friend class GrSkSLFPFactory; |
| 110 | }; |
| 111 | |
| Ethan Nicholas | 0054311 | 2018-07-31 09:44:36 -0400 | [diff] [blame] | 112 | #endif |