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

[Impeller] Implement framebuffer fetch support for OpenGLES. #46585

Merged
merged 11 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions impeller/compiler/compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ static CompilerBackend CreateGLSLCompiler(const spirv_cross::ParsedIR& ir,
? source_options.gles_language_version
: 100;
sl_options.es = true;
if (source_options.require_framebuffer_fetch &&
source_options.type == SourceType::kFragmentShader) {
gl_compiler->remap_ext_framebuffer_fetch(0, 0, true);
}
gl_compiler->set_variable_type_remap_callback(
[&](const spirv_cross::SPIRType& type, const std::string& var_name,
std::string& name_of_type) {
Expand Down
1 change: 1 addition & 0 deletions impeller/compiler/impellerc_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ bool Main(const fml::CommandLine& command_line) {
options.gles_language_version = switches.gles_language_version;
options.metal_version = switches.metal_version;
options.use_half_textures = switches.use_half_textures;
options.require_framebuffer_fetch = switches.require_framebuffer_fetch;

Reflector::Options reflector_options;
reflector_options.target_platform = switches.target_platform;
Expand Down
5 changes: 5 additions & 0 deletions impeller/compiler/source_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ struct SourceOptions {
/// opengl semantics. Only used on metal targets.
bool use_half_textures = false;

/// @brief Whether the GLSL framebuffer fetch extension will be required.
///
/// Only used on OpenGLES targets.
bool require_framebuffer_fetch = false;

SourceOptions();

~SourceOptions();
Expand Down
5 changes: 4 additions & 1 deletion impeller/compiler/switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ void Switches::PrintHelp(std::ostream& stream) {
stream << "[optional] --use-half-textures (force openGL semantics when "
"targeting metal)"
<< std::endl;
stream << "[optional] --require-framebuffer-fetch" << std::endl;
}

Switches::Switches() = default;
Expand Down Expand Up @@ -136,7 +137,9 @@ Switches::Switches(const fml::CommandLine& command_line)
command_line.GetOptionValueWithDefault("metal-version", "1.2")),
entry_point(
command_line.GetOptionValueWithDefault("entry-point", "main")),
use_half_textures(command_line.HasOption("use-half-textures")) {
use_half_textures(command_line.HasOption("use-half-textures")),
require_framebuffer_fetch(
command_line.HasOption("require-framebuffer-fetch")) {
auto language =
command_line.GetOptionValueWithDefault("source-language", "glsl");
std::transform(language.begin(), language.end(), language.begin(),
Expand Down
3 changes: 2 additions & 1 deletion impeller/compiler/switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ struct Switches {
std::string metal_version = "";
std::string entry_point = "";
bool use_half_textures = false;
bool require_framebuffer_fetch = false;

Switches();

~Switches();

Switches(const fml::CommandLine& command_line);
explicit Switches(const fml::CommandLine& command_line);

bool AreValid(std::ostream& explain) const;

Expand Down
13 changes: 4 additions & 9 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,17 @@ impeller_shaders("modern_entity_shaders") {

impeller_shaders("framebuffer_blend_entity_shaders") {
name = "framebuffer_blend"
require_framebuffer_fetch = true

# malioc does not support analyzing shaders that use the framebuffer fetch extension on some GPUs.
analyze = false

if (is_mac && !is_ios) {
# Note: this needs to correspond to the Apple7 Support family
# for M1 and M2.
metal_version = "2.3"
}

# This version is to disable malioc checks.
if (impeller_enable_opengles) {
gles_language_version = 460
}

if (impeller_enable_vulkan) {
vulkan_language_version = 130
}

shaders = [
"shaders/blending/ios/framebuffer_blend.vert",
"shaders/blending/ios/framebuffer_blend_color.frag",
Expand Down
8 changes: 3 additions & 5 deletions impeller/entity/contents/framebuffer_blend_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,10 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer,
FS::FragInfo frag_info;

auto src_sampler_descriptor = src_snapshot->sampler_descriptor;
if (!renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
// No known devices that support framebuffer fetch but not decal tile mode.
return false;
if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
src_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
src_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
}
src_sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
src_sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
auto src_sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler(
src_sampler_descriptor);
FS::BindTextureSamplerSrc(cmd, src_snapshot->texture, src_sampler);
Expand Down
25 changes: 13 additions & 12 deletions impeller/entity/shaders/blending/ios/framebuffer_blend.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,13 @@
#include <impeller/texture.glsl>
#include <impeller/types.glsl>

#ifdef IMPELLER_TARGET_METAL
layout(set = 0,
binding = 0,
input_attachment_index = 0) uniform subpassInput uSub;

vec4 ReadDestination() {
return subpassLoad(uSub);
}
#else

vec4 ReadDestination() {
return vec4(0);
}
#endif

uniform sampler2D texture_sampler_src;

Expand All @@ -35,12 +28,20 @@ in vec2 v_src_texture_coords;

out vec4 frag_color;

vec4 Sample(sampler2D texture_sampler, vec2 texture_coords) {
// gles 2.0 is the only backend without native decal support.
#ifdef IMPELLER_TARGET_OPENGLES
return IPSampleDecal(texture_sampler, texture_coords);
#else
return texture(texture_sampler, texture_coords);
#endif
}

void main() {
f16vec4 dst_sample = f16vec4(ReadDestination());
f16vec4 dst = dst_sample;
f16vec4 src = f16vec4(texture(texture_sampler_src, // sampler
v_src_texture_coords // texture coordinates
)) *
f16vec4 dst = f16vec4(ReadDestination());
f16vec4 src = f16vec4(Sample(texture_sampler_src, // sampler
v_src_texture_coords // texture coordinates
)) *
frag_info.src_input_alpha;

f16vec4 blended = mix(src, f16vec4(Blend(dst.rgb, src.rgb), dst.a), dst.a);
Expand Down
22 changes: 18 additions & 4 deletions impeller/renderer/backend/gles/capabilities_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@

namespace impeller {

// https://registry.khronos.org/OpenGL/extensions/EXT/EXT_shader_framebuffer_fetch.txt
static const constexpr char* kFramebufferFetchExt =
"GL_EXT_shader_framebuffer_fetch";

static const constexpr char* kTextureBorderClampExt =
"GL_EXT_texture_border_clamp";
static const constexpr char* kNvidiaTextureBorderClampExt =
"GL_NV_texture_border_clamp";
static const constexpr char* kOESTextureBorderClampExt =
"GL_OES_texture_border_clamp";

CapabilitiesGLES::CapabilitiesGLES(const ProcTableGLES& gl) {
{
GLint value = 0;
Expand Down Expand Up @@ -87,9 +98,12 @@ CapabilitiesGLES::CapabilitiesGLES(const ProcTableGLES& gl) {
num_shader_binary_formats = value;
}

if (gl.GetDescription()->HasExtension("GL_EXT_texture_border_clamp") ||
gl.GetDescription()->HasExtension("GL_NV_texture_border_clamp") ||
gl.GetDescription()->HasExtension("GL_OES_texture_border_clamp")) {
supports_framebuffer_fetch_ =
gl.GetDescription()->HasExtension(kFramebufferFetchExt);

if (gl.GetDescription()->HasExtension(kTextureBorderClampExt) ||
gl.GetDescription()->HasExtension(kNvidiaTextureBorderClampExt) ||
gl.GetDescription()->HasExtension(kOESTextureBorderClampExt)) {
supports_decal_sampler_address_mode_ = true;
}
}
Expand Down Expand Up @@ -126,7 +140,7 @@ bool CapabilitiesGLES::SupportsTextureToTextureBlits() const {
}

bool CapabilitiesGLES::SupportsFramebufferFetch() const {
return false;
return supports_framebuffer_fetch_;
}

bool CapabilitiesGLES::SupportsCompute() const {
Expand Down
1 change: 1 addition & 0 deletions impeller/renderer/backend/gles/capabilities_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class CapabilitiesGLES final
PixelFormat GetDefaultDepthStencilFormat() const override;

private:
bool supports_framebuffer_fetch_ = false;
bool supports_decal_sampler_address_mode_ = false;
};

Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/backend/gles/pipeline_library_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class PipelineLibraryGLES final : public PipelineLibrary {
ReactorGLES::Ref reactor_;
PipelineMap pipelines_;

PipelineLibraryGLES(ReactorGLES::Ref reactor);
explicit PipelineLibraryGLES(ReactorGLES::Ref reactor);

// |PipelineLibrary|
bool IsValid() const override;
Expand Down
11 changes: 11 additions & 0 deletions impeller/renderer/backend/gles/test/capabilities_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,16 @@ TEST(CapabilitiesGLES, SupportsDecalSamplerAddressMode) {
EXPECT_TRUE(capabilities->SupportsDecalSamplerAddressMode());
}

TEST(CapabilitiesGLES, SupportsFramebufferFetch) {
auto const extensions = std::vector<const unsigned char*>{
reinterpret_cast<const unsigned char*>("GL_KHR_debug"), //
reinterpret_cast<const unsigned char*>(
"GL_EXT_shader_framebuffer_fetch"), //
};
auto mock_gles = MockGLES::Init(extensions);
auto capabilities = mock_gles->GetProcTable().GetCapabilities();
EXPECT_TRUE(capabilities->SupportsFramebufferFetch());
}

} // namespace testing
} // namespace impeller
24 changes: 23 additions & 1 deletion impeller/tools/impeller.gni
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ template("impellerc") {
if (defined(invoker.use_half_textures) && invoker.use_half_textures) {
args += [ "--use-half-textures" ]
}
if (defined(invoker.require_framebuffer_fetch) &&
invoker.require_framebuffer_fetch) {
args += [ "--require-framebuffer-fetch" ]
}

if (json) {
args += [ "--json" ]
Expand Down Expand Up @@ -506,6 +510,12 @@ template("_impeller_shaders_gles") {
assert(defined(invoker.name), "Name of the shader library must be specified.")
assert(defined(invoker.analyze), "Whether to analyze must be specified.")

require_framebuffer_fetch = false
if (defined(invoker.require_framebuffer_fetch) &&
invoker.require_framebuffer_fetch) {
require_framebuffer_fetch = invoker.require_framebuffer_fetch
}

shaders_base_name = string_join("",
[
invoker.name,
Expand All @@ -515,6 +525,7 @@ template("_impeller_shaders_gles") {
impellerc(impellerc_gles) {
shaders = invoker.shaders
sl_file_extension = "gles"
require_framebuffer_fetch = require_framebuffer_fetch
if (defined(invoker.gles_language_version)) {
gles_language_version = invoker.gles_language_version
}
Expand Down Expand Up @@ -690,11 +701,14 @@ template("_impeller_shaders_vk") {
#
# The SPIR-V version required by the shaders.
#
# @param[options] use_half_textures
# @param[optional] use_half_textures
#
# Whether the metal shader is using half-precision textures and requires
# openGL semantics when compilig SPIR-V.
#
# @param[optional] require_framebuffer_fetch
#
# Whether to require the framebuffer fetch extension for GLES fragment shaders.
template("impeller_shaders") {
if (defined(invoker.metal_version)) {
metal_version = invoker.metal_version
Expand All @@ -705,9 +719,16 @@ template("impeller_shaders") {
use_half_textures = true
}

require_framebuffer_fetch = false
if (defined(invoker.require_framebuffer_fetch) &&
invoker.require_framebuffer_fetch) {
require_framebuffer_fetch = true
}

not_needed([
"metal_version",
"use_half_textures",
"require_framebuffer_fetch",
])

enable_opengles = impeller_enable_opengles
Expand Down Expand Up @@ -737,6 +758,7 @@ template("impeller_shaders") {
gles_shaders = "gles_$target_name"
_impeller_shaders_gles(gles_shaders) {
name = invoker.name
require_framebuffer_fetch = require_framebuffer_fetch
if (defined(invoker.gles_language_version)) {
gles_language_version = invoker.gles_language_version
}
Expand Down
Loading