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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,6 +8,8 @@
#include <vector>
#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/renderer/backend/gles/device_buffer_gles.h"
#include "impeller/renderer/backend/gles/formats_gles.h"
@ -101,6 +103,38 @@ bool BufferBindingsGLES::ReadUniformsBindings(const ProcTableGLES& gl,
if (!gl.IsProgram(program)) {
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;
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());
if (location == -1) {
if (use_ubo_) {
continue;
}
VALIDATION_LOG << "Could not query the location of an active uniform.";
return false;
}
@ -280,8 +317,47 @@ bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl,
}
const DeviceBufferGLES& device_buffer_gles =
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 =
device_buffer_gles.GetBufferData() + buffer.resource.GetRange().offset;
device_buffer_gles.GetBufferData() + buffer.GetRange().offset;
if (metadata->members.empty()) {
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());
}
switch (member.type) {
case ShaderType::kFloat:
switch (member.size) {
case sizeof(Matrix):
gl.UniformMatrix4fv(location, // location
element_count, // count
GL_FALSE, // normalize
buffer_data // data
);
continue;
case sizeof(Vector4):
gl.Uniform4fv(location, // location
element_count, // count
buffer_data // data
);
continue;
case sizeof(Vector3):
gl.Uniform3fv(location, // location
element_count, // count
buffer_data // data
);
continue;
case sizeof(Vector2):
gl.Uniform2fv(location, // location
element_count, // count
buffer_data // data
);
continue;
case sizeof(Scalar):
gl.Uniform1fv(location, // location
element_count, // count
buffer_data // data
);
continue;
}
VALIDATION_LOG << "Size " << member.size
<< " could not be mapped ShaderType::kFloat for key: "
<< member.name;
case ShaderType::kBoolean:
case ShaderType::kSignedByte:
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);
if (member.type != ShaderType::kFloat) {
VALIDATION_LOG << "Could not bind uniform buffer data for key: "
<< member.name << " : " << static_cast<int>(member.type);
return false;
}
switch (member.size) {
case sizeof(Matrix):
gl.UniformMatrix4fv(location, // location
element_count, // count
GL_FALSE, // normalize
buffer_data // data
);
continue;
case sizeof(Vector4):
gl.Uniform4fv(location, // location
element_count, // count
buffer_data // data
);
continue;
case sizeof(Vector3):
gl.Uniform3fv(location, // location
element_count, // count
buffer_data // data
);
continue;
case sizeof(Vector2):
gl.Uniform2fv(location, // location
element_count, // count
buffer_data // data
);
continue;
case sizeof(Scalar):
gl.Uniform1fv(location, // location
element_count, // count
buffer_data // data
);
continue;
default:
VALIDATION_LOG << "Invalid member size binding: " << member.size;
return false;
}
}

View File

