[Flutter GPU] Add CullMode. (flutter/engine#55409)
Part of https://github.com/flutter/flutter/issues/155636. New golden `flutter_gpu_test_cull_mode` will draw a red triangle if the CullMode isn't working: 
This commit is contained in:
parent
9f1cee211c
commit
e496b1ed26
@ -501,6 +501,27 @@ constexpr impeller::StencilOperation ToImpellerStencilOperation(int value) {
|
||||
static_cast<FlutterGPUStencilOperation>(value));
|
||||
}
|
||||
|
||||
enum class FlutterGPUCullMode {
|
||||
kNone,
|
||||
kFrontFace,
|
||||
kBackFace,
|
||||
};
|
||||
|
||||
constexpr impeller::CullMode ToImpellerCullMode(FlutterGPUCullMode value) {
|
||||
switch (value) {
|
||||
case FlutterGPUCullMode::kNone:
|
||||
return impeller::CullMode::kNone;
|
||||
case FlutterGPUCullMode::kFrontFace:
|
||||
return impeller::CullMode::kFrontFace;
|
||||
case FlutterGPUCullMode::kBackFace:
|
||||
return impeller::CullMode::kBackFace;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr impeller::CullMode ToImpellerCullMode(int value) {
|
||||
return ToImpellerCullMode(static_cast<FlutterGPUCullMode>(value));
|
||||
}
|
||||
|
||||
} // namespace gpu
|
||||
} // namespace flutter
|
||||
|
||||
|
@ -135,6 +135,12 @@ enum PrimitiveType {
|
||||
point,
|
||||
}
|
||||
|
||||
enum CullMode {
|
||||
none,
|
||||
frontFace,
|
||||
backFace,
|
||||
}
|
||||
|
||||
enum CompareFunction {
|
||||
/// Comparison test never passes.
|
||||
never,
|
||||
|
@ -264,6 +264,10 @@ base class RenderPass extends NativeFieldWrapperClass1 {
|
||||
targetFace.index);
|
||||
}
|
||||
|
||||
void setCullMode(CullMode cullMode) {
|
||||
_setCullMode(cullMode.index);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
if (!_draw()) {
|
||||
throw Exception("Failed to append draw");
|
||||
@ -402,6 +406,10 @@ base class RenderPass extends NativeFieldWrapperClass1 {
|
||||
int writeMask,
|
||||
int target_face);
|
||||
|
||||
@Native<Void Function(Pointer<Void>, Int)>(
|
||||
symbol: 'InternalFlutterGpu_RenderPass_SetCullMode')
|
||||
external void _setCullMode(int cullMode);
|
||||
|
||||
@Native<Bool Function(Pointer<Void>)>(
|
||||
symbol: 'InternalFlutterGpu_RenderPass_Draw')
|
||||
external bool _draw();
|
||||
|
@ -76,6 +76,10 @@ impeller::VertexBuffer& RenderPass::GetVertexBuffer() {
|
||||
return vertex_buffer_;
|
||||
}
|
||||
|
||||
impeller::PipelineDescriptor& RenderPass::GetPipelineDescriptor() {
|
||||
return pipeline_descriptor_;
|
||||
}
|
||||
|
||||
bool RenderPass::Begin(flutter::gpu::CommandBuffer& command_buffer) {
|
||||
render_pass_ =
|
||||
command_buffer.GetCommandBuffer()->CreateRenderPass(render_target_);
|
||||
@ -558,6 +562,14 @@ void InternalFlutterGpu_RenderPass_SetStencilConfig(
|
||||
}
|
||||
}
|
||||
|
||||
void InternalFlutterGpu_RenderPass_SetCullMode(
|
||||
flutter::gpu::RenderPass* wrapper,
|
||||
int cull_mode) {
|
||||
impeller::PipelineDescriptor& pipeline_descriptor =
|
||||
wrapper->GetPipelineDescriptor();
|
||||
pipeline_descriptor.SetCullMode(flutter::gpu::ToImpellerCullMode(cull_mode));
|
||||
}
|
||||
|
||||
bool InternalFlutterGpu_RenderPass_Draw(flutter::gpu::RenderPass* wrapper) {
|
||||
return wrapper->Draw();
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ class RenderPass : public RefCountedDartWrappable<RenderPass> {
|
||||
|
||||
impeller::VertexBuffer& GetVertexBuffer();
|
||||
|
||||
impeller::PipelineDescriptor& GetPipelineDescriptor();
|
||||
|
||||
bool Begin(flutter::gpu::CommandBuffer& command_buffer);
|
||||
|
||||
void SetPipeline(fml::RefPtr<RenderPipeline> pipeline);
|
||||
@ -241,6 +243,11 @@ extern void InternalFlutterGpu_RenderPass_SetStencilConfig(
|
||||
int write_mask,
|
||||
int target);
|
||||
|
||||
FLUTTER_GPU_EXPORT
|
||||
extern void InternalFlutterGpu_RenderPass_SetCullMode(
|
||||
flutter::gpu::RenderPass* wrapper,
|
||||
int cull_mode);
|
||||
|
||||
FLUTTER_GPU_EXPORT
|
||||
extern bool InternalFlutterGpu_RenderPass_Draw(
|
||||
flutter::gpu::RenderPass* wrapper);
|
||||
|
@ -11,6 +11,7 @@ import 'dart:typed_data';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vector_math/vector_math.dart';
|
||||
|
||||
import '../../lib/gpu/lib/gpu.dart' as gpu;
|
||||
|
||||
@ -21,6 +22,16 @@ ByteData float32(List<double> values) {
|
||||
return Float32List.fromList(values).buffer.asByteData();
|
||||
}
|
||||
|
||||
ByteData unlitUBO(Matrix4 mvp, Vector4 color) {
|
||||
return float32(<double>[
|
||||
mvp[0], mvp[1], mvp[2], mvp[3], //
|
||||
mvp[4], mvp[5], mvp[6], mvp[7], //
|
||||
mvp[8], mvp[9], mvp[10], mvp[11], //
|
||||
mvp[12], mvp[13], mvp[14], mvp[15], //
|
||||
color.r, color.g, color.b, color.a,
|
||||
]);
|
||||
}
|
||||
|
||||
gpu.RenderPipeline createUnlitRenderPipeline() {
|
||||
final gpu.ShaderLibrary? library =
|
||||
gpu.ShaderLibrary.fromAsset('test.shaderbundle');
|
||||
@ -425,4 +436,47 @@ void main() async {
|
||||
await comparer.addGoldenImage(
|
||||
image, 'flutter_gpu_test_triangle_stencil.png');
|
||||
}, skip: !impellerEnabled);
|
||||
|
||||
test('Drawing respects cull mode', () async {
|
||||
final state = createSimpleRenderPass();
|
||||
|
||||
final gpu.RenderPipeline pipeline = createUnlitRenderPipeline();
|
||||
state.renderPass.bindPipeline(pipeline);
|
||||
|
||||
state.renderPass.setColorBlendEnable(true);
|
||||
state.renderPass.setColorBlendEquation(gpu.ColorBlendEquation());
|
||||
|
||||
final gpu.HostBuffer transients = gpu.gpuContext.createHostBuffer();
|
||||
// Counter-clockwise triangle.
|
||||
final List<double> triangle = [
|
||||
-0.5, 0.5, //
|
||||
0.0, -0.5, //
|
||||
0.5, 0.5, //
|
||||
];
|
||||
final gpu.BufferView vertices = transients.emplace(float32(triangle));
|
||||
|
||||
void drawTriangle(Vector4 color) {
|
||||
final gpu.BufferView vertInfoUboFront =
|
||||
transients.emplace(unlitUBO(Matrix4.identity(), color));
|
||||
|
||||
final gpu.UniformSlot vertInfo =
|
||||
pipeline.vertexShader.getUniformSlot('VertInfo');
|
||||
// TODO(bdero): Overwrite bindings with the same slot so we don't need to clear.
|
||||
// https://github.com/flutter/flutter/issues/155335
|
||||
state.renderPass.clearBindings();
|
||||
state.renderPass.bindVertexBuffer(vertices, 3);
|
||||
state.renderPass.bindUniform(vertInfo, vertInfoUboFront);
|
||||
state.renderPass.draw();
|
||||
}
|
||||
|
||||
state.renderPass.setCullMode(gpu.CullMode.frontFace);
|
||||
drawTriangle(Colors.lime);
|
||||
state.renderPass.setCullMode(gpu.CullMode.backFace);
|
||||
drawTriangle(Colors.red);
|
||||
|
||||
state.commandBuffer.submit();
|
||||
|
||||
final ui.Image image = state.renderTexture.asImage();
|
||||
await comparer.addGoldenImage(image, 'flutter_gpu_test_cull_mode.png');
|
||||
}, skip: !impellerEnabled);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user