Flutter Impeller
impeller::BufferBindingsGLES Class Reference

Sets up stage bindings for single draw call in the OpenGLES backend. More...

#include <buffer_bindings_gles.h>

Public Member Functions

 BufferBindingsGLES ()
 
 ~BufferBindingsGLES ()
 
bool RegisterVertexStageInput (const ProcTableGLES &gl, const std::vector< ShaderStageIOSlot > &inputs, const std::vector< ShaderStageBufferLayout > &layouts)
 
bool ReadUniformsBindings (const ProcTableGLES &gl, GLuint program)
 
bool BindVertexAttributes (const ProcTableGLES &gl, size_t binding, size_t vertex_offset, size_t instance=0)
 
bool BindUniformData (const ProcTableGLES &gl, const std::vector< TextureAndSampler > &bound_textures, const std::vector< BufferResource > &bound_buffers, Range texture_range, Range buffer_range)
 
bool UnbindVertexAttributes (const ProcTableGLES &gl)
 

Detailed Description

Sets up stage bindings for single draw call in the OpenGLES backend.

Definition at line 30 of file buffer_bindings_gles.h.

Constructor & Destructor Documentation

◆ BufferBindingsGLES()

impeller::BufferBindingsGLES::BufferBindingsGLES ( )
default

◆ ~BufferBindingsGLES()

impeller::BufferBindingsGLES::~BufferBindingsGLES ( )
default

Member Function Documentation

◆ BindUniformData()

bool impeller::BufferBindingsGLES::BindUniformData ( const ProcTableGLES &  gl,
const std::vector< TextureAndSampler > &  bound_textures,
const std::vector< BufferResource > &  bound_buffers,
Range  texture_range,
Range  buffer_range 
)

Definition at line 261 of file buffer_bindings_gles.cc.

266  {
267  for (auto i = 0u; i < buffer_range.length; i++) {
268  if (!BindUniformBuffer(gl, bound_buffers[buffer_range.offset + i])) {
269  return false;
270  }
271  }
272  std::optional<size_t> next_unit_index =
273  BindTextures(gl, bound_textures, texture_range, ShaderStage::kVertex);
274  if (!next_unit_index.has_value()) {
275  return false;
276  }
277  if (!BindTextures(gl, bound_textures, texture_range, ShaderStage::kFragment,
278  *next_unit_index)
279  .has_value()) {
280  return false;
281  }
282 
283  return true;
284 }

References impeller::kFragment, impeller::kVertex, impeller::Range::length, and impeller::Range::offset.

Referenced by impeller::EncodeCommandsInReactor(), and impeller::testing::TEST().

◆ BindVertexAttributes()

bool impeller::BufferBindingsGLES::BindVertexAttributes ( const ProcTableGLES &  gl,
size_t  binding,
size_t  vertex_offset,
size_t  instance = 0 
)

Bind the vertex attributes for buffer slot [binding].

[instance] re-points instance-rate attributes at the given instance, used to emulate an instanced draw on drivers without hardware instancing support. It is 0 for a non-instanced or hardware-instanced draw.

Definition at line 197 of file buffer_bindings_gles.cc.

200  {
201  if (binding >= vertex_attrib_arrays_.size()) {
202  return false;
203  }
204 
205  // For an emulated instanced draw (instance > 0), a binding whose attributes
206  // are all vertex-rate (divisor 0) does not change across instances, so the
207  // state bound for instance 0 still applies. Skip the redundant re-binding.
208  if (instance > 0u) {
209  bool has_instance_rate = false;
210  for (const auto& array : vertex_attrib_arrays_[binding]) {
211  if (array.vertex_attrib_divisor != 0u) {
212  has_instance_rate = true;
213  break;
214  }
215  }
216  if (!has_instance_rate) {
217  return true;
218  }
219  }
220 
221  if (!gl.GetCapabilities()->IsES()) {
222  FML_DCHECK(vertex_array_object_ == 0);
223  gl.GenVertexArrays(1, &vertex_array_object_);
224  gl.BindVertexArray(vertex_array_object_);
225  }
226 
227  for (const auto& array : vertex_attrib_arrays_[binding]) {
228  gl.EnableVertexAttribArray(array.index);
229  // For an emulated instanced draw, an instance-rate attribute is
230  // re-pointed at instance `instance`, since there is no hardware divisor
231  // to advance it. A non-instanced or hardware-instanced draw passes
232  // instance 0 and lets the divisor (if any) do the stepping.
233  size_t attribute_offset = vertex_offset + array.offset;
234  if (array.vertex_attrib_divisor != 0u) {
235  attribute_offset += instance * static_cast<size_t>(array.stride);
236  }
237  gl.VertexAttribPointer(array.index, // index
238  array.size, // size (must be 1, 2, 3, or 4)
239  array.type, // type
240  array.normalized, // normalized
241  array.stride, // stride
242  reinterpret_cast<const GLvoid*>(
243  static_cast<uintptr_t>(attribute_offset)) // ptr
244  );
245  // Set the instancing divisor when the driver supports it. It is core
246  // on ES 3.0+ and comes from GL_EXT_instanced_arrays on ES 2.0. When
247  // unavailable, only per-vertex (divisor 0) bindings are possible,
248  // which is the default. Setting it for every attribute (including
249  // divisor 0) also clears any stale divisor left by a prior pipeline,
250  // which matters on ES, where there is no vertex array object.
251  if (gl.VertexAttribDivisor.IsAvailable()) {
252  gl.VertexAttribDivisor(array.index, array.vertex_attrib_divisor);
253  } else if (gl.VertexAttribDivisorEXT.IsAvailable()) {
254  gl.VertexAttribDivisorEXT(array.index, array.vertex_attrib_divisor);
255  }
256  }
257 
258  return true;
259 }

