10 #include "flutter/fml/container.h"
11 #include "flutter/fml/trace_event.h"
19 : reactor_(
std::move(reactor)) {}
23 gl.GetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
24 if (log_length == 0) {
28 reinterpret_cast<char*
>(std::calloc(log_length,
sizeof(
char)));
29 gl.GetShaderInfoLog(shader, log_length, &log_length, log_buffer);
30 auto log_string = std::string(log_buffer, log_length);
31 std::free(log_buffer);
37 const std::string& name,
38 const fml::Mapping& source_mapping,
40 std::stringstream stream;
41 stream <<
"Failed to compile ";
53 stream <<
"tessellation control";
56 stream <<
"tessellation evaluation";
62 stream <<
" shader for '" << name <<
"' with error:" << std::endl;
64 stream <<
"Shader source was: " << std::endl;
65 stream << std::string{
reinterpret_cast<const char*
>(
66 source_mapping.GetMapping()),
67 source_mapping.GetSize()}
74 const std::shared_ptr<PipelineGLES>& pipeline,
75 const std::shared_ptr<const ShaderFunction>& vert_function,
76 const std::shared_ptr<const ShaderFunction>& frag_function) {
77 TRACE_EVENT0(
"impeller", __FUNCTION__);
79 const auto& descriptor = pipeline->GetDescriptor();
88 auto vert_shader = gl.CreateShader(GL_VERTEX_SHADER);
89 auto frag_shader = gl.CreateShader(GL_FRAGMENT_SHADER);
91 if (vert_shader == 0 || frag_shader == 0) {
97 SPrintF(
"%s Vertex Shader", descriptor.GetLabel().c_str()));
100 SPrintF(
"%s Fragment Shader", descriptor.GetLabel().c_str()));
102 fml::ScopedCleanupClosure delete_vert_shader(
103 [&gl, vert_shader]() { gl.DeleteShader(vert_shader); });
104 fml::ScopedCleanupClosure delete_frag_shader(
105 [&gl, frag_shader]() { gl.DeleteShader(frag_shader); });
107 gl.ShaderSourceMapping(vert_shader, *vert_mapping);
108 gl.ShaderSourceMapping(frag_shader, *frag_mapping);
110 gl.CompileShader(vert_shader);
111 gl.CompileShader(frag_shader);
113 GLint vert_status = GL_FALSE;
114 GLint frag_status = GL_FALSE;
116 gl.GetShaderiv(vert_shader, GL_COMPILE_STATUS, &vert_status);
117 gl.GetShaderiv(frag_shader, GL_COMPILE_STATUS, &frag_status);
119 if (vert_status != GL_TRUE) {
125 if (frag_status != GL_TRUE) {
131 auto program = reactor.
GetGLHandle(pipeline->GetProgramHandle());
132 if (!program.has_value()) {
137 gl.AttachShader(*program, vert_shader);
138 gl.AttachShader(*program, frag_shader);
140 fml::ScopedCleanupClosure detach_vert_shader(
141 [&gl, program = *program, vert_shader]() {
142 gl.DetachShader(program, vert_shader);
144 fml::ScopedCleanupClosure detach_frag_shader(
145 [&gl, program = *program, frag_shader]() {
146 gl.DetachShader(program, frag_shader);
149 for (
const auto& stage_input :
150 descriptor.GetVertexDescriptor()->GetStageInputs()) {
151 gl.BindAttribLocation(*program,
152 static_cast<GLuint
>(stage_input.location),
157 gl.LinkProgram(*program);
159 GLint link_status = GL_FALSE;
160 gl.GetProgramiv(*program, GL_LINK_STATUS, &link_status);
162 if (link_status != GL_TRUE) {
164 << gl.GetProgramInfoLogString(*program);
171 bool PipelineLibraryGLES::IsValid()
const {
172 return reactor_ !=
nullptr;
176 PipelineFuture<PipelineDescriptor> PipelineLibraryGLES::GetPipeline(
177 PipelineDescriptor descriptor) {
178 if (
auto found = pipelines_.find(descriptor); found != pipelines_.end()) {
179 return found->second;
185 RealizedFuture<std::shared_ptr<Pipeline<PipelineDescriptor>>>(
nullptr)};
191 if (!vert_function || !frag_function) {
193 <<
"Could not find stage entrypoint functions in pipeline descriptor.";
196 RealizedFuture<std::shared_ptr<Pipeline<PipelineDescriptor>>>(
nullptr)};
199 auto promise = std::make_shared<
200 std::promise<std::shared_ptr<Pipeline<PipelineDescriptor>>>>();
201 auto pipeline_future =
202 PipelineFuture<PipelineDescriptor>{descriptor, promise->get_future()};
203 pipelines_[descriptor] = pipeline_future;
204 auto weak_this = weak_from_this();
206 auto result = reactor_->AddOperation(
207 [promise, weak_this, reactor_ptr = reactor_, descriptor, vert_function,
208 frag_function](
const ReactorGLES& reactor) {
209 auto strong_this = weak_this.lock();
211 promise->set_value(
nullptr);
212 VALIDATION_LOG <<
"Library was collected before a pending pipeline "
213 "creation could finish.";
216 auto pipeline = std::shared_ptr<PipelineGLES>(
217 new PipelineGLES(reactor_ptr, strong_this, descriptor));
218 auto program = reactor.GetGLHandle(pipeline->GetProgramHandle());
219 if (!program.has_value()) {
220 promise->set_value(
nullptr);
230 promise->set_value(
nullptr);
234 if (!pipeline->BuildVertexDescriptor(reactor.GetProcTable(),
236 promise->set_value(
nullptr);
240 if (!pipeline->IsValid()) {
241 promise->set_value(
nullptr);
245 promise->set_value(std::move(pipeline));
249 return pipeline_future;
253 PipelineFuture<ComputePipelineDescriptor> PipelineLibraryGLES::GetPipeline(
254 ComputePipelineDescriptor descriptor) {
255 auto promise = std::make_shared<
256 std::promise<std::shared_ptr<Pipeline<ComputePipelineDescriptor>>>>();
258 promise->set_value(
nullptr);
259 return {descriptor, promise->get_future()};
263 void PipelineLibraryGLES::RemovePipelinesWithEntryPoint(
264 std::shared_ptr<const ShaderFunction>
function) {
265 fml::erase_if(pipelines_, [&](
auto item) {
266 return item->first.GetEntrypointForStage(function->GetStage())
267 ->IsEqual(*
function);