blob: bafebbec2b8ff88f778db3ca5292387e09942b8a [file] [log] [blame] [edit]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/blobcat/blob_writer.h"
#include <array>
#include <filesystem>
#include <optional>
#include "impeller/blobcat/blob_flatbuffers.h"
namespace impeller {
BlobWriter::BlobWriter() = default;
BlobWriter::~BlobWriter() = default;
std::optional<BlobShaderType> InferShaderTypefromFileExtension(
const std::filesystem::path& path) {
if (path == ".vert") {
return BlobShaderType::kVertex;
} else if (path == ".frag") {
return BlobShaderType::kFragment;
} else if (path == ".comp") {
return BlobShaderType::kCompute;
}
return std::nullopt;
}
bool BlobWriter::AddBlobAtPath(const std::string& std_path) {
std::filesystem::path path(std_path);
if (path.stem().empty()) {
FML_LOG(ERROR) << "File path stem was empty for " << path;
return false;
}
if (path.extension() != ".gles" && path.extension() != ".vkspv") {
FML_LOG(ERROR) << "File path doesn't have a known shader extension "
<< path;
return false;
}
// Get rid of .gles
path = path.replace_extension();
auto shader_type = InferShaderTypefromFileExtension(path.extension());
if (!shader_type.has_value()) {
FML_LOG(ERROR) << "Could not infer shader type from file extension: "
<< path.extension().string();
return false;
}
// Get rid of the shader type extension (.vert, .frag, etc..).
path = path.replace_extension();
const auto shader_name = path.stem().string();
if (shader_name.empty()) {
FML_LOG(ERROR) << "Shader name was empty.";
return false;
}
auto file_mapping = fml::FileMapping::CreateReadOnly(std_path);
if (!file_mapping) {
FML_LOG(ERROR) << "File doesn't exist at path: " << path;
return false;
}
return AddBlob(shader_type.value(), shader_name, std::move(file_mapping));
}
bool BlobWriter::AddBlob(BlobShaderType type,
std::string name,
std::shared_ptr<fml::Mapping> mapping) {
if (name.empty() || !mapping || mapping->GetMapping() == nullptr) {
return false;
}
blob_descriptions_.emplace_back(
BlobDescription{type, std::move(name), std::move(mapping)});
return true;
}
constexpr fb::Stage ToStage(BlobShaderType type) {
switch (type) {
case BlobShaderType::kVertex:
return fb::Stage::kVertex;
case BlobShaderType::kFragment:
return fb::Stage::kFragment;
case BlobShaderType::kCompute:
return fb::Stage::kCompute;
}
FML_UNREACHABLE();
}
std::shared_ptr<fml::Mapping> BlobWriter::CreateMapping() const {
fb::BlobLibraryT blobs;
for (const auto& blob_description : blob_descriptions_) {
auto mapping = blob_description.mapping;
if (!mapping) {
return nullptr;
}
auto desc = std::make_unique<fb::BlobT>();
desc->name = blob_description.name;
desc->stage = ToStage(blob_description.type);
desc->mapping = {mapping->GetMapping(),
mapping->GetMapping() + mapping->GetSize()};
blobs.items.emplace_back(std::move(desc));
}
auto builder = std::make_shared<flatbuffers::FlatBufferBuilder>();
builder->Finish(fb::BlobLibrary::Pack(*builder.get(), &blobs),
fb::BlobLibraryIdentifier());
return std::make_shared<fml::NonOwnedMapping>(builder->GetBufferPointer(),
builder->GetSize(),
[builder](auto, auto) {});
}
} // namespace impeller