@ -10,6 +10,7 @@
#include "flutter/third_party/abseil-cpp/absl/container/flat_hash_map.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/proc_table_gles.h"
#include "impeller/renderer/command.h"
@ -65,18 +66,35 @@ class BufferBindingsGLES {
std::vector<std::vector<VertexAttribPointer>> vertex_attrib_arrays_;
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>>;
BindingMap binding_map_ = {};
GLuint vertex_array_object_ = 0;
GLuint program_handle_ = GL_NONE;
bool use_ubo_ = false;
const std::vector<GLint>& ComputeUniformLocations(
const ShaderMetadata* metadata);
bool ReadUniformsBindingsV2(const ProcTableGLES& gl, GLuint program);
bool ReadUniformsBindingsV3(const ProcTableGLES& gl, GLuint program);
GLint ComputeTextureLocation(const ShaderMetadata* metadata);
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(
const ProcTableGLES& gl,
const std::vector<TextureAndSampler>& bound_textures,

View File

@ -7,6 +7,8 @@
#include "impeller/base/config.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/gpu_tracer_gles.h"
#include "impeller/renderer/backend/gles/handle_gles.h"
@ -180,4 +182,13 @@ bool ContextGLES::AddTrackingFence(
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

View File

@ -6,6 +6,7 @@
#define FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_CONTEXT_GLES_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/capabilities_gles.h"
#include "impeller/renderer/backend/gles/gpu_tracer_gles.h"
@ -106,6 +107,9 @@ class ContextGLES final : public Context,
// |Context|
[[nodiscard]] bool FlushCommandBuffers() override;
// |Context|
RuntimeStageBackend GetRuntimeStageBackend() const override;
ContextGLES(const ContextGLES&) = delete;
ContextGLES& operator=(const ContextGLES&) = delete;

View File

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

View File

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

View File

@ -6,7 +6,6 @@
#include <sstream>
#include "fml/closure.h"
#include "impeller/base/allocation.h"
#include "impeller/base/comparable.h"
#include "impeller/base/strings.h"
@ -180,12 +179,12 @@ void ProcTableGLES::ShaderSourceMapping(
std::optional<std::string> ProcTableGLES::ComputeShaderWithDefines(
const fml::Mapping& mapping,
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()};
// Look for the first newline after the '#version' header, which impellerc
// 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) {
VALIDATION_LOG << "Failed to append constant data to shader";
return std::nullopt;

View File

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

View File

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

View File

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

View File

@ -13,6 +13,7 @@
#include "flutter/fml/paths.h"
#include "flutter/fml/synchronization/sync_switch.h"
#include "impeller/core/formats.h"
#include "impeller/core/runtime_types.h"
#include "impeller/core/sampler_descriptor.h"
#include "impeller/renderer/backend/metal/gpu_tracer_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_;
}
// |Context|
RuntimeStageBackend ContextMTL::GetRuntimeStageBackend() const {
return RuntimeStageBackend::kMetal;
}
#ifdef IMPELLER_DEBUG
const std::shared_ptr<ImpellerMetalCaptureManager>
ContextMTL::GetCaptureManager() const {

View File

@ -8,6 +8,7 @@
#include "fml/concurrent_message_loop.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/descriptor_pool_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_;
}
RuntimeStageBackend ContextVK::GetRuntimeStageBackend() const {
return RuntimeStageBackend::kVulkan;
}
} // namespace impeller

View File

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

View File

@ -5,6 +5,7 @@
#include "impeller/renderer/backend/vulkan/surface_context_vk.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/context_vk.h"
#include "impeller/renderer/backend/vulkan/swapchain/khr/khr_swapchain_vk.h"
@ -128,4 +129,8 @@ bool SurfaceContextVK::FlushCommandBuffers() {
return parent_->FlushCommandBuffers();
}
RuntimeStageBackend SurfaceContextVK::GetRuntimeStageBackend() const {
return parent_->GetRuntimeStageBackend();
}
} // namespace impeller

View File

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

View File

@ -236,6 +236,12 @@ class Context {
///
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:
Context();

View File

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

View File

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

View File

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

View File

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

View File

@ -97,6 +97,7 @@ template("impeller_shaders") {
analyze = false
}
gles_shaders = "gles_$target_name"
impeller_shaders_gles(gles_shaders) {
name = invoker.name
require_framebuffer_fetch = require_framebuffer_fetch
@ -110,6 +111,22 @@ template("impeller_shaders") {
}
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) {
@ -139,7 +156,10 @@ template("impeller_shaders") {
}
if (enable_opengles) {
public_deps += [ ":$gles_shaders" ]
public_deps += [
":$gles3_shaders",
":$gles_shaders",
]
}
if (impeller_enable_vulkan) {

View File

@ -19,6 +19,8 @@ template("impeller_shaders_gles") {
require_framebuffer_fetch = invoker.require_framebuffer_fetch
}
is_300 = defined(invoker.is_300) && invoker.is_300
shaders_base_name = string_join("",
[
invoker.name,
@ -35,11 +37,18 @@ template("impeller_shaders_gles") {
# Metal reflectors generate a superset of information.
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" ]
defines = [ "IMPELLER_TARGET_OPENGLES" ]
if (is_300) {
defines += [ "IMPELLER_TARGET_OPENGLES3" ]
}
}
gles_shaders =
@ -68,13 +77,24 @@ template("impeller_shaders_gles") {
}
embed_gles_lib = "embed_$target_name"
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" ]
if (is_300) {
embed_blob(embed_gles_lib) {
gles_library_files = get_target_outputs(":$gles_lib")
symbol_name = shaders_base_name + "3"
blob = gles_library_files[0]
hdr = "$target_gen_dir/gles3/$shaders_base_name.h"
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) {

View File

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

View File

@ -24,6 +24,7 @@
#include "flutter/testing/test_gl_surface.h"
#include "flutter/testing/testing.h"
#include "fml/logging.h"
#include "impeller/core/runtime_types.h"
#include "impeller/renderer/command_queue.h"
#include "third_party/skia/include/codec/SkCodecAnimation.h"
#include "third_party/skia/include/core/SkData.h"
@ -96,6 +97,10 @@ class TestImpellerContext : public impeller::Context {
void Shutdown() override {}
RuntimeStageBackend GetRuntimeStageBackend() const override {
return RuntimeStageBackend::kVulkan;
}
bool DidDisposeResources() const { return did_dispose_; }
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/switches.h"
#include "flutter/shell/common/vsync_waiter.h"
#include "impeller/runtime_stage/runtime_stage.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
@ -200,14 +199,7 @@ static impeller::RuntimeStageBackend DetermineRuntimeStageBackend(
if (!impeller_context) {
return impeller::RuntimeStageBackend::kSkSL;
}
switch (impeller_context->GetBackendType()) {
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;
}
return impeller_context->GetRuntimeStageBackend();
}
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(

View File

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

View File

@ -11,6 +11,8 @@
#include "flutter/impeller/toolkit/egl/surface.h"
#include "impeller/entity/gles/entity_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 {
@ -55,8 +57,10 @@ static std::shared_ptr<impeller::Context> CreateImpellerContext(
FML_LOG(ERROR) << "Could not create OpenGL proc table.";
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>(
impeller_entity_shaders_gles_data,
impeller_entity_shaders_gles_length),
@ -65,8 +69,19 @@ static std::shared_ptr<impeller::Context> CreateImpellerContext(
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(
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) {
FML_LOG(ERROR) << "Could not create OpenGLES Impeller Context.";
return nullptr;

View File

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