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());
177 if (location == -1) {
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(
263 auto location = binding_map_.find(metadata->
name);
264 if (location != binding_map_.end()) {
265 return location->second[0];
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()) {
282 return location->second;
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);
297 size_t element_count = member.array_elements.value_or(1);
298 const std::string member_key =
300 const absl::flat_hash_map<std::string, GLint>::iterator computed_location =
301 uniform_locations_.find(member_key);
302 if (computed_location == uniform_locations_.end()) {
304 locations.push_back(-1);
307 locations.push_back(computed_location->second);
312 bool BufferBindingsGLES::BindUniformBuffer(
const ProcTableGLES& gl,
314 const ShaderMetadata* metadata = buffer.GetMetadata();
315 const DeviceBuffer* device_buffer = buffer.resource.GetBuffer();
316 if (!device_buffer) {
320 const DeviceBufferGLES& device_buffer_gles =
324 return BindUniformBufferV3(gl, buffer.resource, metadata,
327 return BindUniformBufferV2(gl, buffer.resource, metadata, device_buffer_gles);
330 bool BufferBindingsGLES::BindUniformBufferV3(
331 const ProcTableGLES& gl,
332 const BufferView& buffer,
333 const ShaderMetadata* metadata,
334 const DeviceBufferGLES& device_buffer_gles) {
335 absl::flat_hash_map<std::string, std::pair<GLint, GLuint>>::iterator it =
336 ubo_locations_.find(metadata->name);
337 if (it == ubo_locations_.end()) {
338 return BindUniformBufferV2(gl, buffer, metadata, device_buffer_gles);
340 const auto& [block_index, binding_point] = it->second;
341 if (!device_buffer_gles.BindAndUploadDataIfNecessary(
345 auto handle = device_buffer_gles.GetHandle();
346 if (!handle.has_value()) {
349 gl.BindBufferRange(GL_UNIFORM_BUFFER, binding_point, handle.value(),
350 buffer.GetRange().offset, buffer.GetRange().length);
354 bool BufferBindingsGLES::BindUniformBufferV2(
355 const ProcTableGLES& gl,
356 const BufferView& buffer,
357 const ShaderMetadata* metadata,
358 const DeviceBufferGLES& device_buffer_gles) {
359 const uint8_t* buffer_ptr =
360 device_buffer_gles.GetBufferData() + buffer.GetRange().offset;
362 if (metadata->members.empty()) {
363 VALIDATION_LOG <<
"Uniform buffer had no members. This is currently "
364 "unsupported in the OpenGL ES backend. Use a uniform "
369 const std::vector<GLint>& locations = ComputeUniformLocations(metadata);
370 for (
size_t i = 0u; i < metadata->members.size(); i++) {
371 const ShaderStructMemberMetadata& member = metadata->members[i];
372 GLint location = locations[i];
385 size_t element_count = member.array_elements.value_or(1);
386 if (element_count == 0) {
389 size_t element_stride = member.byte_length / element_count;
391 reinterpret_cast<const GLfloat*
>(buffer_ptr + member.offset);
396 std::vector<uint8_t> array_element_buffer;
397 if (element_count > 1 && element_stride != member.size) {
398 array_element_buffer.resize(member.size * element_count);
399 for (
size_t element_i = 0; element_i < element_count; element_i++) {
400 std::memcpy(array_element_buffer.data() + element_i * member.size,
401 reinterpret_cast<const char*
>(buffer_data) +
402 element_i * element_stride,
406 reinterpret_cast<const GLfloat*
>(array_element_buffer.data());
411 << member.name <<
" : " <<
static_cast<int>(member.type);
415 switch (member.size) {
417 gl.UniformMatrix4fv(location,
423 case sizeof(Vector4):
424 gl.Uniform4fv(location,
429 case sizeof(Vector3):
430 gl.Uniform3fv(location,
436 gl.Uniform2fv(location,
442 gl.Uniform1fv(location,
455 std::optional<size_t> BufferBindingsGLES::BindTextures(
456 const ProcTableGLES& gl,
457 const std::vector<TextureAndSampler>& bound_textures,
460 size_t unit_start_index) {
461 size_t active_index = unit_start_index;
462 for (
auto i = 0u; i < texture_range.length; i++) {
463 const TextureAndSampler&
data = bound_textures[texture_range.offset + i];
464 if (
data.stage != stage) {
468 if (
data.texture.GetMetadata() ==
nullptr) {
473 auto location = ComputeTextureLocation(
data.texture.GetMetadata());
474 if (location == -1) {
482 if (active_index >= gl.GetCapabilities()->GetMaxTextureUnits(stage)) {
483 VALIDATION_LOG <<
"Texture units specified exceed the capabilities for "
484 "this shader stage.";
487 gl.ActiveTexture(GL_TEXTURE0 + active_index);
492 if (!texture_gles.Bind()) {
501 if (!sampler_gles.ConfigureBoundTexture(texture_gles, gl)) {
508 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
std::shared_ptr< const fml::Mapping > data