diff --git a/impeller/fixtures/BUILD.gn b/impeller/fixtures/BUILD.gn index 6480392da6820..a52d020d65bfb 100644 --- a/impeller/fixtures/BUILD.gn +++ b/impeller/fixtures/BUILD.gn @@ -59,6 +59,7 @@ test_fixtures("file_fixtures") { "boston.jpg", "embarcadero.jpg", "flutter_logo.glb", + "flutter_logo_baked.png", "kalimba.jpg", "multiple_stages.hlsl", "resources_limit.vert", diff --git a/impeller/fixtures/flutter_logo_baked.png b/impeller/fixtures/flutter_logo_baked.png new file mode 100644 index 0000000000000..fe8477286e8fc Binary files /dev/null and b/impeller/fixtures/flutter_logo_baked.png differ diff --git a/impeller/playground/backend/gles/playground_impl_gles.cc b/impeller/playground/backend/gles/playground_impl_gles.cc index 999ccfbae07e5..a1441a7bf6e2f 100644 --- a/impeller/playground/backend/gles/playground_impl_gles.cc +++ b/impeller/playground/backend/gles/playground_impl_gles.cc @@ -68,7 +68,7 @@ PlaygroundImplGLES::PlaygroundImplGLES() ::glfwWindowHint(GLFW_GREEN_BITS, 8); ::glfwWindowHint(GLFW_BLUE_BITS, 8); ::glfwWindowHint(GLFW_ALPHA_BITS, 8); - ::glfwWindowHint(GLFW_DEPTH_BITS, 0); // no depth buffer + ::glfwWindowHint(GLFW_DEPTH_BITS, 32); // 32 bit depth buffer ::glfwWindowHint(GLFW_STENCIL_BITS, 8); // 8 bit stencil buffer ::glfwWindowHint(GLFW_SAMPLES, 4); // 4xMSAA diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc index 4cfb98b93e80e..bc7137ae1e1f7 100644 --- a/impeller/playground/playground.cc +++ b/impeller/playground/playground.cc @@ -263,35 +263,8 @@ bool Playground::OpenPlaygroundHere( } render_target.SetColorAttachment(color0, 0); -#ifndef IMPELLER_ENABLE_VULKAN - { - TextureDescriptor stencil0_tex; - stencil0_tex.storage_mode = StorageMode::kDeviceTransient; - stencil0_tex.type = TextureType::kTexture2D; - stencil0_tex.sample_count = SampleCount::kCount1; - stencil0_tex.format = PixelFormat::kDefaultStencil; - stencil0_tex.size = color0.texture->GetSize(); - stencil0_tex.usage = - static_cast(TextureUsage::kRenderTarget); - auto stencil_texture = - renderer->GetContext()->GetResourceAllocator()->CreateTexture( - stencil0_tex); - - if (!stencil_texture) { - VALIDATION_LOG << "Could not create stencil texture."; - return false; - } - stencil_texture->SetLabel("ImguiStencil"); - - StencilAttachment stencil0; - stencil0.texture = stencil_texture; - stencil0.clear_stencil = 0; - stencil0.load_action = LoadAction::kClear; - stencil0.store_action = StoreAction::kDontCare; - - render_target.SetStencilAttachment(stencil0); - } -#endif + render_target.SetStencilAttachment(std::nullopt); + render_target.SetDepthAttachment(std::nullopt); auto pass = buffer->CreateRenderPass(render_target); if (!pass) { diff --git a/impeller/renderer/backend/gles/texture_gles.cc b/impeller/renderer/backend/gles/texture_gles.cc index e8a8f9b455721..e9346b7168e55 100644 --- a/impeller/renderer/backend/gles/texture_gles.cc +++ b/impeller/renderer/backend/gles/texture_gles.cc @@ -109,6 +109,7 @@ struct TexImage2DData { break; case PixelFormat::kUnknown: case PixelFormat::kS8UInt: + case PixelFormat::kD32FloatS8UInt: case PixelFormat::kR8UNormInt: case PixelFormat::kR8G8UNormInt: return; @@ -136,15 +137,11 @@ struct TexImage2DData { break; } case PixelFormat::kR8G8B8A8UNormIntSRGB: - return; case PixelFormat::kB8G8R8A8UNormInt: - return; case PixelFormat::kB8G8R8A8UNormIntSRGB: - return; case PixelFormat::kS8UInt: - return; + case PixelFormat::kD32FloatS8UInt: case PixelFormat::kR8UNormInt: - return; case PixelFormat::kR8G8UNormInt: return; } @@ -279,6 +276,8 @@ static std::optional ToRenderBufferFormat(PixelFormat format) { return GL_RGBA4; case PixelFormat::kS8UInt: return GL_STENCIL_INDEX8; + case PixelFormat::kD32FloatS8UInt: + return GL_DEPTH32F_STENCIL8; case PixelFormat::kUnknown: case PixelFormat::kA8UNormInt: case PixelFormat::kR8UNormInt: diff --git a/impeller/renderer/backend/metal/formats_mtl.h b/impeller/renderer/backend/metal/formats_mtl.h index 591ecb8d24cc8..fc4956bec212d 100644 --- a/impeller/renderer/backend/metal/formats_mtl.h +++ b/impeller/renderer/backend/metal/formats_mtl.h @@ -27,10 +27,12 @@ constexpr PixelFormat FromMTLPixelFormat(MTLPixelFormat format) { return PixelFormat::kB8G8R8A8UNormIntSRGB; case MTLPixelFormatRGBA8Unorm: return PixelFormat::kR8G8B8A8UNormInt; - case MTLPixelFormatStencil8: - return PixelFormat::kS8UInt; case MTLPixelFormatRGBA8Unorm_sRGB: return PixelFormat::kR8G8B8A8UNormIntSRGB; + case MTLPixelFormatStencil8: + return PixelFormat::kS8UInt; + case MTLPixelFormatDepth32Float_Stencil8: + return PixelFormat::kD32FloatS8UInt; default: return PixelFormat::kUnknown; } @@ -53,10 +55,12 @@ constexpr MTLPixelFormat ToMTLPixelFormat(PixelFormat format) { return MTLPixelFormatBGRA8Unorm_sRGB; case PixelFormat::kR8G8B8A8UNormInt: return MTLPixelFormatRGBA8Unorm; - case PixelFormat::kS8UInt: - return MTLPixelFormatStencil8; case PixelFormat::kR8G8B8A8UNormIntSRGB: return MTLPixelFormatRGBA8Unorm_sRGB; + case PixelFormat::kS8UInt: + return MTLPixelFormatStencil8; + case PixelFormat::kD32FloatS8UInt: + return MTLPixelFormatDepth32Float_Stencil8; } return MTLPixelFormatInvalid; }; diff --git a/impeller/renderer/backend/vulkan/formats_vk.h b/impeller/renderer/backend/vulkan/formats_vk.h index 70a4220347094..f0d56741b3255 100644 --- a/impeller/renderer/backend/vulkan/formats_vk.h +++ b/impeller/renderer/backend/vulkan/formats_vk.h @@ -150,6 +150,8 @@ constexpr vk::Format ToVKImageFormat(PixelFormat format) { return vk::Format::eB8G8R8A8Srgb; case PixelFormat::kS8UInt: return vk::Format::eS8Uint; + case PixelFormat::kD32FloatS8UInt: + return vk::Format::eD32SfloatS8Uint; case PixelFormat::kR8UNormInt: return vk::Format::eR8Unorm; case PixelFormat::kR8G8UNormInt: @@ -179,6 +181,9 @@ constexpr PixelFormat ToPixelFormat(vk::Format format) { case vk::Format::eS8Uint: return PixelFormat::kS8UInt; + case vk::Format::eD32SfloatS8Uint: + return PixelFormat::kD32FloatS8UInt; + case vk::Format::eR8Unorm: return PixelFormat::kR8UNormInt; diff --git a/impeller/renderer/formats.h b/impeller/renderer/formats.h index 945b7f87752ed..a35378dbde1ec 100644 --- a/impeller/renderer/formats.h +++ b/impeller/renderer/formats.h @@ -87,7 +87,10 @@ enum class PixelFormat { kR8G8B8A8UNormIntSRGB, kB8G8R8A8UNormInt, kB8G8R8A8UNormIntSRGB, + + // Depth and stencil formats. kS8UInt, + kD32FloatS8UInt, // Defaults. If you don't know which ones to use, these are usually a safe // bet. @@ -285,6 +288,8 @@ constexpr size_t BytesPerPixelForPixelFormat(PixelFormat format) { case PixelFormat::kB8G8R8A8UNormInt: case PixelFormat::kB8G8R8A8UNormIntSRGB: return 4u; + case PixelFormat::kD32FloatS8UInt: + return 5u; } return 0u; } diff --git a/impeller/renderer/render_target.cc b/impeller/renderer/render_target.cc index 7c13412a384fa..57f3d71c6893a 100644 --- a/impeller/renderer/render_target.cc +++ b/impeller/renderer/render_target.cc @@ -149,15 +149,21 @@ RenderTarget& RenderTarget::SetColorAttachment( return *this; } -RenderTarget& RenderTarget::SetDepthAttachment(DepthAttachment attachment) { - if (attachment.IsValid()) { +RenderTarget& RenderTarget::SetDepthAttachment( + std::optional attachment) { + if (!attachment.has_value()) { + depth_ = std::nullopt; + } else if (attachment->IsValid()) { depth_ = std::move(attachment); } return *this; } -RenderTarget& RenderTarget::SetStencilAttachment(StencilAttachment attachment) { - if (attachment.IsValid()) { +RenderTarget& RenderTarget::SetStencilAttachment( + std::optional attachment) { + if (!attachment.has_value()) { + stencil_ = std::nullopt; + } else if (attachment->IsValid()) { stencil_ = std::move(attachment); } return *this; diff --git a/impeller/renderer/render_target.h b/impeller/renderer/render_target.h index 802671afa8ad4..5951d5900cab6 100644 --- a/impeller/renderer/render_target.h +++ b/impeller/renderer/render_target.h @@ -61,9 +61,10 @@ class RenderTarget { RenderTarget& SetColorAttachment(const ColorAttachment& attachment, size_t index); - RenderTarget& SetDepthAttachment(DepthAttachment attachment); + RenderTarget& SetDepthAttachment(std::optional attachment); - RenderTarget& SetStencilAttachment(StencilAttachment attachment); + RenderTarget& SetStencilAttachment( + std::optional attachment); const std::map& GetColorAttachments() const; diff --git a/impeller/scene/material.cc b/impeller/scene/material.cc index a37b2bf51f631..b7bcbe882698f 100644 --- a/impeller/scene/material.cc +++ b/impeller/scene/material.cc @@ -55,6 +55,10 @@ void UnlitMaterial::SetColorTexture(std::shared_ptr color_texture) { color_texture_ = std::move(color_texture); } +void UnlitMaterial::SetVertexColorWeight(Scalar weight) { + vertex_color_weight_ = weight; +} + // |Material| std::shared_ptr> UnlitMaterial::GetPipeline( const SceneContext& scene_context, @@ -69,6 +73,7 @@ void UnlitMaterial::BindToCommand(const SceneContext& scene_context, // Uniform buffer. UnlitPipeline::FragmentShader::FragInfo info; info.color = color_; + info.vertex_color_weight = vertex_color_weight_; UnlitPipeline::FragmentShader::BindFragInfo(command, buffer.EmplaceUniform(info)); diff --git a/impeller/scene/material.h b/impeller/scene/material.h index a579467304846..7c5e1a2caf26b 100644 --- a/impeller/scene/material.h +++ b/impeller/scene/material.h @@ -66,6 +66,8 @@ class UnlitMaterial final : public Material { void SetColorTexture(std::shared_ptr color_texture); + void SetVertexColorWeight(Scalar weight); + // |Material| std::shared_ptr> GetPipeline( const SceneContext& scene_context, @@ -79,6 +81,7 @@ class UnlitMaterial final : public Material { private: Color color_ = Color::White(); std::shared_ptr color_texture_; + Scalar vertex_color_weight_ = 1; }; class StandardMaterial final : public Material { diff --git a/impeller/scene/scene_context.cc b/impeller/scene/scene_context.cc index dcf1ce81f0475..6a270b9d1ed31 100644 --- a/impeller/scene/scene_context.cc +++ b/impeller/scene/scene_context.cc @@ -10,6 +10,18 @@ namespace scene { void SceneContextOptions::ApplyToPipelineDescriptor( PipelineDescriptor& desc) const { + DepthAttachmentDescriptor depth; + depth.depth_compare = CompareFunction::kLess; + depth.depth_write_enabled = true; + desc.SetDepthStencilAttachmentDescriptor(depth); + desc.SetDepthPixelFormat(PixelFormat::kD32FloatS8UInt); + + StencilAttachmentDescriptor stencil; + stencil.stencil_compare = CompareFunction::kAlways; + stencil.depth_stencil_pass = StencilOperation::kKeep; + desc.SetStencilAttachmentDescriptors(stencil); + desc.SetStencilPixelFormat(PixelFormat::kD32FloatS8UInt); + desc.SetSampleCount(sample_count); desc.SetPrimitiveType(primitive_type); } diff --git a/impeller/scene/scene_encoder.cc b/impeller/scene/scene_encoder.cc index c4a460bca7f4e..1f3ffd8f7e549 100644 --- a/impeller/scene/scene_encoder.cc +++ b/impeller/scene/scene_encoder.cc @@ -49,7 +49,37 @@ static void EncodeCommand(const SceneContext& scene_context, std::shared_ptr SceneEncoder::BuildSceneCommandBuffer( const SceneContext& scene_context, const Camera& camera, - const RenderTarget& render_target) const { + RenderTarget render_target) const { + { + TextureDescriptor ds_texture; + ds_texture.type = TextureType::kTexture2DMultisample; + ds_texture.format = PixelFormat::kD32FloatS8UInt; + ds_texture.size = render_target.GetRenderTargetSize(); + ds_texture.usage = + static_cast(TextureUsage::kRenderTarget); + ds_texture.sample_count = SampleCount::kCount4; + ds_texture.storage_mode = StorageMode::kDeviceTransient; + auto texture = + scene_context.GetContext()->GetResourceAllocator()->CreateTexture( + ds_texture); + + DepthAttachment depth; + depth.load_action = LoadAction::kClear; + depth.store_action = StoreAction::kDontCare; + depth.clear_depth = 1.0; + depth.texture = texture; + render_target.SetDepthAttachment(depth); + + // The stencil and depth buffers must be the same texture for MacOS ARM + // and Vulkan. + StencilAttachment stencil; + stencil.load_action = LoadAction::kClear; + stencil.store_action = StoreAction::kDontCare; + stencil.clear_stencil = 0u; + stencil.texture = texture; + render_target.SetStencilAttachment(stencil); + } + auto command_buffer = scene_context.GetContext()->CreateCommandBuffer(); if (!command_buffer) { FML_LOG(ERROR) << "Failed to create command buffer."; diff --git a/impeller/scene/scene_encoder.h b/impeller/scene/scene_encoder.h index 208e4f51a0208..600dd727b3466 100644 --- a/impeller/scene/scene_encoder.h +++ b/impeller/scene/scene_encoder.h @@ -36,7 +36,7 @@ class SceneEncoder { std::shared_ptr BuildSceneCommandBuffer( const SceneContext& scene_context, const Camera& camera, - const RenderTarget& render_target) const; + RenderTarget render_target) const; std::vector commands_; diff --git a/impeller/scene/scene_unittests.cc b/impeller/scene/scene_unittests.cc index 44b25f7a7cf3a..b2a15adc01778 100644 --- a/impeller/scene/scene_unittests.cc +++ b/impeller/scene/scene_unittests.cc @@ -2,13 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include +#include + #include "flutter/testing/testing.h" #include "impeller/geometry/color.h" #include "impeller/geometry/constants.h" #include "impeller/geometry/matrix.h" +#include "impeller/geometry/quaternion.h" #include "impeller/geometry/vector.h" #include "impeller/playground/playground.h" #include "impeller/playground/playground_test.h" +#include "impeller/renderer/formats.h" #include "impeller/scene/camera.h" #include "impeller/scene/geometry.h" #include "impeller/scene/importer/scene_flatbuffers.h" @@ -80,18 +85,27 @@ TEST_P(SceneTest, GLTFScene) { auto geometry = Geometry::MakeFromFBMesh(*fb_mesh, *allocator); ASSERT_NE(geometry, nullptr); + std::shared_ptr material = Material::MakeUnlit(); + auto bridge = CreateTextureForFixture("flutter_logo_baked.png"); + material->SetColorTexture(bridge); + material->SetVertexColorWeight(0); + Renderer::RenderCallback callback = [&](RenderTarget& render_target) { auto scene = Scene(GetContext()); auto mesh = SceneEntity::MakeStaticMesh(); - mesh->SetMaterial(Material::MakeUnlit()); + mesh->SetMaterial(material); mesh->SetGeometry(geometry); + mesh->SetLocalTransform(Matrix::MakeScale({3, 3, 3})); scene.Add(mesh); + Quaternion rotation({0, 1, 0}, -GetSecondsElapsed() * 0.5); + Vector3 start_position(-1, -1.5, -5); + // Face towards the +Z direction (+X right, +Y up). auto camera = Camera::MakePerspective( - /* fov */ Radians(kPiOver4), - /* position */ {2, 2, -5}) + /* fov */ Degrees(60), + /* position */ rotation * start_position) .LookAt( /* target */ Vector3(), /* up */ {0, 1, 0}); diff --git a/impeller/scene/shaders/unlit.frag b/impeller/scene/shaders/unlit.frag index 7647aa3b29a2f..f9d8cd4173131 100644 --- a/impeller/scene/shaders/unlit.frag +++ b/impeller/scene/shaders/unlit.frag @@ -4,6 +4,7 @@ uniform FragInfo { vec4 color; + float vertex_color_weight; } frag_info; @@ -17,6 +18,7 @@ in vec4 v_color; out vec4 frag_color; void main() { - frag_color = - texture(base_color_texture, v_texture_coords) * v_color * frag_info.color; + vec4 vertex_color = mix(vec4(1), v_color, frag_info.vertex_color_weight); + frag_color = texture(base_color_texture, v_texture_coords) * vertex_color * + frag_info.color; }