Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 502755d

Browse files
authored
[Impeller] Add support for multi-rendering-backend fat shader archives. (#47278)
Existing shader archive ctors have been made private. Instead a factory is used to check to see if the blob is a single or multi-archive and do the right thing. This allows us to keep the existing code the same. But, when multi-archives are encountered, the right shaders libraries will be picked. Creating multi-archives will be done in ImpellerC in an upcoming patch. Towards flutter/flutter#123741
1 parent e3e59ba commit 502755d

13 files changed

Lines changed: 360 additions & 19 deletions

ci/licenses_golden/licenses_flutter

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2333,6 +2333,11 @@ ORIGIN: ../../../flutter/impeller/scene/shaders/unlit.frag + ../../../flutter/LI
23332333
ORIGIN: ../../../flutter/impeller/scene/shaders/unskinned.vert + ../../../flutter/LICENSE
23342334
ORIGIN: ../../../flutter/impeller/scene/skin.cc + ../../../flutter/LICENSE
23352335
ORIGIN: ../../../flutter/impeller/scene/skin.h + ../../../flutter/LICENSE
2336+
ORIGIN: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive.cc + ../../../flutter/LICENSE
2337+
ORIGIN: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive.fbs + ../../../flutter/LICENSE
2338+
ORIGIN: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive.h + ../../../flutter/LICENSE
2339+
ORIGIN: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive_writer.cc + ../../../flutter/LICENSE
2340+
ORIGIN: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive_writer.h + ../../../flutter/LICENSE
23362341
ORIGIN: ../../../flutter/impeller/shader_archive/shader_archive.cc + ../../../flutter/LICENSE
23372342
ORIGIN: ../../../flutter/impeller/shader_archive/shader_archive.fbs + ../../../flutter/LICENSE
23382343
ORIGIN: ../../../flutter/impeller/shader_archive/shader_archive.h + ../../../flutter/LICENSE
@@ -5109,6 +5114,11 @@ FILE: ../../../flutter/impeller/scene/shaders/unlit.frag
51095114
FILE: ../../../flutter/impeller/scene/shaders/unskinned.vert
51105115
FILE: ../../../flutter/impeller/scene/skin.cc
51115116
FILE: ../../../flutter/impeller/scene/skin.h
5117+
FILE: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive.cc
5118+
FILE: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive.fbs
5119+
FILE: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive.h
5120+
FILE: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive_writer.cc
5121+
FILE: ../../../flutter/impeller/shader_archive/multi_arch_shader_archive_writer.h
51125122
FILE: ../../../flutter/impeller/shader_archive/shader_archive.cc
51135123
FILE: ../../../flutter/impeller/shader_archive/shader_archive.fbs
51145124
FILE: ../../../flutter/impeller/shader_archive/shader_archive.h

impeller/renderer/backend/gles/shader_library_gles.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "impeller/base/config.h"
1111
#include "impeller/base/validation.h"
1212
#include "impeller/renderer/backend/gles/shader_function_gles.h"
13+
#include "impeller/shader_archive/multi_arch_shader_archive.h"
1314
#include "impeller/shader_archive/shader_archive.h"
1415

1516
namespace impeller {
@@ -74,12 +75,13 @@ ShaderLibraryGLES::ShaderLibraryGLES(
7475
return true;
7576
};
7677
for (auto library : shader_libraries) {
77-
auto blob_library = ShaderArchive{std::move(library)};
78-
if (!blob_library.IsValid()) {
79-
VALIDATION_LOG << "Could not construct blob library for shaders.";
78+
auto gles_archive = MultiArchShaderArchive::CreateArchiveFromMapping(
79+
std::move(library), ArchiveRenderingBackend::kOpenGLES);
80+
if (!gles_archive || !gles_archive->IsValid()) {
81+
VALIDATION_LOG << "Could not construct shader library.";
8082
return;
8183
}
82-
blob_library.IterateAllShaders(iterator);
84+
gles_archive->IterateAllShaders(iterator);
8385
}
8486

8587
functions_ = functions;

impeller/renderer/backend/vulkan/shader_library_vk.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "flutter/fml/trace_event.h"
99
#include "impeller/renderer/backend/vulkan/context_vk.h"
1010
#include "impeller/renderer/backend/vulkan/shader_function_vk.h"
11+
#include "impeller/shader_archive/multi_arch_shader_archive.h"
1112
#include "impeller/shader_archive/shader_archive.h"
1213

1314
namespace impeller {
@@ -69,12 +70,13 @@ ShaderLibraryVK::ShaderLibraryVK(
6970
return true;
7071
};
7172
for (const auto& library_data : shader_libraries_data) {
72-
auto blob_library = ShaderArchive{library_data};
73-
if (!blob_library.IsValid()) {
74-
VALIDATION_LOG << "Could not construct shader blob library.";
73+
auto vulkan_library = MultiArchShaderArchive::CreateArchiveFromMapping(
74+
library_data, ArchiveRenderingBackend::kVulkan);
75+
if (!vulkan_library || !vulkan_library->IsValid()) {
76+
VALIDATION_LOG << "Could not construct Vulkan shader library archive.";
7577
return;
7678
}
77-
blob_library.IterateAllShaders(iterator);
79+
vulkan_library->IterateAllShaders(iterator);
7880
}
7981

8082
if (!success) {

impeller/shader_archive/BUILD.gn

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,20 @@ config("shader_archive_config") {
1111
}
1212

1313
flatbuffers("shader_archive_flatbuffers") {
14-
flatbuffers = [ "shader_archive.fbs" ]
14+
flatbuffers = [
15+
"shader_archive.fbs",
16+
"multi_arch_shader_archive.fbs",
17+
]
1518
public_configs = [ ":shader_archive_config" ]
1619
public_deps = [ "//third_party/flatbuffers" ]
1720
}
1821

1922
impeller_component("shader_archive") {
2023
sources = [
24+
"multi_arch_shader_archive.cc",
25+
"multi_arch_shader_archive.h",
26+
"multi_arch_shader_archive_writer.cc",
27+
"multi_arch_shader_archive_writer.h",
2128
"shader_archive.cc",
2229
"shader_archive.h",
2330
"shader_archive_types.h",
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "impeller/shader_archive/multi_arch_shader_archive.h"
6+
7+
#include "impeller/shader_archive/multi_arch_shader_archive_flatbuffers.h"
8+
9+
namespace impeller {
10+
11+
constexpr ArchiveRenderingBackend ToArchiveRenderingBackend(
12+
fb::RenderingBackend backend) {
13+
switch (backend) {
14+
case fb::RenderingBackend::kOpenGLES:
15+
return ArchiveRenderingBackend::kOpenGLES;
16+
case fb::RenderingBackend::kVulkan:
17+
return ArchiveRenderingBackend::kVulkan;
18+
case fb::RenderingBackend::kMetal:
19+
return ArchiveRenderingBackend::kMetal;
20+
}
21+
FML_UNREACHABLE();
22+
}
23+
24+
std::shared_ptr<ShaderArchive> MultiArchShaderArchive::CreateArchiveFromMapping(
25+
const std::shared_ptr<const fml::Mapping>& mapping,
26+
ArchiveRenderingBackend backend) {
27+
{
28+
auto multi_archive = std::make_shared<MultiArchShaderArchive>(mapping);
29+
if (multi_archive->IsValid()) {
30+
return multi_archive->GetShaderArchive(backend);
31+
}
32+
}
33+
{
34+
auto single_archive =
35+
std::shared_ptr<ShaderArchive>(new ShaderArchive(mapping));
36+
if (single_archive->IsValid()) {
37+
return single_archive;
38+
}
39+
}
40+
return nullptr;
41+
}
42+
43+
MultiArchShaderArchive::MultiArchShaderArchive(
44+
const std::shared_ptr<const fml::Mapping>& mapping) {
45+
if (!mapping) {
46+
return;
47+
}
48+
49+
if (!fb::MultiArchShaderArchiveBufferHasIdentifier(mapping->GetMapping())) {
50+
return;
51+
}
52+
53+
const auto* multi_arch = fb::GetMultiArchShaderArchive(mapping->GetMapping());
54+
55+
if (!multi_arch) {
56+
return;
57+
}
58+
59+
if (auto archives = multi_arch->items()) {
60+
for (auto i = archives->begin(), end = archives->end(); i != end; i++) {
61+
// This implementation is unable to handle multiple archives for the same
62+
// backend.
63+
backend_mappings_[ToArchiveRenderingBackend(i->rendering_backend())] =
64+
std::make_shared<fml::NonOwnedMapping>(i->mapping()->Data(),
65+
i->mapping()->size(),
66+
[mapping](auto, auto) {
67+
// Just hold the mapping.
68+
});
69+
}
70+
}
71+
72+
is_valid_ = true;
73+
}
74+
75+
MultiArchShaderArchive::~MultiArchShaderArchive() = default;
76+
77+
bool MultiArchShaderArchive::IsValid() const {
78+
return is_valid_;
79+
}
80+
81+
std::shared_ptr<const fml::Mapping> MultiArchShaderArchive::GetArchive(
82+
ArchiveRenderingBackend backend) const {
83+
auto found = backend_mappings_.find(backend);
84+
if (found == backend_mappings_.end()) {
85+
return nullptr;
86+
}
87+
return found->second;
88+
}
89+
90+
std::shared_ptr<ShaderArchive> MultiArchShaderArchive::GetShaderArchive(
91+
ArchiveRenderingBackend backend) const {
92+
auto archive = GetArchive(backend);
93+
if (!archive) {
94+
return nullptr;
95+
}
96+
auto shader_archive =
97+
std::shared_ptr<ShaderArchive>(new ShaderArchive(std::move(archive)));
98+
if (!shader_archive->IsValid()) {
99+
return nullptr;
100+
}
101+
return shader_archive;
102+
}
103+
104+
} // namespace impeller
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
namespace impeller.fb;
6+
7+
enum RenderingBackend:byte {
8+
kOpenGLES,
9+
kVulkan,
10+
kMetal,
11+
}
12+
13+
table ShaderArchiveBlob {
14+
rendering_backend: RenderingBackend;
15+
mapping: [ubyte];
16+
}
17+
18+
table MultiArchShaderArchive {
19+
// We could have just as easily used the existing `ShaderArchive` table here.
20+
// However, those tables aren't used by Metal.
21+
items: [ShaderArchiveBlob];
22+
}
23+
24+
root_type MultiArchShaderArchive;
25+
file_identifier "MARC";
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#pragma once
6+
7+
#include <map>
8+
#include <memory>
9+
10+
#include "flutter/fml/macros.h"
11+
#include "flutter/fml/mapping.h"
12+
#include "impeller/shader_archive/shader_archive.h"
13+
#include "impeller/shader_archive/shader_archive_types.h"
14+
15+
namespace impeller {
16+
17+
class MultiArchShaderArchive {
18+
public:
19+
static std::shared_ptr<ShaderArchive> CreateArchiveFromMapping(
20+
const std::shared_ptr<const fml::Mapping>& mapping,
21+
ArchiveRenderingBackend backend);
22+
23+
explicit MultiArchShaderArchive(
24+
const std::shared_ptr<const fml::Mapping>& mapping);
25+
26+
~MultiArchShaderArchive();
27+
28+
std::shared_ptr<const fml::Mapping> GetArchive(
29+
ArchiveRenderingBackend backend) const;
30+
31+
std::shared_ptr<ShaderArchive> GetShaderArchive(
32+
ArchiveRenderingBackend backend) const;
33+
34+
bool IsValid() const;
35+
36+
private:
37+
std::map<ArchiveRenderingBackend, std::shared_ptr<const fml::Mapping>>
38+
backend_mappings_;
39+
bool is_valid_ = false;
40+
41+
FML_DISALLOW_COPY_AND_ASSIGN(MultiArchShaderArchive);
42+
};
43+
44+
} // namespace impeller
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "impeller/shader_archive/multi_arch_shader_archive_writer.h"
6+
7+
#include "impeller/base/validation.h"
8+
#include "impeller/shader_archive/multi_arch_shader_archive_flatbuffers.h"
9+
10+
namespace impeller {
11+
12+
MultiArchShaderArchiveWriter::MultiArchShaderArchiveWriter() = default;
13+
14+
MultiArchShaderArchiveWriter::~MultiArchShaderArchiveWriter() = default;
15+
16+
bool MultiArchShaderArchiveWriter::RegisterShaderArchive(
17+
ArchiveRenderingBackend backend,
18+
std::shared_ptr<const fml::Mapping> mapping) {
19+
if (!mapping || mapping->GetMapping() == nullptr) {
20+
return false;
21+
}
22+
if (archives_.find(backend) != archives_.end()) {
23+
VALIDATION_LOG << "Multi-archive already has a shader library registered "
24+
"for that backend.";
25+
return false;
26+
}
27+
archives_[backend] = std::move(mapping);
28+
return true;
29+
}
30+
31+
constexpr fb::RenderingBackend ToRenderingBackend(
32+
ArchiveRenderingBackend backend) {
33+
switch (backend) {
34+
case ArchiveRenderingBackend::kMetal:
35+
return fb::RenderingBackend::kMetal;
36+
case ArchiveRenderingBackend::kVulkan:
37+
return fb::RenderingBackend::kVulkan;
38+
case ArchiveRenderingBackend::kOpenGLES:
39+
return fb::RenderingBackend::kOpenGLES;
40+
}
41+
FML_UNREACHABLE();
42+
}
43+
44+
std::shared_ptr<fml::Mapping> MultiArchShaderArchiveWriter::CreateMapping()
45+
const {
46+
fb::MultiArchShaderArchiveT multi_archive;
47+
for (const auto& archive : archives_) {
48+
auto archive_blob = std::make_unique<fb::ShaderArchiveBlobT>();
49+
archive_blob->rendering_backend = ToRenderingBackend(archive.first);
50+
archive_blob->mapping = {
51+
archive.second->GetMapping(),
52+
archive.second->GetMapping() + archive.second->GetSize()};
53+
multi_archive.items.emplace_back(std::move(archive_blob));
54+
}
55+
auto builder = std::make_shared<flatbuffers::FlatBufferBuilder>();
56+
builder->Finish(
57+
fb::MultiArchShaderArchive::Pack(*builder.get(), &multi_archive),
58+
fb::MultiArchShaderArchiveIdentifier());
59+
return std::make_shared<fml::NonOwnedMapping>(builder->GetBufferPointer(),
60+
builder->GetSize(),
61+
[builder](auto, auto) {});
62+
}
63+
64+
} // namespace impeller
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#pragma once
6+
7+
#include <map>
8+
9+
#include "flutter/fml/macros.h"
10+
#include "flutter/fml/mapping.h"
11+
#include "impeller/shader_archive/shader_archive_types.h"
12+
13+
namespace impeller {
14+
15+
class MultiArchShaderArchiveWriter {
16+
public:
17+
MultiArchShaderArchiveWriter();
18+
19+
~MultiArchShaderArchiveWriter();
20+
21+
[[nodiscard]] bool RegisterShaderArchive(
22+
ArchiveRenderingBackend backend,
23+
std::shared_ptr<const fml::Mapping> mapping);
24+
25+
std::shared_ptr<fml::Mapping> CreateMapping() const;
26+
27+
private:
28+
std::map<ArchiveRenderingBackend, std::shared_ptr<const fml::Mapping>>
29+
archives_;
30+
31+
FML_DISALLOW_COPY_AND_ASSIGN(MultiArchShaderArchiveWriter);
32+
};
33+
34+
} // namespace impeller

impeller/shader_archive/shader_archive.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ constexpr ArchiveShaderType ToShaderType(fb::Stage stage) {
2525
FML_UNREACHABLE();
2626
}
2727

28-
ShaderArchive::ShaderArchive(std::shared_ptr<fml::Mapping> payload)
28+
ShaderArchive::ShaderArchive(std::shared_ptr<const fml::Mapping> payload)
2929
: payload_(std::move(payload)) {
3030
if (!payload_ || payload_->GetMapping() == nullptr) {
3131
VALIDATION_LOG << "Shader mapping was absent.";
3232
return;
3333
}
3434

3535
if (!fb::ShaderArchiveBufferHasIdentifier(payload_->GetMapping())) {
36-
VALIDATION_LOG << "Invalid shader magic.";
36+
VALIDATION_LOG << "Invalid shader archive magic.";
3737
return;
3838
}
3939

0 commit comments

Comments
 (0)