| // 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/shader_archive/shader_archive.h" |
| |
| #include <array> |
| #include <string> |
| #include <utility> |
| |
| #include "impeller/base/validation.h" |
| #include "impeller/shader_archive/shader_archive_flatbuffers.h" |
| |
| namespace impeller { |
| |
| constexpr ArchiveShaderType ToShaderType(fb::Stage stage) { |
| switch (stage) { |
| case fb::Stage::kVertex: |
| return ArchiveShaderType::kVertex; |
| case fb::Stage::kFragment: |
| return ArchiveShaderType::kFragment; |
| case fb::Stage::kCompute: |
| return ArchiveShaderType::kCompute; |
| } |
| FML_UNREACHABLE(); |
| } |
| |
| ShaderArchive::ShaderArchive(std::shared_ptr<const fml::Mapping> payload) |
| : payload_(std::move(payload)) { |
| if (!payload_ || payload_->GetMapping() == nullptr) { |
| VALIDATION_LOG << "Shader mapping was absent."; |
| return; |
| } |
| |
| if (!fb::ShaderArchiveBufferHasIdentifier(payload_->GetMapping())) { |
| VALIDATION_LOG << "Invalid shader archive magic."; |
| return; |
| } |
| |
| auto shader_archive = fb::GetShaderArchive(payload_->GetMapping()); |
| if (!shader_archive) { |
| return; |
| } |
| |
| if (auto items = shader_archive->items()) { |
| for (auto i = items->begin(), end = items->end(); i != end; i++) { |
| ShaderKey key; |
| key.name = i->name()->str(); |
| key.type = ToShaderType(i->stage()); |
| shaders_[key] = std::make_shared<fml::NonOwnedMapping>( |
| i->mapping()->Data(), i->mapping()->size(), |
| [payload = payload_](auto, auto) { |
| // The pointers are into the base payload. Instead of copying the |
| // data, just hold onto the payload. |
| }); |
| } |
| } |
| |
| is_valid_ = true; |
| } |
| |
| ShaderArchive::ShaderArchive(ShaderArchive&&) = default; |
| |
| ShaderArchive::~ShaderArchive() = default; |
| |
| bool ShaderArchive::IsValid() const { |
| return is_valid_; |
| } |
| |
| size_t ShaderArchive::GetShaderCount() const { |
| return shaders_.size(); |
| } |
| |
| std::shared_ptr<fml::Mapping> ShaderArchive::GetMapping( |
| ArchiveShaderType type, |
| std::string name) const { |
| ShaderKey key; |
| key.type = type; |
| key.name = std::move(name); |
| auto found = shaders_.find(key); |
| return found == shaders_.end() ? nullptr : found->second; |
| } |
| |
| size_t ShaderArchive::IterateAllShaders( |
| const std::function<bool(ArchiveShaderType type, |
| const std::string& name, |
| const std::shared_ptr<fml::Mapping>& mapping)>& |
| callback) const { |
| if (!IsValid() || !callback) { |
| return 0u; |
| } |
| size_t count = 0u; |
| for (const auto& shader : shaders_) { |
| count++; |
| if (!callback(shader.first.type, shader.first.name, shader.second)) { |
| break; |
| } |
| } |
| return count; |
| } |
| |
| } // namespace impeller |