Skip to content

Commit 79f2e86

Browse files
chinmaygardednfield
authored andcommitted
Compile and package all shaders for the OpenGL ES backend. (flutter#146)
* Dries up GN rules for Metal and OpenGL ES shader compilation and embedding in a target binary. * Adds support for shader compile time macro definitions. This is so that workarounds for specific shader backends can be implemented. In the case of this patch, there are temporary OpenGLES workaround for users of instancing and SSBOs. These will be removed when I rework glyph rendering to not use these features that are missing in legacy targets. * Since there is no concept of an OpenGLES shader library akin to a `.metallib`, adds a target called `blobcat` that concatenates shader blobs into single blob that can be embedded into a target binary. No parsing or data copying is necessary. * `imgui_raster.vert` has been rewritten to work around the absence of unsigned integer types in legacy backends.
1 parent 80bb5f9 commit 79f2e86

22 files changed

+828
-116
lines changed

impeller/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ executable("impeller_unittests") {
4848
deps = [
4949
"archivist:archivist_unittests",
5050
"base:base_unittests",
51+
"blobcat:blobcat_unittests",
5152
"compiler:compiler_unittests",
5253
"fixtures",
5354
"geometry:geometry_unittests",

impeller/blobcat/BUILD.gn

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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+
import("../tools/impeller.gni")
6+
7+
impeller_component("blobcat_lib") {
8+
sources = [
9+
"blob.cc",
10+
"blob.h",
11+
"blob_library.cc",
12+
"blob_library.h",
13+
"blob_writer.cc",
14+
"blob_writer.h",
15+
]
16+
17+
deps = [
18+
"../base",
19+
"//flutter/fml",
20+
]
21+
}
22+
23+
impeller_component("blobcat") {
24+
target_type = "executable"
25+
26+
sources = [ "blobcat_main.cc" ]
27+
28+
deps = [
29+
":blobcat_lib",
30+
"../base",
31+
"//flutter/fml",
32+
33+
# FML depends on the Dart VM for tracing and getting the current
34+
# timepoint.
35+
"//flutter/runtime:libdart",
36+
]
37+
}
38+
39+
impeller_component("blobcat_unittests") {
40+
testonly = true
41+
42+
sources = [ "blobcat_unittests.cc" ]
43+
44+
deps = [
45+
":blobcat_lib",
46+
"//flutter/fml",
47+
"//flutter/testing",
48+
]
49+
}

impeller/blobcat/blob.cc

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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/blobcat/blob.h"
6+
7+
namespace impeller {
8+
9+
//
10+
11+
} // namespace impeller

impeller/blobcat/blob.h

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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 <cstddef>
8+
#include <cstdint>
9+
#include <memory>
10+
#include <string>
11+
12+
#include "flutter/fml/macros.h"
13+
#include "flutter/fml/mapping.h"
14+
15+
namespace impeller {
16+
17+
constexpr const uint32_t kBlobCatMagic = 0x0B10BCA7;
18+
struct BlobHeader {
19+
uint32_t magic = kBlobCatMagic;
20+
uint32_t blob_count = 0u;
21+
};
22+
23+
struct Blob {
24+
enum class ShaderType : uint8_t {
25+
kVertex,
26+
kFragment,
27+
};
28+
29+
static constexpr size_t kMaxNameLength = 24u;
30+
31+
ShaderType type = ShaderType::kVertex;
32+
uint64_t offset = 0;
33+
uint64_t length = 0;
34+
uint8_t name[kMaxNameLength] = {};
35+
};
36+
37+
struct BlobDescription {
38+
Blob::ShaderType type;
39+
std::string name;
40+
std::shared_ptr<fml::Mapping> mapping;
41+
};
42+
43+
} // namespace impeller

impeller/blobcat/blob_library.cc

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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/blobcat/blob_library.h"
6+
7+
#include <string>
8+
9+
namespace impeller {
10+
11+
BlobLibrary::BlobLibrary(std::shared_ptr<fml::Mapping> mapping)
12+
: mapping_(std::move(mapping)) {
13+
if (!mapping_ || mapping_->GetMapping() == nullptr) {
14+
FML_LOG(ERROR) << "Invalid mapping.";
15+
return;
16+
}
17+
18+
BlobHeader header;
19+
std::vector<Blob> blobs;
20+
21+
size_t offset = 0u;
22+
23+
// Read the header.
24+
{
25+
const size_t read_size = sizeof(BlobHeader);
26+
if (mapping_->GetSize() < offset + read_size) {
27+
return;
28+
}
29+
std::memcpy(&header, mapping_->GetMapping() + offset, read_size);
30+
offset += read_size;
31+
32+
// Validate the header.
33+
if (header.magic != kBlobCatMagic) {
34+
FML_LOG(ERROR) << "Invalid blob magic.";
35+
return;
36+
}
37+
38+
blobs.resize(header.blob_count);
39+
}
40+
41+
// Read the blob descriptions.
42+
{
43+
const size_t read_size = sizeof(Blob) * header.blob_count;
44+
::memcpy(blobs.data(), mapping_->GetMapping() + offset, read_size);
45+
offset += read_size;
46+
}
47+
48+
// Read the blobs.
49+
{
50+
for (size_t i = 0; i < header.blob_count; i++) {
51+
const auto& blob = blobs[i];
52+
53+
BlobKey key;
54+
key.type = blob.type;
55+
key.name = std::string{reinterpret_cast<const char*>(blob.name)};
56+
auto mapping = std::make_shared<fml::NonOwnedMapping>(
57+
mapping_->GetMapping() + blob.offset, // offset
58+
blob.length, // length
59+
[mapping = mapping_](const uint8_t* data, size_t size) {}
60+
// release proc
61+
);
62+
63+
auto inserted = blobs_.insert({key, mapping});
64+
if (!inserted.second) {
65+
FML_LOG(ERROR) << "Shader library had duplicate shader named "
66+
<< key.name;
67+
return;
68+
}
69+
}
70+
}
71+
72+
is_valid_ = true;
73+
}
74+
75+
BlobLibrary::~BlobLibrary() = default;
76+
77+
bool BlobLibrary::IsValid() const {
78+
return is_valid_;
79+
}
80+
81+
size_t BlobLibrary::GetShaderCount() const {
82+
return blobs_.size();
83+
}
84+
85+
std::shared_ptr<fml::Mapping> BlobLibrary::GetMapping(Blob::ShaderType type,
86+
std::string name) const {
87+
BlobKey key;
88+
key.type = type;
89+
key.name = name;
90+
auto found = blobs_.find(key);
91+
return found == blobs_.end() ? nullptr : found->second;
92+
}
93+
94+
} // namespace impeller

impeller/blobcat/blob_library.h

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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 <memory>
8+
#include <type_traits>
9+
#include <unordered_map>
10+
11+
#include "flutter/fml/hash_combine.h"
12+
#include "flutter/fml/macros.h"
13+
#include "flutter/fml/mapping.h"
14+
#include "impeller/blobcat/blob.h"
15+
16+
namespace impeller {
17+
18+
class BlobLibrary {
19+
public:
20+
BlobLibrary(std::shared_ptr<fml::Mapping> mapping);
21+
22+
~BlobLibrary();
23+
24+
bool IsValid() const;
25+
26+
size_t GetShaderCount() const;
27+
28+
std::shared_ptr<fml::Mapping> GetMapping(Blob::ShaderType type,
29+
std::string name) const;
30+
31+
private:
32+
struct BlobKey {
33+
Blob::ShaderType type = Blob::ShaderType::kFragment;
34+
std::string name;
35+
36+
struct Hash {
37+
size_t operator()(const BlobKey& key) const {
38+
return fml::HashCombine(
39+
static_cast<std::underlying_type_t<decltype(key.type)>>(key.type),
40+
key.name);
41+
}
42+
};
43+
44+
struct Equal {
45+
bool operator()(const BlobKey& lhs, const BlobKey& rhs) const {
46+
return lhs.type == rhs.type && lhs.name == rhs.name;
47+
}
48+
};
49+
};
50+
51+
using Blobs = std::unordered_map<BlobKey,
52+
std::shared_ptr<fml::Mapping>,
53+
BlobKey::Hash,
54+
BlobKey::Equal>;
55+
56+
std::shared_ptr<fml::Mapping> mapping_;
57+
Blobs blobs_;
58+
bool is_valid_ = false;
59+
60+
FML_DISALLOW_COPY_AND_ASSIGN(BlobLibrary);
61+
};
62+
63+
} // namespace impeller

0 commit comments

Comments
 (0)