Flutter Impeller
code_gen_template.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <string_view>
6 
7 namespace impeller {
8 namespace compiler {
9 
10 constexpr std::string_view kReflectionHeaderTemplate =
11  R"~~(// THIS FILE IS GENERATED BY impellerc.
12 // DO NOT EDIT OR CHECK THIS INTO SOURCE CONTROL
13 
14 #pragma once
15 
16 {# Note: The nogncheck decorations are only to make GN not mad at the template#}
17 {# this file is generated from. There are no GN rule violations in the generated#}
18 {# file itself and the no-check declarations will be stripped in generated files.#}
19 #include "impeller/core/buffer_view.h" {# // nogncheck #}
20 
21 #include "impeller/core/sampler.h" {# // nogncheck #}
22 
23 #include "impeller/core/shader_types.h" {# // nogncheck #}
24 
25 #include "impeller/core/resource_binder.h" {# // nogncheck #}
26 
27 #include "impeller/core/texture.h" {# // nogncheck #}
28 
29 
30 namespace impeller {
31 
32 struct {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader {
33  // ===========================================================================
34  // Stage Info ================================================================
35  // ===========================================================================
36  static constexpr std::string_view kLabel = "{{camel_case(shader_name)}}";
37  static constexpr std::string_view kEntrypointName = "{{entrypoint}}";
38  static constexpr ShaderStage kShaderStage = {{to_shader_stage(shader_stage)}};
39  // The generator used to prepare these bindings. Metal generators may be used
40  // by GLES backends but GLES generators are unsuitable for the metal backend.
41  static constexpr std::string_view kGeneratorName = "{{get_generator_name()}}";
42 {% if shader_stage == "compute" %}
43  // The workgroup (threadgroup) size declared by the shader. A dimension of 0
44  // is sized by a specialization constant and resolved by the backend at
45  // dispatch (for example, to the device maximum).
46  static constexpr std::array<uint32_t, 3> kWorkgroupSize = {
47  {{workgroup_size_x}}u, {{workgroup_size_y}}u, {{workgroup_size_z}}u};
48 {% endif %}
49 {% if length(struct_definitions) > 0 %}
50  // ===========================================================================
51  // Struct Definitions ========================================================
52  // ===========================================================================
53 {% for def in struct_definitions %}
54 
55 {% if last(def.members).array_elements == 0 %}
56  template <size_t FlexCount>
57 {% endif %}
58  struct {{def.name}} {
59 {% for member in def.members %}
60 {{" "}}{% if member.element_padding > 0 %}Padded<{{member.type}}, {{member.element_padding}}>{% else %}{{member.type}}{% endif %}{{" " + member.name}}{% if member.array_elements != "std::nullopt" %}[{% if member.array_elements == 0 %}FlexCount{% else %}{{member.array_elements}}{% endif %}]{% endif %}; // (offset {{member.offset}}, size {{member.byte_length}})
61 {% endfor %}
62  }; // struct {{def.name}} (size {{def.byte_length}})
63 {% endfor %}
64 {% endif %}
65 {% if length(buffers) > 0 %}
66 
67  // ===========================================================================
68  // Stage Uniform & Storage Buffers ===========================================
69  // ===========================================================================
70 {% for buffer in buffers %}
71 
72  static constexpr auto kResource{{camel_case(buffer.name)}} = ShaderUniformSlot { // {{buffer.name}}
73  "{{buffer.name}}", // name
74  {{buffer.ext_res_0}}u, // ext_res_0
75  {{buffer.set}}u, // set
76  {{buffer.binding}}u, // binding
77  };
78  static ShaderMetadata kMetadata{{camel_case(buffer.name)}};
79 {% endfor %}
80 {% endif %}
81 
82  // ===========================================================================
83  // Stage Inputs ==============================================================
84  // ===========================================================================
85 {% for stage_input in stage_inputs %}
86  static constexpr auto kInput{{camel_case(stage_input.name)}} = ShaderStageIOSlot { // {{stage_input.name}}
87  "{{stage_input.name}}", // name
88  {{stage_input.location}}u, // attribute location
89  {{stage_input.descriptor_set}}u, // attribute set
90  {{stage_input.binding}}u, // attribute binding
91  {{stage_input.type.type_name}}, // type
92  {{stage_input.type.bit_width}}u, // bit width of type
93  {{stage_input.type.vec_size}}u, // vec size
94  {{stage_input.type.columns}}u, // number of columns
95  {{stage_input.offset}}u, // offset for interleaved layout
96  {{stage_input.relaxed_precision}}, // relaxed precision
97  };
98 {% endfor %}
99 
100  static constexpr std::array<const ShaderStageIOSlot*, {{length(stage_inputs)}}> kAllShaderStageInputs = {
101 {% for stage_input in stage_inputs %}
102  &kInput{{camel_case(stage_input.name)}}, // {{stage_input.name}}
103 {% endfor %}
104  };
105 
106 {% if shader_stage == "vertex" %}
107  static constexpr auto kInterleavedLayout = ShaderStageBufferLayout {
108 {% if length(stage_inputs) > 0 %}
109  sizeof(PerVertexData), // stride for interleaved layout
110 {% else %}
111  0u,
112 {% endif %}
113  0u, // attribute binding
114  };
115  static constexpr std::array<const ShaderStageBufferLayout*, 1> kInterleavedBufferLayout = {
116  &kInterleavedLayout
117  };
118 {% endif %}
119 
120 {% if length(sampled_images) > 0 %}
121  // ===========================================================================
122  // Sampled Images ============================================================
123  // ===========================================================================
124 {% for sampled_image in sampled_images %}
125 
126  static constexpr auto kResource{{camel_case(sampled_image.name)}} = SampledImageSlot { // {{sampled_image.name}}
127  "{{sampled_image.name}}", // name
128  {{sampled_image.ext_res_0}}u, // ext_res_0
129  {{sampled_image.set}}u, // set
130  {{sampled_image.binding}}u, // binding
131  };
132  static ShaderMetadata kMetadata{{camel_case(sampled_image.name)}};
133 {% endfor %}
134 {% endif %}
135  // ===========================================================================
136  // Stage Outputs =============================================================
137  // ===========================================================================
138 {% for stage_output in stage_outputs %}
139  static constexpr auto kOutput{{camel_case(stage_output.name)}} = ShaderStageIOSlot { // {{stage_output.name}}
140  "{{stage_output.name}}", // name
141  {{stage_output.location}}u, // attribute location
142  {{stage_output.descriptor_set}}u, // attribute set
143  {{stage_output.binding}}u, // attribute binding
144  {{stage_output.type.type_name}}, // type
145  {{stage_output.type.bit_width}}u, // bit width of type
146  {{stage_output.type.vec_size}}u, // vec size
147  {{stage_output.type.columns}}u, // number of columns
148  {{stage_output.offset}}u, // offset for interleaved layout
149  {{stage_output.relaxed_precision}}, // relaxed precision
150  };
151 {% endfor %}
152  static constexpr std::array<const ShaderStageIOSlot*, {{length(stage_outputs)}}> kAllShaderStageOutputs = {
153 {% for stage_output in stage_outputs %}
154  &kOutput{{camel_case(stage_output.name)}}, // {{stage_output.name}}
155 {% endfor %}
156  };
157 
158  // ===========================================================================
159  // Resource Binding Utilities ================================================
160  // ===========================================================================
161 
162 {% for proto in bind_prototypes %}
163  /// {{proto.docstring}}
164  static {{proto.return_type}} Bind{{proto.name}}({% for arg in proto.args %}
165 {{arg.type_name}} {{arg.argument_name}}{% if not loop.is_last %}, {% endif %}
166 {% endfor %}) {
167  return {{ proto.args.0.argument_name }}.BindResource({% for arg in proto.args %}
168  {% if loop.is_first %}
169 {{to_shader_stage(shader_stage)}}, {{ proto.descriptor_type }}, kResource{{ proto.name }}, &kMetadata{{ proto.name }}, {% else %}
170 std::move({{ arg.argument_name }}){% if not loop.is_last %}, {% endif %}
171  {% endif %}
172  {% endfor %});
173  }
174 
175 {% endfor %}
176 
177  // ===========================================================================
178  // Metadata for Vulkan =======================================================
179  // ===========================================================================
180  static constexpr std::array<DescriptorSetLayout,{{length(buffers)+length(sampled_images)+length(subpass_inputs)}}> kDescriptorSetLayouts{
181 {% for subpass_input in subpass_inputs %}
182  DescriptorSetLayout{
183  {{subpass_input.binding}}, // binding = {{subpass_input.binding}}
184  {{subpass_input.descriptor_type}}, // descriptor_type = {{subpass_input.descriptor_type}}
185  {{to_shader_stage(shader_stage)}}, // shader_stage = {{to_shader_stage(shader_stage)}}
186  },
187 {% endfor %}
188 {% for buffer in buffers %}
189  DescriptorSetLayout{
190  {{buffer.binding}}, // binding = {{buffer.binding}}
191  {{buffer.descriptor_type}}, // descriptor_type = {{buffer.descriptor_type}}
192  {{to_shader_stage(shader_stage)}}, // shader_stage = {{to_shader_stage(shader_stage)}}
193  },
194 {% endfor %}
195 {% for sampled_image in sampled_images %}
196  DescriptorSetLayout{
197  {{sampled_image.binding}}, // binding = {{sampled_image.binding}}
198  {{sampled_image.descriptor_type}}, // descriptor_type = {{sampled_image.descriptor_type}}
199  {{to_shader_stage(shader_stage)}}, // shader_stage = {{to_shader_stage(shader_stage)}}
200  },
201 {% endfor %}
202  };
203 
204 }; // struct {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader
205 
206 } // namespace impeller
207 )~~";
208 
209 constexpr std::string_view kReflectionCCTemplate =
210  R"~~(// THIS FILE IS GENERATED BY impellerc.
211 // DO NOT EDIT OR CHECK THIS INTO SOURCE CONTROL
212 
213 #include "{{header_file_name}}"
214 
215 #include <type_traits>
216 
217 namespace impeller {
218 
219 using Shader = {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader;
220 
221 {% for def in struct_definitions %}
222 // Sanity checks for {{def.name}}
223 {% if last(def.members).array_elements == 0 %}
224 static_assert(std::is_standard_layout_v<Shader::{{def.name}}<0>>);
225 {% for member in def.members %}
226 static_assert(offsetof(Shader::{{def.name}}<0>, {{member.name}}) == {{member.offset}});
227 {% endfor %}
228 {% else %}
229 static_assert(std::is_standard_layout_v<Shader::{{def.name}}>);
230 static_assert(sizeof(Shader::{{def.name}}) == {{def.byte_length}});
231 {% for member in def.members %}
232 static_assert(offsetof(Shader::{{def.name}}, {{member.name}}) == {{member.offset}});
233 {% endfor %}
234 {% endif %}
235 {% endfor %}
236 
237 {% for buffer in buffers %}
238 ShaderMetadata Shader::kMetadata{{camel_case(buffer.name)}} = {
239  "{{buffer.name}}", // name
240  std::vector<ShaderStructMemberMetadata> {
241  {% for member in buffer.type.members %}
242  ShaderStructMemberMetadata {
243  /*type=*/{{ member.base_type }},
244  /*name=*/"{{ member.name }}",
245  /*offset=*/{{ member.offset }},
246  /*size=*/{{ member.size }},
247  /*byte_length=*/{{ member.byte_length }},
248  /*array_elements=*/{{ member.array_elements }},
249  /*float_type=*/{{ member.float_type }},
250  },
251  {% endfor %}
252  } // members
253 };
254 {% endfor %}
255 
256 {% for sampled_image in sampled_images %}
257 ShaderMetadata Shader::kMetadata{{camel_case(sampled_image.name)}} = {
258  "{{sampled_image.name}}", // name
259  std::vector<ShaderStructMemberMetadata> {}, // 0 members
260 };
261 {% endfor %}
262 
263 } // namespace impeller
264 )~~";
265 
266 } // namespace compiler
267 } // namespace impeller
constexpr std::string_view kReflectionHeaderTemplate
constexpr std::string_view kReflectionCCTemplate