Skip to content

Commit 12518fa

Browse files
author
Jonah Williams
authored
[Impellerc] correctly pad arrays of vec3s in reflector. (#161697)
When processing the metadata for a struct with an array, incorporate the padding into the layout. Previously we would register a vec3[n] array as being 4*n bytes (including the padding), but when uploading this would result in us writing data into the padding and then leave the rest uninitialized. now we correctly insert a padding element between 3 byte elements. Fixes flutter/flutter#161645
1 parent 747f5ff commit 12518fa

File tree

4 files changed

+53
-5
lines changed

4 files changed

+53
-5
lines changed

engine/src/flutter/impeller/compiler/reflector.cc

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -398,11 +398,25 @@ std::shared_ptr<RuntimeStageData::Shader> Reflector::GenerateRuntimeStageData()
398398
break;
399399
}
400400
case StructMember::UnderlyingType::kFloat: {
401-
size_t member_float_count = member.byte_length / sizeof(float);
402-
float_count += member_float_count;
403-
while (member_float_count > 0) {
404-
struct_layout.push_back(1);
405-
member_float_count--;
401+
if (member.array_elements > 1) {
402+
// For each array element member, insert 1 layout property per byte
403+
// and 0 layout property per byte of padding
404+
for (auto i = 0; i < member.array_elements; i++) {
405+
for (auto j = 0u; j < member.size / sizeof(float); j++) {
406+
struct_layout.push_back(1);
407+
}
408+
for (auto j = 0u; j < member.element_padding / sizeof(float);
409+
j++) {
410+
struct_layout.push_back(0);
411+
}
412+
}
413+
} else {
414+
size_t member_float_count = member.byte_length / sizeof(float);
415+
float_count += member_float_count;
416+
while (member_float_count > 0) {
417+
struct_layout.push_back(1);
418+
member_float_count--;
419+
}
406420
}
407421
break;
408422
}

engine/src/flutter/lib/ui/fixtures/shaders/general_shaders/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ if (enable_unittests) {
2020
"filter_shader.frag",
2121
"missing_size.frag",
2222
"missing_texture.frag",
23+
"vec3_uniform.frag",
2324
]
2425

2526
group("general_shaders") {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#version 320 es
2+
3+
// Copyright 2013 The Flutter Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style license that can be
5+
// found in the LICENSE file.
6+
7+
precision highp float;
8+
9+
uniform vec3[4] color_array;
10+
11+
out vec4 fragColor;
12+
13+
void main() {
14+
fragColor = vec4(color_array[3].xyz, 1);
15+
}

engine/src/flutter/testing/dart/fragment_shader_test.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,24 @@ void main() async {
376376
}
377377
});
378378

379+
test('Shader Compiler appropriately pads vec3 uniform arrays', () async {
380+
if (!impellerEnabled) {
381+
print('Skipped for Skia');
382+
return;
383+
}
384+
385+
final FragmentProgram program = await FragmentProgram.fromAsset('vec3_uniform.frag.iplr');
386+
final FragmentShader shader = program.fragmentShader();
387+
388+
// Set the last vec3 in the uniform array to green. The shader will read this
389+
// value, and if the uniforms were padded correctly will render green.
390+
shader.setFloat(12, 0);
391+
shader.setFloat(13, 1.0);
392+
shader.setFloat(14, 0);
393+
394+
await _expectShaderRendersGreen(shader);
395+
});
396+
379397
test('ImageFilter.shader can be applied to canvas operations', () async {
380398
if (!impellerEnabled) {
381399
print('Skipped for Skia');

0 commit comments

Comments
 (0)