1 // Copyright 2021 The Tint Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef SRC_TRANSFORM_CANONICALIZE_ENTRY_POINT_IO_H_ 16 #define SRC_TRANSFORM_CANONICALIZE_ENTRY_POINT_IO_H_ 17 18 #include "src/transform/transform.h" 19 20 namespace tint { 21 namespace transform { 22 23 /// CanonicalizeEntryPointIO is a transform used to rewrite shader entry point 24 /// interfaces into a form that the generators can handle. Each entry point 25 /// function is stripped of all shader IO attributes and wrapped in a function 26 /// that provides the shader interface. 27 /// The transform config determines whether to use global variables, structures, 28 /// or parameters for the shader inputs and outputs, and optionally adds 29 /// additional builtins to the shader interface. 30 /// 31 /// Before: 32 /// ``` 33 /// struct Locations{ 34 /// [[location(1)]] loc1 : f32; 35 /// [[location(2)]] loc2 : vec4<u32>; 36 /// }; 37 /// 38 /// [[stage(fragment)]] 39 /// fn frag_main([[builtin(position)]] coord : vec4<f32>, 40 /// locations : Locations) -> [[location(0)]] f32 { 41 /// if (coord.w > 1.0) { 42 /// return 0.0; 43 /// } 44 /// var col : f32 = (coord.x * locations.loc1); 45 /// return col; 46 /// } 47 /// ``` 48 /// 49 /// After (using structures for all parameters): 50 /// ``` 51 /// struct Locations{ 52 /// loc1 : f32; 53 /// loc2 : vec4<u32>; 54 /// }; 55 /// 56 /// struct frag_main_in { 57 /// [[builtin(position)]] coord : vec4<f32>; 58 /// [[location(1)]] loc1 : f32; 59 /// [[location(2)]] loc2 : vec4<u32> 60 /// }; 61 /// 62 /// struct frag_main_out { 63 /// [[location(0)]] loc0 : f32; 64 /// }; 65 /// 66 /// fn frag_main_inner(coord : vec4<f32>, 67 /// locations : Locations) -> f32 { 68 /// if (coord.w > 1.0) { 69 /// return 0.0; 70 /// } 71 /// var col : f32 = (coord.x * locations.loc1); 72 /// return col; 73 /// } 74 /// 75 /// [[stage(fragment)]] 76 /// fn frag_main(in : frag_main_in) -> frag_main_out { 77 /// let inner_retval = frag_main_inner(in.coord, Locations(in.loc1, in.loc2)); 78 /// var wrapper_result : frag_main_out; 79 /// wrapper_result.loc0 = inner_retval; 80 /// return wrapper_result; 81 /// } 82 /// ``` 83 class CanonicalizeEntryPointIO 84 : public Castable<CanonicalizeEntryPointIO, Transform> { 85 public: 86 /// ShaderStyle is an enumerator of different ways to emit shader IO. 87 enum class ShaderStyle { 88 /// Target SPIR-V (using global variables). 89 kSpirv, 90 /// Target MSL (using non-struct function parameters for builtins). 91 kMsl, 92 /// Target HLSL (using structures for all IO). 93 kHlsl, 94 }; 95 96 /// Configuration options for the transform. 97 struct Config : public Castable<Config, Data> { 98 /// Constructor 99 /// @param style the approach to use for emitting shader IO. 100 /// @param sample_mask an optional sample mask to combine with shader masks 101 /// @param emit_vertex_point_size `true` to generate a pointsize builtin 102 explicit Config(ShaderStyle style, 103 uint32_t sample_mask = 0xFFFFFFFF, 104 bool emit_vertex_point_size = false); 105 106 /// Copy constructor 107 Config(const Config&); 108 109 /// Destructor 110 ~Config() override; 111 112 /// The approach to use for emitting shader IO. 113 const ShaderStyle shader_style; 114 115 /// A fixed sample mask to combine into masks produced by fragment shaders. 116 const uint32_t fixed_sample_mask; 117 118 /// Set to `true` to generate a pointsize builtin and have it set to 1.0 119 /// from all vertex shaders in the module. 120 const bool emit_vertex_point_size; 121 }; 122 123 /// Constructor 124 CanonicalizeEntryPointIO(); 125 ~CanonicalizeEntryPointIO() override; 126 127 protected: 128 /// Runs the transform using the CloneContext built for transforming a 129 /// program. Run() is responsible for calling Clone() on the CloneContext. 130 /// @param ctx the CloneContext primed with the input program and 131 /// ProgramBuilder 132 /// @param inputs optional extra transform-specific input data 133 /// @param outputs optional extra transform-specific output data 134 void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) override; 135 136 struct State; 137 }; 138 139 } // namespace transform 140 } // namespace tint 141 142 #endif // SRC_TRANSFORM_CANONICALIZE_ENTRY_POINT_IO_H_ 143