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);
114 statement(
"// This SkSL shader is autogenerated by spirv-cross.");
116 statement(
"float4 flutter_FragCoord;");
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) +
"'");
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()");
402 if (
type.basetype != SPIRType::SampledImage ||
type.image.dim != Dim2D) {
410 StorageClass storage) {
411 std::string gl_builtin = CompilerGLSL::builtin_to_glsl(builtin, storage);
413 case BuiltInFragCoord:
414 return "flutter_FragCoord";
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);
437 const CompilerGLSL::TextureFunctionNameArguments&
args) {
438 std::string
name = to_expression(
args.base.img);
439 return name +
".eval";
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 to_function_name(const spirv_cross::CompilerGLSL::TextureFunctionNameArguments &args) override
void emit_header() override
std::string to_function_args(const spirv_cross::CompilerGLSL::TextureFunctionArguments &args, bool *p_forward) override
std::string image_type_glsl(const spirv_cross::SPIRType &type, uint32_t id=0, bool member=false) override
std::string compile() override
void emit_uniform(const spirv_cross::SPIRVariable &var) override
std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override
std::string to_texture_op(const spirv_cross::Instruction &i, bool sparse, bool *forward, spirv_cross::SmallVector< uint32_t > &inherited_expressions) override
void emit_function_prototype(spirv_cross::SPIRFunction &func, const spirv_cross::Bitset &return_flags) override
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t 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.
SINT Vec< 2 *N, T > join(const Vec< N, T > &lo, const Vec< N, T > &hi)
#define FLUTTER_CROSS_THROW(x)