[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:
parent
f5325bf597
commit
2e80dbea2c
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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},
|
||||
};
|
||||
|
||||
|
@ -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:
|
||||
|
@ -34,6 +34,7 @@ enum class TargetPlatform {
|
||||
kVulkan,
|
||||
kRuntimeStageMetal,
|
||||
kRuntimeStageGLES,
|
||||
kRuntimeStageGLES3,
|
||||
kRuntimeStageVulkan,
|
||||
kSkSL,
|
||||
};
|
||||
|
@ -17,6 +17,7 @@ enum class RuntimeStageBackend {
|
||||
kSkSL,
|
||||
kMetal,
|
||||
kOpenGLES,
|
||||
kOpenGLES3,
|
||||
kVulkan,
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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, //
|
||||
|
@ -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|
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)},
|
||||
};
|
||||
|
@ -83,5 +83,6 @@ table RuntimeStages {
|
||||
sksl: RuntimeStage;
|
||||
metal: RuntimeStage;
|
||||
opengles: RuntimeStage;
|
||||
opengles3: RuntimeStage;
|
||||
vulkan: RuntimeStage;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -33,6 +33,8 @@ static std::string RuntimeStageBackendToString(
|
||||
return "OpenGLES";
|
||||
case impeller::RuntimeStageBackend::kVulkan:
|
||||
return "Vulkan";
|
||||
case impeller::RuntimeStageBackend::kOpenGLES3:
|
||||
return "OpenGLES3";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user