Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
buffer_bindings_gles_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/testing/testing.h" // IWYU pragma: keep
6#include "gtest/gtest.h"
13
14namespace impeller {
15namespace testing {
16
17using ::testing::_;
18
19TEST(BufferBindingsGLESTest, ToVertexAttribTypeSupportedFormats) {
21 std::optional<GLenum>(GL_FLOAT));
23 std::optional<GLenum>(GL_BYTE));
25 std::optional<GLenum>(GL_UNSIGNED_BYTE));
27 std::optional<GLenum>(GL_SHORT));
29 std::optional<GLenum>(GL_UNSIGNED_SHORT));
30}
31
32TEST(BufferBindingsGLESTest, ToVertexAttribTypeRejectsUnsupportedFormats) {
33 // Half-float and 32-bit integer vertex attributes are not available on the
34 // GLES 2.0 floor.
35 EXPECT_FALSE(ToVertexAttribType(VertexAttributeFormat::kFloat16).has_value());
36 EXPECT_FALSE(ToVertexAttribType(VertexAttributeFormat::kSInt32).has_value());
37 EXPECT_FALSE(
39 EXPECT_FALSE(ToVertexAttribType(VertexAttributeFormat::kInvalid).has_value());
40}
41
42TEST(BufferBindingsGLESTest, BindUniformData) {
43 BufferBindingsGLES bindings;
44 absl::flat_hash_map<std::string, GLint> uniform_bindings;
45 uniform_bindings["SHADERMETADATA.FOOBAR"] = 1;
46 bindings.SetUniformBindings(std::move(uniform_bindings));
47 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
48
49 EXPECT_CALL(*mock_gles_impl, Uniform1fv(_, _, _)).Times(1);
50
51 std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
52 std::vector<BufferResource> bound_buffers;
53 std::vector<TextureAndSampler> bound_textures;
54
55 ShaderMetadata shader_metadata = {
56 .name = "shader_metadata",
57 .members = {
59 .name = "foobar",
60 .offset = 0,
61 .size = sizeof(float),
62 .byte_length = sizeof(float),
63 .array_elements = std::nullopt,
64 .float_type = ShaderFloatType::kFloat}}};
65 std::shared_ptr<ReactorGLES> reactor;
66 auto backing_store = std::make_unique<Allocation>();
67 ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float)}));
68 DeviceBufferGLES device_buffer(DeviceBufferDescriptor{.size = sizeof(float)},
69 reactor, std::move(backing_store));
70 BufferView buffer_view(&device_buffer, Range(0, sizeof(float)));
71 bound_buffers.push_back(BufferResource(&shader_metadata, buffer_view));
72
73 EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
74 bound_buffers, Range{0, 0},
75 Range{0, 1}));
76}
77
78TEST(BufferBindingsGLESTest, BindArrayData) {
79 BufferBindingsGLES bindings;
80 absl::flat_hash_map<std::string, GLint> uniform_bindings;
81 uniform_bindings["SHADERMETADATA.FOOBAR[0]"] = 1;
82 bindings.SetUniformBindings(std::move(uniform_bindings));
83 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
84
85 EXPECT_CALL(*mock_gles_impl, Uniform1fv(_, _, _)).Times(1);
86
87 std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
88 std::vector<BufferResource> bound_buffers;
89 std::vector<TextureAndSampler> bound_textures;
90
91 ShaderMetadata shader_metadata = {
92 .name = "shader_metadata",
93 .members = {
95 .name = "foobar",
96 .offset = 0,
97 .size = sizeof(float),
98 .byte_length = sizeof(float) * 4,
99 .array_elements = 4,
100 .float_type = ShaderFloatType::kFloat}}};
101 std::shared_ptr<ReactorGLES> reactor;
102 auto backing_store = std::make_unique<Allocation>();
103 ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float) * 4}));
104 DeviceBufferGLES device_buffer(
105 DeviceBufferDescriptor{.size = sizeof(float) * 4}, reactor,
106 std::move(backing_store));
107 BufferView buffer_view(&device_buffer, Range(0, sizeof(float)));
108 bound_buffers.push_back(BufferResource(&shader_metadata, buffer_view));
109
110 EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
111 bound_buffers, Range{0, 0},
112 Range{0, 1}));
113}
114
115TEST(BufferBindingsGLESTest, BindUniformDataVerticesAndMatrices) {
116 BufferBindingsGLES bindings;
117 absl::flat_hash_map<std::string, GLint> uniform_bindings;
118 uniform_bindings["SHADERMETADATA.VEC2"] = 1;
119 uniform_bindings["SHADERMETADATA.VEC3"] = 2;
120 uniform_bindings["SHADERMETADATA.VEC4"] = 3;
121 uniform_bindings["SHADERMETADATA.MAT2"] = 4;
122 uniform_bindings["SHADERMETADATA.MAT3"] = 5;
123 uniform_bindings["SHADERMETADATA.MAT4"] = 6;
124 bindings.SetUniformBindings(std::move(uniform_bindings));
125 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
126
127 EXPECT_CALL(*mock_gles_impl, Uniform2fv(1, 1, _)).Times(1);
128 EXPECT_CALL(*mock_gles_impl, Uniform3fv(2, 1, _)).Times(1);
129 EXPECT_CALL(*mock_gles_impl, Uniform4fv(3, 1, _)).Times(1);
130 EXPECT_CALL(*mock_gles_impl, UniformMatrix2fv(4, 1, GL_FALSE, _)).Times(1);
131 EXPECT_CALL(*mock_gles_impl, UniformMatrix3fv(5, 1, GL_FALSE, _)).Times(1);
132 EXPECT_CALL(*mock_gles_impl, UniformMatrix4fv(6, 1, GL_FALSE, _)).Times(1);
133
134 std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
135 std::vector<BufferResource> bound_buffers;
136 std::vector<TextureAndSampler> bound_textures;
137
138 auto make_metadata = [](ShaderFloatType float_type, const char* name,
139 size_t size) {
141 .name = name,
142 .offset = 0,
143 .size = size,
144 .byte_length = size,
145 .array_elements = std::nullopt,
146 .float_type = float_type};
147 };
148
149 ShaderMetadata shader_metadata = {
150 .name = "shader_metadata",
151 .members = {
152 make_metadata(ShaderFloatType::kVec2, "vec2", sizeof(Vector2)),
153 make_metadata(ShaderFloatType::kVec3, "vec3", sizeof(Vector3)),
154 make_metadata(ShaderFloatType::kVec4, "vec4", sizeof(Vector4)),
155 make_metadata(ShaderFloatType::kMat2, "mat2", sizeof(float) * 4),
156 make_metadata(ShaderFloatType::kMat3, "mat3", sizeof(float) * 9),
157 make_metadata(ShaderFloatType::kMat4, "mat4", sizeof(Matrix)),
158 }};
159
160 std::shared_ptr<ReactorGLES> reactor;
161 auto backing_store = std::make_unique<Allocation>();
162 ASSERT_TRUE(backing_store->Truncate(Bytes{1024})); // Plenty of space
163 DeviceBufferGLES device_buffer(DeviceBufferDescriptor{.size = 1024}, reactor,
164 std::move(backing_store));
165 BufferView buffer_view(&device_buffer, Range(0, 1024));
166 bound_buffers.push_back(BufferResource(&shader_metadata, buffer_view));
167
168 EXPECT_TRUE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
169 bound_buffers, Range{0, 0},
170 Range{0, 1}));
171}
172
173// Regression guard: a float uniform that arrives at the GLES backend without
174// `float_type` populated must be rejected rather than silently dispatched to
175// the wrong glUniform call. This is the fault mode that motivated the schema
176// extension; if a future change forgets to populate `float_type` (in the
177// shader bundle loader, runtime effects, or anywhere else), this test
178// catches it at unit-test time instead of at runtime.
179TEST(BufferBindingsGLESTest, BindUniformFailsWithoutFloatType) {
180 BufferBindingsGLES bindings;
181 absl::flat_hash_map<std::string, GLint> uniform_bindings;
182 uniform_bindings["SHADERMETADATA.FOOBAR"] = 1;
183 bindings.SetUniformBindings(std::move(uniform_bindings));
184 auto mock_gles_impl = std::make_unique<MockGLESImpl>();
185 std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
186 std::vector<BufferResource> bound_buffers;
187 std::vector<TextureAndSampler> bound_textures;
188
189 ShaderMetadata shader_metadata = {
190 .name = "shader_metadata",
192 .name = "foobar",
193 .offset = 0,
194 .size = sizeof(float),
195 .byte_length = sizeof(float),
196 .array_elements = std::nullopt,
197 .float_type = std::nullopt}}};
198 std::shared_ptr<ReactorGLES> reactor;
199 auto backing_store = std::make_unique<Allocation>();
200 ASSERT_TRUE(backing_store->Truncate(Bytes{sizeof(float)}));
201 DeviceBufferGLES device_buffer(DeviceBufferDescriptor{.size = sizeof(float)},
202 reactor, std::move(backing_store));
203 BufferView buffer_view(&device_buffer, Range(0, sizeof(float)));
204 bound_buffers.push_back(BufferResource(&shader_metadata, buffer_view));
205
206 EXPECT_FALSE(bindings.BindUniformData(mock_gl->GetProcTable(), bound_textures,
207 bound_buffers, Range{0, 0},
208 Range{0, 1}));
209}
210
211// An instanced draw reaches per-instance data through instance-rate vertex
212// attributes. A vertex layout with an instance-rate binding must set a
213// glVertexAttribDivisor of 1 on that binding's attributes, while a
214// per-vertex binding keeps a divisor of 0.
215TEST(BufferBindingsGLESTest, BindVertexAttributesSetsInstanceRateDivisor) {
216 auto mock_gles_impl = std::make_unique<::testing::NiceMock<MockGLESImpl>>();
217 EXPECT_CALL(*mock_gles_impl, VertexAttribDivisor(0, 0)).Times(1);
218 EXPECT_CALL(*mock_gles_impl, VertexAttribDivisor(1, 1)).Times(1);
219 std::shared_ptr<MockGLES> mock_gl = MockGLES::Init(std::move(mock_gles_impl));
220
221 BufferBindingsGLES bindings;
222
223 ShaderStageIOSlot per_vertex_input = {
224 .name = "position",
225 .location = 0,
226 .set = 0,
227 .binding = 0,
228 .type = ShaderType::kFloat,
229 .bit_width = sizeof(float) * 8,
230 .vec_size = 2,
231 .columns = 1,
232 .offset = 0,
233 };
234 ShaderStageIOSlot per_instance_input = {
235 .name = "instance_offset",
236 .location = 1,
237 .set = 0,
238 .binding = 1,
239 .type = ShaderType::kFloat,
240 .bit_width = sizeof(float) * 8,
241 .vec_size = 2,
242 .columns = 1,
243 .offset = 0,
244 };
245 std::vector<ShaderStageIOSlot> inputs = {per_vertex_input,
246 per_instance_input};
247 std::vector<ShaderStageBufferLayout> layouts = {
248 ShaderStageBufferLayout{.stride = sizeof(float) * 2,
249 .binding = 0,
250 .input_rate = VertexInputRate::kVertex},
251 ShaderStageBufferLayout{.stride = sizeof(float) * 2,
252 .binding = 1,
253 .input_rate = VertexInputRate::kInstance},
254 };
255
256 ASSERT_TRUE(bindings.RegisterVertexStageInput(mock_gl->GetProcTable(), inputs,
257 layouts));
258 // Binding 0 is per-vertex (divisor 0); binding 1 is per-instance
259 // (divisor 1).
260 EXPECT_TRUE(bindings.BindVertexAttributes(mock_gl->GetProcTable(),
261 /*binding=*/0, /*vertex_offset=*/0,
262 /*instance=*/0));
263 EXPECT_TRUE(bindings.BindVertexAttributes(mock_gl->GetProcTable(),
264 /*binding=*/1, /*vertex_offset=*/0,
265 /*instance=*/0));
266}
267
268} // namespace testing
269} // namespace impeller
Sets up stage bindings for single draw call in the OpenGLES backend.
bool BindVertexAttributes(const ProcTableGLES &gl, size_t binding, size_t vertex_offset, size_t instance=0)
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)
static std::shared_ptr< MockGLES > Init(std::unique_ptr< MockGLESImpl > impl, const std::optional< std::vector< const char * > > &extensions=std::nullopt, const char *version_string="OpenGL ES 3.0")
Definition mock_gles.cc:417
uint32_t vec_size
uint32_t columns
TEST(FrameTimingsRecorderTest, RecordVsync)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library name
Definition switch_defs.h:27
@ kInstance
The binding is read once per instance.
@ kVertex
The binding is read once per vertex. This is the default.
Resource< BufferView > BufferResource
Definition command.h:55
constexpr std::optional< GLenum > ToVertexAttribType(VertexAttributeFormat type)
std::shared_ptr< ReactorGLES > reactor
std::shared_ptr< MockGLES > mock_gl
A 4x4 matrix using column-major storage.
Definition matrix.h:37