Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
138 changes: 87 additions & 51 deletions impeller/renderer/backend/gles/buffer_bindings_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@

#include "impeller/renderer/backend/gles/buffer_bindings_gles.h"

#include <algorithm>
#include <cstring>
#include <vector>

#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"
Expand Down Expand Up @@ -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<GLchar> name;
name.resize(max_name_size);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<GLint>& 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);
Expand All @@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preserve the comment about inactive uniformed being optimized out?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see it up top. Maybe just "void type or inactive".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

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<const GLfloat*>(buffer_ptr + member.offset);

std::vector<uint8_t> 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,
Expand All @@ -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;
}
Expand All @@ -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;
}
}
Expand All @@ -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);
Expand All @@ -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;
}

Expand Down Expand Up @@ -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.
Expand Down
21 changes: 15 additions & 6 deletions impeller/renderer/backend/gles/buffer_bindings_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

#pragma once

#include <map>
#include <unordered_map>
#include <vector>

#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 {

Expand All @@ -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;

Expand All @@ -55,15 +55,24 @@ class BufferBindingsGLES {
GLsizei offset = 0u;
};
std::vector<VertexAttribPointer> vertex_attrib_arrays_;
std::map<std::string, GLint> uniform_locations_;

std::unordered_map<std::string, GLint> uniform_locations_;

using BindingMap = std::unordered_map<std::string, std::vector<GLint>>;
BindingMap binding_map_ = {};

const std::vector<GLint>& 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);
};
Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/backend/gles/pipeline_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const HandleGLES& PipelineGLES::GetProgramHandle() const {
return handle_;
}

const BufferBindingsGLES* PipelineGLES::GetBufferBindings() const {
BufferBindingsGLES* PipelineGLES::GetBufferBindings() const {
return buffer_bindings_.get();
}

Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/backend/gles/pipeline_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/backend/gles/render_pass_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down