[Impeller Scene] Depth attachment; baked lighting example (flutter/engine#38118)

* [Impeller Scene] Depth buffer; baked lighting example

* vk formats

* Remove kD24UNormS8UInt

* Address comments
This commit is contained in:
Brandon DeRosier 2022-12-07 14:11:30 -08:00 committed by GitHub
parent 0fab2ea52d
commit 5ad4bcdd38
16 changed files with 112 additions and 52 deletions

View File

@ -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",

View File

@ -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

View File

@ -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<TextureUsageMask>(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) {

View File

@ -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<GLenum> 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:

View File

@ -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;
};

View File

@ -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;

View File

@ -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;
}

View File

@ -149,15 +149,21 @@ RenderTarget& RenderTarget::SetColorAttachment(
return *this;
}
RenderTarget& RenderTarget::SetDepthAttachment(DepthAttachment attachment) {
if (attachment.IsValid()) {
RenderTarget& RenderTarget::SetDepthAttachment(
std::optional<DepthAttachment> 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<StencilAttachment> attachment) {
if (!attachment.has_value()) {
stencil_ = std::nullopt;
} else if (attachment->IsValid()) {
stencil_ = std::move(attachment);
}
return *this;

View File

@ -61,9 +61,10 @@ class RenderTarget {
RenderTarget& SetColorAttachment(const ColorAttachment& attachment,
size_t index);
RenderTarget& SetDepthAttachment(DepthAttachment attachment);
RenderTarget& SetDepthAttachment(std::optional<DepthAttachment> attachment);
RenderTarget& SetStencilAttachment(StencilAttachment attachment);
RenderTarget& SetStencilAttachment(
std::optional<StencilAttachment> attachment);
const std::map<size_t, ColorAttachment>& GetColorAttachments() const;

View File

@ -55,6 +55,10 @@ void UnlitMaterial::SetColorTexture(std::shared_ptr<Texture> color_texture) {
color_texture_ = std::move(color_texture);
}
void UnlitMaterial::SetVertexColorWeight(Scalar weight) {
vertex_color_weight_ = weight;
}
// |Material|
std::shared_ptr<Pipeline<PipelineDescriptor>> 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));

View File

@ -66,6 +66,8 @@ class UnlitMaterial final : public Material {
void SetColorTexture(std::shared_ptr<Texture> color_texture);
void SetVertexColorWeight(Scalar weight);
// |Material|
std::shared_ptr<Pipeline<PipelineDescriptor>> GetPipeline(
const SceneContext& scene_context,
@ -79,6 +81,7 @@ class UnlitMaterial final : public Material {
private:
Color color_ = Color::White();
std::shared_ptr<Texture> color_texture_;
Scalar vertex_color_weight_ = 1;
};
class StandardMaterial final : public Material {

View File

@ -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);
}

View File

@ -49,7 +49,37 @@ static void EncodeCommand(const SceneContext& scene_context,
std::shared_ptr<CommandBuffer> 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<TextureUsageMask>(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.";

View File

@ -36,7 +36,7 @@ class SceneEncoder {
std::shared_ptr<CommandBuffer> BuildSceneCommandBuffer(
const SceneContext& scene_context,
const Camera& camera,
const RenderTarget& render_target) const;
RenderTarget render_target) const;
std::vector<SceneCommand> commands_;

View File

@ -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 <cmath>
#include <memory>
#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<UnlitMaterial> 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});

View File

@ -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;
}