References impeller::ProcTableGLES::GetCapabilities().

Referenced by impeller::BindVertexBuffer(), and impeller::testing::TEST().

◆ ReadUniformsBindings()

bool impeller::BufferBindingsGLES::ReadUniformsBindings ( const ProcTableGLES &  gl,
GLuint  program 
)

Definition at line 104 of file buffer_bindings_gles.cc.

105  {
106  if (!gl.IsProgram(program)) {
107  return false;
108  }
109  program_handle_ = program;
110  if (gl.GetDescription()->GetGlVersion().IsAtLeast(Version{3, 0, 0})) {
111  return ReadUniformsBindingsV3(gl, program);
112  }
113  return ReadUniformsBindingsV2(gl, program);
114 }

References impeller::ProcTableGLES::GetDescription(), impeller::DescriptionGLES::GetGlVersion(), and impeller::Version::IsAtLeast().

◆ RegisterVertexStageInput()

bool impeller::BufferBindingsGLES::RegisterVertexStageInput ( const ProcTableGLES &  gl,
const std::vector< ShaderStageIOSlot > &  inputs,
const std::vector< ShaderStageBufferLayout > &  layouts 
)

Definition at line 32 of file buffer_bindings_gles.cc.

35  {
36  std::vector<std::vector<VertexAttribPointer>> vertex_attrib_arrays(
37  layouts.size());
38  // Every layout corresponds to a vertex binding.
39  // As we record, separate the attributes into buckets for each layout in
40  // ascending order. We do this because later on, we'll need to associate each
41  // of the attributes with bound buffers corresponding to the binding.
42  for (auto layout_i = 0u; layout_i < layouts.size(); layout_i++) {
43  const auto& layout = layouts[layout_i];
44  for (const auto& input : p_inputs) {
45  if (input.binding != layout_i) {
46  continue;
47  }
48  VertexAttribPointer attrib;
49  attrib.index = input.location;
50  // Component counts must be 1, 2, 3 or 4. Do that validation now.
51  if (input.vec_size < 1u || input.vec_size > 4u) {
52  return false;
53  }
54  attrib.size = input.vec_size;
55  auto type = ToVertexAttribType(input.GetVertexAttributeFormat());
56  if (!type.has_value()) {
57  return false;
58  }
59  attrib.type = type.value();
60  attrib.normalized = GL_FALSE;
61  attrib.offset = input.offset;
62  attrib.stride = layout.stride;
63  attrib.vertex_attrib_divisor =
64  layout.input_rate == VertexInputRate::kInstance ? 1u : 0u;
65  vertex_attrib_arrays[layout_i].push_back(attrib);
66  }
67  }
68  vertex_attrib_arrays_ = std::move(vertex_attrib_arrays);
69  return true;
70 }
@ kInstance
The binding is read once per instance.
constexpr std::optional< GLenum > ToVertexAttribType(VertexAttributeFormat type)
Definition: formats_gles.h:145

References impeller::kInstance, and impeller::ToVertexAttribType().

Referenced by impeller::testing::TEST().

◆ UnbindVertexAttributes()

bool impeller::BufferBindingsGLES::UnbindVertexAttributes ( const ProcTableGLES &  gl)

Definition at line 286 of file buffer_bindings_gles.cc.

286  {
287  for (const auto& array : vertex_attrib_arrays_) {
288  for (const auto& attribute : array) {
289  gl.DisableVertexAttribArray(attribute.index);
290  }
291  }
292  if (!gl.GetCapabilities()->IsES()) {
293  gl.DeleteVertexArrays(1, &vertex_array_object_);
294  vertex_array_object_ = 0;
295  }
296 
297  return true;
298 }

References impeller::ProcTableGLES::GetCapabilities().

Referenced by impeller::EncodeCommandsInReactor().


The documentation for this class was generated from the following files: