26 "ANGLEInputAttachment";
34 const std::vector<ShaderStageIOSlot>& p_inputs,
35 const std::vector<ShaderStageBufferLayout>& layouts) {
36 std::vector<std::vector<VertexAttribPointer>> vertex_attrib_arrays(
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) {
48 VertexAttribPointer attrib;
49 attrib.index =
input.location;
51 if (
input.vec_size < 1u ||
input.vec_size > 4u) {
54 attrib.size =
input.vec_size;
56 if (!
type.has_value()) {
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 =
65 vertex_attrib_arrays[layout_i].push_back(attrib);
68 vertex_attrib_arrays_ = std::move(vertex_attrib_arrays);
74 result.reserve(
key.length());
77 result.push_back(toupper(ch));
84 const std::string& member,
87 result.reserve(struct_name.length() + member.length() + (is_array ? 4 : 1));
88 result += struct_name;
89 if (!member.empty()) {
100 const std::string& non_struct_member) {
106 if (!gl.IsProgram(program)) {
109 program_handle_ = program;
111 return ReadUniformsBindingsV3(gl, program);
113 return ReadUniformsBindingsV2(gl, program);
116bool BufferBindingsGLES::ReadUniformsBindingsV3(
const ProcTableGLES& gl,
118 program_handle_ = program;
119 GLint uniform_blocks = 0;
120 gl.GetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &uniform_blocks);
121 for (GLint
i = 0;
i < uniform_blocks;
i++) {
122 GLint name_length = 0;
123 gl.GetActiveUniformBlockiv(program,
i, GL_UNIFORM_BLOCK_NAME_LENGTH,
126 std::vector<GLchar>
name;
127 name.resize(name_length);
129 gl.GetActiveUniformBlockName(program,
i, name_length, &
length,
name.data());
131 GLuint block_index = gl.GetUniformBlockIndex(program,
name.data());
132 gl.UniformBlockBinding(program_handle_, block_index,
i);
134 ubo_locations_[std::string{
name.data(),
static_cast<size_t>(
length)}] =
135 std::make_pair(block_index,
i);
138 return ReadUniformsBindingsV2(gl, program);
141bool BufferBindingsGLES::ReadUniformsBindingsV2(
const ProcTableGLES& gl,
143 GLint max_name_size = 0;
144 gl.GetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_size);
146 GLint uniform_count = 0;
147 gl.GetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniform_count);
151 for (GLint
i = 0;
i < uniform_count;
i++) {
152 std::vector<GLchar>
name;
153 name.resize(max_name_size);
154 GLsizei written_count = 0u;
155 GLint uniform_var_size = 0u;
156 GLenum uniform_type = GL_FLOAT;
160 gl.GetActiveUniform(program,
170 if (gl.GetCapabilities()->IsANGLE()) {
179 auto location = gl.GetUniformLocation(program,
name.data());
184 VALIDATION_LOG <<
"Could not query the location of an active uniform.";
187 if (written_count <= 0) {
188 VALIDATION_LOG <<
"Uniform name could not be read for active uniform.";
192 name.data(),
static_cast<size_t>(written_count)})] =
location;
199 size_t vertex_offset,
201 if (binding >= vertex_attrib_arrays_.size()) {
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;
216 if (!has_instance_rate) {
223 gl.GenVertexArrays(1, &vertex_array_object_);
224 gl.BindVertexArray(vertex_array_object_);
227 for (
const auto& array : vertex_attrib_arrays_[binding]) {
228 gl.EnableVertexAttribArray(array.index);
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);
237 gl.VertexAttribPointer(array.index,
242 reinterpret_cast<const GLvoid*
>(
243 static_cast<uintptr_t
>(attribute_offset))
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);
263 const std::vector<TextureAndSampler>& bound_textures,
264 const std::vector<BufferResource>& bound_buffers,
266 Range buffer_range) {
267 for (
auto i = 0u;
i < buffer_range.
length;
i++) {
268 if (!BindUniformBuffer(gl, bound_buffers[buffer_range.
offset +
i])) {
272 std::optional<size_t> next_unit_index =
274 if (!next_unit_index.has_value()) {
287 for (
const auto& array : vertex_attrib_arrays_) {
288 for (
const auto& attribute : array) {
289 gl.DisableVertexAttribArray(attribute.index);
293 gl.DeleteVertexArrays(1, &vertex_array_object_);
294 vertex_array_object_ = 0;
300GLint BufferBindingsGLES::ComputeTextureLocation(
303 if (
location != binding_map_.end()) {
306 auto& locations = binding_map_[metadata->
name] = {};
307 auto computed_location =
309 if (computed_location == uniform_locations_.end()) {
310 locations.push_back(-1);
312 locations.push_back(computed_location->second);
317const std::vector<GLint>& BufferBindingsGLES::ComputeUniformLocations(
318 const ShaderMetadata* metadata) {
319 BindingMap::iterator
location = binding_map_.find(metadata->name);
320 if (
location != binding_map_.end()) {
326 std::vector<GLint>& locations = binding_map_[metadata->name] = {};
327 locations.reserve(metadata->members.size());
328 for (
const ShaderStructMemberMetadata& member : metadata->members) {
332 locations.push_back(-1);
337 metadata->name, member.name, member.array_elements.has_value());
338 const absl::flat_hash_map<std::string, GLint>::iterator computed_location =
339 uniform_locations_.find(member_key);
340 if (computed_location == uniform_locations_.end()) {
342 locations.push_back(-1);
345 locations.push_back(computed_location->second);
350bool BufferBindingsGLES::BindUniformBuffer(
const ProcTableGLES& gl,
352 const ShaderMetadata* metadata =
buffer.GetMetadata();
353 const DeviceBuffer* device_buffer =
buffer.resource.GetBuffer();
354 if (!device_buffer) {
358 const DeviceBufferGLES& device_buffer_gles =
362 return BindUniformBufferV3(gl,
buffer.resource, metadata,
365 return BindUniformBufferV2(gl,
buffer.resource, metadata, device_buffer_gles);
368bool BufferBindingsGLES::BindUniformBufferV3(
369 const ProcTableGLES& gl,
370 const BufferView& buffer,
371 const ShaderMetadata* metadata,
372 const DeviceBufferGLES& device_buffer_gles) {
373 absl::flat_hash_map<std::string, std::pair<GLint, GLuint>>::iterator it =
374 ubo_locations_.find(metadata->name);
375 if (it == ubo_locations_.end()) {
379 return BindUniformBufferV2(gl, buffer, metadata, device_buffer_gles);
381 const auto& [block_index, binding_point] = it->second;
382 if (!device_buffer_gles.BindAndUploadDataIfNecessary(
386 auto handle = device_buffer_gles.GetHandle();
387 if (!handle.has_value()) {
390 gl.BindBufferRange(GL_UNIFORM_BUFFER, binding_point, handle.value(),
395bool BufferBindingsGLES::BindUniformBufferV2(
396 const ProcTableGLES& gl,
397 const BufferView& buffer,
398 const ShaderMetadata* metadata,
399 const DeviceBufferGLES& device_buffer_gles) {
400 const uint8_t* buffer_ptr =
401 device_buffer_gles.GetBufferData() +
buffer.GetRange().offset;
403 if (metadata->members.empty()) {
404 VALIDATION_LOG <<
"Uniform buffer had no members. This is currently "
405 "unsupported in the OpenGL ES backend. Use a uniform "
410 const std::vector<GLint>& locations = ComputeUniformLocations(metadata);
411 for (
size_t i = 0u;
i < metadata->members.size();
i++) {
412 const ShaderStructMemberMetadata& member = metadata->members[
i];
419 size_t element_count = member.array_elements.value_or(1);
420 size_t element_stride = member.byte_length / element_count;
422 reinterpret_cast<const GLfloat*
>(buffer_ptr + member.offset);
427 std::vector<uint8_t> array_element_buffer;
428 if (element_count > 1 && element_stride != member.size) {
429 array_element_buffer.resize(member.size * element_count);
430 for (
size_t element_i = 0; element_i < element_count; element_i++) {
431 std::memcpy(array_element_buffer.data() + element_i * member.size,
432 reinterpret_cast<const char*
>(buffer_data) +
433 element_i * element_stride,
437 reinterpret_cast<const GLfloat*
>(array_element_buffer.data());
441 VALIDATION_LOG <<
"Unsupported uniform data type for key: " << member.name
442 <<
", has type " <<
static_cast<int>(member.type)
443 <<
". Only float uniforms are supported.";
447 if (!member.float_type.has_value()) {
452 switch (member.float_type.value()) {
454 gl.Uniform1fv(
location, element_count, buffer_data);
457 gl.Uniform2fv(
location, element_count, buffer_data);
460 gl.Uniform3fv(
location, element_count, buffer_data);
463 gl.Uniform4fv(
location, element_count, buffer_data);
466 gl.UniformMatrix2fv(
location, element_count, GL_FALSE, buffer_data);
469 gl.UniformMatrix3fv(
location, element_count, GL_FALSE, buffer_data);
472 gl.UniformMatrix4fv(
location, element_count, GL_FALSE, buffer_data);
479std::optional<size_t> BufferBindingsGLES::BindTextures(
480 const ProcTableGLES& gl,
481 const std::vector<TextureAndSampler>& bound_textures,
484 size_t unit_start_index) {
485 size_t active_index = unit_start_index;
486 for (
auto i = 0u;
i < texture_range.length;
i++) {
487 const TextureAndSampler&
data = bound_textures[texture_range.offset +
i];
488 if (
data.stage != stage) {
492 if (
data.texture.GetMetadata() ==
nullptr) {
497 auto location = ComputeTextureLocation(
data.texture.GetMetadata());
506 if (active_index >= gl.GetCapabilities()->GetMaxTextureUnits(stage)) {
507 VALIDATION_LOG <<
"Texture units specified exceed the capabilities for "
508 "this shader stage.";
511 gl.ActiveTexture(GL_TEXTURE0 + active_index);
522 if (!
const_cast<TextureGLES&
>(texture_gles).
Bind()) {
531 if (!sampler_gles.ConfigureBoundTexture(texture_gles, gl)) {
538 gl.Uniform1i(
location, active_index);
static DeviceBufferGLES & Cast(DeviceBuffer &base)
bool BindVertexAttributes(const ProcTableGLES &gl, size_t binding, size_t vertex_offset, size_t instance=0)
bool ReadUniformsBindings(const ProcTableGLES &gl, GLuint program)
bool UnbindVertexAttributes(const ProcTableGLES &gl)
bool RegisterVertexStageInput(const ProcTableGLES &gl, const std::vector< ShaderStageIOSlot > &inputs, const std::vector< ShaderStageBufferLayout > &layouts)
bool BindUniformData(const ProcTableGLES &gl, const std::vector< TextureAndSampler > &bound_textures, const std::vector< BufferResource > &bound_buffers, Range texture_range, Range buffer_range)
Version GetGlVersion() const
const std::shared_ptr< const CapabilitiesGLES > & GetCapabilities() const
const DescriptionGLES * GetDescription() const
#define FML_DCHECK(condition)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
@ kInstance
The binding is read once per instance.
static std::string CreateUniformMemberKey(const std::string &struct_name, const std::string &member, bool is_array)
static constexpr std::string_view kAngleInputAttachmentPrefix
Resource< BufferView > BufferResource
static std::string NormalizeUniformKey(const std::string &key)
constexpr std::optional< GLenum > ToVertexAttribType(ShaderType type)
static bool Bind(PassBindingsCacheMTL &pass, ShaderStage stage, size_t bind_index, const BufferView &view)
impeller::ShaderType type
constexpr bool IsAtLeast(const Version &other) const