diff --git a/engine/src/flutter/impeller/compiler/code_gen_template.h b/engine/src/flutter/impeller/compiler/code_gen_template.h index a93b8fd3bdc..326a4464773 100644 --- a/engine/src/flutter/impeller/compiler/code_gen_template.h +++ b/engine/src/flutter/impeller/compiler/code_gen_template.h @@ -80,15 +80,10 @@ struct {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader { // =========================================================================== {% for sampled_image in sampled_images %} - static constexpr auto kInput{{camel_case(sampled_image.name)}} = ShaderStageIOSlot { // {{sampled_image.name}} - "{{sampled_image.name}}", // name - {{sampled_image.location}}u, // attribute location - {{sampled_image.descriptor_set}}u, // attribute set - {{sampled_image.binding}}u, // attribute binding - {{sampled_image.type.type_name}}, // type - {{sampled_image.type.bit_width}}u, // bit width of type - {{sampled_image.type.vec_size}}u, // vec size - {{sampled_image.type.columns}}u // number of columns + static constexpr auto kSampledImage{{camel_case(sampled_image.name)}} = SampledImageSlot { // {{sampled_image.name}} + "{{sampled_image.name}}", // name + {{sampled_image.msl_res_0}}u, // auto primary + {{sampled_image.msl_res_1}}u, // auto secondary }; {% endfor %} {% endif %} diff --git a/engine/src/flutter/impeller/compiler/reflector.cc b/engine/src/flutter/impeller/compiler/reflector.cc index db6c3400732..efdb1f3c90d 100644 --- a/engine/src/flutter/impeller/compiler/reflector.cc +++ b/engine/src/flutter/impeller/compiler/reflector.cc @@ -284,6 +284,14 @@ std::optional Reflector::ReflectResource( resource.id, spv::Decoration::DecorationLocation); result["index"] = compiler_->get_decoration(resource.id, spv::Decoration::DecorationIndex); + result["msl_res_0"] = + compiler_->get_automatic_msl_resource_binding(resource.id); + result["msl_res_1"] = + compiler_->get_automatic_msl_resource_binding_secondary(resource.id); + result["msl_res_2"] = + compiler_->get_automatic_msl_resource_binding_tertiary(resource.id); + result["msl_res_3"] = + compiler_->get_automatic_msl_resource_binding_quaternary(resource.id); auto type = ReflectType(resource.type_id); if (!type.has_value()) { return std::nullopt; diff --git a/engine/src/flutter/impeller/playground/playground.h b/engine/src/flutter/impeller/playground/playground.h index 081e24a9e91..dfd6179be20 100644 --- a/engine/src/flutter/impeller/playground/playground.h +++ b/engine/src/flutter/impeller/playground/playground.h @@ -6,6 +6,7 @@ #include "flutter/fml/macros.h" #include "gtest/gtest.h" #include "impeller/compositor/renderer.h" +#include "impeller/compositor/texture.h" namespace impeller { @@ -19,6 +20,9 @@ class Playground : public ::testing::Test { bool OpenPlaygroundHere(Renderer::RenderCallback render_callback); + std::shared_ptr CreateTextureForFixture( + const char* fixture_name) const; + private: Renderer renderer_; diff --git a/engine/src/flutter/impeller/playground/playground.mm b/engine/src/flutter/impeller/playground/playground.mm index 387beb894a3..3bf2b117dec 100644 --- a/engine/src/flutter/impeller/playground/playground.mm +++ b/engine/src/flutter/impeller/playground/playground.mm @@ -6,11 +6,13 @@ #include "flutter/fml/paths.h" #include "flutter/testing/testing.h" +#include "impeller/compositor/allocator.h" #include "impeller/compositor/context.h" #include "impeller/compositor/formats_metal.h" #include "impeller/compositor/render_pass.h" #include "impeller/compositor/renderer.h" #include "impeller/compositor/surface.h" +#include "impeller/image/compressed_image.h" #include "impeller/playground/playground.h" #define GLFW_INCLUDE_NONE @@ -144,4 +146,37 @@ bool Playground::OpenPlaygroundHere(Renderer::RenderCallback render_callback) { return true; } +std::shared_ptr Playground::CreateTextureForFixture( + const char* fixture_name) const { + CompressedImage compressed_image( + flutter::testing::OpenFixtureAsMapping(fixture_name)); + auto image = compressed_image.Decode().ConvertToRGBA(); + if (!image.IsValid()) { + FML_LOG(ERROR) << "Could not find fixture named " << fixture_name; + return nullptr; + } + auto texture_descriptor = TextureDescriptor::MakeFromImageResult(image); + if (!texture_descriptor.has_value()) { + FML_LOG(ERROR) << "Could not figure out texture descriptor for fixture " + << fixture_name; + return nullptr; + } + auto texture = + renderer_.GetContext()->GetPermanentsAllocator()->CreateTexture( + StorageMode::kHostVisible, texture_descriptor.value()); + if (!texture) { + FML_LOG(ERROR) << "Could not allocate texture for fixture " << fixture_name; + return nullptr; + } + texture->SetLabel(fixture_name); + auto uploaded = texture->SetContents(image.GetAllocation()->GetMapping(), + image.GetAllocation()->GetSize()); + if (!uploaded) { + FML_LOG(ERROR) << "Could not upload texture to device memory for fixture " + << fixture_name; + return nullptr; + } + return texture; +} + } // namespace impeller diff --git a/engine/src/flutter/impeller/primitives/box.frag b/engine/src/flutter/impeller/primitives/box.frag index c1d0500b372..2e07bddef33 100644 --- a/engine/src/flutter/impeller/primitives/box.frag +++ b/engine/src/flutter/impeller/primitives/box.frag @@ -2,13 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +uniform FrameInfo { + float current_time; +} frame; + in vec4 color; in vec2 interporlated_texture_coordinates; out vec4 frag_color; -uniform sampler2D contents_texture; +uniform sampler2D contents1_texture; +uniform sampler2D contents2_texture; void main() { - frag_color = texture(contents_texture, interporlated_texture_coordinates); + vec4 tex1 = texture(contents1_texture, interporlated_texture_coordinates); + vec4 tex2 = texture(contents2_texture, interporlated_texture_coordinates); + frag_color = mix(tex1, tex2, frame.current_time - floor(frame.current_time)); } diff --git a/engine/src/flutter/impeller/primitives/primitives_unittests.mm b/engine/src/flutter/impeller/primitives/primitives_unittests.mm index 2c81ea01dc3..2aae7c5c213 100644 --- a/engine/src/flutter/impeller/primitives/primitives_unittests.mm +++ b/engine/src/flutter/impeller/primitives/primitives_unittests.mm @@ -47,20 +47,9 @@ TEST_F(PrimitivesTest, CanCreateBoxPrimitive) { vertex_builder.CreateVertexBuffer(*context->GetPermanentsAllocator()); ASSERT_TRUE(vertex_buffer); - // Contents texture. - CompressedImage compressed_image( - flutter::testing::OpenFixtureAsMapping("bay_bridge.jpg")); - auto image = compressed_image.Decode().ConvertToRGBA(); - ASSERT_TRUE(image.IsValid()); - auto texture_descriptor = TextureDescriptor::MakeFromImageResult(image); - ASSERT_TRUE(texture_descriptor.has_value()); - auto texture = context->GetPermanentsAllocator()->CreateTexture( - StorageMode::kHostVisible, texture_descriptor.value()); - ASSERT_TRUE(texture); - texture->SetLabel("Bay Bridge"); - auto uploaded = texture->SetContents(image.GetAllocation()->GetMapping(), - image.GetAllocation()->GetSize()); - ASSERT_TRUE(uploaded); + auto bridge = CreateTextureForFixture("bay_bridge.jpg"); + auto boston = CreateTextureForFixture("boston.jpg"); + ASSERT_TRUE(bridge && boston); auto sampler = context->GetSamplerLibrary()->GetSampler({}); ASSERT_TRUE(sampler); Renderer::RenderCallback callback = [&](const Surface& surface, @@ -78,10 +67,23 @@ TEST_F(PrimitivesTest, CanCreateBoxPrimitive) { .buffers[BoxVertexShader::kUniformUniformBuffer.binding] = pass.GetTransientsBuffer().EmplaceUniform(uniforms); + BoxFragmentShader::FrameInfo frame_info; + frame_info.current_time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF(); cmd.fragment_bindings - .textures[BoxFragmentShader::kInputContentsTexture.location] = texture; + .buffers[BoxFragmentShader::kUniformFrameInfo.binding] = + pass.GetTransientsBuffer().EmplaceUniform(frame_info); cmd.fragment_bindings - .samplers[BoxFragmentShader::kInputContentsTexture.location] = sampler; + .textures[BoxFragmentShader::kSampledImageContents1Texture + .texture_index] = bridge; + cmd.fragment_bindings + .samplers[BoxFragmentShader::kSampledImageContents1Texture + .sampler_index] = sampler; + cmd.fragment_bindings + .textures[BoxFragmentShader::kSampledImageContents2Texture + .texture_index] = boston; + cmd.fragment_bindings + .samplers[BoxFragmentShader::kSampledImageContents2Texture + .sampler_index] = sampler; cmd.index_buffer = vertex_buffer.index_buffer; cmd.index_count = vertex_buffer.index_count; diff --git a/engine/src/flutter/impeller/shader_glue/shader_types.h b/engine/src/flutter/impeller/shader_glue/shader_types.h index d13ab4d2ce1..90458296817 100644 --- a/engine/src/flutter/impeller/shader_glue/shader_types.h +++ b/engine/src/flutter/impeller/shader_glue/shader_types.h @@ -58,6 +58,16 @@ struct ShaderStageIOSlot { size_t columns; }; +struct SampledImageSlot { + const char* name; + size_t texture_index; + size_t sampler_index; + + constexpr bool HasTexture() const { return texture_index < 32u; } + + constexpr bool HasSampler() const { return sampler_index < 32u; } +}; + template struct Padding { private: