Skip to content

Commit

Permalink
Compile and package all shaders for the OpenGL ES backend. (#146)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
chinmaygarde authored Apr 20, 2022
1 parent 862f6d0 commit 191d3bf
Show file tree
Hide file tree
Showing 22 changed files with 828 additions and 116 deletions.
1 change: 1 addition & 0 deletions impeller/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ executable("impeller_unittests") {
deps = [
"archivist:archivist_unittests",
"base:base_unittests",
"blobcat:blobcat_unittests",
"compiler:compiler_unittests",
"fixtures",
"geometry:geometry_unittests",
Expand Down
49 changes: 49 additions & 0 deletions impeller/blobcat/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 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.

import("../tools/impeller.gni")

impeller_component("blobcat_lib") {
sources = [
"blob.cc",
"blob.h",
"blob_library.cc",
"blob_library.h",
"blob_writer.cc",
"blob_writer.h",
]

deps = [
"../base",
"//flutter/fml",
]
}

impeller_component("blobcat") {
target_type = "executable"

sources = [ "blobcat_main.cc" ]

deps = [
":blobcat_lib",
"../base",
"//flutter/fml",

# FML depends on the Dart VM for tracing and getting the current
# timepoint.
"//flutter/runtime:libdart",
]
}

impeller_component("blobcat_unittests") {
testonly = true

sources = [ "blobcat_unittests.cc" ]

deps = [
":blobcat_lib",
"//flutter/fml",
"//flutter/testing",
]
}
11 changes: 11 additions & 0 deletions impeller/blobcat/blob.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 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.h"

namespace impeller {

//

} // namespace impeller
43 changes: 43 additions & 0 deletions impeller/blobcat/blob.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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.

#pragma once

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>

#include "flutter/fml/macros.h"
#include "flutter/fml/mapping.h"

namespace impeller {

constexpr const uint32_t kBlobCatMagic = 0x0B10BCA7;
struct BlobHeader {
uint32_t magic = kBlobCatMagic;
uint32_t blob_count = 0u;
};

struct Blob {
enum class ShaderType : uint8_t {
kVertex,
kFragment,
};

static constexpr size_t kMaxNameLength = 24u;

ShaderType type = ShaderType::kVertex;
uint64_t offset = 0;
uint64_t length = 0;
uint8_t name[kMaxNameLength] = {};
};

struct BlobDescription {
Blob::ShaderType type;
std::string name;
std::shared_ptr<fml::Mapping> mapping;
};

} // namespace impeller
94 changes: 94 additions & 0 deletions impeller/blobcat/blob_library.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// 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_library.h"

#include <string>

namespace impeller {

BlobLibrary::BlobLibrary(std::shared_ptr<fml::Mapping> mapping)
: mapping_(std::move(mapping)) {
if (!mapping_ || mapping_->GetMapping() == nullptr) {
FML_LOG(ERROR) << "Invalid mapping.";
return;
}

BlobHeader header;
std::vector<Blob> blobs;

size_t offset = 0u;

// Read the header.
{
const size_t read_size = sizeof(BlobHeader);
if (mapping_->GetSize() < offset + read_size) {
return;
}
std::memcpy(&header, mapping_->GetMapping() + offset, read_size);
offset += read_size;

// Validate the header.
if (header.magic != kBlobCatMagic) {
FML_LOG(ERROR) << "Invalid blob magic.";
return;
}

blobs.resize(header.blob_count);
}

// Read the blob descriptions.
{
const size_t read_size = sizeof(Blob) * header.blob_count;
::memcpy(blobs.data(), mapping_->GetMapping() + offset, read_size);
offset += read_size;
}

// Read the blobs.
{
for (size_t i = 0; i < header.blob_count; i++) {
const auto& blob = blobs[i];

BlobKey key;
key.type = blob.type;
key.name = std::string{reinterpret_cast<const char*>(blob.name)};
auto mapping = std::make_shared<fml::NonOwnedMapping>(
mapping_->GetMapping() + blob.offset, // offset
blob.length, // length
[mapping = mapping_](const uint8_t* data, size_t size) {}
// release proc
);

auto inserted = blobs_.insert({key, mapping});
if (!inserted.second) {
FML_LOG(ERROR) << "Shader library had duplicate shader named "
<< key.name;
return;
}
}
}

is_valid_ = true;
}

BlobLibrary::~BlobLibrary() = default;

bool BlobLibrary::IsValid() const {
return is_valid_;
}

size_t BlobLibrary::GetShaderCount() const {
return blobs_.size();
}

std::shared_ptr<fml::Mapping> BlobLibrary::GetMapping(Blob::ShaderType type,
std::string name) const {
BlobKey key;
key.type = type;
key.name = name;
auto found = blobs_.find(key);
return found == blobs_.end() ? nullptr : found->second;
}

} // namespace impeller
63 changes: 63 additions & 0 deletions impeller/blobcat/blob_library.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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.

#pragma once

#include <memory>
#include <type_traits>
#include <unordered_map>

#include "flutter/fml/hash_combine.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/mapping.h"
#include "impeller/blobcat/blob.h"

namespace impeller {

class BlobLibrary {
public:
BlobLibrary(std::shared_ptr<fml::Mapping> mapping);

~BlobLibrary();

bool IsValid() const;

size_t GetShaderCount() const;

std::shared_ptr<fml::Mapping> GetMapping(Blob::ShaderType type,
std::string name) const;

private:
struct BlobKey {
Blob::ShaderType type = Blob::ShaderType::kFragment;
std::string name;

struct Hash {
size_t operator()(const BlobKey& key) const {
return fml::HashCombine(
static_cast<std::underlying_type_t<decltype(key.type)>>(key.type),
key.name);
}
};

struct Equal {
bool operator()(const BlobKey& lhs, const BlobKey& rhs) const {
return lhs.type == rhs.type && lhs.name == rhs.name;
}
};
};

using Blobs = std::unordered_map<BlobKey,
std::shared_ptr<fml::Mapping>,
BlobKey::Hash,
BlobKey::Equal>;

std::shared_ptr<fml::Mapping> mapping_;
Blobs blobs_;
bool is_valid_ = false;

FML_DISALLOW_COPY_AND_ASSIGN(BlobLibrary);
};

} // namespace impeller
Loading

0 comments on commit 191d3bf

Please sign in to comment.