diff --git a/impeller/renderer/backend/gles/buffer_bindings_gles.cc b/impeller/renderer/backend/gles/buffer_bindings_gles.cc index 65aa3ac26b6a9..9335f4c0b3b77 100644 --- a/impeller/renderer/backend/gles/buffer_bindings_gles.cc +++ b/impeller/renderer/backend/gles/buffer_bindings_gles.cc @@ -4,11 +4,9 @@ #include "impeller/renderer/backend/gles/buffer_bindings_gles.h" -#include #include #include -#include "impeller/base/config.h" #include "impeller/base/validation.h" #include "impeller/renderer/backend/gles/device_buffer_gles.h" #include "impeller/renderer/backend/gles/formats_gles.h" @@ -90,6 +88,9 @@ bool BufferBindingsGLES::ReadUniformsBindings(const ProcTableGLES& gl, GLint uniform_count = 0; gl.GetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniform_count); + + // Query the Program for all active uniform locations, and + // record this via normalized key. for (GLint i = 0; i < uniform_count; i++) { std::vector name; name.resize(max_name_size); @@ -139,11 +140,10 @@ bool BufferBindingsGLES::BindVertexAttributes(const ProcTableGLES& gl, return true; } -bool BufferBindingsGLES::BindUniformData( - const ProcTableGLES& gl, - Allocator& transients_allocator, - const Bindings& vertex_bindings, - const Bindings& fragment_bindings) const { +bool BufferBindingsGLES::BindUniformData(const ProcTableGLES& gl, + Allocator& transients_allocator, + const Bindings& vertex_bindings, + const Bindings& fragment_bindings) { for (const auto& buffer : vertex_bindings.buffers) { if (!BindUniformBuffer(gl, transients_allocator, buffer.second.view)) { return false; @@ -173,9 +173,58 @@ bool BufferBindingsGLES::UnbindVertexAttributes(const ProcTableGLES& gl) const { return true; } +GLint BufferBindingsGLES::ComputeTextureLocation( + const ShaderMetadata* metadata) { + auto location = binding_map_.find(metadata->name); + if (location != binding_map_.end()) { + return location->second[0]; + } + auto& locations = binding_map_[metadata->name] = {}; + auto computed_location = + uniform_locations_.find(CreateUniformMemberKey(metadata->name)); + if (computed_location == uniform_locations_.end()) { + locations.push_back(-1); + } else { + locations.push_back(computed_location->second); + } + return locations[0]; +} + +const std::vector& BufferBindingsGLES::ComputeUniformLocations( + const ShaderMetadata* metadata) { + auto location = binding_map_.find(metadata->name); + if (location != binding_map_.end()) { + return location->second; + } + + // For each metadata member, look up the binding location and record + // it in the binding map. + auto& locations = binding_map_[metadata->name] = {}; + for (const auto member : metadata->members) { + if (member.type == ShaderType::kVoid) { + // Void types are used for padding. We are obviously not going to find + // mappings for these. Keep going. + locations.push_back(-1); + continue; + } + + size_t element_count = member.array_elements.value_or(1); + const auto member_key = + CreateUniformMemberKey(metadata->name, member.name, element_count > 1); + const auto computed_location = uniform_locations_.find(member_key); + if (computed_location == uniform_locations_.end()) { + // Uniform was not active. + locations.push_back(-1); + continue; + } + locations.push_back(computed_location->second); + } + return locations; +} + bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl, Allocator& transients_allocator, - const BufferResource& buffer) const { + const BufferResource& buffer) { const auto* metadata = buffer.GetMetadata(); auto device_buffer = buffer.resource.buffer->GetDeviceBuffer(transients_allocator); @@ -194,35 +243,25 @@ bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl, return false; } - for (const auto& member : metadata->members) { - if (member.type == ShaderType::kVoid) { - // Void types are used for padding. We are obviously not going to find - // mappings for these. Keep going. + const auto& locations = ComputeUniformLocations(metadata); + for (auto i = 0u; i < metadata->members.size(); i++) { + const auto& member = metadata->members[i]; + auto location = locations[i]; + // Void type or inactive uniform. + if (location == -1) { continue; } size_t element_count = member.array_elements.value_or(1); - - const auto member_key = - CreateUniformMemberKey(metadata->name, member.name, element_count > 1); - const auto location = uniform_locations_.find(member_key); - if (location == uniform_locations_.end()) { - // The list of uniform locations only contains "active" uniforms that are - // not optimized out. So this situation is expected to happen when unused - // uniforms are present in the shader. - continue; - } - size_t element_stride = member.byte_length / element_count; - auto* buffer_data = reinterpret_cast(buffer_ptr + member.offset); std::vector array_element_buffer; if (element_count > 1) { - // When binding uniform arrays, the elements must be contiguous. Copy the - // uniforms to a temp buffer to eliminate any padding needed by the other - // backends. + // When binding uniform arrays, the elements must be contiguous. Copy + // the uniforms to a temp buffer to eliminate any padding needed by the + // other backends. array_element_buffer.resize(member.size * element_count); for (size_t element_i = 0; element_i < element_count; element_i++) { std::memcpy(array_element_buffer.data() + element_i * member.size, @@ -238,34 +277,34 @@ bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl, case ShaderType::kFloat: switch (member.size) { case sizeof(Matrix): - gl.UniformMatrix4fv(location->second, // location - element_count, // count - GL_FALSE, // normalize - buffer_data // data + gl.UniformMatrix4fv(location, // location + element_count, // count + GL_FALSE, // normalize + buffer_data // data ); continue; case sizeof(Vector4): - gl.Uniform4fv(location->second, // location - element_count, // count - buffer_data // data + gl.Uniform4fv(location, // location + element_count, // count + buffer_data // data ); continue; case sizeof(Vector3): - gl.Uniform3fv(location->second, // location - element_count, // count - buffer_data // data + gl.Uniform3fv(location, // location + element_count, // count + buffer_data // data ); continue; case sizeof(Vector2): - gl.Uniform2fv(location->second, // location - element_count, // count - buffer_data // data + gl.Uniform2fv(location, // location + element_count, // count + buffer_data // data ); continue; case sizeof(Scalar): - gl.Uniform1fv(location->second, // location - element_count, // count - buffer_data // data + gl.Uniform1fv(location, // location + element_count, // count + buffer_data // data ); continue; } @@ -288,7 +327,7 @@ bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl, case ShaderType::kSampledImage: case ShaderType::kSampler: VALIDATION_LOG << "Could not bind uniform buffer data for key: " - << member_key; + << member.name; return false; } } @@ -297,7 +336,7 @@ bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl, bool BufferBindingsGLES::BindTextures(const ProcTableGLES& gl, const Bindings& bindings, - ShaderStage stage) const { + ShaderStage stage) { size_t active_index = 0; for (const auto& data : bindings.sampled_images) { const auto& texture_gles = TextureGLES::Cast(*data.second.texture.resource); @@ -306,11 +345,8 @@ bool BufferBindingsGLES::BindTextures(const ProcTableGLES& gl, return false; } - const auto uniform_key = - CreateUniformMemberKey(data.second.texture.GetMetadata()->name); - auto uniform = uniform_locations_.find(uniform_key); - if (uniform == uniform_locations_.end()) { - VALIDATION_LOG << "Could not find uniform for key: " << uniform_key; + auto location = ComputeTextureLocation(data.second.texture.GetMetadata()); + if (location == -1) { return false; } @@ -343,7 +379,7 @@ bool BufferBindingsGLES::BindTextures(const ProcTableGLES& gl, //-------------------------------------------------------------------------- /// Set the texture uniform location. /// - gl.Uniform1i(uniform->second, active_index); + gl.Uniform1i(location, active_index); //-------------------------------------------------------------------------- /// Bump up the active index at binding. diff --git a/impeller/renderer/backend/gles/buffer_bindings_gles.h b/impeller/renderer/backend/gles/buffer_bindings_gles.h index b556364b9ea86..78b64c9434b94 100644 --- a/impeller/renderer/backend/gles/buffer_bindings_gles.h +++ b/impeller/renderer/backend/gles/buffer_bindings_gles.h @@ -4,14 +4,14 @@ #pragma once -#include +#include #include #include "flutter/fml/macros.h" +#include "impeller/core/shader_types.h" #include "impeller/renderer/backend/gles/gles.h" #include "impeller/renderer/backend/gles/proc_table_gles.h" #include "impeller/renderer/command.h" -#include "impeller/renderer/vertex_descriptor.h" namespace impeller { @@ -38,7 +38,7 @@ class BufferBindingsGLES { bool BindUniformData(const ProcTableGLES& gl, Allocator& transients_allocator, const Bindings& vertex_bindings, - const Bindings& fragment_bindings) const; + const Bindings& fragment_bindings); bool UnbindVertexAttributes(const ProcTableGLES& gl) const; @@ -55,15 +55,24 @@ class BufferBindingsGLES { GLsizei offset = 0u; }; std::vector vertex_attrib_arrays_; - std::map uniform_locations_; + + std::unordered_map uniform_locations_; + + using BindingMap = std::unordered_map>; + BindingMap binding_map_ = {}; + + const std::vector& ComputeUniformLocations( + const ShaderMetadata* metadata); + + GLint ComputeTextureLocation(const ShaderMetadata* metadata); bool BindUniformBuffer(const ProcTableGLES& gl, Allocator& transients_allocator, - const BufferResource& buffer) const; + const BufferResource& buffer); bool BindTextures(const ProcTableGLES& gl, const Bindings& bindings, - ShaderStage stage) const; + ShaderStage stage); FML_DISALLOW_COPY_AND_ASSIGN(BufferBindingsGLES); }; diff --git a/impeller/renderer/backend/gles/pipeline_gles.cc b/impeller/renderer/backend/gles/pipeline_gles.cc index 79efe7454d5ae..eb996613f5a5c 100644 --- a/impeller/renderer/backend/gles/pipeline_gles.cc +++ b/impeller/renderer/backend/gles/pipeline_gles.cc @@ -35,7 +35,7 @@ const HandleGLES& PipelineGLES::GetProgramHandle() const { return handle_; } -const BufferBindingsGLES* PipelineGLES::GetBufferBindings() const { +BufferBindingsGLES* PipelineGLES::GetBufferBindings() const { return buffer_bindings_.get(); } diff --git a/impeller/renderer/backend/gles/pipeline_gles.h b/impeller/renderer/backend/gles/pipeline_gles.h index 4097684a24717..53559fc7d878e 100644 --- a/impeller/renderer/backend/gles/pipeline_gles.h +++ b/impeller/renderer/backend/gles/pipeline_gles.h @@ -28,7 +28,7 @@ class PipelineGLES final [[nodiscard]] bool UnbindProgram() const; - const BufferBindingsGLES* GetBufferBindings() const; + BufferBindingsGLES* GetBufferBindings() const; [[nodiscard]] bool BuildVertexDescriptor(const ProcTableGLES& gl, GLuint program); diff --git a/impeller/renderer/backend/gles/render_pass_gles.cc b/impeller/renderer/backend/gles/render_pass_gles.cc index 5536a3cd6c40a..265fa1b492f76 100644 --- a/impeller/renderer/backend/gles/render_pass_gles.cc +++ b/impeller/renderer/backend/gles/render_pass_gles.cc @@ -374,7 +374,7 @@ struct RenderPassData { return false; } - const auto& vertex_desc_gles = pipeline.GetBufferBindings(); + auto vertex_desc_gles = pipeline.GetBufferBindings(); //-------------------------------------------------------------------------- /// Bind vertex and index buffers.