25 "ANGLEInputAttachment";
33 const std::vector<ShaderStageIOSlot>& p_inputs,
34 const std::vector<ShaderStageBufferLayout>& layouts) {
35 std::vector<std::vector<VertexAttribPointer>> vertex_attrib_arrays(
41 for (
auto layout_i = 0u; layout_i < layouts.size(); layout_i++) {
42 const auto& layout = layouts[layout_i];
43 for (
const auto& input : p_inputs) {
44 if (input.binding != layout_i) {
47 VertexAttribPointer attrib;
48 attrib.index = input.location;
50 if (input.vec_size < 1u || input.vec_size > 4u) {
53 attrib.size = input.vec_size;
55 if (!type.has_value()) {
58 attrib.type = type.value();
59 attrib.normalized = GL_FALSE;
60 attrib.offset = input.offset;
61 attrib.stride = layout.stride;
62 vertex_attrib_arrays[layout_i].push_back(attrib);
65 vertex_attrib_arrays_ = std::move(vertex_attrib_arrays);
71 result.reserve(key.length());
74 result.push_back(toupper(ch));
81 const std::string& member,
84 result.reserve(struct_name.length() + member.length() + (is_array ? 4 : 1));
85 result += struct_name;
86 if (!member.empty()) {
97 const std::string& non_struct_member) {
103 if (!gl.IsProgram(program)) {
106 program_handle_ = program;
108 return ReadUniformsBindingsV3(gl, program);
110 return ReadUniformsBindingsV2(gl, program);
113 bool BufferBindingsGLES::ReadUniformsBindingsV3(
const ProcTableGLES& gl,
115 program_handle_ = program;
116 GLint uniform_blocks = 0;
117 gl.GetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &uniform_blocks);
118 for (GLint i = 0; i < uniform_blocks; i++) {
119 GLint name_length = 0;
120 gl.GetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_NAME_LENGTH,
123 std::vector<GLchar> name;
124 name.resize(name_length);
126 gl.GetActiveUniformBlockName(program, i, name_length, &length, name.data());
128 GLuint block_index = gl.GetUniformBlockIndex(program, name.data());
129 gl.UniformBlockBinding(program_handle_, block_index, i);
131 ubo_locations_[std::string{name.data(),
static_cast<size_t>(length)}] =
132 std::make_pair(block_index, i);
135 return ReadUniformsBindingsV2(gl, program);
138 bool BufferBindingsGLES::ReadUniformsBindingsV2(
const ProcTableGLES& gl,
140 GLint max_name_size = 0;
141 gl.GetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_size);
143 GLint uniform_count = 0;
144 gl.GetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniform_count);
148 for (GLint i = 0; i < uniform_count; i++) {
149 std::vector<GLchar> name;
150 name.resize(max_name_size);
151 GLsizei written_count = 0u;
152 GLint uniform_var_size = 0u;
153 GLenum uniform_type = GL_FLOAT;
157 gl.GetActiveUniform(program,
167 if (gl.GetCapabilities()->IsANGLE()) {
176 auto location = gl.GetUniformLocation(program, name.data());
181 VALIDATION_LOG <<
"Could not query the location of an active uniform.";
184 if (written_count <= 0) {
185 VALIDATION_LOG <<
"Uniform name could not be read for active uniform.";
189 name.data(),
static_cast<size_t>(written_count)})] =
location;
196 size_t vertex_offset) {
197 if (binding >= vertex_attrib_arrays_.size()) {
202 FML_DCHECK(vertex_array_object_ == 0);
203 gl.GenVertexArrays(1, &vertex_array_object_);
204 gl.BindVertexArray(vertex_array_object_);
207 for (
const auto& array : vertex_attrib_arrays_[binding]) {
208 gl.EnableVertexAttribArray(array.index);
209 gl.VertexAttribPointer(array.index,
214 reinterpret_cast<const GLvoid*
>(
static_cast<GLsizei
>(
215 vertex_offset + array.offset))
224 const std::vector<TextureAndSampler>& bound_textures,
225 const std::vector<BufferResource>& bound_buffers,
227 Range buffer_range) {
228 for (
auto i = 0u; i < buffer_range.
length; i++) {
229 if (!BindUniformBuffer(gl, bound_buffers[buffer_range.
offset + i])) {
233 std::optional<size_t> next_unit_index =
235 if (!next_unit_index.has_value()) {
248 for (
const auto& array : vertex_attrib_arrays_) {
249 for (
const auto& attribute : array) {
250 gl.DisableVertexAttribArray(attribute.index);
254 gl.DeleteVertexArrays(1, &vertex_array_object_);
255 vertex_array_object_ = 0;
261 GLint BufferBindingsGLES::ComputeTextureLocation(
264 if (
location != binding_map_.end()) {
267 auto& locations = binding_map_[metadata->
name] = {};
268 auto computed_location =
270 if (computed_location == uniform_locations_.end()) {
271 locations.push_back(-1);
273 locations.push_back(computed_location->second);
278 const std::vector<GLint>& BufferBindingsGLES::ComputeUniformLocations(
279 const ShaderMetadata* metadata) {
280 BindingMap::iterator
location = binding_map_.find(metadata->name);
281 if (
location != binding_map_.end()) {
287 std::vector<GLint>& locations = binding_map_[metadata->name] = {};
288 locations.reserve(metadata->members.size());
289 for (
const ShaderStructMemberMetadata& member : metadata->members) {
293 locations.push_back(-1);
298 metadata->name, member.name, member.array_elements.has_value());
299 const absl::flat_hash_map<std::string, GLint>::iterator computed_location =
300 uniform_locations_.find(member_key);
301 if (computed_location == uniform_locations_.end()) {
303 locations.push_back(-1);
306 locations.push_back(computed_location->second);
311 bool BufferBindingsGLES::BindUniformBuffer(
const ProcTableGLES& gl,
313 const ShaderMetadata* metadata = buffer.GetMetadata();
314 const DeviceBuffer* device_buffer = buffer.resource.GetBuffer();
315 if (!device_buffer) {
319 const DeviceBufferGLES& device_buffer_gles =
323 return BindUniformBufferV3(gl, buffer.resource, metadata,
326 return BindUniformBufferV2(gl, buffer.resource, metadata, device_buffer_gles);
329 bool BufferBindingsGLES::BindUniformBufferV3(
330 const ProcTableGLES& gl,
331 const BufferView& buffer,
332 const ShaderMetadata* metadata,
333 const DeviceBufferGLES& device_buffer_gles) {
334 absl::flat_hash_map<std::string, std::pair<GLint, GLuint>>::iterator it =
335 ubo_locations_.find(metadata->name);
336 if (it == ubo_locations_.end()) {
340 return BindUniformBufferV2(gl, buffer, metadata, device_buffer_gles);
342 const auto& [block_index, binding_point] = it->second;
343 if (!device_buffer_gles.BindAndUploadDataIfNecessary(
347 auto handle = device_buffer_gles.GetHandle();
348 if (!handle.has_value()) {
351 gl.BindBufferRange(GL_UNIFORM_BUFFER, binding_point, handle.value(),
352 buffer.GetRange().offset, buffer.GetRange().length);
356 bool BufferBindingsGLES::BindUniformBufferV2(
357 const ProcTableGLES& gl,
358 const BufferView& buffer,
359 const ShaderMetadata* metadata,
360 const DeviceBufferGLES& device_buffer_gles) {
361 const uint8_t* buffer_ptr =
362 device_buffer_gles.GetBufferData() + buffer.GetRange().offset;
364 if (metadata->members.empty()) {
365 VALIDATION_LOG <<
"Uniform buffer had no members. This is currently "
366 "unsupported in the OpenGL ES backend. Use a uniform "
371 const std::vector<GLint>& locations = ComputeUniformLocations(metadata);
372 for (
size_t i = 0u; i < metadata->members.size(); i++) {
373 const ShaderStructMemberMetadata& member = metadata->members[i];
380 size_t element_count = member.array_elements.value_or(1);
381 size_t element_stride = member.byte_length / element_count;
383 reinterpret_cast<const GLfloat*
>(buffer_ptr + member.offset);
388 std::vector<uint8_t> array_element_buffer;
389 if (element_count > 1 && element_stride != member.size) {
390 array_element_buffer.resize(member.size * element_count);
391 for (
size_t element_i = 0; element_i < element_count; element_i++) {
392 std::memcpy(array_element_buffer.data() + element_i * member.size,
393 reinterpret_cast<const char*
>(buffer_data) +
394 element_i * element_stride,
398 reinterpret_cast<const GLfloat*
>(array_element_buffer.data());
402 VALIDATION_LOG <<
"Unsupported uniform data type for key: " << member.name
403 <<
", has type " <<
static_cast<int>(member.type)
404 <<
". Only float uniforms are supported.";
408 if (!member.float_type.has_value()) {
413 switch (member.float_type.value()) {
415 gl.Uniform1fv(
location, element_count, buffer_data);
418 gl.Uniform2fv(
location, element_count, buffer_data);
421 gl.Uniform3fv(
location, element_count, buffer_data);
424 gl.Uniform4fv(
location, element_count, buffer_data);
427 gl.UniformMatrix2fv(
location, element_count, GL_FALSE, buffer_data);
430 gl.UniformMatrix3fv(
location, element_count, GL_FALSE, buffer_data);
433 gl.UniformMatrix4fv(
location, element_count, GL_FALSE, buffer_data);
440 std::optional<size_t> BufferBindingsGLES::BindTextures(
441 const ProcTableGLES& gl,
442 const std::vector<TextureAndSampler>& bound_textures,
445 size_t unit_start_index) {
446 size_t active_index = unit_start_index;
447 for (
auto i = 0u; i < texture_range.length; i++) {
448 const TextureAndSampler& data = bound_textures[texture_range.offset + i];
449 if (data.stage != stage) {
453 if (data.texture.GetMetadata() ==
nullptr) {
458 auto location = ComputeTextureLocation(data.texture.GetMetadata());
467 if (active_index >= gl.GetCapabilities()->GetMaxTextureUnits(stage)) {
468 VALIDATION_LOG <<
"Texture units specified exceed the capabilities for "
469 "this shader stage.";
472 gl.ActiveTexture(GL_TEXTURE0 + active_index);
477 if (!texture_gles.Bind()) {
486 if (!sampler_gles.ConfigureBoundTexture(texture_gles, gl)) {
493 gl.Uniform1i(
location, active_index);
static DeviceBufferGLES & Cast(DeviceBuffer &base)
bool BindVertexAttributes(const ProcTableGLES &gl, size_t binding, size_t vertex_offset)
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
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
constexpr std::optional< GLenum > ToVertexAttribType(ShaderType type)
static std::string NormalizeUniformKey(const std::string &key)
constexpr bool IsAtLeast(const Version &other) const