10 #include "flutter/fml/container.h"
11 #include "flutter/fml/trace_event.h"
12 #include "fml/closure.h"
20 : reactor_(
std::move(reactor)) {}
24 gl.GetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
25 if (log_length == 0) {
29 reinterpret_cast<char*
>(std::calloc(log_length,
sizeof(
char)));
30 gl.GetShaderInfoLog(shader, log_length, &log_length, log_buffer);
31 auto log_string = std::string(log_buffer, log_length);
32 std::free(log_buffer);
40 auto data =
static_cast<char*
>(malloc(10240));
42 gl.GetShaderSource(shader, 10240, &length,
data);
44 auto result = std::string{
data,
static_cast<size_t>(length)};
51 const std::string& name,
52 const fml::Mapping& source_mapping,
54 std::stringstream stream;
55 stream <<
"Failed to compile ";
70 stream <<
" shader for '" << name <<
"' with error:" << std::endl;
72 stream <<
"Shader source was: " << std::endl;
79 const std::shared_ptr<PipelineGLES>& pipeline,
80 const std::shared_ptr<const ShaderFunction>& vert_function,
81 const std::shared_ptr<const ShaderFunction>& frag_function) {
82 TRACE_EVENT0(
"impeller", __FUNCTION__);
84 const auto& descriptor = pipeline->GetDescriptor();
93 auto vert_shader = gl.CreateShader(GL_VERTEX_SHADER);
94 auto frag_shader = gl.CreateShader(GL_FRAGMENT_SHADER);
96 if (vert_shader == 0 || frag_shader == 0) {
102 SPrintF(
"%s Vertex Shader", descriptor.GetLabel().c_str()));
105 SPrintF(
"%s Fragment Shader", descriptor.GetLabel().c_str()));
107 fml::ScopedCleanupClosure delete_vert_shader(
108 [&gl, vert_shader]() { gl.DeleteShader(vert_shader); });
109 fml::ScopedCleanupClosure delete_frag_shader(
110 [&gl, frag_shader]() { gl.DeleteShader(frag_shader); });
112 gl.ShaderSourceMapping(vert_shader, *vert_mapping,
113 descriptor.GetSpecializationConstants());
114 gl.ShaderSourceMapping(frag_shader, *frag_mapping,
115 descriptor.GetSpecializationConstants());
117 gl.CompileShader(vert_shader);
118 gl.CompileShader(frag_shader);
120 GLint vert_status = GL_FALSE;
121 GLint frag_status = GL_FALSE;
123 gl.GetShaderiv(vert_shader, GL_COMPILE_STATUS, &vert_status);
124 gl.GetShaderiv(frag_shader, GL_COMPILE_STATUS, &frag_status);
126 if (vert_status != GL_TRUE) {
132 if (frag_status != GL_TRUE) {
138 auto program = reactor.
GetGLHandle(pipeline->GetProgramHandle());
139 if (!program.has_value()) {
144 gl.AttachShader(*program, vert_shader);
145 gl.AttachShader(*program, frag_shader);
147 fml::ScopedCleanupClosure detach_vert_shader(
148 [&gl, program = *program, vert_shader]() {
149 gl.DetachShader(program, vert_shader);
151 fml::ScopedCleanupClosure detach_frag_shader(
152 [&gl, program = *program, frag_shader]() {
153 gl.DetachShader(program, frag_shader);
156 for (
const auto& stage_input :
157 descriptor.GetVertexDescriptor()->GetStageInputs()) {
158 gl.BindAttribLocation(*program,
159 static_cast<GLuint
>(stage_input.location),
164 gl.LinkProgram(*program);
166 GLint link_status = GL_FALSE;
167 gl.GetProgramiv(*program, GL_LINK_STATUS, &link_status);
169 if (link_status != GL_TRUE) {
171 << gl.GetProgramInfoLogString(*program);
178 bool PipelineLibraryGLES::IsValid()
const {
179 return reactor_ !=
nullptr;
182 std::shared_ptr<PipelineGLES> PipelineLibraryGLES::CreatePipeline(
183 const std::weak_ptr<PipelineLibrary>& weak_library,
184 const PipelineDescriptor& desc,
185 const std::shared_ptr<const ShaderFunction>& vert_function,
186 const std::shared_ptr<const ShaderFunction>& frag_function) {
187 auto strong_library = weak_library.lock();
189 if (!strong_library) {
190 VALIDATION_LOG <<
"Library was collected before a pending pipeline "
191 "creation could finish.";
197 const auto& reactor = library.GetReactor();
203 auto program_key = ProgramKey{vert_function, frag_function,
204 desc.GetSpecializationConstants()};
206 auto cached_program = library.GetProgramForKey(program_key);
208 const auto has_cached_program = !!cached_program;
210 auto pipeline = std::shared_ptr<PipelineGLES>(
new PipelineGLES(
215 ? std::move(cached_program)
218 auto program = reactor->GetGLHandle(pipeline->GetProgramHandle());
220 if (!program.has_value()) {
225 const auto link_result = !has_cached_program ?
LinkProgram(*reactor,
237 if (!pipeline->BuildVertexDescriptor(reactor->GetProcTable(),
243 if (!pipeline->IsValid()) {
248 if (!has_cached_program) {
249 library.SetProgramForKey(program_key, pipeline->GetSharedHandle());
256 PipelineFuture<PipelineDescriptor> PipelineLibraryGLES::GetPipeline(
257 PipelineDescriptor descriptor,
259 if (
auto found = pipelines_.find(descriptor); found != pipelines_.end()) {
260 return found->second;
266 RealizedFuture<std::shared_ptr<Pipeline<PipelineDescriptor>>>(
nullptr)};
272 if (!vert_function || !frag_function) {
274 <<
"Could not find stage entrypoint functions in pipeline descriptor.";
277 RealizedFuture<std::shared_ptr<Pipeline<PipelineDescriptor>>>(
nullptr)};
280 auto promise = std::make_shared<
281 std::promise<std::shared_ptr<Pipeline<PipelineDescriptor>>>>();
282 auto pipeline_future =
283 PipelineFuture<PipelineDescriptor>{descriptor, promise->get_future()};
284 pipelines_[descriptor] = pipeline_future;
286 const auto result = reactor_->AddOperation([promise,
287 weak_this = weak_from_this(),
291 ](
const ReactorGLES& reactor) {
293 CreatePipeline(weak_this, descriptor, vert_function, frag_function));
297 return pipeline_future;
301 PipelineFuture<ComputePipelineDescriptor> PipelineLibraryGLES::GetPipeline(
302 ComputePipelineDescriptor descriptor,
304 auto promise = std::make_shared<
305 std::promise<std::shared_ptr<Pipeline<ComputePipelineDescriptor>>>>();
306 promise->set_value(
nullptr);
307 return {descriptor, promise->get_future()};
311 bool PipelineLibraryGLES::HasPipeline(
const PipelineDescriptor& descriptor) {
312 return pipelines_.find(descriptor) != pipelines_.end();
316 void PipelineLibraryGLES::RemovePipelinesWithEntryPoint(
317 std::shared_ptr<const ShaderFunction>
function) {
318 fml::erase_if(pipelines_, [&](
auto item) {
319 return item->first.GetEntrypointForStage(function->GetStage())
320 ->IsEqual(*
function);
331 std::shared_ptr<UniqueHandleGLES> PipelineLibraryGLES::GetProgramForKey(
332 const ProgramKey& key) {
333 Lock lock(programs_mutex_);
334 auto found = programs_.find(key);
335 if (found != programs_.end()) {
336 return found->second;
341 void PipelineLibraryGLES::SetProgramForKey(
342 const ProgramKey& key,
343 std::shared_ptr<UniqueHandleGLES> program) {
344 Lock lock(programs_mutex_);
345 programs_[key] = std::move(program);