Fully wire up the box primitive in the playground.

This commit is contained in:
Chinmay Garde 2021-07-03 15:29:16 -07:00 committed by Dan Field
parent cf598d57d7
commit 727acd40ff
17 changed files with 136 additions and 213 deletions

View File

@ -15,6 +15,7 @@ namespace impeller {
enum class PixelFormat {
kUnknown,
kPixelFormat_B8G8R8A8_UNormInt,
kPixelFormat_B8G8R8A8_UNormInt_SRGB,
kPixelFormat_D32_Float_S8_UNormInt,
};

View File

@ -20,6 +20,8 @@ constexpr MTLPixelFormat ToMTLPixelFormat(PixelFormat format) {
switch (format) {
case PixelFormat::kUnknown:
return MTLPixelFormatInvalid;
case PixelFormat::kPixelFormat_B8G8R8A8_UNormInt:
return MTLPixelFormatBGRA8Unorm;
case PixelFormat::kPixelFormat_B8G8R8A8_UNormInt_SRGB:
return MTLPixelFormatBGRA8Unorm_sRGB;
case PixelFormat::kPixelFormat_D32_Float_S8_UNormInt:

View File

@ -6,6 +6,7 @@
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "impeller/base/base.h"
#include "impeller/compositor/context.h"
#include "impeller/compositor/pipeline_descriptor.h"
#include "impeller/compositor/shader_library.h"
@ -84,7 +85,7 @@ struct PipelineBuilder {
// TODO(csg): This can be easily reflected but we are sticking to the
// convention that the first stage output is the color output.
ColorAttachmentDescriptor color0;
color0.format = PixelFormat::kPixelFormat_B8G8R8A8_UNormInt_SRGB;
color0.format = PixelFormat::kPixelFormat_B8G8R8A8_UNormInt;
desc.SetColorAttachmentDescriptor(0u, std::move(color0));
}
@ -94,10 +95,10 @@ struct PipelineBuilder {
// TODO(csg): Make this configurable if possible as the D32 component is
// wasted. This can even be moved out of the "default" descriptor
// construction as a case can be made that this is caller responsibility.
const auto combined_depth_stencil_format =
PixelFormat::kPixelFormat_D32_Float_S8_UNormInt;
desc.SetDepthPixelFormat(combined_depth_stencil_format);
desc.SetStencilPixelFormat(combined_depth_stencil_format);
// const auto combined_depth_stencil_format =
// PixelFormat::kPixelFormat_D32_Float_S8_UNormInt;
// desc.SetDepthPixelFormat(combined_depth_stencil_format);
// desc.SetStencilPixelFormat(combined_depth_stencil_format);
}
return desc;

View File

@ -6,6 +6,7 @@
#include <dispatch/dispatch.h>
#include <functional>
#include <memory>
#include "flutter/fml/macros.h"
@ -19,21 +20,19 @@ class RenderPass;
class Renderer {
public:
virtual ~Renderer();
using RenderCallback =
std::function<bool(const Surface& surface, RenderPass& pass)>;
Renderer(std::string shaders_directory);
~Renderer();
bool IsValid() const;
bool Render(const Surface& surface);
bool Render(const Surface& surface, RenderCallback callback) const;
std::shared_ptr<Context> GetContext() const;
protected:
Renderer(std::string shaders_directory);
virtual bool OnIsValid() const = 0;
virtual bool OnRender(const Surface& surface, RenderPass& pass) = 0;
private:
dispatch_semaphore_t frames_in_flight_sema_ = nullptr;
std::shared_ptr<Context> context_;

View File

@ -25,10 +25,11 @@ Renderer::Renderer(std::string shaders_directory)
Renderer::~Renderer() = default;
bool Renderer::IsValid() const {
return is_valid_ && OnIsValid();
return is_valid_;
}
bool Renderer::Render(const Surface& surface) {
bool Renderer::Render(const Surface& surface,
RenderCallback render_callback) const {
if (!IsValid()) {
return false;
}
@ -44,16 +45,12 @@ bool Renderer::Render(const Surface& surface) {
}
auto render_pass =
command_buffer->CreateRenderPass(surface.GetRenderPassDescriptor());
command_buffer->CreateRenderPass(surface.GetTargetRenderPassDescriptor());
if (!render_pass) {
return false;
}
if (!OnRender(surface, *render_pass)) {
return false;
}
if (!surface.Present()) {
if (render_callback && !render_callback(surface, *render_pass)) {
return false;
}

View File

@ -17,22 +17,18 @@ namespace impeller {
class Surface {
public:
Surface(RenderPassDescriptor desc,
std::function<bool(void)> present_callback);
Surface(RenderPassDescriptor target_desc);
~Surface();
const Size& GetSize() const;
bool Present() const;
bool IsValid() const;
const RenderPassDescriptor& GetRenderPassDescriptor() const;
const RenderPassDescriptor& GetTargetRenderPassDescriptor() const;
private:
RenderPassDescriptor desc_;
std::function<bool(void)> present_callback_;
Size size_;
bool is_valid_ = false;

View File

@ -8,9 +8,8 @@
namespace impeller {
Surface::Surface(RenderPassDescriptor desc,
std::function<bool(void)> present_callback)
: desc_(std::move(desc)), present_callback_(present_callback) {
Surface::Surface(RenderPassDescriptor target_desc)
: desc_(std::move(target_desc)) {
if (auto size = desc_.GetColorAttachmentSize(0u); size.has_value()) {
size_ = size.value();
} else {
@ -26,21 +25,11 @@ const Size& Surface::GetSize() const {
return size_;
}
bool Surface::Present() const {
auto callback = present_callback_;
if (!callback) {
return false;
}
return callback();
}
bool Surface::IsValid() const {
return is_valid_;
}
const RenderPassDescriptor& Surface::GetRenderPassDescriptor() const {
const RenderPassDescriptor& Surface::GetTargetRenderPassDescriptor() const {
return desc_;
}

View File

@ -8,8 +8,6 @@ impeller_component("entity") {
sources = [
"entity.cc",
"entity.h",
"entity_renderer.h",
"entity_renderer.mm",
]
public_deps = [

View File

@ -1,35 +0,0 @@
// 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.
#pragma once
#include "flutter/fml/macros.h"
#include "impeller/compositor/renderer.h"
#include "impeller/compositor/vertex_buffer.h"
#include "impeller/entity/entity.h"
namespace impeller {
class EntityRenderer final : public Renderer {
public:
EntityRenderer(std::string shaders_directory);
~EntityRenderer() override;
private:
std::shared_ptr<Entity> root_;
std::shared_ptr<Pipeline> box_pipeline_;
VertexBuffer vertex_buffer_;
bool is_valid_ = false;
// |Renderer|
bool OnIsValid() const override;
// |Renderer|
bool OnRender(const Surface& surface, RenderPass& pass) override;
FML_DISALLOW_COPY_AND_ASSIGN(EntityRenderer);
};
} // namespace impeller

View File

@ -1,96 +0,0 @@
// 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.
#include "impeller/entity/entity_renderer.h"
#include "flutter/fml/time/time_point.h"
#include "impeller/compositor/command.h"
#include "impeller/compositor/pipeline_builder.h"
#include "impeller/compositor/sampler_descriptor.h"
#include "impeller/compositor/surface.h"
#include "impeller/compositor/vertex_buffer_builder.h"
#include "impeller/primitives/box.frag.h"
#include "impeller/primitives/box.vert.h"
namespace impeller {
EntityRenderer::EntityRenderer(std::string shaders_directory)
: Renderer(std::move(shaders_directory)),
root_(std::make_shared<Entity>()) {
root_->SetBackgroundColor(Color::DarkGray());
auto context = GetContext();
if (!context) {
return;
}
using BoxPipelineBuilder =
PipelineBuilder<BoxVertexShader, BoxFragmentShader>;
auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
box_pipeline_ =
context->GetPipelineLibrary()->GetRenderPipeline(std::move(desc)).get();
if (!box_pipeline_) {
return;
}
VertexBufferBuilder<BoxVertexShader::PerVertexData> vertex_builder;
vertex_builder.SetLabel("Box");
vertex_builder.AddVertices({
{{100, 100, 0.0}, {Color::Red()}, {0.0, 0.0}}, // 1
{{800, 100, 0.0}, {Color::Green()}, {1.0, 0.0}}, // 2
{{800, 800, 0.0}, {Color::Blue()}, {1.0, 1.0}}, // 3
{{100, 100, 0.0}, {Color::Cyan()}, {0.0, 0.0}}, // 1
{{800, 800, 0.0}, {Color::White()}, {1.0, 1.0}}, // 3
{{100, 800, 0.0}, {Color::Purple()}, {0.0, 1.0}}, // 4
});
vertex_buffer_ =
vertex_builder.CreateVertexBuffer(*context->GetPermanentsAllocator());
if (!vertex_buffer_) {
return;
}
is_valid_ = true;
}
EntityRenderer::~EntityRenderer() = default;
bool EntityRenderer::OnIsValid() const {
return is_valid_;
}
bool EntityRenderer::OnRender(const Surface& surface, RenderPass& pass) {
pass.SetLabel("EntityRenderer Render Pass");
BoxVertexShader::UniformBuffer uniforms;
uniforms.mvp = Matrix::MakeOrthographic(surface.GetSize());
Command cmd;
cmd.label = "Box";
cmd.pipeline = box_pipeline_;
cmd.vertex_bindings.buffers[VertexDescriptor::kReservedVertexBufferIndex] =
vertex_buffer_.vertex_buffer;
cmd.vertex_bindings.buffers[BoxVertexShader::kUniformUniformBuffer.binding] =
pass.GetTransientsBuffer().EmplaceUniform(uniforms);
cmd.fragment_bindings.samplers[BoxFragmentShader::kInputContents1.binding] =
GetContext()->GetSamplerLibrary()->GetSampler({});
cmd.fragment_bindings.samplers[BoxFragmentShader::kInputContents2.binding] =
GetContext()->GetSamplerLibrary()->GetSampler({});
cmd.fragment_bindings.samplers[BoxFragmentShader::kInputContents3.binding] =
GetContext()->GetSamplerLibrary()->GetSampler({});
cmd.index_buffer = vertex_buffer_.index_buffer;
cmd.index_count = vertex_buffer_.index_count;
cmd.primitive_type = PrimitiveType::kTriange;
if (!pass.RecordCommand(std::move(cmd))) {
return false;
}
return true;
}
} // namespace impeller

View File

@ -3,14 +3,11 @@
// found in the LICENSE file.
#include "flutter/testing/testing.h"
#include "impeller/playground/playground.h"
namespace impeller {
namespace testing {
TEST_F(Playground, CanCreateEntity) {
OpenPlaygroundHere([]() { return true; });
}
//
} // namespace testing
} // namespace impeller

View File

@ -5,6 +5,7 @@
#include "flutter/fml/closure.h"
#include "flutter/fml/macros.h"
#include "gtest/gtest.h"
#include "impeller/compositor/renderer.h"
namespace impeller {
@ -14,9 +15,13 @@ class Playground : public ::testing::Test {
~Playground();
bool OpenPlaygroundHere(std::function<bool()> closure);
std::shared_ptr<Context> GetContext() const;
bool OpenPlaygroundHere(Renderer::RenderCallback render_callback);
private:
Renderer renderer_;
FML_DISALLOW_COPY_AND_ASSIGN(Playground);
};

View File

@ -3,9 +3,11 @@
// found in the LICENSE file.
#include "impeller/playground/playground.h"
#include "flutter/fml/paths.h"
#include "flutter/testing/testing.h"
#include "impeller/compositor/context.h"
#include "impeller/compositor/render_pass.h"
#include "impeller/compositor/renderer.h"
#include "impeller/compositor/surface.h"
#define GLFW_INCLUDE_NONE
@ -18,10 +20,22 @@
namespace impeller {
Playground::Playground() = default;
static std::string ShaderLibraryDirectory() {
auto path_result = fml::paths::GetExecutableDirectoryPath();
if (!path_result.first) {
return {};
}
return fml::paths::JoinPaths({path_result.second, "shaders"});
}
Playground::Playground() : renderer_(ShaderLibraryDirectory()) {}
Playground::~Playground() = default;
std::shared_ptr<Context> Playground::GetContext() const {
return renderer_.IsValid() ? renderer_.GetContext() : nullptr;
}
static void PlaygroundKeyCallback(GLFWwindow* window,
int key,
int scancode,
@ -32,14 +46,12 @@ static void PlaygroundKeyCallback(GLFWwindow* window,
}
}
bool Playground::OpenPlaygroundHere(std::function<bool()> closure) {
if (!closure) {
bool Playground::OpenPlaygroundHere(Renderer::RenderCallback render_callback) {
if (!render_callback) {
return true;
}
Context context(flutter::testing::GetFixturesPath());
if (!context.IsValid()) {
if (!renderer_.IsValid()) {
return false;
}
@ -50,7 +62,8 @@ bool Playground::OpenPlaygroundHere(std::function<bool()> closure) {
::glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
auto window = ::glfwCreateWindow(800, 600, "Impeller Playground", NULL, NULL);
auto window = ::glfwCreateWindow(
800, 600, "Impeller Playground (Press ESC or 'q' to quit)", NULL, NULL);
if (!window) {
return false;
}
@ -63,7 +76,7 @@ bool Playground::OpenPlaygroundHere(std::function<bool()> closure) {
NSWindow* cocoa_window = ::glfwGetCocoaWindow(window);
CAMetalLayer* layer = [CAMetalLayer layer];
layer.device = context.GetMTLDevice();
layer.device = renderer_.GetContext()->GetMTLDevice();
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
cocoa_window.contentView.layer = layer;
cocoa_window.contentView.wantsLayer = YES;
@ -91,23 +104,14 @@ bool Playground::OpenPlaygroundHere(std::function<bool()> closure) {
RenderPassDescriptor desc;
desc.SetColorAttachment(color0, 0u);
Surface surface(desc, [current_drawable, closure]() {
if (!closure()) {
return false;
}
[current_drawable present];
return true;
});
Surface surface(desc);
if (!surface.IsValid()) {
FML_LOG(ERROR) << "Could not wrap surface to render to into.";
if (!renderer_.Render(surface, render_callback)) {
FML_LOG(ERROR) << "Could not render into the surface.";
return false;
}
if (!surface.Present()) {
FML_LOG(ERROR) << "Could not render into playground surface.";
return false;
}
[current_drawable present];
}
return true;

View File

@ -25,5 +25,10 @@ impeller_component("primitives") {
}
impeller_component("primitives_unittests") {
testonly = true
sources = [ "primitives_unittests.mm" ]
deps = [
":primitives",
"../playground",
]
}

View File

@ -3,17 +3,9 @@
// found in the LICENSE file.
in vec4 color;
in vec2 interpolated_texture_coordinates;
uniform sampler2D contents1;
uniform sampler2D contents2;
uniform sampler2D contents3;
out vec4 frag_color;
void main() {
vec4 color1 = texture(contents1, interpolated_texture_coordinates);
vec4 color2 = texture(contents2, interpolated_texture_coordinates);
vec4 color3 = texture(contents3, interpolated_texture_coordinates);
frag_color = color3;
frag_color = color;
}

View File

@ -8,13 +8,10 @@ uniform UniformBuffer {
in vec3 vertex_position;
in vec4 vertex_color;
in vec2 texture_coordinates;
out vec4 color;
out vec2 interpolated_texture_coordinates;
void main() {
gl_Position = uniforms.mvp * vec4(vertex_position, 1.0);
color = vertex_color;
interpolated_texture_coordinates = texture_coordinates;
}

View File

@ -1,3 +1,74 @@
// 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.
#include "flutter/fml/time/time_point.h"
#include "flutter/testing/testing.h"
#include "impeller/compositor/command.h"
#include "impeller/compositor/pipeline_builder.h"
#include "impeller/compositor/renderer.h"
#include "impeller/compositor/sampler_descriptor.h"
#include "impeller/compositor/surface.h"
#include "impeller/compositor/vertex_buffer_builder.h"
#include "impeller/playground/playground.h"
#include "impeller/primitives/box.frag.h"
#include "impeller/primitives/box.vert.h"
namespace impeller {
namespace testing {
using PrimitivesTest = Playground;
TEST_F(PrimitivesTest, CanCreateBoxPrimitive) {
auto context = GetContext();
ASSERT_TRUE(context);
using BoxPipelineBuilder =
PipelineBuilder<BoxVertexShader, BoxFragmentShader>;
auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
auto box_pipeline =
context->GetPipelineLibrary()->GetRenderPipeline(std::move(desc)).get();
ASSERT_TRUE(box_pipeline);
VertexBufferBuilder<BoxVertexShader::PerVertexData> vertex_builder;
vertex_builder.SetLabel("Box");
vertex_builder.AddVertices({
{{100, 100, 0.0}, {Color::Red()}}, // 1
{{800, 100, 0.0}, {Color::Green()}}, // 2
{{800, 800, 0.0}, {Color::Blue()}}, // 3
{{100, 100, 0.0}, {Color::Cyan()}}, // 1
{{800, 800, 0.0}, {Color::White()}}, // 3
{{100, 800, 0.0}, {Color::Purple()}}, // 4
});
auto vertex_buffer =
vertex_builder.CreateVertexBuffer(*context->GetPermanentsAllocator());
ASSERT_TRUE(vertex_buffer);
Renderer::RenderCallback callback = [&](const Surface& surface,
RenderPass& pass) {
pass.SetLabel("EntityRenderer Render Pass");
BoxVertexShader::UniformBuffer uniforms;
uniforms.mvp = Matrix::MakeOrthographic(surface.GetSize());
Command cmd;
cmd.label = "Box";
cmd.pipeline = box_pipeline;
cmd.vertex_bindings.buffers[VertexDescriptor::kReservedVertexBufferIndex] =
vertex_buffer.vertex_buffer;
cmd.vertex_bindings
.buffers[BoxVertexShader::kUniformUniformBuffer.binding] =
pass.GetTransientsBuffer().EmplaceUniform(uniforms);
cmd.index_buffer = vertex_buffer.index_buffer;
cmd.index_count = vertex_buffer.index_count;
cmd.primitive_type = PrimitiveType::kTriange;
if (!pass.RecordCommand(std::move(cmd))) {
return false;
}
return true;
};
OpenPlaygroundHere(callback);
}
} // namespace testing
} // namespace impeller