9using namespace SPIRV_CROSS_NAMESPACE;
17 fprintf(stderr,
"There was a compiler error: %s\n", msg.c_str());
22#define FLUTTER_CROSS_THROW(x) report_and_exit(x)
25 ir.fixup_reserved_names();
27 if (get_execution_model() != ExecutionModelFragment) {
34 options.vulkan_semantics =
false;
35 options.enable_420pack_extension =
false;
36 options.flatten_multidimensional_arrays =
true;
38 backend.allow_precision_qualifiers =
false;
39 backend.basic_int16_type =
"short";
41 backend.basic_uint16_type =
"ushort";
42 backend.basic_uint_type =
"uint";
43 backend.double_literal_suffix =
false;
44 backend.float_literal_suffix =
false;
45 backend.long_long_literal_suffix =
false;
46 backend.needs_row_major_load_workaround =
true;
47 backend.nonuniform_qualifier =
"";
48 backend.support_precise_qualifier =
false;
49 backend.uint32_t_literal_suffix =
false;
50 backend.use_array_constructor =
true;
51 backend.workgroup_size_is_hidden =
true;
53 fixup_user_functions();
55 fixup_anonymous_struct_names();
58 build_function_control_flow_graphs_and_analyze();
59 fixup_image_load_store_access();
60 update_active_builtins();
61 analyze_image_and_sampler_usage();
62 analyze_interlocked_resource_usage();
64 uint32_t pass_count = 0;
74 emit_function(get<SPIRFunction>(ir.default_entry_point), Bitset());
77 }
while (is_forcing_recompilation());
79 statement(
"half4 main(float2 iFragCoord)");
81 statement(
" flutter_FragCoord = float4(iFragCoord, 0, 0);");
82 statement(
" FLT_main();");
83 statement(
" return " + output_name_ +
";");
89void CompilerSkSL::fixup_user_functions() {
90 const std::string
prefix =
"FLT_flutter_local_";
91 ir.for_each_typed_id<SPIRFunction>([&](uint32_t,
const SPIRFunction& func) {
92 const auto& original_name = get_name(func.self);
94 if (original_name.rfind(
prefix, 0) == 0) {
97 std::string new_name =
prefix + original_name;
98 set_name(func.self, new_name);
101 ir.for_each_typed_id<SPIRFunctionPrototype>(
102 [&](uint32_t,
const SPIRFunctionPrototype& func) {
103 const auto& original_name = get_name(func.self);
105 if (original_name.rfind(
prefix, 0) == 0) {
108 std::string new_name =
prefix + original_name;
109 set_name(func.self, new_name);
113void CompilerSkSL::emit_header() {
114 statement(
"// This SkSL shader is autogenerated by spirv-cross.");
116 statement(
"float4 flutter_FragCoord;");
120void CompilerSkSL::emit_uniform(
const SPIRVariable& var) {
121 auto&
type = get<SPIRType>(var.basetype);
122 if (
type.basetype == SPIRType::UInt && is_legacy()) {
124 get_name(var.self) +
"'");
127 add_resource_name(var.self);
128 statement(variable_decl(var),
";");
132 if (
type.basetype == SPIRType::SampledImage) {
133 std::string
name = to_name(var.self);
134 statement(
"uniform half2 " +
name +
"_size;");
138bool CompilerSkSL::emit_constant_resources() {
139 bool emitted =
false;
141 for (
auto&
id : ir.ids) {
142 if (
id.get_type() == TypeConstant) {
143 auto& c =
id.get<SPIRConstant>();
144 bool needs_declaration = c.specialization || c.is_used_as_lut;
145 if (needs_declaration) {
146 if (!
options.vulkan_semantics && c.specialization) {
147 c.specialization_constant_macro_name = constant_value_macro_name(
148 get_decoration(c.self, DecorationSpecId));
153 }
else if (
id.get_type() == TypeConstantOp) {
154 emit_specialization_constant_op(
id.get<SPIRConstantOp>());
162bool CompilerSkSL::emit_struct_resources() {
163 bool emitted =
false;
167 for (
auto&
id : ir.ids) {
168 if (
id.get_type() == TypeType) {
169 auto&
type =
id.get<SPIRType>();
170 if (
type.basetype == SPIRType::Struct &&
type.array.empty() &&
172 (!ir.meta[
type.self].decoration.decoration_flags.get(
174 !ir.meta[
type.self].decoration.decoration_flags.get(
175 DecorationBufferBlock))) {
185void CompilerSkSL::detect_unsupported_resources() {
186 for (
auto&
id : ir.ids) {
187 if (
id.get_type() == TypeVariable) {
188 auto& var =
id.get<SPIRVariable>();
189 auto&
type = get<SPIRType>(var.basetype);
192 if (var.storage != StorageClassFunction &&
type.pointer &&
193 type.storage == StorageClassUniform && !is_hidden_variable(var) &&
194 (ir.meta[
type.self].decoration.decoration_flags.get(
196 ir.meta[
type.self].decoration.decoration_flags.get(
197 DecorationBufferBlock))) {
199 get_name(var.self) +
"'");
203 if (!is_hidden_variable(var) && var.storage != StorageClassFunction &&
204 type.pointer &&
type.storage == StorageClassPushConstant) {
206 get_name(var.self) +
"'");
210 if (!is_hidden_variable(var) && var.storage != StorageClassFunction &&
211 type.pointer &&
type.storage == StorageClassInput) {
213 get_name(var.self) +
"'");
219bool CompilerSkSL::emit_uniform_resources() {
220 bool emitted =
false;
223 std::vector<ID> regular_uniforms =
225 std::vector<ID> shader_uniforms =
227 if (regular_uniforms.size() > 0 || shader_uniforms.size() > 0) {
231 for (
const auto&
id : regular_uniforms) {
232 auto& var = get<SPIRVariable>(
id);
236 for (
const auto&
id : shader_uniforms) {
237 auto& var = get<SPIRVariable>(
id);
244bool CompilerSkSL::emit_output_resources() {
245 bool emitted =
false;
249 for (
auto&
id : ir.ids) {
250 if (
id.get_type() == TypeVariable) {
251 auto& var =
id.get<SPIRVariable>();
252 auto&
type = get<SPIRType>(var.basetype);
253 if (var.storage != StorageClassFunction && !is_hidden_variable(var) &&
255 (var.storage == StorageClassInput ||
256 var.storage == StorageClassOutput) &&
257 interface_variable_exists_in_entry_point(var.self)) {
258 emit_interface_block(var);
267bool CompilerSkSL::emit_global_variable_resources() {
268 bool emitted =
false;
270 for (
auto global : global_variables) {
271 auto& var = get<SPIRVariable>(global);
272 if (is_hidden_variable(var,
true)) {
275 if (var.storage != StorageClassOutput) {
276 if (!variable_is_lut(var)) {
277 add_resource_name(var.self);
279 if (
options.force_zero_initialized_variables &&
280 var.storage == StorageClassPrivate && !var.initializer &&
281 !var.static_expression &&
282 type_can_zero_initialize(get_variable_data_type(var))) {
284 get_variable_data_type_id(var)));
289 }
else if (var.initializer &&
290 maybe_get<SPIRConstant>(var.initializer) !=
nullptr) {
291 emit_output_variable_initializer(var);
298bool CompilerSkSL::emit_undefined_values() {
299 bool emitted =
false;
301 ir.for_each_typed_id<SPIRUndef>([&](uint32_t,
const SPIRUndef& undef) {
302 auto&
type = this->get<SPIRType>(undef.basetype);
304 if (
type.basetype == SPIRType::Void) {
309 if (
options.force_zero_initialized_variables &&
310 type_can_zero_initialize(
type)) {
311 initializer =
join(
" = ", to_zero_initialized_expression(undef.basetype));
314 statement(variable_decl(
type, to_name(undef.self), undef.self),
initializer,
322void CompilerSkSL::emit_resources() {
323 detect_unsupported_resources();
325 if (emit_constant_resources()) {
329 if (emit_struct_resources()) {
333 if (emit_uniform_resources()) {
337 if (emit_output_resources()) {
341 if (emit_global_variable_resources()) {
345 if (emit_undefined_values()) {
350void CompilerSkSL::emit_interface_block(
const SPIRVariable& var) {
351 auto&
type = get<SPIRType>(var.basetype);
353 ir.meta[
type.self].decoration.decoration_flags.get(DecorationBlock);
356 to_name(var.self) +
"'");
361 add_resource_name(var.self);
362 statement(variable_decl(
type, to_name(var.self), var.self),
";");
363 if (output_name_.empty()) {
364 output_name_ = to_name(var.self);
365 }
else if (to_name(var.self) != output_name_) {
367 to_name(var.self) +
"'");
371void CompilerSkSL::emit_function_prototype(SPIRFunction& func,
372 const Bitset& return_flags) {
375 if (func.self != ir.default_entry_point) {
376 CompilerGLSL::emit_function_prototype(func, return_flags);
380 auto&
type = get<SPIRType>(func.return_type);
381 if (
type.basetype != SPIRType::Void) {
383 "Return type of the entrypoint function must be 'void'");
386 if (func.arguments.size() != 0) {
388 "The entry point function should not acept any parameters.");
391 processing_entry_point =
true;
396 statement(
"void FLT_main()");
399std::string CompilerSkSL::image_type_glsl(
const SPIRType&
type,
402 if (
type.basetype != SPIRType::SampledImage ||
type.image.dim != Dim2D) {
409std::string CompilerSkSL::builtin_to_glsl(BuiltIn builtin,
410 StorageClass storage) {
411 std::string gl_builtin = CompilerGLSL::builtin_to_glsl(builtin, storage);
413 case BuiltInFragCoord:
414 return "flutter_FragCoord";
423std::string CompilerSkSL::to_texture_op(
424 const Instruction&
i,
427 SmallVector<uint32_t>& inherited_expressions) {
428 auto op =
static_cast<Op>(
i.op);
429 if (op != OpImageSampleImplicitLod) {
433 return CompilerGLSL::to_texture_op(
i, sparse, forward, inherited_expressions);
436std::string CompilerSkSL::to_function_name(
437 const CompilerGLSL::TextureFunctionNameArguments&
args) {
438 std::string
name = to_expression(
args.base.img);
439 return name +
".eval";
442std::string CompilerSkSL::to_function_args(
const TextureFunctionArguments&
args,
444 std::string
name = to_expression(
args.base.img);
446 std::string glsl_args = CompilerGLSL::to_function_args(
args, p_forward);
452 "Only sampler and position arguments are supported in texture() "
459 std::string no_shader;
460 auto npos = glsl_args.find(
", ");
461 if (npos != std::string::npos) {
462 no_shader = glsl_args.substr(npos + 1);
465 if (no_shader.empty()) {
471 return name +
"_size * (" + no_shader +
")";
static struct Initializer initializer
std::string compile() override
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
DEF_SWITCHES_START aot vmservice shared library name
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
void report_and_exit(const std::string &msg)
std::vector< spirv_cross::ID > SortUniforms(const spirv_cross::ParsedIR *ir, const spirv_cross::Compiler *compiler, std::optional< spirv_cross::SPIRType::BaseType > type_filter, bool include)
Sorts uniform declarations in an IR according to decoration order.
static SkString join(const CommandLineFlags::StringArray &)
#define FLUTTER_CROSS_THROW(x)