mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fully wire up the box primitive in the playground.
This commit is contained in:
parent
cf598d57d7
commit
727acd40ff
@ -15,6 +15,7 @@ namespace impeller {
|
||||
|
||||
enum class PixelFormat {
|
||||
kUnknown,
|
||||
kPixelFormat_B8G8R8A8_UNormInt,
|
||||
kPixelFormat_B8G8R8A8_UNormInt_SRGB,
|
||||
kPixelFormat_D32_Float_S8_UNormInt,
|
||||
};
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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_;
|
||||
}
|
||||
|
||||
|
||||
@ -8,8 +8,6 @@ impeller_component("entity") {
|
||||
sources = [
|
||||
"entity.cc",
|
||||
"entity.h",
|
||||
"entity_renderer.h",
|
||||
"entity_renderer.mm",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -25,5 +25,10 @@ impeller_component("primitives") {
|
||||
}
|
||||
|
||||
impeller_component("primitives_unittests") {
|
||||
testonly = true
|
||||
sources = [ "primitives_unittests.mm" ]
|
||||
deps = [
|
||||
":primitives",
|
||||
"../playground",
|
||||
]
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user