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);
113bool 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);
138bool 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()) {
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;
261GLint 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);
278const 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);
312bool 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);
330bool 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(),
354bool 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,
455std::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
#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 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
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)
constexpr bool IsAtLeast(const Version &other) const
std::shared_ptr< const fml::Mapping > data