[Impeller] create a 300 es variant of all GLES shaders to support UBO binding. (flutter/engine#56960)

Create a GLES3 "backend" by compiling a second set of GLES shaders to 300 es. This allows the usage of UBOs and SSBOs.
This commit is contained in:
Jonah Williams 2024-12-05 12:56:16 -08:00 committed by GitHub
parent f5325bf597
commit 2e80dbea2c
36 changed files with 318 additions and 86 deletions

View File

@ -156,11 +156,15 @@ static CompilerBackend CreateGLSLCompiler(const spirv_cross::ParsedIR& ir,
sl_options.force_zero_initialized_variables = true; sl_options.force_zero_initialized_variables = true;
sl_options.vertex.fixup_clipspace = true; sl_options.vertex.fixup_clipspace = true;
if (source_options.target_platform == TargetPlatform::kOpenGLES || if (source_options.target_platform == TargetPlatform::kOpenGLES ||
source_options.target_platform == TargetPlatform::kRuntimeStageGLES) { source_options.target_platform == TargetPlatform::kRuntimeStageGLES ||
source_options.target_platform == TargetPlatform::kRuntimeStageGLES3) {
sl_options.version = source_options.gles_language_version > 0 sl_options.version = source_options.gles_language_version > 0
? source_options.gles_language_version ? source_options.gles_language_version
: 100; : 100;
sl_options.es = true; sl_options.es = true;
if (source_options.target_platform == TargetPlatform::kRuntimeStageGLES3) {
sl_options.version = 300;
}
if (source_options.require_framebuffer_fetch && if (source_options.require_framebuffer_fetch &&
source_options.type == SourceType::kFragmentShader) { source_options.type == SourceType::kFragmentShader) {
gl_compiler->remap_ext_framebuffer_fetch(0, 0, true); gl_compiler->remap_ext_framebuffer_fetch(0, 0, true);
@ -202,6 +206,7 @@ static bool EntryPointMustBeNamedMain(TargetPlatform platform) {
case TargetPlatform::kOpenGLES: case TargetPlatform::kOpenGLES:
case TargetPlatform::kOpenGLDesktop: case TargetPlatform::kOpenGLDesktop:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
return true; return true;
} }
FML_UNREACHABLE(); FML_UNREACHABLE();
@ -224,6 +229,7 @@ static CompilerBackend CreateCompiler(const spirv_cross::ParsedIR& ir,
case TargetPlatform::kOpenGLES: case TargetPlatform::kOpenGLES:
case TargetPlatform::kOpenGLDesktop: case TargetPlatform::kOpenGLDesktop:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
compiler = CreateGLSLCompiler(ir, source_options); compiler = CreateGLSLCompiler(ir, source_options);
break; break;
case TargetPlatform::kSkSL: case TargetPlatform::kSkSL:
@ -317,7 +323,8 @@ Compiler::Compiler(const std::shared_ptr<const fml::Mapping>& source_mapping,
spirv_options.target = target; spirv_options.target = target;
} break; } break;
case TargetPlatform::kRuntimeStageMetal: case TargetPlatform::kRuntimeStageMetal:
case TargetPlatform::kRuntimeStageGLES: { case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3: {
SPIRVCompilerTargetEnv target; SPIRVCompilerTargetEnv target;
target.env = shaderc_target_env::shaderc_target_env_opengl; target.env = shaderc_target_env::shaderc_target_env_opengl;

View File

@ -207,6 +207,7 @@ static bool OutputDepfile(const Compiler& compiler, const Switches& switches) {
case TargetPlatform::kOpenGLDesktop: case TargetPlatform::kOpenGLDesktop:
case TargetPlatform::kRuntimeStageMetal: case TargetPlatform::kRuntimeStageMetal:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
case TargetPlatform::kRuntimeStageVulkan: case TargetPlatform::kRuntimeStageVulkan:
case TargetPlatform::kSkSL: case TargetPlatform::kSkSL:
case TargetPlatform::kVulkan: case TargetPlatform::kVulkan:

View File

@ -312,6 +312,8 @@ static std::optional<RuntimeStageBackend> GetRuntimeStageBackend(
return RuntimeStageBackend::kMetal; return RuntimeStageBackend::kMetal;
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
return RuntimeStageBackend::kOpenGLES; return RuntimeStageBackend::kOpenGLES;
case TargetPlatform::kRuntimeStageGLES3:
return RuntimeStageBackend::kOpenGLES3;
case TargetPlatform::kRuntimeStageVulkan: case TargetPlatform::kRuntimeStageVulkan:
return RuntimeStageBackend::kVulkan; return RuntimeStageBackend::kVulkan;
case TargetPlatform::kSkSL: case TargetPlatform::kSkSL:

View File

@ -204,6 +204,8 @@ static std::string RuntimeStageBackendToString(RuntimeStageBackend backend) {
return "opengles"; return "opengles";
case RuntimeStageBackend::kVulkan: case RuntimeStageBackend::kVulkan:
return "vulkan"; return "vulkan";
case RuntimeStageBackend::kOpenGLES3:
return "opengles3";
} }
} }
@ -384,6 +386,9 @@ RuntimeStageData::CreateMultiStageFlatbuffer() const {
case RuntimeStageBackend::kVulkan: case RuntimeStageBackend::kVulkan:
runtime_stages->vulkan = std::move(runtime_stage); runtime_stages->vulkan = std::move(runtime_stage);
break; break;
case RuntimeStageBackend::kOpenGLES3:
runtime_stages->opengles3 = std::move(runtime_stage);
break;
} }
} }
return runtime_stages; return runtime_stages;

View File

@ -29,6 +29,7 @@ static const std::map<std::string, TargetPlatform> kKnownRuntimeStages = {
{"sksl", TargetPlatform::kSkSL}, {"sksl", TargetPlatform::kSkSL},
{"runtime-stage-metal", TargetPlatform::kRuntimeStageMetal}, {"runtime-stage-metal", TargetPlatform::kRuntimeStageMetal},
{"runtime-stage-gles", TargetPlatform::kRuntimeStageGLES}, {"runtime-stage-gles", TargetPlatform::kRuntimeStageGLES},
{"runtime-stage-gles3", TargetPlatform::kRuntimeStageGLES3},
{"runtime-stage-vulkan", TargetPlatform::kRuntimeStageVulkan}, {"runtime-stage-vulkan", TargetPlatform::kRuntimeStageVulkan},
}; };

View File

@ -89,6 +89,8 @@ std::string TargetPlatformToString(TargetPlatform platform) {
return "RuntimeStageMetal"; return "RuntimeStageMetal";
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
return "RuntimeStageGLES"; return "RuntimeStageGLES";
case TargetPlatform::kRuntimeStageGLES3:
return "RuntimeStageGLES3";
case TargetPlatform::kRuntimeStageVulkan: case TargetPlatform::kRuntimeStageVulkan:
return "RuntimeStageVulkan"; return "RuntimeStageVulkan";
case TargetPlatform::kSkSL: case TargetPlatform::kSkSL:
@ -146,6 +148,7 @@ bool TargetPlatformNeedsReflection(TargetPlatform platform) {
case TargetPlatform::kOpenGLDesktop: case TargetPlatform::kOpenGLDesktop:
case TargetPlatform::kRuntimeStageMetal: case TargetPlatform::kRuntimeStageMetal:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
case TargetPlatform::kRuntimeStageVulkan: case TargetPlatform::kRuntimeStageVulkan:
case TargetPlatform::kVulkan: case TargetPlatform::kVulkan:
return true; return true;
@ -221,6 +224,7 @@ spirv_cross::CompilerMSL::Options::Platform TargetPlatformToMSLPlatform(
case TargetPlatform::kOpenGLES: case TargetPlatform::kOpenGLES:
case TargetPlatform::kOpenGLDesktop: case TargetPlatform::kOpenGLDesktop:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
case TargetPlatform::kRuntimeStageVulkan: case TargetPlatform::kRuntimeStageVulkan:
case TargetPlatform::kVulkan: case TargetPlatform::kVulkan:
case TargetPlatform::kUnknown: case TargetPlatform::kUnknown:
@ -255,6 +259,7 @@ std::string TargetPlatformSLExtension(TargetPlatform platform) {
case TargetPlatform::kOpenGLES: case TargetPlatform::kOpenGLES:
case TargetPlatform::kOpenGLDesktop: case TargetPlatform::kOpenGLDesktop:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
return "glsl"; return "glsl";
case TargetPlatform::kVulkan: case TargetPlatform::kVulkan:
case TargetPlatform::kRuntimeStageVulkan: case TargetPlatform::kRuntimeStageVulkan:
@ -268,6 +273,7 @@ bool TargetPlatformIsOpenGL(TargetPlatform platform) {
case TargetPlatform::kOpenGLES: case TargetPlatform::kOpenGLES:
case TargetPlatform::kOpenGLDesktop: case TargetPlatform::kOpenGLDesktop:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
return true; return true;
case TargetPlatform::kMetalDesktop: case TargetPlatform::kMetalDesktop:
case TargetPlatform::kRuntimeStageMetal: case TargetPlatform::kRuntimeStageMetal:
@ -292,6 +298,7 @@ bool TargetPlatformIsMetal(TargetPlatform platform) {
case TargetPlatform::kOpenGLES: case TargetPlatform::kOpenGLES:
case TargetPlatform::kOpenGLDesktop: case TargetPlatform::kOpenGLDesktop:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
case TargetPlatform::kRuntimeStageVulkan: case TargetPlatform::kRuntimeStageVulkan:
case TargetPlatform::kVulkan: case TargetPlatform::kVulkan:
return false; return false;
@ -312,6 +319,7 @@ bool TargetPlatformIsVulkan(TargetPlatform platform) {
case TargetPlatform::kOpenGLES: case TargetPlatform::kOpenGLES:
case TargetPlatform::kOpenGLDesktop: case TargetPlatform::kOpenGLDesktop:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
return false; return false;
} }
FML_UNREACHABLE(); FML_UNREACHABLE();
@ -322,6 +330,7 @@ bool TargetPlatformBundlesSkSL(TargetPlatform platform) {
case TargetPlatform::kSkSL: case TargetPlatform::kSkSL:
case TargetPlatform::kRuntimeStageMetal: case TargetPlatform::kRuntimeStageMetal:
case TargetPlatform::kRuntimeStageGLES: case TargetPlatform::kRuntimeStageGLES:
case TargetPlatform::kRuntimeStageGLES3:
case TargetPlatform::kRuntimeStageVulkan: case TargetPlatform::kRuntimeStageVulkan:
return true; return true;
case TargetPlatform::kMetalDesktop: case TargetPlatform::kMetalDesktop:

View File

@ -34,6 +34,7 @@ enum class TargetPlatform {
kVulkan, kVulkan,
kRuntimeStageMetal, kRuntimeStageMetal,
kRuntimeStageGLES, kRuntimeStageGLES,
kRuntimeStageGLES3,
kRuntimeStageVulkan, kRuntimeStageVulkan,
kSkSL, kSkSL,
}; };

View File

@ -17,6 +17,7 @@ enum class RuntimeStageBackend {
kSkSL, kSkSL,
kMetal, kMetal,
kOpenGLES, kOpenGLES,
kOpenGLES3,
kVulkan, kVulkan,
}; };

View File

@ -8,6 +8,8 @@
#include <vector> #include <vector>
#include "impeller/base/validation.h" #include "impeller/base/validation.h"
#include "impeller/core/buffer_view.h"
#include "impeller/core/device_buffer.h"
#include "impeller/core/shader_types.h" #include "impeller/core/shader_types.h"
#include "impeller/renderer/backend/gles/device_buffer_gles.h" #include "impeller/renderer/backend/gles/device_buffer_gles.h"
#include "impeller/renderer/backend/gles/formats_gles.h" #include "impeller/renderer/backend/gles/formats_gles.h"
@ -101,6 +103,38 @@ bool BufferBindingsGLES::ReadUniformsBindings(const ProcTableGLES& gl,
if (!gl.IsProgram(program)) { if (!gl.IsProgram(program)) {
return false; return false;
} }
program_handle_ = program;
if (gl.GetDescription()->GetGlVersion().IsAtLeast(Version{3, 0, 0})) {
return ReadUniformsBindingsV3(gl, program);
}
return ReadUniformsBindingsV2(gl, program);
}
bool BufferBindingsGLES::ReadUniformsBindingsV3(const ProcTableGLES& gl,
GLuint program) {
program_handle_ = program;
GLint uniform_blocks = 0;
gl.GetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &uniform_blocks);
for (GLint i = 0; i < uniform_blocks; i++) {
GLint name_length = 0;
gl.GetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_NAME_LENGTH,
&name_length);
std::vector<GLchar> name;
name.resize(name_length);
GLint length = 0;
gl.GetActiveUniformBlockName(program, i, name_length, &length, name.data());
GLuint block_index = gl.GetUniformBlockIndex(program, name.data());
ubo_locations_[std::string{name.data(), static_cast<size_t>(length)}] =
std::make_pair(block_index, i);
}
use_ubo_ = true;
return ReadUniformsBindingsV2(gl, program);
}
bool BufferBindingsGLES::ReadUniformsBindingsV2(const ProcTableGLES& gl,
GLuint program) {
GLint max_name_size = 0; GLint max_name_size = 0;
gl.GetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_size); gl.GetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_size);
@ -139,6 +173,9 @@ bool BufferBindingsGLES::ReadUniformsBindings(const ProcTableGLES& gl,
auto location = gl.GetUniformLocation(program, name.data()); auto location = gl.GetUniformLocation(program, name.data());
if (location == -1) { if (location == -1) {
if (use_ubo_) {
continue;
}
VALIDATION_LOG << "Could not query the location of an active uniform."; VALIDATION_LOG << "Could not query the location of an active uniform.";
return false; return false;
} }
@ -280,8 +317,47 @@ bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl,
} }
const DeviceBufferGLES& device_buffer_gles = const DeviceBufferGLES& device_buffer_gles =
DeviceBufferGLES::Cast(*device_buffer); DeviceBufferGLES::Cast(*device_buffer);
if (use_ubo_) {
return BindUniformBufferV3(gl, buffer.resource, metadata,
device_buffer_gles);
}
return BindUniformBufferV2(gl, buffer.resource, metadata, device_buffer_gles);
}
bool BufferBindingsGLES::BindUniformBufferV3(
const ProcTableGLES& gl,
const BufferView& buffer,
const ShaderMetadata* metadata,
const DeviceBufferGLES& device_buffer_gles) {
absl::flat_hash_map<std::string, std::pair<GLint, GLuint>>::iterator it =
ubo_locations_.find(metadata->name);
if (it == ubo_locations_.end()) {
return BindUniformBufferV2(gl, buffer, metadata, device_buffer_gles);
}
const auto& [block_index, binding_point] = it->second;
gl.UniformBlockBinding(program_handle_, block_index, binding_point);
if (!device_buffer_gles.BindAndUploadDataIfNecessary(
DeviceBufferGLES::BindingType::kUniformBuffer)) {
return false;
}
auto handle = device_buffer_gles.GetHandle();
if (!handle.has_value()) {
return false;
}
gl.BindBufferRange(GL_UNIFORM_BUFFER, binding_point, handle.value(),
buffer.GetRange().offset, buffer.GetRange().length);
return true;
}
bool BufferBindingsGLES::BindUniformBufferV2(
const ProcTableGLES& gl,
const BufferView& buffer,
const ShaderMetadata* metadata,
const DeviceBufferGLES& device_buffer_gles) {
const uint8_t* buffer_ptr = const uint8_t* buffer_ptr =
device_buffer_gles.GetBufferData() + buffer.resource.GetRange().offset; device_buffer_gles.GetBufferData() + buffer.GetRange().offset;
if (metadata->members.empty()) { if (metadata->members.empty()) {
VALIDATION_LOG << "Uniform buffer had no members. This is currently " VALIDATION_LOG << "Uniform buffer had no members. This is currently "
@ -320,64 +396,46 @@ bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl,
reinterpret_cast<const GLfloat*>(array_element_buffer.data()); reinterpret_cast<const GLfloat*>(array_element_buffer.data());
} }
switch (member.type) { if (member.type != ShaderType::kFloat) {
case ShaderType::kFloat: VALIDATION_LOG << "Could not bind uniform buffer data for key: "
switch (member.size) { << member.name << " : " << static_cast<int>(member.type);
case sizeof(Matrix): return false;
gl.UniformMatrix4fv(location, // location }
element_count, // count
GL_FALSE, // normalize switch (member.size) {
buffer_data // data case sizeof(Matrix):
); gl.UniformMatrix4fv(location, // location
continue; element_count, // count
case sizeof(Vector4): GL_FALSE, // normalize
gl.Uniform4fv(location, // location buffer_data // data
element_count, // count );
buffer_data // data continue;
); case sizeof(Vector4):
continue; gl.Uniform4fv(location, // location
case sizeof(Vector3): element_count, // count
gl.Uniform3fv(location, // location buffer_data // data
element_count, // count );
buffer_data // data continue;
); case sizeof(Vector3):
continue; gl.Uniform3fv(location, // location
case sizeof(Vector2): element_count, // count
gl.Uniform2fv(location, // location buffer_data // data
element_count, // count );
buffer_data // data continue;
); case sizeof(Vector2):
continue; gl.Uniform2fv(location, // location
case sizeof(Scalar): element_count, // count
gl.Uniform1fv(location, // location buffer_data // data
element_count, // count );
buffer_data // data continue;
); case sizeof(Scalar):
continue; gl.Uniform1fv(location, // location
} element_count, // count
VALIDATION_LOG << "Size " << member.size buffer_data // data
<< " could not be mapped ShaderType::kFloat for key: " );
<< member.name; continue;
case ShaderType::kBoolean: default:
case ShaderType::kSignedByte: VALIDATION_LOG << "Invalid member size binding: " << member.size;
case ShaderType::kUnsignedByte:
case ShaderType::kSignedShort:
case ShaderType::kUnsignedShort:
case ShaderType::kSignedInt:
case ShaderType::kUnsignedInt:
case ShaderType::kSignedInt64:
case ShaderType::kUnsignedInt64:
case ShaderType::kAtomicCounter:
case ShaderType::kUnknown:
case ShaderType::kVoid:
case ShaderType::kHalfFloat:
case ShaderType::kDouble:
case ShaderType::kStruct:
case ShaderType::kImage:
case ShaderType::kSampledImage:
case ShaderType::kSampler:
VALIDATION_LOG << "Could not bind uniform buffer data for key: "
<< member.name << " : " << static_cast<int>(member.type);
return false; return false;
} }
} }

View File

@ -10,6 +10,7 @@
#include "flutter/third_party/abseil-cpp/absl/container/flat_hash_map.h" #include "flutter/third_party/abseil-cpp/absl/container/flat_hash_map.h"
#include "impeller/core/shader_types.h" #include "impeller/core/shader_types.h"
#include "impeller/renderer/backend/gles/device_buffer_gles.h"
#include "impeller/renderer/backend/gles/gles.h" #include "impeller/renderer/backend/gles/gles.h"
#include "impeller/renderer/backend/gles/proc_table_gles.h" #include "impeller/renderer/backend/gles/proc_table_gles.h"
#include "impeller/renderer/command.h" #include "impeller/renderer/command.h"
@ -65,18 +66,35 @@ class BufferBindingsGLES {
std::vector<std::vector<VertexAttribPointer>> vertex_attrib_arrays_; std::vector<std::vector<VertexAttribPointer>> vertex_attrib_arrays_;
absl::flat_hash_map<std::string, GLint> uniform_locations_; absl::flat_hash_map<std::string, GLint> uniform_locations_;
absl::flat_hash_map<std::string, std::pair<GLint, GLuint>> ubo_locations_;
using BindingMap = absl::flat_hash_map<std::string, std::vector<GLint>>; using BindingMap = absl::flat_hash_map<std::string, std::vector<GLint>>;
BindingMap binding_map_ = {}; BindingMap binding_map_ = {};
GLuint vertex_array_object_ = 0; GLuint vertex_array_object_ = 0;
GLuint program_handle_ = GL_NONE;
bool use_ubo_ = false;
const std::vector<GLint>& ComputeUniformLocations( const std::vector<GLint>& ComputeUniformLocations(
const ShaderMetadata* metadata); const ShaderMetadata* metadata);
bool ReadUniformsBindingsV2(const ProcTableGLES& gl, GLuint program);
bool ReadUniformsBindingsV3(const ProcTableGLES& gl, GLuint program);
GLint ComputeTextureLocation(const ShaderMetadata* metadata); GLint ComputeTextureLocation(const ShaderMetadata* metadata);
bool BindUniformBuffer(const ProcTableGLES& gl, const BufferResource& buffer); bool BindUniformBuffer(const ProcTableGLES& gl, const BufferResource& buffer);
bool BindUniformBufferV2(const ProcTableGLES& gl,
const BufferView& buffer,
const ShaderMetadata* metadata,
const DeviceBufferGLES& device_buffer_gles);
bool BindUniformBufferV3(const ProcTableGLES& gl,
const BufferView& buffer,
const ShaderMetadata* metadata,
const DeviceBufferGLES& device_buffer_gles);
std::optional<size_t> BindTextures( std::optional<size_t> BindTextures(
const ProcTableGLES& gl, const ProcTableGLES& gl,
const std::vector<TextureAndSampler>& bound_textures, const std::vector<TextureAndSampler>& bound_textures,

View File

@ -7,6 +7,8 @@
#include "impeller/base/config.h" #include "impeller/base/config.h"
#include "impeller/base/validation.h" #include "impeller/base/validation.h"
#include "impeller/base/version.h"
#include "impeller/core/runtime_types.h"
#include "impeller/renderer/backend/gles/command_buffer_gles.h" #include "impeller/renderer/backend/gles/command_buffer_gles.h"
#include "impeller/renderer/backend/gles/gpu_tracer_gles.h" #include "impeller/renderer/backend/gles/gpu_tracer_gles.h"
#include "impeller/renderer/backend/gles/handle_gles.h" #include "impeller/renderer/backend/gles/handle_gles.h"
@ -180,4 +182,13 @@ bool ContextGLES::AddTrackingFence(
return true; return true;
} }
// |Context|
RuntimeStageBackend ContextGLES::GetRuntimeStageBackend() const {
if (GetReactor()->GetProcTable().GetDescription()->GetGlVersion().IsAtLeast(
Version{3, 0, 0})) {
return RuntimeStageBackend::kOpenGLES3;
}
return RuntimeStageBackend::kOpenGLES;
}
} // namespace impeller } // namespace impeller

View File

@ -6,6 +6,7 @@
#define FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_CONTEXT_GLES_H_ #define FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_CONTEXT_GLES_H_
#include "impeller/base/backend_cast.h" #include "impeller/base/backend_cast.h"
#include "impeller/core/runtime_types.h"
#include "impeller/renderer/backend/gles/allocator_gles.h" #include "impeller/renderer/backend/gles/allocator_gles.h"
#include "impeller/renderer/backend/gles/capabilities_gles.h" #include "impeller/renderer/backend/gles/capabilities_gles.h"
#include "impeller/renderer/backend/gles/gpu_tracer_gles.h" #include "impeller/renderer/backend/gles/gpu_tracer_gles.h"
@ -106,6 +107,9 @@ class ContextGLES final : public Context,
// |Context| // |Context|
[[nodiscard]] bool FlushCommandBuffers() override; [[nodiscard]] bool FlushCommandBuffers() override;
// |Context|
RuntimeStageBackend GetRuntimeStageBackend() const override;
ContextGLES(const ContextGLES&) = delete; ContextGLES(const ContextGLES&) = delete;
ContextGLES& operator=(const ContextGLES&) = delete; ContextGLES& operator=(const ContextGLES&) = delete;

View File

@ -56,6 +56,10 @@ bool DeviceBufferGLES::OnCopyHostBuffer(const uint8_t* source,
return true; return true;
} }
std::optional<GLuint> DeviceBufferGLES::GetHandle() const {
return reactor_->GetGLHandle(handle_);
}
void DeviceBufferGLES::Flush(std::optional<Range> range) const { void DeviceBufferGLES::Flush(std::optional<Range> range) const {
if (!range.has_value()) { if (!range.has_value()) {
dirty_range_ = Range{ dirty_range_ = Range{
@ -75,6 +79,8 @@ static GLenum ToTarget(DeviceBufferGLES::BindingType type) {
return GL_ARRAY_BUFFER; return GL_ARRAY_BUFFER;
case DeviceBufferGLES::BindingType::kElementArrayBuffer: case DeviceBufferGLES::BindingType::kElementArrayBuffer:
return GL_ELEMENT_ARRAY_BUFFER; return GL_ELEMENT_ARRAY_BUFFER;
case DeviceBufferGLES::BindingType::kUniformBuffer:
return GL_UNIFORM_BUFFER;
} }
FML_UNREACHABLE(); FML_UNREACHABLE();
} }

View File

@ -34,12 +34,15 @@ class DeviceBufferGLES final
enum class BindingType { enum class BindingType {
kArrayBuffer, kArrayBuffer,
kElementArrayBuffer, kElementArrayBuffer,
kUniformBuffer,
}; };
[[nodiscard]] bool BindAndUploadDataIfNecessary(BindingType type) const; [[nodiscard]] bool BindAndUploadDataIfNecessary(BindingType type) const;
void Flush(std::optional<Range> range = std::nullopt) const override; void Flush(std::optional<Range> range = std::nullopt) const override;
std::optional<GLuint> GetHandle() const;
private: private:
ReactorGLES::Ref reactor_; ReactorGLES::Ref reactor_;
HandleGLES handle_; HandleGLES handle_;

View File

@ -6,7 +6,6 @@
#include <sstream> #include <sstream>
#include "fml/closure.h"
#include "impeller/base/allocation.h" #include "impeller/base/allocation.h"
#include "impeller/base/comparable.h" #include "impeller/base/comparable.h"
#include "impeller/base/strings.h" #include "impeller/base/strings.h"
@ -180,12 +179,12 @@ void ProcTableGLES::ShaderSourceMapping(
std::optional<std::string> ProcTableGLES::ComputeShaderWithDefines( std::optional<std::string> ProcTableGLES::ComputeShaderWithDefines(
const fml::Mapping& mapping, const fml::Mapping& mapping,
const std::vector<Scalar>& defines) const { const std::vector<Scalar>& defines) const {
auto shader_source = std::string{ std::string shader_source = std::string{
reinterpret_cast<const char*>(mapping.GetMapping()), mapping.GetSize()}; reinterpret_cast<const char*>(mapping.GetMapping()), mapping.GetSize()};
// Look for the first newline after the '#version' header, which impellerc // Look for the first newline after the '#version' header, which impellerc
// will always emit as the first line of a compiled shader. // will always emit as the first line of a compiled shader.
auto index = shader_source.find('\n'); size_t index = shader_source.find('\n');
if (index == std::string::npos) { if (index == std::string::npos) {
VALIDATION_LOG << "Failed to append constant data to shader"; VALIDATION_LOG << "Failed to append constant data to shader";
return std::nullopt; return std::nullopt;

View File

@ -241,6 +241,11 @@ void(glDepthRange)(GLdouble n, GLdouble f);
#define FOR_EACH_IMPELLER_GLES3_PROC(PROC) \ #define FOR_EACH_IMPELLER_GLES3_PROC(PROC) \
PROC(FenceSync); \ PROC(FenceSync); \
PROC(DeleteSync); \ PROC(DeleteSync); \
PROC(GetActiveUniformBlockiv); \
PROC(GetActiveUniformBlockName); \
PROC(GetUniformBlockIndex); \
PROC(UniformBlockBinding); \
PROC(BindBufferRange); \
PROC(WaitSync); \ PROC(WaitSync); \
PROC(BlitFramebuffer); PROC(BlitFramebuffer);

View File

@ -57,7 +57,6 @@ ShaderLibraryGLES::ShaderLibraryGLES(
) -> bool { ) -> bool {
const auto stage = ToShaderStage(type); const auto stage = ToShaderStage(type);
const auto key_name = GLESShaderNameToShaderKeyName(name, stage); const auto key_name = GLESShaderNameToShaderKeyName(name, stage);
functions[ShaderKey{key_name, stage}] = std::shared_ptr<ShaderFunctionGLES>( functions[ShaderKey{key_name, stage}] = std::shared_ptr<ShaderFunctionGLES>(
new ShaderFunctionGLES(library_id, // new ShaderFunctionGLES(library_id, //
stage, // stage, //

View File

@ -118,6 +118,9 @@ class ContextMTL final : public Context,
// |Context| // |Context|
const std::shared_ptr<const Capabilities>& GetCapabilities() const override; const std::shared_ptr<const Capabilities>& GetCapabilities() const override;
// |Context|
RuntimeStageBackend GetRuntimeStageBackend() const override;
void SetCapabilities(const std::shared_ptr<const Capabilities>& capabilities); void SetCapabilities(const std::shared_ptr<const Capabilities>& capabilities);
// |Context| // |Context|

View File

@ -13,6 +13,7 @@
#include "flutter/fml/paths.h" #include "flutter/fml/paths.h"
#include "flutter/fml/synchronization/sync_switch.h" #include "flutter/fml/synchronization/sync_switch.h"
#include "impeller/core/formats.h" #include "impeller/core/formats.h"
#include "impeller/core/runtime_types.h"
#include "impeller/core/sampler_descriptor.h" #include "impeller/core/sampler_descriptor.h"
#include "impeller/renderer/backend/metal/gpu_tracer_mtl.h" #include "impeller/renderer/backend/metal/gpu_tracer_mtl.h"
#include "impeller/renderer/backend/metal/sampler_library_mtl.h" #include "impeller/renderer/backend/metal/sampler_library_mtl.h"
@ -430,6 +431,11 @@ std::shared_ptr<CommandQueue> ContextMTL::GetCommandQueue() const {
return command_queue_ip_; return command_queue_ip_;
} }
// |Context|
RuntimeStageBackend ContextMTL::GetRuntimeStageBackend() const {
return RuntimeStageBackend::kMetal;
}
#ifdef IMPELLER_DEBUG #ifdef IMPELLER_DEBUG
const std::shared_ptr<ImpellerMetalCaptureManager> const std::shared_ptr<ImpellerMetalCaptureManager>
ContextMTL::GetCaptureManager() const { ContextMTL::GetCaptureManager() const {

View File

@ -8,6 +8,7 @@
#include "fml/concurrent_message_loop.h" #include "fml/concurrent_message_loop.h"
#include "impeller/core/formats.h" #include "impeller/core/formats.h"
#include "impeller/core/runtime_types.h"
#include "impeller/renderer/backend/vulkan/command_queue_vk.h" #include "impeller/renderer/backend/vulkan/command_queue_vk.h"
#include "impeller/renderer/backend/vulkan/descriptor_pool_vk.h" #include "impeller/renderer/backend/vulkan/descriptor_pool_vk.h"
#include "impeller/renderer/backend/vulkan/render_pass_builder_vk.h" #include "impeller/renderer/backend/vulkan/render_pass_builder_vk.h"
@ -721,4 +722,8 @@ bool ContextVK::GetShouldDisableSurfaceControlSwapchain() const {
return should_disable_surface_control_; return should_disable_surface_control_;
} }
RuntimeStageBackend ContextVK::GetRuntimeStageBackend() const {
return RuntimeStageBackend::kVulkan;
}
} // namespace impeller } // namespace impeller

View File

@ -13,6 +13,7 @@
#include "impeller/base/backend_cast.h" #include "impeller/base/backend_cast.h"
#include "impeller/base/strings.h" #include "impeller/base/strings.h"
#include "impeller/core/formats.h" #include "impeller/core/formats.h"
#include "impeller/core/runtime_types.h"
#include "impeller/renderer/backend/vulkan/command_pool_vk.h" #include "impeller/renderer/backend/vulkan/command_pool_vk.h"
#include "impeller/renderer/backend/vulkan/device_holder_vk.h" #include "impeller/renderer/backend/vulkan/device_holder_vk.h"
#include "impeller/renderer/backend/vulkan/driver_info_vk.h" #include "impeller/renderer/backend/vulkan/driver_info_vk.h"
@ -229,6 +230,8 @@ class ContextVK final : public Context,
// | Context | // | Context |
bool FlushCommandBuffers() override; bool FlushCommandBuffers() override;
RuntimeStageBackend GetRuntimeStageBackend() const override;
std::shared_ptr<const IdleWaiter> GetIdleWaiter() const override { std::shared_ptr<const IdleWaiter> GetIdleWaiter() const override {
return idle_waiter_vk_; return idle_waiter_vk_;
} }

View File

@ -5,6 +5,7 @@
#include "impeller/renderer/backend/vulkan/surface_context_vk.h" #include "impeller/renderer/backend/vulkan/surface_context_vk.h"
#include "flutter/fml/trace_event.h" #include "flutter/fml/trace_event.h"
#include "impeller/core/runtime_types.h"
#include "impeller/renderer/backend/vulkan/command_pool_vk.h" #include "impeller/renderer/backend/vulkan/command_pool_vk.h"
#include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h" #include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h"
@ -128,4 +129,8 @@ bool SurfaceContextVK::FlushCommandBuffers() {
return parent_->FlushCommandBuffers(); return parent_->FlushCommandBuffers();
} }
RuntimeStageBackend SurfaceContextVK::GetRuntimeStageBackend() const {
return parent_->GetRuntimeStageBackend();
}
} // namespace impeller } // namespace impeller

View File

@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include "impeller/base/backend_cast.h" #include "impeller/base/backend_cast.h"
#include "impeller/core/runtime_types.h"
#include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/backend/vulkan/vk.h"
#include "impeller/renderer/command_queue.h" #include "impeller/renderer/command_queue.h"
#include "impeller/renderer/context.h" #include "impeller/renderer/context.h"
@ -66,8 +67,12 @@ class SurfaceContextVK : public Context,
// |Context| // |Context|
std::shared_ptr<CommandQueue> GetCommandQueue() const override; std::shared_ptr<CommandQueue> GetCommandQueue() const override;
// |Context|
std::shared_ptr<const IdleWaiter> GetIdleWaiter() const override; std::shared_ptr<const IdleWaiter> GetIdleWaiter() const override;
// |Context|
RuntimeStageBackend GetRuntimeStageBackend() const override;
// |Context| // |Context|
void Shutdown() override; void Shutdown() override;

View File

@ -236,6 +236,12 @@ class Context {
/// ///
virtual void ResetThreadLocalState() const; virtual void ResetThreadLocalState() const;
/// @brief Retrieve the runtime stage for this context type.
///
/// This is used by the engine shell and other subsystems for loading the
/// correct shader types.
virtual RuntimeStageBackend GetRuntimeStageBackend() const = 0;
protected: protected:
Context(); Context();

View File

@ -7,6 +7,7 @@
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "impeller/core/allocator.h" #include "impeller/core/allocator.h"
#include "impeller/core/runtime_types.h"
#include "impeller/core/sampler_descriptor.h" #include "impeller/core/sampler_descriptor.h"
#include "impeller/core/texture.h" #include "impeller/core/texture.h"
#include "impeller/renderer/command_buffer.h" #include "impeller/renderer/command_buffer.h"
@ -184,6 +185,11 @@ class MockImpellerContext : public Context {
GetCommandQueue, GetCommandQueue,
(), (),
(const, override)); (const, override));
MOCK_METHOD(RuntimeStageBackend,
GetRuntimeStageBackend,
(),
(const, override));
}; };
class MockTexture : public Texture { class MockTexture : public Texture {

View File

@ -75,6 +75,8 @@ RuntimeStage::Map RuntimeStage::DecodeRuntimeStages(
RuntimeStageIfPresent(raw_stages->metal(), payload)}, RuntimeStageIfPresent(raw_stages->metal(), payload)},
{RuntimeStageBackend::kOpenGLES, {RuntimeStageBackend::kOpenGLES,
RuntimeStageIfPresent(raw_stages->opengles(), payload)}, RuntimeStageIfPresent(raw_stages->opengles(), payload)},
{RuntimeStageBackend::kOpenGLES3,
RuntimeStageIfPresent(raw_stages->opengles3(), payload)},
{RuntimeStageBackend::kVulkan, {RuntimeStageBackend::kVulkan,
RuntimeStageIfPresent(raw_stages->vulkan(), payload)}, RuntimeStageIfPresent(raw_stages->vulkan(), payload)},
}; };

View File

@ -83,5 +83,6 @@ table RuntimeStages {
sksl: RuntimeStage; sksl: RuntimeStage;
metal: RuntimeStage; metal: RuntimeStage;
opengles: RuntimeStage; opengles: RuntimeStage;
opengles3: RuntimeStage;
vulkan: RuntimeStage; vulkan: RuntimeStage;
} }

View File

@ -36,6 +36,7 @@ template("_impellerc") {
# --vulkan # --vulkan
# --runtime-stage-metal # --runtime-stage-metal
# --runtime-stage-gles # --runtime-stage-gles
# --runtime-stage-gles3
# --runtime-stage-vulkan # --runtime-stage-vulkan
# Not required for --shader_bundle mode. # Not required for --shader_bundle mode.
# Required: sl_file_extension The file extension to use for output files. # Required: sl_file_extension The file extension to use for output files.

View File

@ -97,6 +97,7 @@ template("impeller_shaders") {
analyze = false analyze = false
} }
gles_shaders = "gles_$target_name" gles_shaders = "gles_$target_name"
impeller_shaders_gles(gles_shaders) { impeller_shaders_gles(gles_shaders) {
name = invoker.name name = invoker.name
require_framebuffer_fetch = require_framebuffer_fetch require_framebuffer_fetch = require_framebuffer_fetch
@ -110,6 +111,22 @@ template("impeller_shaders") {
} }
analyze = analyze analyze = analyze
} }
gles3_shaders = "gles3_$target_name"
impeller_shaders_gles(gles3_shaders) {
name = invoker.name
require_framebuffer_fetch = require_framebuffer_fetch
gles_language_version = 300
is_300 = true
analyze = false
if (defined(invoker.gles_exclusions)) {
shaders = invoker.shaders - invoker.gles_exclusions
} else {
shaders = invoker.shaders
}
analyze = analyze
}
} }
if (impeller_enable_vulkan) { if (impeller_enable_vulkan) {
@ -139,7 +156,10 @@ template("impeller_shaders") {
} }
if (enable_opengles) { if (enable_opengles) {
public_deps += [ ":$gles_shaders" ] public_deps += [
":$gles3_shaders",
":$gles_shaders",
]
} }
if (impeller_enable_vulkan) { if (impeller_enable_vulkan) {

View File

@ -19,6 +19,8 @@ template("impeller_shaders_gles") {
require_framebuffer_fetch = invoker.require_framebuffer_fetch require_framebuffer_fetch = invoker.require_framebuffer_fetch
} }
is_300 = defined(invoker.is_300) && invoker.is_300
shaders_base_name = string_join("", shaders_base_name = string_join("",
[ [
invoker.name, invoker.name,
@ -35,11 +37,18 @@ template("impeller_shaders_gles") {
# Metal reflectors generate a superset of information. # Metal reflectors generate a superset of information.
if (impeller_enable_metal || impeller_enable_vulkan) { if (impeller_enable_metal || impeller_enable_vulkan) {
intermediates_subdir = "gles" if (is_300) {
intermediates_subdir = "gles3"
} else {
intermediates_subdir = "gles"
}
} }
shader_target_flags = [ "--opengl-es" ] shader_target_flags = [ "--opengl-es" ]
defines = [ "IMPELLER_TARGET_OPENGLES" ] defines = [ "IMPELLER_TARGET_OPENGLES" ]
if (is_300) {
defines += [ "IMPELLER_TARGET_OPENGLES3" ]
}
} }
gles_shaders = gles_shaders =
@ -68,13 +77,24 @@ template("impeller_shaders_gles") {
} }
embed_gles_lib = "embed_$target_name" embed_gles_lib = "embed_$target_name"
embed_blob(embed_gles_lib) { if (is_300) {
gles_library_files = get_target_outputs(":$gles_lib") embed_blob(embed_gles_lib) {
symbol_name = shaders_base_name gles_library_files = get_target_outputs(":$gles_lib")
blob = gles_library_files[0] symbol_name = shaders_base_name + "3"
hdr = "$target_gen_dir/gles/$shaders_base_name.h" blob = gles_library_files[0]
cc = "$target_gen_dir/gles/$shaders_base_name.cc" hdr = "$target_gen_dir/gles3/$shaders_base_name.h"
deps = [ ":$gles_lib" ] cc = "$target_gen_dir/gles3/$shaders_base_name.cc"
deps = [ ":$gles_lib" ]
}
} else {
embed_blob(embed_gles_lib) {
gles_library_files = get_target_outputs(":$gles_lib")
symbol_name = shaders_base_name
blob = gles_library_files[0]
hdr = "$target_gen_dir/gles/$shaders_base_name.h"
cc = "$target_gen_dir/gles/$shaders_base_name.cc"
deps = [ ":$gles_lib" ]
}
} }
group(target_name) { group(target_name) {

View File

@ -33,6 +33,8 @@ static std::string RuntimeStageBackendToString(
return "OpenGLES"; return "OpenGLES";
case impeller::RuntimeStageBackend::kVulkan: case impeller::RuntimeStageBackend::kVulkan:
return "Vulkan"; return "Vulkan";
case impeller::RuntimeStageBackend::kOpenGLES3:
return "OpenGLES3";
} }
} }

View File

@ -24,6 +24,7 @@
#include "flutter/testing/test_gl_surface.h" #include "flutter/testing/test_gl_surface.h"
#include "flutter/testing/testing.h" #include "flutter/testing/testing.h"
#include "fml/logging.h" #include "fml/logging.h"
#include "impeller/core/runtime_types.h"
#include "impeller/renderer/command_queue.h" #include "impeller/renderer/command_queue.h"
#include "third_party/skia/include/codec/SkCodecAnimation.h" #include "third_party/skia/include/codec/SkCodecAnimation.h"
#include "third_party/skia/include/core/SkData.h" #include "third_party/skia/include/core/SkData.h"
@ -96,6 +97,10 @@ class TestImpellerContext : public impeller::Context {
void Shutdown() override {} void Shutdown() override {}
RuntimeStageBackend GetRuntimeStageBackend() const override {
return RuntimeStageBackend::kVulkan;
}
bool DidDisposeResources() const { return did_dispose_; } bool DidDisposeResources() const { return did_dispose_; }
mutable size_t command_buffer_count_ = 0; mutable size_t command_buffer_count_ = 0;

View File

@ -29,7 +29,6 @@
#include "flutter/shell/common/skia_event_tracer_impl.h" #include "flutter/shell/common/skia_event_tracer_impl.h"
#include "flutter/shell/common/switches.h" #include "flutter/shell/common/switches.h"
#include "flutter/shell/common/vsync_waiter.h" #include "flutter/shell/common/vsync_waiter.h"
#include "impeller/runtime_stage/runtime_stage.h"
#include "rapidjson/stringbuffer.h" #include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h" #include "rapidjson/writer.h"
#include "third_party/dart/runtime/include/dart_tools_api.h" #include "third_party/dart/runtime/include/dart_tools_api.h"
@ -200,14 +199,7 @@ static impeller::RuntimeStageBackend DetermineRuntimeStageBackend(
if (!impeller_context) { if (!impeller_context) {
return impeller::RuntimeStageBackend::kSkSL; return impeller::RuntimeStageBackend::kSkSL;
} }
switch (impeller_context->GetBackendType()) { return impeller_context->GetRuntimeStageBackend();
case impeller::Context::BackendType::kMetal:
return impeller::RuntimeStageBackend::kMetal;
case impeller::Context::BackendType::kOpenGLES:
return impeller::RuntimeStageBackend::kOpenGLES;
case impeller::Context::BackendType::kVulkan:
return impeller::RuntimeStageBackend::kVulkan;
}
} }
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread( std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(

View File

@ -4876,7 +4876,7 @@ TEST_F(ShellTest, RuntimeStageBackendWithImpeller) {
EXPECT_EQ(backend, impeller::RuntimeStageBackend::kMetal); EXPECT_EQ(backend, impeller::RuntimeStageBackend::kMetal);
break; break;
case impeller::Context::BackendType::kOpenGLES: case impeller::Context::BackendType::kOpenGLES:
EXPECT_EQ(backend, impeller::RuntimeStageBackend::kOpenGLES); EXPECT_EQ(backend, impeller::RuntimeStageBackend::kOpenGLES3);
break; break;
case impeller::Context::BackendType::kVulkan: case impeller::Context::BackendType::kVulkan:
EXPECT_EQ(backend, impeller::RuntimeStageBackend::kVulkan); EXPECT_EQ(backend, impeller::RuntimeStageBackend::kVulkan);

View File

@ -11,6 +11,8 @@
#include "flutter/impeller/toolkit/egl/surface.h" #include "flutter/impeller/toolkit/egl/surface.h"
#include "impeller/entity/gles/entity_shaders_gles.h" #include "impeller/entity/gles/entity_shaders_gles.h"
#include "impeller/entity/gles/framebuffer_blend_shaders_gles.h" #include "impeller/entity/gles/framebuffer_blend_shaders_gles.h"
#include "impeller/entity/gles3/entity_shaders_gles.h"
#include "impeller/entity/gles3/framebuffer_blend_shaders_gles.h"
namespace flutter { namespace flutter {
@ -55,8 +57,10 @@ static std::shared_ptr<impeller::Context> CreateImpellerContext(
FML_LOG(ERROR) << "Could not create OpenGL proc table."; FML_LOG(ERROR) << "Could not create OpenGL proc table.";
return nullptr; return nullptr;
} }
bool is_gles3 = proc_table->GetDescription()->GetGlVersion().IsAtLeast(
impeller::Version{3, 0, 0});
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = { std::vector<std::shared_ptr<fml::Mapping>> gles2_shader_mappings = {
std::make_shared<fml::NonOwnedMapping>( std::make_shared<fml::NonOwnedMapping>(
impeller_entity_shaders_gles_data, impeller_entity_shaders_gles_data,
impeller_entity_shaders_gles_length), impeller_entity_shaders_gles_length),
@ -65,8 +69,19 @@ static std::shared_ptr<impeller::Context> CreateImpellerContext(
impeller_framebuffer_blend_shaders_gles_length), impeller_framebuffer_blend_shaders_gles_length),
}; };
std::vector<std::shared_ptr<fml::Mapping>> gles3_shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(
impeller_entity_shaders_gles3_data,
impeller_entity_shaders_gles3_length),
std::make_shared<fml::NonOwnedMapping>(
impeller_framebuffer_blend_shaders_gles3_data,
impeller_framebuffer_blend_shaders_gles3_length),
};
auto context = impeller::ContextGLES::Create( auto context = impeller::ContextGLES::Create(
std::move(proc_table), shader_mappings, enable_gpu_tracing); std::move(proc_table),
is_gles3 ? gles3_shader_mappings : gles2_shader_mappings,
enable_gpu_tracing);
if (!context) { if (!context) {
FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context."; FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context.";
return nullptr; return nullptr;

View File

@ -13,6 +13,7 @@
#include "fml/logging.h" #include "fml/logging.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "impeller/core/runtime_types.h"
#include "shell/platform/android/context/android_context.h" #include "shell/platform/android/context/android_context.h"
namespace flutter { namespace flutter {
@ -84,6 +85,10 @@ class TestImpellerContext : public impeller::Context {
void Shutdown() override { did_shutdown = true; } void Shutdown() override { did_shutdown = true; }
impeller::RuntimeStageBackend GetRuntimeStageBackend() const override {
return impeller::RuntimeStageBackend::kVulkan;
}
bool did_shutdown = false; bool did_shutdown = false;
}; };