// 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 #include #include #include "impeller/blobcat/blob_flatbuffers.h" namespace impeller { BlobWriter::BlobWriter() = default; BlobWriter::~BlobWriter() = default; std::optional 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 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 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(); 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(); builder->Finish(fb::BlobLibrary::Pack(*builder.get(), &blobs), fb::BlobLibraryIdentifier()); return std::make_shared(builder->GetBufferPointer(), builder->GetSize(), [builder](auto, auto) {}); } } // namespace impeller