Skip to content

Commit f250437

Browse files
Jonah Williamsmboetger
authored andcommitted
[Impeller] fix array uniforms on GLES backend. (flutter#170710)
Fixes flutter#170647 Correctly account for the size of array elements for runtime effect shaders on the GLES backend.
1 parent b54410a commit f250437

File tree

4 files changed

+55
-4
lines changed

4 files changed

+55
-4
lines changed

engine/src/flutter/impeller/entity/contents/runtime_effect_contents.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,12 @@ static std::unique_ptr<ShaderMetadata> MakeShaderMetadata(
8888
std::unique_ptr<ShaderMetadata> metadata = std::make_unique<ShaderMetadata>();
8989
metadata->name = uniform.name;
9090
metadata->members.emplace_back(ShaderStructMemberMetadata{
91-
.type = GetShaderType(uniform.type),
92-
.size = uniform.GetSize(),
93-
.byte_length = uniform.bit_width / 8,
91+
.type = GetShaderType(uniform.type), //
92+
.size = uniform.dimensions.rows * uniform.dimensions.cols *
93+
(uniform.bit_width / 8u), //
94+
.byte_length =
95+
(uniform.bit_width / 8u) * uniform.array_elements.value_or(1), //
96+
.array_elements = uniform.array_elements //
9497
});
9598

9699
return metadata;

engine/src/flutter/impeller/renderer/backend/gles/buffer_bindings_gles.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,17 @@ bool BufferBindingsGLES::BindUniformBufferV2(
375375
continue;
376376
}
377377

378+
// The reflector/runtime stage data is confused as to whether 0 means
379+
// no elements or whether it is not an array. Specifically:
380+
// * The built-in generated header files use std::nullopt to mean not
381+
// an array. Setting the array_elements count to 1 generates incorrect
382+
// code that tries to create 1 length arrays.
383+
// * The runtime stage flatbuffer serializes the std::nullopt as 0,
384+
// and thus needs to treat array length of 0 as a scalar element.
378385
size_t element_count = member.array_elements.value_or(1);
386+
if (element_count == 0) {
387+
element_count = 1;
388+
}
379389
size_t element_stride = member.byte_length / element_count;
380390
auto* buffer_data =
381391
reinterpret_cast<const GLfloat*>(buffer_ptr + member.offset);

engine/src/flutter/impeller/renderer/backend/gles/buffer_bindings_gles.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace impeller {
1818

1919
namespace testing {
2020
FML_TEST_CLASS(BufferBindingsGLESTest, BindUniformData);
21+
FML_TEST_CLASS(BufferBindingsGLESTest, BindArrayData);
2122
} // namespace testing
2223

2324
//------------------------------------------------------------------------------
@@ -51,6 +52,7 @@ class BufferBindingsGLES {
5152

5253
private:
5354
FML_FRIEND_TEST(testing::BufferBindingsGLESTest, BindUniformData);
55+
FML_FRIEND_TEST(testing::BufferBindingsGLESTest, BindArrayData);
5456
//----------------------------------------------------------------------------
5557
/// @brief The arguments to glVertexAttribPointer.
5658
///

engine/src/flutter/impeller/renderer/backend/gles/buffer_bindings_gles_unittests.cc

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ TEST(BufferBindingsGLESTest, BindUniformData) {
3333
.name = "foobar",
3434
.offset = 0,
3535
.size = sizeof(float),
36-
.byte_length = sizeof(float)}}};
36+
.byte_length = sizeof(float),
37+
.array_elements = 0}}};
3738
std::shared_ptr<ReactorGLES> reactor;
3839
std::shared_ptr<Allocation> backing_store = std::make_shared<Allocation>();
3940
ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float)}));
@@ -47,5 +48,40 @@ TEST(BufferBindingsGLESTest, BindUniformData) {
4748
Range{0, 1}));
4849
}
4950

51+
TEST(BufferBindingsGLESTest, BindArrayData) {
52+
BufferBindingsGLES bindings;
53+
absl::flat_hash_map<std::string, GLint> uniform_bindings;
54+
uniform_bindings["SHADERMETADATA.FOOBAR[0]"] = 1;
55+
bindings.SetUniformBindings(std::move(uniform_bindings));
56+
auto mock_gles_impl = std::make_unique<MockGLESImpl>();
57+
58+
EXPECT_CALL(*mock_gles_impl, Uniform1fv(_, _, _)).Times(1);
59+
60+
std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
61+
std::vector<BufferResource> bound_buffers;
62+
std::vector<TextureAndSampler> bound_textures;
63+
64+
ShaderMetadata shader_metadata = {
65+
.name = "shader_metadata",
66+
.members = {ShaderStructMemberMetadata{.type = ShaderType::kFloat,
67+
.name = "foobar",
68+
.offset = 0,
69+
.size = sizeof(float),
70+
.byte_length = sizeof(float) * 4,
71+
.array_elements = 4}}};
72+
std::shared_ptr<ReactorGLES> reactor;
73+
std::shared_ptr<Allocation> backing_store = std::make_shared<Allocation>();
74+
ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float) * 4}));
75+
DeviceBufferGLES device_buffer(
76+
DeviceBufferDescriptor{.size = sizeof(float) * 4}, reactor,
77+
backing_store);
78+
BufferView buffer_view(&device_buffer, Range(0, sizeof(float)));
79+
bound_buffers.push_back(BufferResource(&shader_metadata, buffer_view));
80+
81+
EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
82+
bound_buffers, Range{0, 0},
83+
Range{0, 1}));
84+
}
85+
5086
} // namespace testing
5187
} // namespace impeller

0 commit comments

Comments
 (0)