Swap JSON handling in code generator.

This commit is contained in:
Chinmay Garde 2021-06-11 16:52:39 -07:00 committed by Dan Field
parent 4b3190494a
commit 27eaa2af6e
2 changed files with 107 additions and 189 deletions

View File

@ -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<rapidjson::StringBuffer>;
static std::string BaseTypeToString(SPIRType::BaseType type) {
using Type = SPIRType::BaseType;
switch (type) {
@ -88,10 +81,10 @@ static std::optional<std::string> 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<nlohmann::json>(std::move(template_arguments.value()));
} else {
return;
}
@ -261,7 +157,16 @@ bool Reflector::IsValid() const {
}
std::shared_ptr<fml::Mapping> Reflector::GetReflectionJSON() const {
return template_arguments_;
if (!is_valid_) {
return nullptr;
}
auto json_string =
std::make_shared<std::string>(template_arguments_->dump(2u));
return std::make_shared<fml::NonOwnedMapping>(
reinterpret_cast<const uint8_t*>(json_string->data()),
json_string->size(), [json_string](auto, auto) {});
}
std::shared_ptr<fml::Mapping> Reflector::GetReflectionHeader() const {
@ -272,92 +177,48 @@ std::shared_ptr<fml::Mapping> Reflector::GetReflectionCC() const {
return reflection_cc_;
}
std::shared_ptr<fml::Mapping> Reflector::GenerateTemplateArguments() const {
auto buffer = std::make_shared<rapidjson::StringBuffer>();
Writer writer(*buffer);
writer.StartObject(); // root
std::optional<nlohmann::json> 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<Resource> 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<fml::NonOwnedMapping>(
reinterpret_cast<const uint8_t*>(buffer->GetString()), buffer->GetSize(),
[buffer](auto, auto) {});
return root;
}
std::shared_ptr<fml::Mapping> Reflector::GenerateReflectionHeader() const {
@ -382,16 +243,62 @@ std::shared_ptr<fml::Mapping> Reflector::InflateTemplate(
return StringToShaderStage(args.at(0u)->get<std::string>());
});
auto template_data = inja::json::parse(
reinterpret_cast<const char*>(template_arguments_->GetMapping()));
auto inflated_template =
std::make_shared<std::string>(env.render(tmpl, template_data));
std::make_shared<std::string>(env.render(tmpl, *template_arguments_));
return std::make_shared<fml::NonOwnedMapping>(
reinterpret_cast<const uint8_t*>(inflated_template->data()),
inflated_template->size(), [inflated_template](auto, auto) {});
}
std::optional<nlohmann::json::object_t> 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<nlohmann::json::object_t> 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<nlohmann::json::array_t> Reflector::ReflectResources(
const spirv_cross::SmallVector<spirv_cross::Resource>& 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

View File

@ -5,9 +5,11 @@
#pragma once
#include <memory>
#include <optional>
#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<const spirv_cross::ParsedIR> ir_;
const std::shared_ptr<const spirv_cross::CompilerMSL> compiler_;
std::shared_ptr<fml::Mapping> template_arguments_;
std::unique_ptr<const nlohmann::json> template_arguments_;
std::shared_ptr<fml::Mapping> reflection_header_;
std::shared_ptr<fml::Mapping> reflection_cc_;
bool is_valid_ = false;
std::shared_ptr<fml::Mapping> GenerateTemplateArguments() const;
std::optional<nlohmann::json> GenerateTemplateArguments() const;
std::shared_ptr<fml::Mapping> GenerateReflectionHeader() const;
@ -53,6 +55,15 @@ class Reflector {
std::shared_ptr<fml::Mapping> InflateTemplate(
const std::string_view& tmpl) const;
std::optional<nlohmann::json::object_t> ReflectResource(
const spirv_cross::Resource& resource) const;
std::optional<nlohmann::json::array_t> ReflectResources(
const spirv_cross::SmallVector<spirv_cross::Resource>& resources) const;
std::optional<nlohmann::json::object_t> ReflectType(
const spirv_cross::TypeID& type_id) const;
FML_DISALLOW_COPY_AND_ASSIGN(Reflector);
};