diff --git a/engine/src/flutter/impeller/compiler/reflector.cc b/engine/src/flutter/impeller/compiler/reflector.cc index e5599d2c4e6..3abe20f8722 100644 --- a/engine/src/flutter/impeller/compiler/reflector.cc +++ b/engine/src/flutter/impeller/compiler/reflector.cc @@ -12,19 +12,12 @@ #include "flutter/fml/logging.h" #include "flutter/impeller/compiler/code_gen_template.h" #include "flutter/impeller/compiler/utilities.h" -#include "inja/inja.hpp" -#include "rapidjson/document.h" -#include "rapidjson/prettywriter.h" -#include "rapidjson/rapidjson.h" -#include "rapidjson/stringbuffer.h" namespace impeller { namespace compiler { using namespace spirv_cross; -using Writer = rapidjson::PrettyWriter; - static std::string BaseTypeToString(SPIRType::BaseType type) { using Type = SPIRType::BaseType; switch (type) { @@ -88,10 +81,10 @@ static std::optional GetMemberNameAtIndexIfExists( return std::nullopt; } -static std::string GetMemberNameAtIndex(const ParsedIR& ir, - const CompilerMSL& compiler, - const SPIRType& type, - size_t index) { +std::string GetMemberNameAtIndex(const ParsedIR& ir, + const CompilerMSL& compiler, + const SPIRType& type, + size_t index) { if (auto name = GetMemberNameAtIndexIfExists(ir, compiler, type, index); name.has_value()) { return name.value(); @@ -103,106 +96,6 @@ static std::string GetMemberNameAtIndex(const ParsedIR& ir, return stream.str(); } -static bool ReflectType(Writer& writer, - const ParsedIR& ir, - const CompilerMSL& compiler, - const TypeID& type_id) { - const auto type = compiler.get_type(type_id); - - writer.Key("type"); - writer.StartObject(); - - writer.Key("type_name"); - writer.String(BaseTypeToString(type.basetype)); - - writer.Key("bit_width"); - writer.Uint64(type.width); - - writer.Key("vec_size"); - writer.Uint64(type.vecsize); - - writer.Key("columns"); - writer.Uint64(type.columns); - - // Member types should only be present if the base type is a struct. - if (!type.member_types.empty()) { - writer.Key("member"); - writer.StartArray(); - for (size_t i = 0; i < type.member_types.size(); i++) { - writer.StartObject(); - { - writer.Key("type_id"); - writer.Uint64(type.member_types[i]); - writer.Key("member_name"); - writer.String(GetMemberNameAtIndex(ir, compiler, type, i)); - } - writer.EndObject(); - } - writer.EndArray(); - } - - writer.EndObject(); - return true; -} - -static bool ReflectBaseResource(Writer& writer, - const ParsedIR& ir, - const CompilerMSL& compiler, - const Resource& res) { - writer.Key("name"); - writer.String(res.name); - - writer.Key("descriptor_set"); - writer.Uint64(compiler.get_decoration( - res.id, spv::Decoration::DecorationDescriptorSet)); - - writer.Key("binding"); - writer.Uint64( - compiler.get_decoration(res.id, spv::Decoration::DecorationBinding)); - - writer.Key("location"); - writer.Uint64( - compiler.get_decoration(res.id, spv::Decoration::DecorationLocation)); - - writer.Key("index"); - writer.Uint64( - compiler.get_decoration(res.id, spv::Decoration::DecorationIndex)); - - if (!ReflectType(writer, ir, compiler, res.type_id)) { - return false; - } - - return true; -} - -static bool ReflectStageIO(Writer& writer, - const ParsedIR& ir, - const CompilerMSL& compiler, - const Resource& io) { - writer.StartObject(); - - if (!ReflectBaseResource(writer, ir, compiler, io)) { - return false; - } - - writer.EndObject(); - return true; -} - -static bool ReflectUniformBuffer(Writer& writer, - const ParsedIR& ir, - const CompilerMSL& compiler, - const Resource& buffer) { - writer.StartObject(); - - if (!ReflectBaseResource(writer, ir, compiler, buffer)) { - return false; - } - - writer.EndObject(); - return true; -} - static std::string ExecutionModelToString(spv::ExecutionModel model) { switch (model) { case spv::ExecutionModel::ExecutionModelVertex: @@ -236,8 +129,11 @@ Reflector::Reflector(Options options, return; } - template_arguments_ = GenerateTemplateArguments(); - if (!template_arguments_) { + if (auto template_arguments = GenerateTemplateArguments(); + template_arguments.has_value()) { + template_arguments_ = + std::make_unique(std::move(template_arguments.value())); + } else { return; } @@ -261,7 +157,16 @@ bool Reflector::IsValid() const { } std::shared_ptr Reflector::GetReflectionJSON() const { - return template_arguments_; + if (!is_valid_) { + return nullptr; + } + + auto json_string = + std::make_shared(template_arguments_->dump(2u)); + + return std::make_shared( + reinterpret_cast(json_string->data()), + json_string->size(), [json_string](auto, auto) {}); } std::shared_ptr Reflector::GetReflectionHeader() const { @@ -272,92 +177,48 @@ std::shared_ptr Reflector::GetReflectionCC() const { return reflection_cc_; } -std::shared_ptr Reflector::GenerateTemplateArguments() const { - auto buffer = std::make_shared(); - Writer writer(*buffer); - - writer.StartObject(); // root +std::optional Reflector::GenerateTemplateArguments() const { + nlohmann::json root; { const auto& entrypoints = compiler_->get_entry_points_and_stages(); if (entrypoints.size() != 1) { FML_LOG(ERROR) << "Incorrect number of entrypoints in the shader. Found " << entrypoints.size() << " but expected 1."; - return nullptr; + return std::nullopt; } - writer.Key("entrypoint"); - writer.String(entrypoints.front().name); - - writer.Key("shader_name"); - writer.String(options_.shader_name); - - writer.Key("shader_stage"); - writer.String(ExecutionModelToString(entrypoints.front().execution_model)); - - writer.Key("header_file_name"); - writer.String(options_.header_file_name); + root["entrypoint"] = entrypoints.front().name; + root["shader_name"] = options_.shader_name; + root["shader_stage"] = + ExecutionModelToString(entrypoints.front().execution_model); + root["header_file_name"] = options_.header_file_name; } - const auto all_shader_resources = compiler_->get_shader_resources(); + const auto shader_resources = compiler_->get_shader_resources(); - { - writer.Key("uniform_buffers"); - writer.StartArray(); - for (const auto& uniform_buffer : all_shader_resources.uniform_buffers) { - if (!ReflectUniformBuffer(writer, *ir_, *compiler_, uniform_buffer)) { - FML_LOG(ERROR) << "Could not reflect uniform buffer."; - return nullptr; - } - } - writer.EndArray(); + if (auto uniform_buffers = ReflectResources(shader_resources.uniform_buffers); + uniform_buffers.has_value()) { + root["uniform_buffers"] = std::move(uniform_buffers.value()); + } else { + return std::nullopt; } - { - writer.Key("stage_inputs"); - writer.StartArray(); - for (const auto& input : all_shader_resources.stage_inputs) { - if (!ReflectStageIO(writer, *ir_, *compiler_, input)) { - FML_LOG(ERROR) << "Could not reflect stage input."; - return nullptr; - } - } - writer.EndArray(); + if (auto stage_inputs = ReflectResources(shader_resources.stage_inputs); + stage_inputs.has_value()) { + root["stage_inputs"] = std::move(stage_inputs.value()); + } else { + return std::nullopt; } - { - writer.Key("stage_outputs"); - writer.StartArray(); - for (const auto& output : all_shader_resources.stage_outputs) { - if (!ReflectStageIO(writer, *ir_, *compiler_, output)) { - FML_LOG(ERROR) << "Could not reflect stage output."; - return nullptr; - } - } - writer.EndArray(); + if (auto stage_outputs = ReflectResources(shader_resources.stage_outputs); + stage_outputs.has_value()) { + root["stage_outputs"] = std::move(stage_outputs.value()); + } else { + return std::nullopt; } - { - auto reflect_types = [&](const SmallVector resources) -> bool { - for (const auto& resource : resources) { - } - return true; - }; - writer.Key("type_definitions"); - writer.StartArray(); - if (!reflect_types(all_shader_resources.uniform_buffers) || - !reflect_types(all_shader_resources.stage_inputs) || - !reflect_types(all_shader_resources.stage_outputs)) { - return nullptr; - } - writer.EndArray(); - } - - writer.EndObject(); // root - - return std::make_shared( - reinterpret_cast(buffer->GetString()), buffer->GetSize(), - [buffer](auto, auto) {}); + return root; } std::shared_ptr Reflector::GenerateReflectionHeader() const { @@ -382,16 +243,62 @@ std::shared_ptr Reflector::InflateTemplate( return StringToShaderStage(args.at(0u)->get()); }); - auto template_data = inja::json::parse( - reinterpret_cast(template_arguments_->GetMapping())); - auto inflated_template = - std::make_shared(env.render(tmpl, template_data)); + std::make_shared(env.render(tmpl, *template_arguments_)); return std::make_shared( reinterpret_cast(inflated_template->data()), inflated_template->size(), [inflated_template](auto, auto) {}); } +std::optional Reflector::ReflectResource( + const spirv_cross::Resource& resource) const { + nlohmann::json::object_t result; + + result["name"] = resource.name; + result["descriptor_set"] = compiler_->get_decoration( + resource.id, spv::Decoration::DecorationDescriptorSet); + result["binding"] = compiler_->get_decoration( + resource.id, spv::Decoration::DecorationBinding); + result["location"] = compiler_->get_decoration( + resource.id, spv::Decoration::DecorationLocation); + result["index"] = + compiler_->get_decoration(resource.id, spv::Decoration::DecorationIndex); + auto type = ReflectType(resource.type_id); + if (!type.has_value()) { + return std::nullopt; + } + result["type"] = std::move(type.value()); + return result; +} + +std::optional Reflector::ReflectType( + const spirv_cross::TypeID& type_id) const { + nlohmann::json::object_t result; + + const auto type = compiler_->get_type(type_id); + + result["type_name"] = BaseTypeToString(type.basetype); + result["bit_width"] = type.width; + result["vec_size"] = type.vecsize; + result["columns"] = type.columns; + + return result; +} + +std::optional Reflector::ReflectResources( + const spirv_cross::SmallVector& resources) const { + nlohmann::json::array_t result; + result.reserve(resources.size()); + for (const auto& resource : resources) { + if (auto reflected = ReflectResource(resource); reflected.has_value()) { + result.emplace_back(std::move(reflected.value())); + } else { + return std::nullopt; + } + } + return result; +} + } // namespace compiler } // namespace impeller diff --git a/engine/src/flutter/impeller/compiler/reflector.h b/engine/src/flutter/impeller/compiler/reflector.h index fe84381175f..027f7e49fe6 100644 --- a/engine/src/flutter/impeller/compiler/reflector.h +++ b/engine/src/flutter/impeller/compiler/reflector.h @@ -5,9 +5,11 @@ #pragma once #include +#include #include "flutter/fml/macros.h" #include "flutter/fml/mapping.h" +#include "inja/inja.hpp" #include "third_party/spirv_cross/spirv_msl.hpp" #include "third_party/spirv_cross/spirv_parser.hpp" @@ -39,12 +41,12 @@ class Reflector { const Options options_; const std::shared_ptr ir_; const std::shared_ptr compiler_; - std::shared_ptr template_arguments_; + std::unique_ptr template_arguments_; std::shared_ptr reflection_header_; std::shared_ptr reflection_cc_; bool is_valid_ = false; - std::shared_ptr GenerateTemplateArguments() const; + std::optional GenerateTemplateArguments() const; std::shared_ptr GenerateReflectionHeader() const; @@ -53,6 +55,15 @@ class Reflector { std::shared_ptr InflateTemplate( const std::string_view& tmpl) const; + std::optional ReflectResource( + const spirv_cross::Resource& resource) const; + + std::optional ReflectResources( + const spirv_cross::SmallVector& resources) const; + + std::optional ReflectType( + const spirv_cross::TypeID& type_id) const; + FML_DISALLOW_COPY_AND_ASSIGN(Reflector); };