WIP on replacing texture contents.

This commit is contained in:
Chinmay Garde 2021-07-06 16:16:30 -07:00 committed by Dan Field
parent cc57340c5e
commit 5110652812
14 changed files with 132 additions and 101 deletions

View File

@ -10,6 +10,7 @@
#include "flutter/fml/macros.h"
#include "flutter/fml/mapping.h"
#include "impeller/compositor/texture_descriptor.h"
namespace impeller {
@ -46,6 +47,7 @@ enum class StorageMode {
class Context;
class DeviceBuffer;
class Texture;
class Allocator {
public:
@ -55,6 +57,9 @@ class Allocator {
std::shared_ptr<DeviceBuffer> CreateBuffer(StorageMode mode, size_t length);
std::shared_ptr<Texture> CreateTexture(StorageMode mode,
const TextureDescriptor& desc);
std::shared_ptr<DeviceBuffer> CreateBufferWithCopy(const uint8_t* buffer,
size_t length);

View File

@ -8,6 +8,7 @@
#include "flutter/fml/logging.h"
#include "impeller/compositor/buffer.h"
#include "impeller/compositor/device_buffer.h"
#include "impeller/compositor/formats_metal.h"
namespace impeller {
@ -26,11 +27,11 @@ bool Allocator::IsValid() const {
return is_valid_;
}
static MTLResourceOptions ResourceOptionsFromStorageType(StorageMode type) {
static MTLResourceOptions ToMTLResourceOptions(StorageMode type) {
switch (type) {
case StorageMode::kHostVisible:
#if OS_IOS
return MTLStorageModeShared;
return MTLResourceStorageModeShared;
#else
return MTLResourceStorageModeManaged;
#endif
@ -38,11 +39,33 @@ static MTLResourceOptions ResourceOptionsFromStorageType(StorageMode type) {
return MTLResourceStorageModePrivate;
case StorageMode::kDeviceTransient:
#if OS_IOS
return MTLStorageModeMemoryless;
return MTLResourceStorageModeMemoryless;
#else
return MTLResourceStorageModePrivate;
#endif
}
return MTLResourceStorageModePrivate;
}
static MTLStorageMode ToMTLStorageMode(StorageMode mode) {
switch (mode) {
case StorageMode::kHostVisible:
#if OS_IOS
return MTLStorageModeShared;
#else
return MTLStorageModeManaged;
#endif
case StorageMode::kDevicePrivate:
return MTLStorageModePrivate;
case StorageMode::kDeviceTransient:
#if OS_IOS
return MTLStorageModeMemoryless;
#else
return MTLStorageModePrivate;
#endif
}
return MTLStorageModeShared;
}
bool Allocator::RequiresExplicitHostSynchronization(StorageMode mode) {
@ -59,6 +82,16 @@ bool Allocator::RequiresExplicitHostSynchronization(StorageMode mode) {
#endif
}
std::shared_ptr<DeviceBuffer> Allocator::CreateBuffer(StorageMode mode,
size_t length) {
auto buffer = [device_ newBufferWithLength:length
options:ToMTLResourceOptions(mode)];
if (!buffer) {
return nullptr;
}
return std::shared_ptr<DeviceBuffer>(new DeviceBuffer(buffer, length, mode));
}
std::shared_ptr<DeviceBuffer> Allocator::CreateBufferWithCopy(
const uint8_t* buffer,
size_t length) {
@ -82,15 +115,20 @@ std::shared_ptr<DeviceBuffer> Allocator::CreateBufferWithCopy(
return CreateBufferWithCopy(mapping.GetMapping(), mapping.GetSize());
}
std::shared_ptr<DeviceBuffer> Allocator::CreateBuffer(StorageMode mode,
size_t length) {
auto buffer =
[device_ newBufferWithLength:length
options:ResourceOptionsFromStorageType(mode)];
if (!buffer) {
std::shared_ptr<Texture> Allocator::CreateTexture(
StorageMode mode,
const TextureDescriptor& desc) {
if (!IsValid()) {
return nullptr;
}
return std::shared_ptr<DeviceBuffer>(new DeviceBuffer(buffer, length, mode));
auto mtl_texture_desc = ToMTLTextureDescriptor(desc);
mtl_texture_desc.storageMode = ToMTLStorageMode(mode);
auto texture = [device_ newTextureWithDescriptor:mtl_texture_desc];
if (!texture) {
return nullptr;
}
return std::make_shared<Texture>(desc, texture);
}
} // namespace impeller

View File

@ -30,20 +30,14 @@ std::shared_ptr<Texture> DeviceBuffer::MakeTexture(TextureDescriptor desc,
return nullptr;
}
auto mtl_desc = [[MTLTextureDescriptor alloc] init];
mtl_desc.pixelFormat = ToMTLPixelFormat(desc.format);
mtl_desc.width = desc.size.width;
mtl_desc.height = desc.size.height;
mtl_desc.mipmapLevelCount = desc.mip_count;
auto texture = [buffer_ newTextureWithDescriptor:mtl_desc
auto texture = [buffer_ newTextureWithDescriptor:ToMTLTextureDescriptor(desc)
offset:offset
bytesPerRow:desc.GetBytesPerRow()];
if (!texture) {
return nullptr;
}
return std::make_shared<Texture>(texture);
return std::make_shared<Texture>(desc, texture);
}
[[nodiscard]] bool DeviceBuffer::CopyHostBuffer(const uint8_t* source,

View File

@ -10,6 +10,7 @@
#include "flutter/fml/macros.h"
#include "impeller/compositor/formats.h"
#include "impeller/compositor/texture_descriptor.h"
#include "impeller/geometry/color.h"
namespace impeller {
@ -244,8 +245,6 @@ constexpr MTLClearColor ToMTLClearColor(const Color& color) {
return MTLClearColorMake(color.red, color.green, color.blue, color.alpha);
}
RenderPassDescriptor FromMTLRenderPassDescriptor(MTLRenderPassDescriptor*);
MTLRenderPipelineColorAttachmentDescriptor*
ToMTLRenderPipelineColorAttachmentDescriptor(
ColorAttachmentDescriptor descriptor);
@ -255,4 +254,6 @@ MTLDepthStencilDescriptor* ToMTLDepthStencilDescriptor(
std::optional<StencilAttachmentDescriptor> front,
std::optional<StencilAttachmentDescriptor> back);
MTLTextureDescriptor* ToMTLTextureDescriptor(const TextureDescriptor& desc);
} // namespace impeller

View File

@ -77,61 +77,13 @@ MTLDepthStencilDescriptor* ToMTLDepthStencilDescriptor(
return des;
}
static bool ConfigureRenderPassAttachment(
RenderPassAttachment& attachment,
MTLRenderPassAttachmentDescriptor* desc) {
attachment.texture = std::make_shared<Texture>(desc.texture);
attachment.load_action = FromMTLLoadAction(desc.loadAction);
attachment.store_action = FromMTLStoreAction(desc.storeAction);
return attachment;
}
static ColorRenderPassAttachment FromMTLRenderPassColorAttachmentDescriptor(
MTLRenderPassColorAttachmentDescriptor* desc) {
ColorRenderPassAttachment attachment;
ConfigureRenderPassAttachment(attachment, desc);
auto clear = desc.clearColor;
attachment.clear_color =
Color{static_cast<Scalar>(clear.red), static_cast<Scalar>(clear.green),
static_cast<Scalar>(clear.blue), static_cast<Scalar>(clear.alpha)};
return attachment;
}
static DepthRenderPassAttachment FromMTLRenderPassDepthAttachmentDescriptor(
MTLRenderPassDepthAttachmentDescriptor* desc) {
DepthRenderPassAttachment attachment;
ConfigureRenderPassAttachment(attachment, desc);
attachment.clear_depth = desc.clearDepth;
return attachment;
}
static StencilRenderPassAttachment FromMTLRenderPassStencilAttachmentDescriptor(
MTLRenderPassStencilAttachmentDescriptor* desc) {
StencilRenderPassAttachment attachment;
ConfigureRenderPassAttachment(attachment, desc);
attachment.clear_stencil = desc.clearStencil;
return attachment;
}
RenderPassDescriptor FromMTLRenderPassDescriptor(
MTLRenderPassDescriptor* desc) {
RenderPassDescriptor result;
if (!desc) {
return result;
}
// From https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
constexpr size_t kMaxPossibleColorAttachments = 8u;
for (size_t i = 0; i < kMaxPossibleColorAttachments; i++) {
result.SetColorAttachment(
FromMTLRenderPassColorAttachmentDescriptor(desc.colorAttachments[i]),
i);
}
result.SetDepthAttachment(
FromMTLRenderPassDepthAttachmentDescriptor(desc.depthAttachment));
result.SetStencilAttachment(
FromMTLRenderPassStencilAttachmentDescriptor(desc.stencilAttachment));
return result;
MTLTextureDescriptor* ToMTLTextureDescriptor(const TextureDescriptor& desc) {
auto mtl_desc = [[MTLTextureDescriptor alloc] init];
mtl_desc.pixelFormat = ToMTLPixelFormat(desc.format);
mtl_desc.width = desc.size.width;
mtl_desc.height = desc.size.height;
mtl_desc.mipmapLevelCount = desc.mip_count;
return mtl_desc;
}
} // namespace impeller

View File

@ -49,7 +49,7 @@ class RenderPassDescriptor {
bool HasColorAttachment(size_t index) const;
std::optional<Size> GetColorAttachmentSize(size_t index) const;
std::optional<ISize> GetColorAttachmentSize(size_t index) const;
RenderPassDescriptor& SetColorAttachment(ColorRenderPassAttachment attachment,
size_t index);

View File

@ -25,7 +25,7 @@ bool RenderPassDescriptor::HasColorAttachment(size_t index) const {
return false;
}
std::optional<Size> RenderPassDescriptor::GetColorAttachmentSize(
std::optional<ISize> RenderPassDescriptor::GetColorAttachmentSize(
size_t index) const {
auto found = colors_.find(index);

View File

@ -21,7 +21,7 @@ class Surface {
~Surface();
const Size& GetSize() const;
const ISize& GetSize() const;
bool IsValid() const;
@ -29,7 +29,7 @@ class Surface {
private:
RenderPassDescriptor desc_;
Size size_;
ISize size_;
bool is_valid_ = false;

View File

@ -21,7 +21,7 @@ Surface::Surface(RenderPassDescriptor target_desc)
Surface::~Surface() = default;
const Size& Surface::GetSize() const {
const ISize& Surface::GetSize() const {
return size_;
}

View File

@ -4,6 +4,8 @@
#pragma once
#include <string_view>
#include <Metal/Metal.h>
#include "flutter/fml/macros.h"
@ -15,18 +17,26 @@ namespace impeller {
class Texture {
public:
Texture(id<MTLTexture> texture);
Texture(TextureDescriptor desc, id<MTLTexture> texture);
~Texture();
void SetLabel(const std::string_view& label);
[[nodiscard]] bool SetContents(const uint8_t* contents,
size_t length,
size_t mip_level = 0u);
bool IsValid() const;
Size GetSize() const;
ISize GetSize() const;
id<MTLTexture> GetMTLTexture() const;
private:
id<MTLTexture> texture_;
const TextureDescriptor desc_;
id<MTLTexture> texture_ = nullptr;
bool is_valid_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(Texture);
};

View File

@ -6,13 +6,39 @@
namespace impeller {
Texture::Texture(id<MTLTexture> texture) : texture_(texture) {}
Texture::Texture(TextureDescriptor desc, id<MTLTexture> texture)
: desc_(std::move(desc)), texture_(texture) {
if (!desc_.IsValid() || !texture_) {
return;
}
is_valid_ = true;
}
Texture::~Texture() = default;
Size Texture::GetSize() const {
return {static_cast<Scalar>(texture_.width),
static_cast<Scalar>(texture_.height)};
bool Texture::SetContents(const uint8_t* contents,
size_t length,
size_t mip_level) {
if (!IsValid() || !contents) {
return false;
}
FML_CHECK(false);
return false;
// MTLRegionMake2D(NSUInteger x, NSUInteger y, NSUInteger width,
// NSUInteger height)
// [texture_ replaceRegion:(MTLRegion)
// mipmapLevel:(NSUInteger)withBytes:(nonnull const
// void*)bytesPerRow
// :(NSUInteger)];
}
ISize Texture::GetSize() const {
return {static_cast<ISize::Type>(texture_.width),
static_cast<ISize::Type>(texture_.height)};
}
id<MTLTexture> Texture::GetMTLTexture() const {
@ -20,7 +46,7 @@ id<MTLTexture> Texture::GetMTLTexture() const {
}
bool Texture::IsValid() const {
return texture_;
return is_valid_;
}
} // namespace impeller

View File

@ -269,9 +269,9 @@ struct Matrix {
Matrix operator+(const Matrix& m) const;
static constexpr Matrix MakeOrthographic(const Size& size) {
static constexpr Matrix MakeOrthographic(Scalar width, Scalar height) {
// Per assumptions about NDC documented above.
const auto scale = MakeScale({1.0f / size.width, -1.0f / size.height, 1.0});
const auto scale = MakeScale({1.0f / width, -1.0f / height, 1.0});
const auto translate = MakeTranslation({-1.0, 1.0, 0.5});
return translate * scale;
}

View File

@ -7,6 +7,7 @@
#include "flutter/fml/paths.h"
#include "flutter/testing/testing.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"
@ -108,8 +109,15 @@ bool Playground::OpenPlaygroundHere(Renderer::RenderCallback render_callback) {
return false;
}
TextureDescriptor color0_desc;
color0_desc.format = PixelFormat::kPixelFormat_B8G8R8A8_UNormInt;
color0_desc.size = {
static_cast<ISize::Type>(current_drawable.texture.width),
static_cast<ISize::Type>(current_drawable.texture.height)};
ColorRenderPassAttachment color0;
color0.texture = std::make_shared<Texture>(current_drawable.texture);
color0.texture =
std::make_shared<Texture>(color0_desc, current_drawable.texture);
color0.clear_color = Color::SkyBlue();
color0.load_action = LoadAction::kClear;
color0.store_action = StoreAction::kStore;

View File

@ -50,23 +50,20 @@ TEST_F(PrimitivesTest, CanCreateBoxPrimitive) {
Image image(flutter::testing::OpenFixtureAsMapping("image.png"));
auto result = image.Decode();
ASSERT_TRUE(result.IsValid());
auto device_image_allocation =
context->GetPermanentsAllocator()->CreateBufferWithCopy(
*result.GetAllocation());
device_image_allocation->SetLabel("Bay Bridge");
ASSERT_TRUE(device_image_allocation);
auto texture_descriptor = TextureDescriptor::MakeFromImageResult(result);
ASSERT_TRUE(texture_descriptor.has_value());
auto texture =
device_image_allocation->MakeTexture(texture_descriptor.value());
auto texture = context->GetPermanentsAllocator()->CreateTexture(
StorageMode::kHostVisible, texture_descriptor.value());
ASSERT_TRUE(texture);
auto uploaded = texture->SetContents(result.GetAllocation()->GetMapping(),
result.GetAllocation()->GetSize());
ASSERT_TRUE(uploaded);
Renderer::RenderCallback callback = [&](const Surface& surface,
RenderPass& pass) {
BoxVertexShader::UniformBuffer uniforms;
uniforms.mvp = Matrix::MakeOrthographic(surface.GetSize());
uniforms.mvp = Matrix::MakeOrthographic(surface.GetSize().width,
surface.GetSize().height);
Command cmd;
cmd.label = "Box";
cmd.pipeline = box_pipeline;