diff --git a/impeller/compiler/compiler.cc b/impeller/compiler/compiler.cc index 6fee0cc600de3..261ab60a64360 100644 --- a/impeller/compiler/compiler.cc +++ b/impeller/compiler/compiler.cc @@ -71,18 +71,24 @@ static CompilerBackend CreateMSLCompiler( // metal backend of spirv-cross will order uniforms according to usage. To fix // this, we use the sorted order and the add_msl_resource_binding API to force // the ordering to match the declared order. Note that while this code runs - // for all compiled shaders, it will only affect fragment shaders due to the - // specified stage. + // for all compiled shaders, it will only affect vertex and fragment shaders + // due to the specified stage. auto floats = SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::Float); auto images = SortUniforms(&ir, sl_compiler.get(), spirv_cross::SPIRType::SampledImage); + spv::ExecutionModel execution_model = + spv::ExecutionModel::ExecutionModelFragment; + if (source_options.type == SourceType::kVertexShader) { + execution_model = spv::ExecutionModel::ExecutionModelVertex; + } + uint32_t buffer_offset = 0; uint32_t sampler_offset = 0; for (auto& float_id : floats) { sl_compiler->add_msl_resource_binding( - {.stage = spv::ExecutionModel::ExecutionModelFragment, + {.stage = execution_model, .basetype = spirv_cross::SPIRType::BaseType::Float, .desc_set = sl_compiler->get_decoration(float_id, spv::DecorationDescriptorSet), @@ -94,7 +100,7 @@ static CompilerBackend CreateMSLCompiler( } for (auto& image_id : images) { sl_compiler->add_msl_resource_binding({ - .stage = spv::ExecutionModel::ExecutionModelFragment, + .stage = execution_model, .basetype = spirv_cross::SPIRType::BaseType::SampledImage, .desc_set = sl_compiler->get_decoration(image_id, spv::DecorationDescriptorSet), diff --git a/impeller/core/formats.h b/impeller/core/formats.h index fbf1a36321c9a..071fc3c88457a 100644 --- a/impeller/core/formats.h +++ b/impeller/core/formats.h @@ -110,6 +110,27 @@ enum class PixelFormat { kD32FloatS8UInt, }; +constexpr bool IsDepthWritable(PixelFormat format) { + switch (format) { + case PixelFormat::kD24UnormS8Uint: + case PixelFormat::kD32FloatS8UInt: + return true; + default: + return false; + } +} + +constexpr bool IsStencilWritable(PixelFormat format) { + switch (format) { + case PixelFormat::kS8UInt: + case PixelFormat::kD24UnormS8Uint: + case PixelFormat::kD32FloatS8UInt: + return true; + default: + return false; + } +} + constexpr const char* PixelFormatToString(PixelFormat format) { switch (format) { case PixelFormat::kUnknown: diff --git a/impeller/fixtures/BUILD.gn b/impeller/fixtures/BUILD.gn index 35bd4134bca43..c225cad315172 100644 --- a/impeller/fixtures/BUILD.gn +++ b/impeller/fixtures/BUILD.gn @@ -119,6 +119,8 @@ impellerc("flutter_gpu_shaders") { # Temporarily build Flutter GPU test shaders as runtime stages. "flutter_gpu_unlit.frag", "flutter_gpu_unlit.vert", + "flutter_gpu_texture.frag", + "flutter_gpu_texture.vert", ] sl_file_extension = "iplr" shader_target_flag = "--runtime-stage-metal" diff --git a/impeller/fixtures/dart_tests.dart b/impeller/fixtures/dart_tests.dart index 8ec5229b37df9..51c9029aac866 100644 --- a/impeller/fixtures/dart_tests.dart +++ b/impeller/fixtures/dart_tests.dart @@ -189,12 +189,19 @@ void canCreateRenderPassAndSubmit() { assert(renderTexture != null); final gpu.CommandBuffer commandBuffer = gpu.gpuContext.createCommandBuffer(); - final gpu.RenderPass encoder = commandBuffer.createRenderPass( - colorAttachment: gpu.ColorAttachment(texture: renderTexture!)); + + final gpu.RenderTarget renderTarget = gpu.RenderTarget.singleColor( + gpu.ColorAttachment(texture: renderTexture!), + ); + final gpu.RenderPass encoder = commandBuffer.createRenderPass(renderTarget); final gpu.RenderPipeline pipeline = createUnlitRenderPipeline(); encoder.bindPipeline(pipeline); + // Configure blending with defaults (just to test the bindings). + encoder.setColorBlendEnable(true); + encoder.setColorBlendEquation(gpu.ColorBlendEquation()); + final gpu.HostBuffer transients = gpu.HostBuffer(); final gpu.BufferView vertices = transients.emplace(float32([ -0.5, -0.5, // diff --git a/impeller/fixtures/flutter_gpu_texture.frag b/impeller/fixtures/flutter_gpu_texture.frag new file mode 100644 index 0000000000000..dc18b9a7c55dc --- /dev/null +++ b/impeller/fixtures/flutter_gpu_texture.frag @@ -0,0 +1,13 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +uniform sampler2D tex; + +in vec2 v_texture_coords; +in vec4 v_color; +out vec4 frag_color; + +void main() { + frag_color = v_color * texture(tex, v_texture_coords); +} diff --git a/impeller/fixtures/flutter_gpu_texture.vert b/impeller/fixtures/flutter_gpu_texture.vert new file mode 100644 index 0000000000000..8f3807d71b15c --- /dev/null +++ b/impeller/fixtures/flutter_gpu_texture.vert @@ -0,0 +1,17 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +uniform mat4 mvp; + +in vec3 position; +in vec2 texture_coords; +in vec4 color; +out vec2 v_texture_coords; +out vec4 v_color; + +void main() { + v_texture_coords = texture_coords; + v_color = color; + gl_Position = mvp * vec4(position, 1.0); +} diff --git a/lib/gpu/device_buffer.cc b/lib/gpu/device_buffer.cc index f783f9b8ada74..1b495350543d8 100644 --- a/lib/gpu/device_buffer.cc +++ b/lib/gpu/device_buffer.cc @@ -54,8 +54,7 @@ bool InternalFlutterGpu_DeviceBuffer_Initialize( int storage_mode, int size_in_bytes) { impeller::DeviceBufferDescriptor desc; - desc.storage_mode = flutter::gpu::ToImpellerStorageMode( - static_cast(storage_mode)); + desc.storage_mode = flutter::gpu::ToImpellerStorageMode(storage_mode); desc.size = size_in_bytes; auto device_buffer = gpu_context->GetContext()->GetResourceAllocator()->CreateBuffer(desc); diff --git a/lib/gpu/fixtures.cc b/lib/gpu/fixtures.cc index c85020b3b7bd3..26b2d8dc9e277 100644 --- a/lib/gpu/fixtures.cc +++ b/lib/gpu/fixtures.cc @@ -130,3 +130,151 @@ unsigned char kFlutterGPUUnlitFragIPLR[] = { 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x75, 0x6e, 0x6c, 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x00}; + +unsigned char kFlutterGPUTextureVertIPLR[] = { + 0x18, 0x00, 0x00, 0x00, 0x49, 0x50, 0x4c, 0x52, 0x00, 0x00, 0x0e, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x23, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x5f, + 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69, 0x6d, 0x64, 0x2f, 0x73, + 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a, 0x75, 0x73, 0x69, 0x6e, + 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, + 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, + 0x63, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, + 0x70, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, + 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, + 0x75, 0x74, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x32, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, + 0x65, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x5b, 0x5b, 0x75, + 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x30, 0x29, 0x5d, 0x5d, + 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, + 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x5b, 0x5b, 0x75, + 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x31, 0x29, 0x5d, 0x5d, + 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, + 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x5b, 0x5b, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5d, + 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, + 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, + 0x75, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x65, + 0x72, 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, + 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x33, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5b, + 0x5b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x30, + 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x32, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, + 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x5b, 0x5b, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x31, 0x29, 0x5d, 0x5d, 0x3b, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, + 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x5b, 0x5b, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x32, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, + 0x7d, 0x3b, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x66, + 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x74, 0x65, + 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x66, + 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x74, 0x65, + 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x66, 0x6c, 0x75, 0x74, 0x74, + 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, + 0x72, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, + 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x5b, 0x73, + 0x74, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x5d, 0x5d, 0x2c, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x34, 0x78, 0x34, 0x26, 0x20, 0x6d, 0x76, 0x70, 0x20, 0x5b, 0x5b, + 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x29, + 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, + 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, + 0x72, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x6d, 0x61, + 0x69, 0x6e, 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x3d, + 0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, + 0x2e, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x63, + 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x2e, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, + 0x73, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x76, + 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x2e, + 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, + 0x75, 0x74, 0x2e, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x6d, 0x76, 0x70, 0x20, 0x2a, 0x20, 0x66, + 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x69, 0x6e, 0x2e, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, + 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x01, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x28, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x70, 0x00, 0x1f, 0x00, 0x00, 0x00, + 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, + 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x74, + 0x65, 0x78, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x00}; + +unsigned char kFlutterGPUTextureFragIPLR[] = { + 0x1c, 0x00, 0x00, 0x00, 0x49, 0x50, 0x4c, 0x52, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x14, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x0c, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xd4, 0x02, 0x00, 0x00, 0x94, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x85, 0x02, 0x00, 0x00, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x64, 0x6c, + 0x69, 0x62, 0x3e, 0x0a, 0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x20, 0x3c, 0x73, 0x69, 0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, + 0x68, 0x3e, 0x0a, 0x0a, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, + 0x6c, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x66, + 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x74, + 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, + 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x75, 0x74, + 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x34, 0x20, 0x66, 0x72, 0x61, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, + 0x20, 0x5b, 0x5b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x30, 0x29, 0x5d, + 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, + 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, + 0x75, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x72, + 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, + 0x69, 0x6e, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, + 0x61, 0x74, 0x32, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, + 0x65, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x5b, 0x5b, 0x75, + 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x30, 0x29, 0x5d, 0x5d, + 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, + 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x5b, 0x5b, 0x75, + 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x31, 0x29, 0x5d, 0x5d, + 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, + 0x70, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, + 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, + 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, + 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, + 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, + 0x69, 0x6e, 0x28, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, + 0x70, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, + 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, + 0x5f, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x5b, 0x73, 0x74, 0x61, + 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x5d, 0x5d, 0x2c, 0x20, 0x74, 0x65, 0x78, + 0x74, 0x75, 0x72, 0x65, 0x32, 0x64, 0x3c, 0x66, 0x6c, 0x6f, 0x61, 0x74, + 0x3e, 0x20, 0x74, 0x65, 0x78, 0x20, 0x5b, 0x5b, 0x74, 0x65, 0x78, 0x74, + 0x75, 0x72, 0x65, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x2c, 0x20, 0x73, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x20, 0x74, 0x65, 0x78, 0x53, 0x6d, 0x70, + 0x6c, 0x72, 0x20, 0x5b, 0x5b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, + 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x66, 0x6c, 0x75, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, + 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x72, 0x61, + 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, + 0x75, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x3b, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x66, 0x72, 0x61, + 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x69, 0x6e, + 0x2e, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x2a, 0x20, 0x74, + 0x65, 0x78, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x28, 0x74, 0x65, + 0x78, 0x53, 0x6d, 0x70, 0x6c, 0x72, 0x2c, 0x20, 0x69, 0x6e, 0x2e, 0x76, + 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x6f, + 0x72, 0x64, 0x73, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x74, 0x65, 0x78, 0x00, 0x21, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x75, 0x74, + 0x74, 0x65, 0x72, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x74, 0x65, 0x78, 0x74, + 0x75, 0x72, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, + 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00}; diff --git a/lib/gpu/fixtures.h b/lib/gpu/fixtures.h index 13926f2c9b928..338c255450b59 100644 --- a/lib/gpu/fixtures.h +++ b/lib/gpu/fixtures.h @@ -40,3 +40,70 @@ extern unsigned char kFlutterGPUUnlitVertIPLR[]; constexpr unsigned int kFlutterGPUUnlitFragIPLRLength = 556; extern unsigned char kFlutterGPUUnlitFragIPLR[]; + +struct FlutterGPUTextureVertexShader { + struct PerVertexData { + impeller::Vector3 position; // (offset 0, size 12) + impeller::Point texture_coords; // (offset 12, size 8) + impeller::Vector4 color; // (offset 20, size 16) + }; // struct PerVertexData (size 36) + + static constexpr auto kInputTextureCoords = impeller::ShaderStageIOSlot{ + // texture_coords + "texture_coords", // name + 1u, // attribute location + 0u, // attribute set + 0u, // attribute binding + impeller::ShaderType::kFloat, // type + 32u, // bit width of type + 2u, // vec size + 1u, // number of columns + 12u, // offset for interleaved layout + }; + + static constexpr auto kInputColor = impeller::ShaderStageIOSlot{ + // color + "color", // name + 2u, // attribute location + 0u, // attribute set + 0u, // attribute binding + impeller::ShaderType::kFloat, // type + 32u, // bit width of type + 4u, // vec size + 1u, // number of columns + 20u, // offset for interleaved layout + }; + + static constexpr auto kInputPosition = impeller::ShaderStageIOSlot{ + // position + "position", // name + 0u, // attribute location + 0u, // attribute set + 0u, // attribute binding + impeller::ShaderType::kFloat, // type + 32u, // bit width of type + 3u, // vec size + 1u, // number of columns + 0u, // offset for interleaved layout + }; + + static constexpr std::array + kAllShaderStageInputs = { + &kInputTextureCoords, // texture_coords + &kInputColor, // color + &kInputPosition, // position + }; + + static constexpr auto kInterleavedLayout = impeller::ShaderStageBufferLayout{ + sizeof(PerVertexData), // stride for interleaved layout + 0u, // attribute binding + }; + static constexpr std::array + kInterleavedBufferLayout = {&kInterleavedLayout}; +}; + +constexpr unsigned int kFlutterGPUTextureVertIPLRLength = 920; +extern unsigned char kFlutterGPUTextureVertIPLR[]; + +constexpr unsigned int kFlutterGPUTextureFragIPLRLength = 800; +extern unsigned char kFlutterGPUTextureFragIPLR[]; diff --git a/lib/gpu/formats.h b/lib/gpu/formats.h index 86b2cf44ad395..e1a2a8d1d4a90 100644 --- a/lib/gpu/formats.h +++ b/lib/gpu/formats.h @@ -31,6 +31,10 @@ constexpr impeller::StorageMode ToImpellerStorageMode( } } +constexpr impeller::StorageMode ToImpellerStorageMode(int value) { + return ToImpellerStorageMode(static_cast(value)); +} + enum class FlutterGPUPixelFormat { kUnknown, kA8UNormInt, @@ -88,6 +92,10 @@ constexpr impeller::PixelFormat ToImpellerPixelFormat( } } +constexpr impeller::PixelFormat ToImpellerPixelFormat(int value) { + return ToImpellerPixelFormat(static_cast(value)); +} + constexpr FlutterGPUPixelFormat FromImpellerPixelFormat( impeller::PixelFormat value) { switch (value) { @@ -141,6 +149,12 @@ constexpr impeller::TextureCoordinateSystem ToImpellerTextureCoordinateSystem( } } +constexpr impeller::TextureCoordinateSystem ToImpellerTextureCoordinateSystem( + int value) { + return ToImpellerTextureCoordinateSystem( + static_cast(value)); +} + enum class FlutterGPUBlendFactor { kZero, kOne, @@ -195,6 +209,10 @@ constexpr impeller::BlendFactor ToImpellerBlendFactor( } } +constexpr impeller::BlendFactor ToImpellerBlendFactor(int value) { + return ToImpellerBlendFactor(static_cast(value)); +} + enum class FlutterGPUBlendOperation { kAdd, kSubtract, @@ -213,6 +231,10 @@ constexpr impeller::BlendOperation ToImpellerBlendOperation( } } +constexpr impeller::BlendOperation ToImpellerBlendOperation(int value) { + return ToImpellerBlendOperation(static_cast(value)); +} + enum class FlutterGPULoadAction { kDontCare, kLoad, @@ -231,6 +253,10 @@ constexpr impeller::LoadAction ToImpellerLoadAction( } } +constexpr impeller::LoadAction ToImpellerLoadAction(int value) { + return ToImpellerLoadAction(static_cast(value)); +} + enum class FlutterGPUStoreAction { kDontCare, kStore, @@ -252,6 +278,10 @@ constexpr impeller::StoreAction ToImpellerStoreAction( } } +constexpr impeller::StoreAction ToImpellerStoreAction(int value) { + return ToImpellerStoreAction(static_cast(value)); +} + enum class FlutterGPUShaderStage { kVertex, kFragment, @@ -267,6 +297,10 @@ constexpr impeller::ShaderStage ToImpellerShaderStage( } } +constexpr impeller::ShaderStage ToImpellerShaderStage(int value) { + return ToImpellerShaderStage(static_cast(value)); +} + constexpr FlutterGPUShaderStage FromImpellerShaderStage( impeller::ShaderStage value) { switch (value) { @@ -278,11 +312,193 @@ constexpr FlutterGPUShaderStage FromImpellerShaderStage( case impeller::ShaderStage::kTessellationControl: case impeller::ShaderStage::kTessellationEvaluation: case impeller::ShaderStage::kCompute: - FML_LOG(ERROR) << "Invalid Flutter GPU ShaderStage " + FML_LOG(FATAL) << "Invalid Flutter GPU ShaderStage " << static_cast(value); FML_UNREACHABLE(); } } +enum class FlutterGPUMinMagFilter { + kNearest, + kLinear, +}; + +constexpr impeller::MinMagFilter ToImpellerMinMagFilter( + FlutterGPUMinMagFilter value) { + switch (value) { + case FlutterGPUMinMagFilter::kNearest: + return impeller::MinMagFilter::kNearest; + case FlutterGPUMinMagFilter::kLinear: + return impeller::MinMagFilter::kLinear; + } +} + +constexpr impeller::MinMagFilter ToImpellerMinMagFilter(int value) { + return ToImpellerMinMagFilter(static_cast(value)); +} + +enum class FlutterGPUMipFilter { + kNearest, + kLinear, +}; + +constexpr impeller::MipFilter ToImpellerMipFilter(FlutterGPUMipFilter value) { + switch (value) { + case FlutterGPUMipFilter::kNearest: + return impeller::MipFilter::kNearest; + case FlutterGPUMipFilter::kLinear: + return impeller::MipFilter::kLinear; + } +} + +constexpr impeller::MipFilter ToImpellerMipFilter(int value) { + return ToImpellerMipFilter(static_cast(value)); +} + +enum class FlutterGPUSamplerAddressMode { + kClampToEdge, + kRepeat, + kMirror, +}; + +constexpr impeller::SamplerAddressMode ToImpellerSamplerAddressMode( + FlutterGPUSamplerAddressMode value) { + switch (value) { + case FlutterGPUSamplerAddressMode::kClampToEdge: + return impeller::SamplerAddressMode::kClampToEdge; + case FlutterGPUSamplerAddressMode::kRepeat: + return impeller::SamplerAddressMode::kRepeat; + case FlutterGPUSamplerAddressMode::kMirror: + return impeller::SamplerAddressMode::kMirror; + } +} + +constexpr impeller::SamplerAddressMode ToImpellerSamplerAddressMode(int value) { + return ToImpellerSamplerAddressMode( + static_cast(value)); +} + +enum class FlutterGPUIndexType { + k16bit, + k32bit, +}; + +constexpr impeller::IndexType ToImpellerIndexType(FlutterGPUIndexType value) { + switch (value) { + case FlutterGPUIndexType::k16bit: + return impeller::IndexType::k16bit; + case FlutterGPUIndexType::k32bit: + return impeller::IndexType::k32bit; + } +} + +constexpr impeller::IndexType ToImpellerIndexType(int value) { + return ToImpellerIndexType(static_cast(value)); +} + +enum class FlutterGPUPrimitiveType { + kTriangle, + kTriangleStrip, + kLine, + kLineStrip, + kPoint, +}; + +constexpr impeller::PrimitiveType ToImpellerPrimitiveType( + FlutterGPUPrimitiveType value) { + switch (value) { + case FlutterGPUPrimitiveType::kTriangle: + return impeller::PrimitiveType::kTriangle; + case FlutterGPUPrimitiveType::kTriangleStrip: + return impeller::PrimitiveType::kTriangleStrip; + case FlutterGPUPrimitiveType::kLine: + return impeller::PrimitiveType::kLine; + case FlutterGPUPrimitiveType::kLineStrip: + return impeller::PrimitiveType::kLineStrip; + case FlutterGPUPrimitiveType::kPoint: + return impeller::PrimitiveType::kPoint; + } +} + +constexpr impeller::PrimitiveType ToImpellerPrimitiveType(int value) { + return ToImpellerPrimitiveType(static_cast(value)); +} + +enum class FlutterGPUCompareFunction { + kNever, + kAlways, + kLess, + kEqual, + kLessEqual, + kGreater, + kNotEqual, + kGreaterEqual, +}; + +constexpr impeller::CompareFunction ToImpellerCompareFunction( + FlutterGPUCompareFunction value) { + switch (value) { + case FlutterGPUCompareFunction::kNever: + return impeller::CompareFunction::kNever; + case FlutterGPUCompareFunction::kAlways: + return impeller::CompareFunction::kAlways; + case FlutterGPUCompareFunction::kLess: + return impeller::CompareFunction::kLess; + case FlutterGPUCompareFunction::kEqual: + return impeller::CompareFunction::kEqual; + case FlutterGPUCompareFunction::kLessEqual: + return impeller::CompareFunction::kLessEqual; + case FlutterGPUCompareFunction::kGreater: + return impeller::CompareFunction::kGreater; + case FlutterGPUCompareFunction::kNotEqual: + return impeller::CompareFunction::kNotEqual; + case FlutterGPUCompareFunction::kGreaterEqual: + return impeller::CompareFunction::kGreaterEqual; + } +} + +constexpr impeller::CompareFunction ToImpellerCompareFunction(int value) { + return ToImpellerCompareFunction( + static_cast(value)); +} + +enum class FlutterGPUStencilOperation { + kKeep, + kZero, + kSetToReferenceValue, + kIncrementClamp, + kDecrementClamp, + kInvert, + kIncrementWrap, + kDecrementWrap, +}; + +constexpr impeller::StencilOperation ToImpellerStencilOperation( + FlutterGPUStencilOperation value) { + switch (value) { + case FlutterGPUStencilOperation::kKeep: + return impeller::StencilOperation::kKeep; + case FlutterGPUStencilOperation::kZero: + return impeller::StencilOperation::kZero; + case FlutterGPUStencilOperation::kSetToReferenceValue: + return impeller::StencilOperation::kSetToReferenceValue; + case FlutterGPUStencilOperation::kIncrementClamp: + return impeller::StencilOperation::kIncrementClamp; + case FlutterGPUStencilOperation::kDecrementClamp: + return impeller::StencilOperation::kDecrementClamp; + case FlutterGPUStencilOperation::kInvert: + return impeller::StencilOperation::kInvert; + case FlutterGPUStencilOperation::kIncrementWrap: + return impeller::StencilOperation::kIncrementWrap; + case FlutterGPUStencilOperation::kDecrementWrap: + return impeller::StencilOperation::kDecrementWrap; + } +} + +constexpr impeller::StencilOperation ToImpellerStencilOperation(int value) { + return ToImpellerStencilOperation( + static_cast(value)); +} + } // namespace gpu } // namespace flutter diff --git a/lib/gpu/lib/src/buffer.dart b/lib/gpu/lib/src/buffer.dart index c2b08220f050c..14401bc369480 100644 --- a/lib/gpu/lib/src/buffer.dart +++ b/lib/gpu/lib/src/buffer.dart @@ -28,6 +28,9 @@ mixin Buffer { void _bindAsVertexBuffer(RenderPass renderPass, int offsetInBytes, int lengthInBytes, int vertexCount); + void _bindAsIndexBuffer(RenderPass renderPass, int offsetInBytes, + int lengthInBytes, IndexType indexType, int indexCount); + bool _bindAsUniform(RenderPass renderPass, UniformSlot slot, int offsetInBytes, int lengthInBytes); } @@ -65,6 +68,13 @@ base class DeviceBuffer extends NativeFieldWrapperClass1 with Buffer { this, offsetInBytes, lengthInBytes, vertexCount); } + @override + void _bindAsIndexBuffer(RenderPass renderPass, int offsetInBytes, + int lengthInBytes, IndexType indexType, int indexCount) { + renderPass._bindIndexBufferDevice( + this, offsetInBytes, lengthInBytes, indexType.index, indexCount); + } + @override bool _bindAsUniform(RenderPass renderPass, UniformSlot slot, int offsetInBytes, int lengthInBytes) { @@ -136,6 +146,13 @@ base class HostBuffer extends NativeFieldWrapperClass1 with Buffer { this, offsetInBytes, lengthInBytes, vertexCount); } + @override + void _bindAsIndexBuffer(RenderPass renderPass, int offsetInBytes, + int lengthInBytes, IndexType indexType, int indexCount) { + renderPass._bindIndexBufferHost( + this, offsetInBytes, lengthInBytes, indexType.index, indexCount); + } + @override bool _bindAsUniform(RenderPass renderPass, UniformSlot slot, int offsetInBytes, int lengthInBytes) { diff --git a/lib/gpu/lib/src/command_buffer.dart b/lib/gpu/lib/src/command_buffer.dart index 06ff0d985bea6..09cae10b8fa75 100644 --- a/lib/gpu/lib/src/command_buffer.dart +++ b/lib/gpu/lib/src/command_buffer.dart @@ -14,10 +14,8 @@ base class CommandBuffer extends NativeFieldWrapperClass1 { _initialize(gpuContext); } - RenderPass createRenderPass( - {required ColorAttachment colorAttachment, - StencilAttachment? stencilAttachment = null}) { - return RenderPass._(this, colorAttachment, stencilAttachment); + RenderPass createRenderPass(RenderTarget renderTarget) { + return RenderPass._(this, renderTarget); } void submit({CompletionCallback? completionCallback}) { diff --git a/lib/gpu/lib/src/formats.dart b/lib/gpu/lib/src/formats.dart index 3252dd31e0db3..9ee89bb6cc50c 100644 --- a/lib/gpu/lib/src/formats.dart +++ b/lib/gpu/lib/src/formats.dart @@ -105,3 +105,84 @@ enum ShaderStage { vertex, fragment, } + +enum MinMagFilter { + nearest, + linear, +} + +enum MipFilter { + nearest, + linear, +} + +enum SamplerAddressMode { + clampToEdge, + repeat, + mirror, +} + +enum IndexType { + int16, + int32, +} + +enum PrimitiveType { + triangle, + triangleStrip, + line, + lineStrip, + point, +} + +enum CompareFunction { + /// Comparison test never passes. + never, + + /// Comparison test passes always passes. + always, + + /// Comparison test passes if new_value < current_value. + less, + + /// Comparison test passes if new_value == current_value. + equal, + + /// Comparison test passes if new_value <= current_value. + lessEqual, + + /// Comparison test passes if new_value > current_value. + greater, + + /// Comparison test passes if new_value != current_value. + notEqual, + + /// Comparison test passes if new_value >= current_value. + greaterEqual, +} + +enum StencilOperation { + /// Don't modify the current stencil value. + keep, + + /// Reset the stencil value to zero. + zero, + + /// Reset the stencil value to the reference value. + setToReferenceValue, + + /// Increment the current stencil value by 1. Clamp it to the maximum. + incrementClamp, + + /// Decrement the current stencil value by 1. Clamp it to zero. + decrementClamp, + + /// Perform a logical bitwise invert on the current stencil value. + invert, + + /// Increment the current stencil value by 1. If at maximum, set to zero. + incrementWrap, + + /// Decrement the current stencil value by 1. If at zero, set to maximum. + decrementWrap, +} diff --git a/lib/gpu/lib/src/render_pass.dart b/lib/gpu/lib/src/render_pass.dart index e8f1ef4157d77..aa56b41102bea 100644 --- a/lib/gpu/lib/src/render_pass.dart +++ b/lib/gpu/lib/src/render_pass.dart @@ -7,58 +7,121 @@ part of flutter_gpu; base class ColorAttachment { - ColorAttachment( - {this.loadAction = LoadAction.clear, - this.storeAction = StoreAction.store, - this.clearColor = const ui.Color(0x00000000), - required this.texture, - this.resolveTexture = null}); + ColorAttachment({ + this.loadAction = LoadAction.clear, + this.storeAction = StoreAction.store, + this.clearValue = const ui.Color(0x00000000), + required this.texture, + this.resolveTexture = null, + }); LoadAction loadAction; StoreAction storeAction; - ui.Color clearColor; + ui.Color clearValue; + Texture texture; Texture? resolveTexture; } -base class StencilAttachment { - StencilAttachment( - {this.loadAction = LoadAction.clear, - this.storeAction = StoreAction.dontCare, - this.clearStencil = 0, - required this.texture}); +base class DepthStencilAttachment { + DepthStencilAttachment({ + this.depthLoadAction = LoadAction.clear, + this.depthStoreAction = StoreAction.dontCare, + this.depthClearValue = 0.0, + this.stencilLoadAction = LoadAction.clear, + this.stencilStoreAction = StoreAction.dontCare, + this.stencilClearValue = 0, + required this.texture, + }); + + LoadAction depthLoadAction; + StoreAction depthStoreAction; + double depthClearValue; + + LoadAction stencilLoadAction; + StoreAction stencilStoreAction; + int stencilClearValue; - LoadAction loadAction; - StoreAction storeAction; - int clearStencil; Texture texture; } -/// A descriptor for RenderPass creation. Defines the output targets for raster -/// pipelines. -base class RenderTarget {} +base class ColorBlendEquation { + ColorBlendEquation({ + this.colorBlendOperation = BlendOperation.add, + this.sourceColorBlendFactor = BlendFactor.one, + this.destinationColorBlendFactor = BlendFactor.oneMinusSourceAlpha, + this.alphaBlendOperation = BlendOperation.add, + this.sourceAlphaBlendFactor = BlendFactor.one, + this.destinationAlphaBlendFactor = BlendFactor.oneMinusSourceAlpha, + }); + + BlendOperation colorBlendOperation; + BlendFactor sourceColorBlendFactor; + BlendFactor destinationColorBlendFactor; + + BlendOperation alphaBlendOperation; + BlendFactor sourceAlphaBlendFactor; + BlendFactor destinationAlphaBlendFactor; +} + +base class SamplerOptions { + SamplerOptions({ + this.minFilter = MinMagFilter.nearest, + this.magFilter = MinMagFilter.nearest, + this.mipFilter = MipFilter.nearest, + this.widthAddressMode = SamplerAddressMode.clampToEdge, + this.heightAddressMode = SamplerAddressMode.clampToEdge, + }); + + MinMagFilter minFilter; + MinMagFilter magFilter; + MipFilter mipFilter; + SamplerAddressMode widthAddressMode; + SamplerAddressMode heightAddressMode; +} + +base class RenderTarget { + const RenderTarget( + {this.colorAttachments = const [], + this.depthStencilAttachment}); + + RenderTarget.singleColor(ColorAttachment colorAttachment, + {DepthStencilAttachment? depthStencilAttachment}) + : this( + colorAttachments: [colorAttachment], + depthStencilAttachment: depthStencilAttachment); + + final List colorAttachments; + final DepthStencilAttachment? depthStencilAttachment; +} base class RenderPass extends NativeFieldWrapperClass1 { /// Creates a new RenderPass. - RenderPass._(CommandBuffer commandBuffer, ColorAttachment colorAttachment, - StencilAttachment? stencilAttachment) { + RenderPass._(CommandBuffer commandBuffer, RenderTarget renderTarget) { _initialize(); String? error; - error = _setColorAttachment( - colorAttachment.loadAction.index, - colorAttachment.storeAction.index, - colorAttachment.clearColor.value, - colorAttachment.texture, - colorAttachment.resolveTexture); - if (error != null) { - throw Exception(error); + for (final (index, color) in renderTarget.colorAttachments.indexed) { + error = _setColorAttachment( + index, + color.loadAction.index, + color.storeAction.index, + color.clearValue.value, + color.texture, + color.resolveTexture); + if (error != null) { + throw Exception(error); + } } - if (stencilAttachment != null) { - error = _setStencilAttachment( - stencilAttachment.loadAction.index, - stencilAttachment.storeAction.index, - stencilAttachment.clearStencil, - stencilAttachment.texture); + if (renderTarget.depthStencilAttachment != null) { + final ds = renderTarget.depthStencilAttachment!; + error = _setDepthStencilAttachment( + ds.depthLoadAction.index, + ds.depthStoreAction.index, + ds.depthClearValue, + ds.stencilLoadAction.index, + ds.stencilStoreAction.index, + ds.stencilClearValue, + ds.texture); if (error != null) { throw Exception(error); } @@ -78,14 +141,68 @@ base class RenderPass extends NativeFieldWrapperClass1 { this, bufferView.offsetInBytes, bufferView.lengthInBytes, vertexCount); } + void bindIndexBuffer( + BufferView bufferView, IndexType indexType, int indexCount) { + bufferView.buffer._bindAsIndexBuffer(this, bufferView.offsetInBytes, + bufferView.lengthInBytes, indexType, indexCount); + } + void bindUniform(UniformSlot slot, BufferView bufferView) { bool success = bufferView.buffer._bindAsUniform( this, slot, bufferView.offsetInBytes, bufferView.lengthInBytes); if (!success) { - throw Exception("Failed to bind uniform slot"); + throw Exception("Failed to bind uniform"); + } + } + + void bindTexture(UniformSlot slot, Texture texture, + {SamplerOptions? sampler}) { + if (sampler == null) { + sampler = SamplerOptions(); + } + + bool success = _bindTexture( + slot.shaderStage.index, + slot.slotId, + texture, + sampler.minFilter.index, + sampler.magFilter.index, + sampler.mipFilter.index, + sampler.widthAddressMode.index, + sampler.heightAddressMode.index); + if (!success) { + throw Exception("Failed to bind texture"); } } + void clearBindings() { + _clearBindings(); + } + + void setColorBlendEnable(bool enable, {int colorAttachmentIndex = 0}) { + _setColorBlendEnable(colorAttachmentIndex, enable); + } + + void setColorBlendEquation(ColorBlendEquation equation, + {int colorAttachmentIndex = 0}) { + _setColorBlendEquation( + colorAttachmentIndex, + equation.colorBlendOperation.index, + equation.sourceColorBlendFactor.index, + equation.destinationColorBlendFactor.index, + equation.alphaBlendOperation.index, + equation.sourceAlphaBlendFactor.index, + equation.destinationAlphaBlendFactor.index); + } + + void setDepthWriteEnable(bool enable) { + _setDepthWriteEnable(enable); + } + + void setDepthCompareOperation(CompareFunction compareFunction) { + _setDepthCompareOperation(compareFunction.index); + } + void draw() { if (!_draw()) { throw Exception("Failed to append draw"); @@ -97,15 +214,29 @@ base class RenderPass extends NativeFieldWrapperClass1 { symbol: 'InternalFlutterGpu_RenderPass_Initialize') external void _initialize(); - @Native, Int, Int, Int, Pointer, Handle)>( - symbol: 'InternalFlutterGpu_RenderPass_SetColorAttachment') - external String? _setColorAttachment(int loadAction, int storeAction, - int clearColor, Texture texture, Texture? resolveTexture); + @Native< + Handle Function(Pointer, Int, Int, Int, Int, Pointer, + Handle)>(symbol: 'InternalFlutterGpu_RenderPass_SetColorAttachment') + external String? _setColorAttachment( + int colorAttachmentIndex, + int loadAction, + int storeAction, + int clearColor, + Texture texture, + Texture? resolveTexture); - @Native, Int, Int, Int, Pointer)>( - symbol: 'InternalFlutterGpu_RenderPass_SetStencilAttachment') - external String? _setStencilAttachment( - int loadAction, int storeAction, int clearStencil, Texture texture); + @Native< + Handle Function( + Pointer, Int, Int, Float, Int, Int, Int, Pointer)>( + symbol: 'InternalFlutterGpu_RenderPass_SetDepthStencilAttachment') + external String? _setDepthStencilAttachment( + int depthLoadAction, + int depthStoreAction, + double depthClearValue, + int stencilLoadAction, + int stencilStoreAction, + int stencilClearValue, + Texture texture); @Native, Pointer)>( symbol: 'InternalFlutterGpu_RenderPass_Begin') @@ -125,6 +256,16 @@ base class RenderPass extends NativeFieldWrapperClass1 { external void _bindVertexBufferHost( HostBuffer buffer, int offsetInBytes, int lengthInBytes, int vertexCount); + @Native, Pointer, Int, Int, Int, Int)>( + symbol: 'InternalFlutterGpu_RenderPass_BindIndexBufferDevice') + external void _bindIndexBufferDevice(DeviceBuffer buffer, int offsetInBytes, + int lengthInBytes, int indexType, int indexCount); + + @Native, Pointer, Int, Int, Int, Int)>( + symbol: 'InternalFlutterGpu_RenderPass_BindIndexBufferHost') + external void _bindIndexBufferHost(HostBuffer buffer, int offsetInBytes, + int lengthInBytes, int indexType, int indexCount); + @Native, Int, Int, Pointer, Int, Int)>( symbol: 'InternalFlutterGpu_RenderPass_BindUniformDevice') external bool _bindUniformDevice(int stage, int slotId, DeviceBuffer buffer, @@ -135,6 +276,46 @@ base class RenderPass extends NativeFieldWrapperClass1 { external bool _bindUniformHost(int stage, int slotId, HostBuffer buffer, int offsetInBytes, int lengthInBytes); + @Native< + Bool Function(Pointer, Int, Int, Pointer, Int, Int, Int, Int, + Int)>(symbol: 'InternalFlutterGpu_RenderPass_BindTexture') + external bool _bindTexture( + int stage, + int slotId, + Texture texture, + int minFilter, + int magFilter, + int mipFilter, + int widthAddressMode, + int heightAddressMode); + + @Native)>( + symbol: 'InternalFlutterGpu_RenderPass_ClearBindings') + external void _clearBindings(); + + @Native, Int, Bool)>( + symbol: 'InternalFlutterGpu_RenderPass_SetColorBlendEnable') + external void _setColorBlendEnable(int colorAttachmentIndex, bool enable); + + @Native, Int, Int, Int, Int, Int, Int, Int)>( + symbol: 'InternalFlutterGpu_RenderPass_SetColorBlendEquation') + external void _setColorBlendEquation( + int colorAttachmentIndex, + int colorBlendOperation, + int sourceColorBlendFactor, + int destinationColorBlendFactor, + int alphaBlendOperation, + int sourceAlphaBlendFactor, + int destinationAlphaBlendFactor); + + @Native, Bool)>( + symbol: 'InternalFlutterGpu_RenderPass_SetDepthWriteEnable') + external void _setDepthWriteEnable(bool enable); + + @Native, Int)>( + symbol: 'InternalFlutterGpu_RenderPass_SetDepthCompareOperation') + external void _setDepthCompareOperation(int compareOperation); + @Native)>( symbol: 'InternalFlutterGpu_RenderPass_Draw') external bool _draw(); diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index 08fbae379368d..8dd9403d2935f 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -9,10 +9,12 @@ #include "fml/memory/ref_ptr.h" #include "impeller/core/buffer_view.h" #include "impeller/core/formats.h" +#include "impeller/core/sampler_descriptor.h" #include "impeller/core/shader_types.h" #include "impeller/core/vertex_buffer.h" #include "impeller/geometry/color.h" #include "impeller/renderer/pipeline_library.h" +#include "impeller/renderer/sampler_library.h" #include "tonic/converter/dart_converter.h" namespace flutter { @@ -46,6 +48,20 @@ const impeller::RenderTarget& RenderPass::GetRenderTarget() const { return render_target_; } +impeller::ColorAttachmentDescriptor& RenderPass::GetColorAttachmentDescriptor( + size_t color_attachment_index) { + auto color = color_descriptors_.find(color_attachment_index); + if (color == color_descriptors_.end()) { + return color_descriptors_[color_attachment_index] = {}; + } + return color->second; +} + +impeller::DepthAttachmentDescriptor& +RenderPass::GetDepthAttachmentDescriptor() { + return depth_desc_; +} + impeller::VertexBuffer& RenderPass::GetVertexBuffer() { return vertex_buffer_; } @@ -68,27 +84,35 @@ std::shared_ptr> RenderPass::GetOrCreatePipeline() { // Infer the pipeline layout based on the shape of the RenderTarget. auto pipeline_desc = pipeline_descriptor_; - { - FML_DCHECK(render_target_.HasColorAttachment(0)) - << "The render target has no color attachment. This should never " - "happen."; - color_desc_.format = render_target_.GetRenderTargetPixelFormat(); - pipeline_desc.SetColorAttachmentDescriptor(0, color_desc_); + for (const auto& it : render_target_.GetColorAttachments()) { + auto& color = GetColorAttachmentDescriptor(it.first); + color.format = render_target_.GetRenderTargetPixelFormat(); } + pipeline_desc.SetColorAttachmentDescriptors(color_descriptors_); - if (auto stencil = render_target_.GetStencilAttachment()) { - pipeline_desc.SetStencilPixelFormat( - stencil->texture->GetTextureDescriptor().format); - pipeline_desc.SetStencilAttachmentDescriptors(stencil_front_desc_, - stencil_back_desc_); - } else { - pipeline_desc.ClearStencilAttachments(); + { + auto stencil = render_target_.GetStencilAttachment(); + if (stencil && impeller::IsStencilWritable( + stencil->texture->GetTextureDescriptor().format)) { + pipeline_desc.SetStencilPixelFormat( + stencil->texture->GetTextureDescriptor().format); + pipeline_desc.SetStencilAttachmentDescriptors(stencil_front_desc_, + stencil_back_desc_); + } else { + pipeline_desc.ClearStencilAttachments(); + } } - if (auto depth = render_target_.GetDepthAttachment()) { - pipeline_desc.SetDepthStencilAttachmentDescriptor(depth_desc_); - } else { - pipeline_desc.ClearDepthAttachment(); + { + auto depth = render_target_.GetDepthAttachment(); + if (depth && impeller::IsDepthWritable( + depth->texture->GetTextureDescriptor().format)) { + pipeline_desc.SetDepthPixelFormat( + depth->texture->GetTextureDescriptor().format); + pipeline_desc.SetDepthStencilAttachmentDescriptor(depth_desc_); + } else { + pipeline_desc.ClearDepthAttachment(); + } } auto& context = *GetContext().lock(); @@ -137,16 +161,15 @@ void InternalFlutterGpu_RenderPass_Initialize(Dart_Handle wrapper) { Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( flutter::gpu::RenderPass* wrapper, + int color_attachment_index, int load_action, int store_action, int clear_color, flutter::gpu::Texture* texture, Dart_Handle resolve_texture_wrapper) { impeller::ColorAttachment desc; - desc.load_action = flutter::gpu::ToImpellerLoadAction( - static_cast(load_action)); - desc.store_action = flutter::gpu::ToImpellerStoreAction( - static_cast(store_action)); + desc.load_action = flutter::gpu::ToImpellerLoadAction(load_action); + desc.store_action = flutter::gpu::ToImpellerStoreAction(store_action); desc.clear_color = ToImpellerColor(static_cast(clear_color)); desc.texture = texture->GetTexture(); if (!Dart_IsNull(resolve_texture_wrapper)) { @@ -155,24 +178,37 @@ Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( resolve_texture_wrapper); desc.resolve_texture = resolve_texture->GetTexture(); } - wrapper->GetRenderTarget().SetColorAttachment(desc, 0); + wrapper->GetRenderTarget().SetColorAttachment(desc, color_attachment_index); return Dart_Null(); } -Dart_Handle InternalFlutterGpu_RenderPass_SetStencilAttachment( +Dart_Handle InternalFlutterGpu_RenderPass_SetDepthStencilAttachment( flutter::gpu::RenderPass* wrapper, - int load_action, - int store_action, - int clear_stencil, + int depth_load_action, + int depth_store_action, + float depth_clear_value, + int stencil_load_action, + int stencil_store_action, + int stencil_clear_value, flutter::gpu::Texture* texture) { - impeller::StencilAttachment desc; - desc.load_action = flutter::gpu::ToImpellerLoadAction( - static_cast(load_action)); - desc.store_action = flutter::gpu::ToImpellerStoreAction( - static_cast(store_action)); - desc.clear_stencil = clear_stencil; - desc.texture = texture->GetTexture(); - wrapper->GetRenderTarget().SetStencilAttachment(desc); + { + impeller::DepthAttachment desc; + desc.load_action = flutter::gpu::ToImpellerLoadAction(depth_load_action); + desc.store_action = flutter::gpu::ToImpellerStoreAction(depth_store_action); + desc.clear_depth = depth_clear_value; + desc.texture = texture->GetTexture(); + wrapper->GetRenderTarget().SetDepthAttachment(desc); + } + { + impeller::StencilAttachment desc; + desc.load_action = flutter::gpu::ToImpellerLoadAction(stencil_load_action); + desc.store_action = + flutter::gpu::ToImpellerStoreAction(stencil_store_action); + desc.clear_stencil = stencil_clear_value; + desc.texture = texture->GetTexture(); + wrapper->GetRenderTarget().SetStencilAttachment(desc); + } + return Dart_Null(); } @@ -203,7 +239,17 @@ static void BindVertexBuffer(flutter::gpu::RenderPass* wrapper, .buffer = buffer->GetBuffer(), .range = impeller::Range(offset_in_bytes, length_in_bytes), }; - vertex_buffer.vertex_count = vertex_count; + // If the index type is set, then the `vertex_count` becomes the index + // count... So don't overwrite the count if it's already been set when binding + // the index buffer. + // TODO(bdero): Consider just doing a more traditional API with + // draw(vertexCount) and drawIndexed(indexCount). This is fine, + // but overall it would be a bit more explicit and we wouldn't + // have to document this behavior where the presence of the index + // buffer always takes precedent. + if (vertex_buffer.index_type == impeller::IndexType::kNone) { + vertex_buffer.vertex_count = vertex_count; + } } void InternalFlutterGpu_RenderPass_BindVertexBufferDevice( @@ -226,6 +272,44 @@ void InternalFlutterGpu_RenderPass_BindVertexBufferHost( vertex_count); } +template +static void BindIndexBuffer(flutter::gpu::RenderPass* wrapper, + TBuffer* buffer, + int offset_in_bytes, + int length_in_bytes, + int index_type, + int index_count) { + auto& vertex_buffer = wrapper->GetVertexBuffer(); + vertex_buffer.index_buffer = impeller::BufferView{ + .buffer = buffer->GetBuffer(), + .range = impeller::Range(offset_in_bytes, length_in_bytes), + }; + vertex_buffer.index_type = flutter::gpu::ToImpellerIndexType(index_type); + vertex_buffer.vertex_count = index_count; +} + +void InternalFlutterGpu_RenderPass_BindIndexBufferDevice( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::DeviceBuffer* device_buffer, + int offset_in_bytes, + int length_in_bytes, + int index_type, + int index_count) { + BindIndexBuffer(wrapper, device_buffer, offset_in_bytes, length_in_bytes, + index_type, index_count); +} + +void InternalFlutterGpu_RenderPass_BindIndexBufferHost( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::HostBuffer* host_buffer, + int offset_in_bytes, + int length_in_bytes, + int index_type, + int index_count) { + BindIndexBuffer(wrapper, host_buffer, offset_in_bytes, length_in_bytes, + index_type, index_count); +} + template static bool BindUniform(flutter::gpu::RenderPass* wrapper, int stage, @@ -244,9 +328,7 @@ static bool BindUniform(flutter::gpu::RenderPass* wrapper, // even use it for anything. slot.ext_res_0 = slot_id; return command.BindResource( - flutter::gpu::ToImpellerShaderStage( - static_cast(stage)), - slot, metadata, + flutter::gpu::ToImpellerShaderStage(stage), slot, metadata, impeller::BufferView{ .buffer = buffer->GetBuffer(), .range = impeller::Range(offset_in_bytes, length_in_bytes), @@ -275,6 +357,97 @@ bool InternalFlutterGpu_RenderPass_BindUniformHost( length_in_bytes); } +bool InternalFlutterGpu_RenderPass_BindTexture( + flutter::gpu::RenderPass* wrapper, + int stage, + int slot_id, + flutter::gpu::Texture* texture, + int min_filter, + int mag_filter, + int mip_filter, + int width_address_mode, + int height_address_mode) { + auto& command = wrapper->GetCommand(); + + // TODO(113715): Populate this metadata once GLES is able to handle + // non-struct uniform names. + impeller::ShaderMetadata metadata; + + impeller::SamplerDescriptor sampler_desc; + sampler_desc.min_filter = flutter::gpu::ToImpellerMinMagFilter(min_filter); + sampler_desc.mag_filter = flutter::gpu::ToImpellerMinMagFilter(mag_filter); + sampler_desc.mip_filter = flutter::gpu::ToImpellerMipFilter(mip_filter); + sampler_desc.width_address_mode = + flutter::gpu::ToImpellerSamplerAddressMode(width_address_mode); + sampler_desc.height_address_mode = + flutter::gpu::ToImpellerSamplerAddressMode(height_address_mode); + auto sampler = wrapper->GetContext().lock()->GetSamplerLibrary()->GetSampler( + sampler_desc); + + impeller::SampledImageSlot image_slot; + image_slot.texture_index = slot_id; + image_slot.sampler_index = slot_id; + return command.BindResource(flutter::gpu::ToImpellerShaderStage(stage), + image_slot, metadata, texture->GetTexture(), + sampler); +} + +void InternalFlutterGpu_RenderPass_ClearBindings( + flutter::gpu::RenderPass* wrapper) { + auto& command = wrapper->GetCommand(); + command.vertex_count = 0; + command.vertex_bindings = {}; + command.fragment_bindings = {}; + command.index_buffer = {}; +} + +void InternalFlutterGpu_RenderPass_SetColorBlendEnable( + flutter::gpu::RenderPass* wrapper, + int color_attachment_index, + bool enable) { + auto& color = wrapper->GetColorAttachmentDescriptor(color_attachment_index); + color.blending_enabled = enable; +} + +void InternalFlutterGpu_RenderPass_SetColorBlendEquation( + flutter::gpu::RenderPass* wrapper, + int color_attachment_index, + int color_blend_operation, + int source_color_blend_factor, + int destination_color_blend_factor, + int alpha_blend_operation, + int source_alpha_blend_factor, + int destination_alpha_blend_factor) { + auto& color = wrapper->GetColorAttachmentDescriptor(color_attachment_index); + color.color_blend_op = + flutter::gpu::ToImpellerBlendOperation(color_blend_operation); + color.src_color_blend_factor = + flutter::gpu::ToImpellerBlendFactor(source_color_blend_factor); + color.dst_color_blend_factor = + flutter::gpu::ToImpellerBlendFactor(destination_color_blend_factor); + color.alpha_blend_op = + flutter::gpu::ToImpellerBlendOperation(alpha_blend_operation); + color.src_alpha_blend_factor = + flutter::gpu::ToImpellerBlendFactor(source_alpha_blend_factor); + color.dst_alpha_blend_factor = + flutter::gpu::ToImpellerBlendFactor(destination_alpha_blend_factor); +} + +void InternalFlutterGpu_RenderPass_SetDepthWriteEnable( + flutter::gpu::RenderPass* wrapper, + bool enable) { + auto& depth = wrapper->GetDepthAttachmentDescriptor(); + depth.depth_write_enabled = true; +} + +void InternalFlutterGpu_RenderPass_SetDepthCompareOperation( + flutter::gpu::RenderPass* wrapper, + int compare_operation) { + auto& depth = wrapper->GetDepthAttachmentDescriptor(); + depth.depth_compare = + flutter::gpu::ToImpellerCompareFunction(compare_operation); +} + bool InternalFlutterGpu_RenderPass_Draw(flutter::gpu::RenderPass* wrapper) { return wrapper->Draw(); } diff --git a/lib/gpu/render_pass.h b/lib/gpu/render_pass.h index 77bfd1e7f9b05..68b4dc1279808 100644 --- a/lib/gpu/render_pass.h +++ b/lib/gpu/render_pass.h @@ -4,11 +4,13 @@ #pragma once +#include #include #include "flutter/lib/gpu/command_buffer.h" #include "flutter/lib/gpu/export.h" #include "flutter/lib/ui/dart_wrapper.h" #include "fml/memory/ref_ptr.h" +#include "impeller/core/formats.h" #include "impeller/core/vertex_buffer.h" #include "impeller/renderer/command.h" #include "impeller/renderer/render_pass.h" @@ -38,6 +40,11 @@ class RenderPass : public RefCountedDartWrappable { impeller::RenderTarget& GetRenderTarget(); const impeller::RenderTarget& GetRenderTarget() const; + impeller::ColorAttachmentDescriptor& GetColorAttachmentDescriptor( + size_t color_attachment_index); + + impeller::DepthAttachmentDescriptor& GetDepthAttachmentDescriptor(); + impeller::VertexBuffer& GetVertexBuffer(); bool Begin(flutter::gpu::CommandBuffer& command_buffer); @@ -64,7 +71,7 @@ class RenderPass : public RefCountedDartWrappable { // Pipeline descriptor layout state. We always keep track of this state, but // we'll only apply it as necessary to match the RenderTarget. - impeller::ColorAttachmentDescriptor color_desc_; + std::map color_descriptors_; impeller::StencilAttachmentDescriptor stencil_front_desc_; impeller::StencilAttachmentDescriptor stencil_back_desc_; impeller::DepthAttachmentDescriptor depth_desc_; @@ -90,6 +97,7 @@ extern void InternalFlutterGpu_RenderPass_Initialize(Dart_Handle wrapper); FLUTTER_GPU_EXPORT extern Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( flutter::gpu::RenderPass* wrapper, + int color_attachment_index, int load_action, int store_action, int clear_color, @@ -97,11 +105,14 @@ extern Dart_Handle InternalFlutterGpu_RenderPass_SetColorAttachment( Dart_Handle resolve_texture_wrapper); FLUTTER_GPU_EXPORT -extern Dart_Handle InternalFlutterGpu_RenderPass_SetStencilAttachment( +extern Dart_Handle InternalFlutterGpu_RenderPass_SetDepthStencilAttachment( flutter::gpu::RenderPass* wrapper, - int load_action, - int store_action, - int clear_stencil, + int depth_load_action, + int depth_store_action, + float depth_clear_value, + int stencil_load_action, + int stencil_store_action, + int stencil_clear_value, flutter::gpu::Texture* texture); FLUTTER_GPU_EXPORT @@ -130,6 +141,24 @@ extern void InternalFlutterGpu_RenderPass_BindVertexBufferHost( int length_in_bytes, int vertex_count); +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_BindIndexBufferDevice( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::DeviceBuffer* device_buffer, + int offset_in_bytes, + int length_in_bytes, + int index_type, + int index_count); + +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_BindIndexBufferHost( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::HostBuffer* host_buffer, + int offset_in_bytes, + int length_in_bytes, + int index_type, + int index_count); + FLUTTER_GPU_EXPORT extern bool InternalFlutterGpu_RenderPass_BindUniformDevice( flutter::gpu::RenderPass* wrapper, @@ -148,6 +177,49 @@ extern bool InternalFlutterGpu_RenderPass_BindUniformHost( int offset_in_bytes, int length_in_bytes); +FLUTTER_GPU_EXPORT +extern bool InternalFlutterGpu_RenderPass_BindTexture( + flutter::gpu::RenderPass* wrapper, + int stage, + int slot_id, + flutter::gpu::Texture* texture, + int min_filter, + int mag_filter, + int mip_filter, + int width_address_mode, + int height_address_mode); + +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_ClearBindings( + flutter::gpu::RenderPass* wrapper); + +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_SetColorBlendEnable( + flutter::gpu::RenderPass* wrapper, + int color_attachment_index, + bool enable); + +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_SetColorBlendEquation( + flutter::gpu::RenderPass* wrapper, + int color_attachment_index, + int color_blend_operation, + int source_color_blend_factor, + int destination_color_blend_factor, + int alpha_blend_operation, + int source_alpha_blend_factor, + int destination_alpha_blend_factor); + +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_SetDepthWriteEnable( + flutter::gpu::RenderPass* wrapper, + bool enable); + +FLUTTER_GPU_EXPORT +extern void InternalFlutterGpu_RenderPass_SetDepthCompareOperation( + flutter::gpu::RenderPass* wrapper, + int compare_operation); + FLUTTER_GPU_EXPORT extern bool InternalFlutterGpu_RenderPass_Draw( flutter::gpu::RenderPass* wrapper); diff --git a/lib/gpu/shader.cc b/lib/gpu/shader.cc index 0d6eb5d8fbc49..95df4f14ccd39 100644 --- a/lib/gpu/shader.cc +++ b/lib/gpu/shader.cc @@ -6,10 +6,11 @@ #include +#include "flutter/lib/gpu/formats.h" #include "fml/make_copyable.h" +#include "impeller/core/runtime_types.h" #include "impeller/renderer/shader_function.h" #include "impeller/renderer/shader_library.h" -#include "lib/gpu/shader_library.h" #include "tonic/converter/dart_converter.h" namespace flutter { @@ -27,6 +28,23 @@ fml::RefPtr Shader::Make( std::shared_ptr code_mapping, std::vector uniforms, std::shared_ptr vertex_desc) { + // Sampler/texture slots start at 0. See runtime_effect_contents.cc + // TODO(bdero): I'm skeptical about the correctness of this. Verify what + // happens with multiple texture samplers spaced apart with other + // uniforms in-between. + size_t minimum_sampler_index = 100000000; + for (const auto& uniform : uniforms) { + if (uniform.type == impeller::kSampledImage && + uniform.location < minimum_sampler_index) { + minimum_sampler_index = uniform.location; + } + } + for (auto& uniform : uniforms) { + if (uniform.type == impeller::kSampledImage) { + uniform.location -= minimum_sampler_index; + } + } + auto shader = fml::MakeRefCounted(); shader->entrypoint_ = std::move(entrypoint); shader->stage_ = stage; @@ -92,7 +110,8 @@ int Shader::GetUniformSlot(const std::string& name) const { /// int InternalFlutterGpu_Shader_GetShaderStage(flutter::gpu::Shader* wrapper) { - return static_cast(wrapper->GetShaderStage()); + return static_cast( + flutter::gpu::FromImpellerShaderStage(wrapper->GetShaderStage())); } int InternalFlutterGpu_Shader_GetUniformSlot(flutter::gpu::Shader* wrapper, diff --git a/lib/gpu/shader_library.cc b/lib/gpu/shader_library.cc index 3abea3e574e6f..c82fbcc5862f3 100644 --- a/lib/gpu/shader_library.cc +++ b/lib/gpu/shader_library.cc @@ -26,28 +26,38 @@ static fml::RefPtr OpenRuntimeStageAsShader( stage.GetCodeMapping(), stage.GetUniforms(), vertex_desc); } -static void InstantiateTestShaderLibrary() { +static fml::RefPtr InstantiateTestShaderLibrary() { ShaderLibrary::ShaderMap shaders; - auto vertex_desc = std::make_shared(); - vertex_desc->SetStageInputs( - // TODO(bdero): The stage inputs need to be packed into the flatbuffer. - FlutterGPUUnlitVertexShader::kAllShaderStageInputs, - // TODO(bdero): Make the vertex attribute layout fully configurable. - // When encoding commands, allow for specifying a stride, - // type, and vertex buffer slot for each attribute. - // Provide a way to lookup vertex attribute slot locations by - // name from the shader. - FlutterGPUUnlitVertexShader::kInterleavedBufferLayout); - shaders["UnlitVertex"] = OpenRuntimeStageAsShader( - std::make_shared(kFlutterGPUUnlitVertIPLR, - kFlutterGPUUnlitVertIPLRLength), - vertex_desc); - shaders["UnlitFragment"] = OpenRuntimeStageAsShader( - std::make_shared(kFlutterGPUUnlitFragIPLR, - kFlutterGPUUnlitFragIPLRLength), - nullptr); + { + auto vertex_desc = std::make_shared(); + vertex_desc->SetStageInputs( + FlutterGPUUnlitVertexShader::kAllShaderStageInputs, + FlutterGPUUnlitVertexShader::kInterleavedBufferLayout); + shaders["UnlitVertex"] = OpenRuntimeStageAsShader( + std::make_shared(kFlutterGPUUnlitVertIPLR, + kFlutterGPUUnlitVertIPLRLength), + vertex_desc); + shaders["UnlitFragment"] = OpenRuntimeStageAsShader( + std::make_shared(kFlutterGPUUnlitFragIPLR, + kFlutterGPUUnlitFragIPLRLength), + nullptr); + } + { + auto vertex_desc = std::make_shared(); + vertex_desc->SetStageInputs( + FlutterGPUTextureVertexShader::kAllShaderStageInputs, + FlutterGPUTextureVertexShader::kInterleavedBufferLayout); + shaders["TextureVertex"] = OpenRuntimeStageAsShader( + std::make_shared( + kFlutterGPUTextureVertIPLR, kFlutterGPUTextureVertIPLRLength), + vertex_desc); + shaders["TextureFragment"] = OpenRuntimeStageAsShader( + std::make_shared( + kFlutterGPUTextureFragIPLR, kFlutterGPUTextureFragIPLRLength), + nullptr); + } auto library = ShaderLibrary::MakeFromShaders(std::move(shaders)); - ShaderLibrary::SetOverride(library); + return library; } // ===[ END MEMES ]============================================================= @@ -61,7 +71,9 @@ fml::RefPtr ShaderLibrary::MakeFromAsset( // =========================================================================== // This is a temporary hack to get the shader library populated in the // framework before the shader bundle format is landed! - InstantiateTestShaderLibrary(); + if (!override_shader_library_) { + return InstantiateTestShaderLibrary(); + } // =========================================================================== if (override_shader_library_) { diff --git a/lib/gpu/texture.cc b/lib/gpu/texture.cc index 49382e631f16d..3ef47da36c67d 100644 --- a/lib/gpu/texture.cc +++ b/lib/gpu/texture.cc @@ -83,11 +83,9 @@ bool InternalFlutterGpu_Texture_Initialize(Dart_Handle wrapper, bool enable_shader_read_usage, bool enable_shader_write_usage) { impeller::TextureDescriptor desc; - desc.storage_mode = flutter::gpu::ToImpellerStorageMode( - static_cast(storage_mode)); + desc.storage_mode = flutter::gpu::ToImpellerStorageMode(storage_mode); desc.size = {width, height}; - desc.format = flutter::gpu::ToImpellerPixelFormat( - static_cast(format)); + desc.format = flutter::gpu::ToImpellerPixelFormat(format); desc.usage = 0; if (enable_render_target_usage) { desc.usage |= static_cast( @@ -120,9 +118,8 @@ bool InternalFlutterGpu_Texture_Initialize(Dart_Handle wrapper, return false; } - texture->SetCoordinateSystem(flutter::gpu::ToImpellerTextureCoordinateSystem( - static_cast( - coordinate_system))); + texture->SetCoordinateSystem( + flutter::gpu::ToImpellerTextureCoordinateSystem(coordinate_system)); auto res = fml::MakeRefCounted(std::move(texture)); res->AssociateWithDartWrapper(wrapper); @@ -134,9 +131,7 @@ void InternalFlutterGpu_Texture_SetCoordinateSystem( flutter::gpu::Texture* wrapper, int coordinate_system) { return wrapper->SetCoordinateSystem( - flutter::gpu::ToImpellerTextureCoordinateSystem( - static_cast( - coordinate_system))); + flutter::gpu::ToImpellerTextureCoordinateSystem(coordinate_system)); } bool InternalFlutterGpu_Texture_Overwrite(flutter::gpu::Texture* texture,