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);
116 bool 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);
141 bool 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) {
222 FML_DCHECK(vertex_array_object_ == 0);
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;
300 GLint 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);
317 const 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);
350 bool 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);
368 bool 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(),
391 buffer.GetRange().offset, buffer.GetRange().length);
395 bool 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);
479 std::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
@ 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
constexpr std::optional< GLenum > ToVertexAttribType(VertexAttributeFormat type)
Resource< BufferView > BufferResource
static std::string NormalizeUniformKey(const std::string &key)
static bool Bind(PassBindingsCacheMTL &pass, ShaderStage stage, size_t bind_index, const BufferView &view)
constexpr bool IsAtLeast(const Version &other) const