mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Turn on full-screen 4xMSAA by default and additional render target validations.
This commit is contained in:
parent
7ebaf2b1f7
commit
f9d781df9b
@ -127,6 +127,17 @@ TEST_F(AiksTest, CanRenderGroupOpacity) {
|
||||
|
||||
canvas.Restore();
|
||||
|
||||
// ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_F(AiksTest, CanPerformFullScreenMSAA) {
|
||||
Canvas canvas;
|
||||
|
||||
Paint red;
|
||||
red.color = Color::Red();
|
||||
|
||||
canvas.DrawCircle({250, 250}, 125, red);
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
|
||||
@ -91,6 +91,15 @@ void Canvas::DrawPath(Path path, Paint paint) {
|
||||
GetCurrentPass().AddEntity(std::move(entity));
|
||||
}
|
||||
|
||||
void Canvas::DrawRect(Rect rect, Paint paint) {
|
||||
DrawPath(PathBuilder{}.AddRect(rect).CreatePath(), std::move(paint));
|
||||
}
|
||||
|
||||
void Canvas::DrawCircle(Point center, Scalar radius, Paint paint) {
|
||||
DrawPath(PathBuilder{}.AddCircle(center, radius).CreatePath(),
|
||||
std::move(paint));
|
||||
}
|
||||
|
||||
void Canvas::SaveLayer(Paint paint, std::optional<Rect> bounds) {
|
||||
GetCurrentPass().SetDelegate(
|
||||
std::make_unique<PaintPassDelegate>(std::move(paint)));
|
||||
@ -189,10 +198,6 @@ size_t Canvas::GetStencilDepth() const {
|
||||
return xformation_stack_.back().stencil_depth;
|
||||
}
|
||||
|
||||
void Canvas::DrawRect(Rect rect, Paint paint) {
|
||||
DrawPath(PathBuilder{}.AddRect(rect).CreatePath(), std::move(paint));
|
||||
}
|
||||
|
||||
void Canvas::Save(bool create_subpass) {
|
||||
auto entry = CanvasStackEntry{};
|
||||
if (create_subpass) {
|
||||
|
||||
@ -53,6 +53,8 @@ class Canvas {
|
||||
|
||||
void DrawRect(Rect rect, Paint paint);
|
||||
|
||||
void DrawCircle(Point center, Scalar radius, Paint paint);
|
||||
|
||||
void DrawImage(std::shared_ptr<Image> image, Point offset, Paint paint);
|
||||
|
||||
void DrawImageRect(std::shared_ptr<Image> image,
|
||||
|
||||
@ -12,6 +12,8 @@ impeller_component("base") {
|
||||
"config.h",
|
||||
"strings.cc",
|
||||
"strings.h",
|
||||
"validation.cc",
|
||||
"validation.h",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -5,3 +5,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "impeller/base/strings.h"
|
||||
#include "impeller/base/validation.h"
|
||||
|
||||
28
engine/src/flutter/impeller/base/validation.cc
Normal file
28
engine/src/flutter/impeller/base/validation.cc
Normal file
@ -0,0 +1,28 @@
|
||||
// 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/impeller/base/validation.h"
|
||||
|
||||
#include "flutter/fml/logging.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
ValidationLog::ValidationLog() = default;
|
||||
|
||||
ValidationLog::~ValidationLog() {
|
||||
FML_LOG(ERROR) << stream_.str();
|
||||
ImpellerValidationBreak();
|
||||
}
|
||||
|
||||
std::ostream& ValidationLog::GetStream() {
|
||||
return stream_;
|
||||
}
|
||||
|
||||
void ImpellerValidationBreak() {
|
||||
// Nothing to do. Exists for the debugger.
|
||||
FML_LOG(ERROR) << "Break on " << __FUNCTION__
|
||||
<< " to inspect point of failure.";
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
31
engine/src/flutter/impeller/base/validation.h
Normal file
31
engine/src/flutter/impeller/base/validation.h
Normal file
@ -0,0 +1,31 @@
|
||||
// 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 <sstream>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
class ValidationLog {
|
||||
public:
|
||||
ValidationLog();
|
||||
|
||||
~ValidationLog();
|
||||
|
||||
std::ostream& GetStream();
|
||||
|
||||
private:
|
||||
std::ostringstream stream_;
|
||||
|
||||
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(ValidationLog);
|
||||
};
|
||||
|
||||
void ImpellerValidationBreak();
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
#define VALIDATION_LOG ::impeller::ValidationLog{}.GetStream()
|
||||
@ -144,23 +144,44 @@ bool Playground::OpenPlaygroundHere(Renderer::RenderCallback render_callback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TextureDescriptor color0_tex;
|
||||
color0_tex.format = PixelFormat::kB8G8R8A8UNormInt;
|
||||
color0_tex.size = {
|
||||
TextureDescriptor msaa_tex_desc;
|
||||
msaa_tex_desc.type = TextureType::k2DMultisample;
|
||||
msaa_tex_desc.sample_count = SampleCount::kCount4;
|
||||
msaa_tex_desc.format = PixelFormat::kB8G8R8A8UNormInt;
|
||||
msaa_tex_desc.size = {
|
||||
static_cast<ISize::Type>(current_drawable.texture.width),
|
||||
static_cast<ISize::Type>(current_drawable.texture.height)};
|
||||
color0_tex.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
|
||||
msaa_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
|
||||
|
||||
auto msaa_tex =
|
||||
renderer_.GetContext()->GetPermanentsAllocator()->CreateTexture(
|
||||
StorageMode::kDeviceTransient, msaa_tex_desc);
|
||||
if (!msaa_tex) {
|
||||
FML_LOG(ERROR) << "Could not allocate MSAA resolve texture.";
|
||||
return false;
|
||||
}
|
||||
|
||||
msaa_tex->SetLabel("PlaygroundMainColor4xMSAA");
|
||||
|
||||
TextureDescriptor onscreen_tex_desc;
|
||||
onscreen_tex_desc.format = PixelFormat::kB8G8R8A8UNormInt;
|
||||
onscreen_tex_desc.size = msaa_tex_desc.size;
|
||||
onscreen_tex_desc.usage =
|
||||
static_cast<uint64_t>(TextureUsage::kRenderTarget);
|
||||
|
||||
ColorAttachment color0;
|
||||
color0.texture =
|
||||
std::make_shared<TextureMTL>(color0_tex, current_drawable.texture);
|
||||
color0.texture = msaa_tex;
|
||||
color0.clear_color = Color::DarkSlateGray();
|
||||
color0.load_action = LoadAction::kClear;
|
||||
color0.store_action = StoreAction::kStore;
|
||||
color0.store_action = StoreAction::kMultisampleResolve;
|
||||
color0.resolve_texture = std::make_shared<TextureMTL>(
|
||||
onscreen_tex_desc, current_drawable.texture);
|
||||
|
||||
TextureDescriptor stencil0_tex;
|
||||
stencil0_tex.type = TextureType::k2DMultisample;
|
||||
stencil0_tex.sample_count = SampleCount::kCount4;
|
||||
stencil0_tex.format = PixelFormat::kD32FloatS8UNormInt;
|
||||
stencil0_tex.size = color0_tex.size;
|
||||
stencil0_tex.size = msaa_tex_desc.size;
|
||||
stencil0_tex.usage =
|
||||
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
|
||||
auto stencil_texture =
|
||||
|
||||
@ -111,6 +111,12 @@ std::shared_ptr<Texture> AllocatorMTL::CreateTexture(
|
||||
}
|
||||
|
||||
auto mtl_texture_desc = ToMTLTextureDescriptor(desc);
|
||||
|
||||
if (!mtl_texture_desc) {
|
||||
FML_DLOG(ERROR) << "Texture descriptor was invalid.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mtl_texture_desc.storageMode = ToMTLStorageMode(mode);
|
||||
auto texture = [device_ newTextureWithDescriptor:mtl_texture_desc];
|
||||
if (!texture) {
|
||||
|
||||
@ -206,6 +206,8 @@ constexpr MTLStoreAction ToMTLStoreAction(StoreAction action) {
|
||||
return MTLStoreActionDontCare;
|
||||
case StoreAction::kStore:
|
||||
return MTLStoreActionStore;
|
||||
case StoreAction::kMultisampleResolve:
|
||||
return MTLStoreActionMultisampleResolve;
|
||||
}
|
||||
return MTLStoreActionDontCare;
|
||||
}
|
||||
@ -216,6 +218,8 @@ constexpr StoreAction FromMTLStoreAction(MTLStoreAction action) {
|
||||
return StoreAction::kDontCare;
|
||||
case MTLStoreActionStore:
|
||||
return StoreAction::kStore;
|
||||
case MTLStoreActionMultisampleResolve:
|
||||
return StoreAction::kMultisampleResolve;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -249,6 +253,16 @@ constexpr MTLClearColor ToMTLClearColor(const Color& color) {
|
||||
return MTLClearColorMake(color.red, color.green, color.blue, color.alpha);
|
||||
}
|
||||
|
||||
constexpr MTLTextureType ToMTLTextureType(TextureType type) {
|
||||
switch (type) {
|
||||
case TextureType::k2D:
|
||||
return MTLTextureType2D;
|
||||
case TextureType::k2DMultisample:
|
||||
return MTLTextureType2DMultisample;
|
||||
}
|
||||
return MTLTextureType2D;
|
||||
}
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor*
|
||||
ToMTLRenderPipelineColorAttachmentDescriptor(
|
||||
ColorAttachmentDescriptor descriptor);
|
||||
|
||||
@ -78,8 +78,13 @@ MTLDepthStencilDescriptor* ToMTLDepthStencilDescriptor(
|
||||
}
|
||||
|
||||
MTLTextureDescriptor* ToMTLTextureDescriptor(const TextureDescriptor& desc) {
|
||||
if (!desc.IsValid()) {
|
||||
return nil;
|
||||
}
|
||||
auto mtl_desc = [[MTLTextureDescriptor alloc] init];
|
||||
mtl_desc.textureType = ToMTLTextureType(desc.type);
|
||||
mtl_desc.pixelFormat = ToMTLPixelFormat(desc.format);
|
||||
mtl_desc.sampleCount = static_cast<NSUInteger>(desc.sample_count);
|
||||
mtl_desc.width = desc.size.width;
|
||||
mtl_desc.height = desc.size.height;
|
||||
mtl_desc.mipmapLevelCount = desc.mip_count;
|
||||
|
||||
@ -53,6 +53,8 @@ static MTLRenderPipelineDescriptor* GetMTLRenderPipelineDescriptor(
|
||||
descriptor.stencilAttachmentPixelFormat =
|
||||
ToMTLPixelFormat(desc.GetStencilPixelFormat());
|
||||
|
||||
descriptor.sampleCount = 4u;
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
||||
@ -17,6 +17,33 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
static bool ConfigureResolveTextureAttachment(
|
||||
const Attachment& desc,
|
||||
MTLRenderPassAttachmentDescriptor* attachment) {
|
||||
if (desc.store_action == StoreAction::kMultisampleResolve &&
|
||||
!desc.resolve_texture) {
|
||||
VALIDATION_LOG << "Resolve store action specified on attachment but no "
|
||||
"resolve texture was specified.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (desc.resolve_texture &&
|
||||
desc.store_action != StoreAction::kMultisampleResolve) {
|
||||
VALIDATION_LOG << "Resolve store action specified but there was no "
|
||||
"resolve attachment.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!desc.resolve_texture) {
|
||||
return true;
|
||||
}
|
||||
|
||||
attachment.resolveTexture =
|
||||
TextureMTL::Cast(*desc.resolve_texture).GetMTLTexture();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ConfigureAttachment(const Attachment& desc,
|
||||
MTLRenderPassAttachmentDescriptor* attachment) {
|
||||
if (!desc.texture) {
|
||||
@ -26,6 +53,11 @@ static bool ConfigureAttachment(const Attachment& desc,
|
||||
attachment.texture = TextureMTL::Cast(*desc.texture).GetMTLTexture();
|
||||
attachment.loadAction = ToMTLLoadAction(desc.load_action);
|
||||
attachment.storeAction = ToMTLStoreAction(desc.store_action);
|
||||
|
||||
if (!ConfigureResolveTextureAttachment(desc, attachment)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -69,8 +101,8 @@ static MTLRenderPassDescriptor* ToMTLRenderPassDescriptor(
|
||||
for (const auto& color : colors) {
|
||||
if (!ConfigureColorAttachment(color.second,
|
||||
result.colorAttachments[color.first])) {
|
||||
FML_DLOG(ERROR) << "Could not configure color attachment at index "
|
||||
<< color.first;
|
||||
VALIDATION_LOG << "Could not configure color attachment at index "
|
||||
<< color.first;
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
@ -79,7 +111,7 @@ static MTLRenderPassDescriptor* ToMTLRenderPassDescriptor(
|
||||
|
||||
if (depth.has_value() &&
|
||||
!ConfigureDepthAttachment(depth.value(), result.depthAttachment)) {
|
||||
FML_DLOG(ERROR) << "Could not configure depth attachment.";
|
||||
VALIDATION_LOG << "Could not configure depth attachment.";
|
||||
return nil;
|
||||
}
|
||||
|
||||
@ -87,7 +119,7 @@ static MTLRenderPassDescriptor* ToMTLRenderPassDescriptor(
|
||||
|
||||
if (stencil.has_value() &&
|
||||
!ConfigureStencilAttachment(stencil.value(), result.stencilAttachment)) {
|
||||
FML_DLOG(ERROR) << "Could not configure stencil attachment.";
|
||||
VALIDATION_LOG << "Could not configure stencil attachment.";
|
||||
return nil;
|
||||
}
|
||||
|
||||
@ -99,7 +131,7 @@ RenderPassMTL::RenderPassMTL(id<MTLCommandBuffer> buffer, RenderTarget target)
|
||||
buffer_(buffer),
|
||||
desc_(ToMTLRenderPassDescriptor(GetRenderTarget())),
|
||||
transients_buffer_(HostBuffer::Create()) {
|
||||
if (!buffer_ || !desc_) {
|
||||
if (!buffer_ || !desc_ || !render_target_.IsValid()) {
|
||||
return;
|
||||
}
|
||||
is_valid_ = true;
|
||||
@ -202,8 +234,7 @@ struct PassBindingsCache {
|
||||
[encoder_ setFragmentBufferOffset:offset atIndex:index];
|
||||
return true;
|
||||
default:
|
||||
FML_DCHECK(false)
|
||||
<< "Cannot update buffer offset of an unknown stage.";
|
||||
VALIDATION_LOG << "Cannot update buffer offset of an unknown stage.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -217,7 +248,7 @@ struct PassBindingsCache {
|
||||
[encoder_ setFragmentBuffer:buffer offset:offset atIndex:index];
|
||||
return true;
|
||||
default:
|
||||
FML_DCHECK(false) << "Cannot bind buffer to unknown shader stage.";
|
||||
VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@ -239,7 +270,7 @@ struct PassBindingsCache {
|
||||
[encoder_ setFragmentTexture:texture atIndex:index];
|
||||
return true;
|
||||
default:
|
||||
FML_DCHECK(false) << "Cannot bind buffer to unknown shader stage.";
|
||||
VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@ -263,7 +294,7 @@ struct PassBindingsCache {
|
||||
[encoder_ setFragmentSamplerState:sampler atIndex:index];
|
||||
return true;
|
||||
default:
|
||||
FML_DCHECK(false) << "Cannot bind buffer to unknown shader stage.";
|
||||
VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@ -360,7 +391,7 @@ bool RenderPassMTL::EncodeCommands(Allocator& allocator,
|
||||
fml::closure pop_debug_marker = [encoder]() { [encoder popDebugGroup]; };
|
||||
for (const auto& command : commands_) {
|
||||
if (command.index_count == 0u) {
|
||||
FML_DLOG(ERROR) << "Zero index count in render pass command.";
|
||||
VALIDATION_LOG << "Zero index count in render pass command.";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -89,6 +89,27 @@ enum class LoadAction {
|
||||
enum class StoreAction {
|
||||
kDontCare,
|
||||
kStore,
|
||||
kMultisampleResolve,
|
||||
};
|
||||
|
||||
enum class TextureType {
|
||||
k2D,
|
||||
k2DMultisample,
|
||||
};
|
||||
|
||||
constexpr bool IsMultisampleCapable(TextureType type) {
|
||||
switch (type) {
|
||||
case TextureType::k2D:
|
||||
return false;
|
||||
case TextureType::k2DMultisample:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
enum class SampleCount {
|
||||
kCount1 = 1,
|
||||
kCount4 = 4,
|
||||
};
|
||||
|
||||
using TextureUsageMask = uint64_t;
|
||||
@ -320,7 +341,8 @@ struct StencilAttachmentDescriptor {
|
||||
};
|
||||
|
||||
struct Attachment {
|
||||
std::shared_ptr<Texture> texture = nullptr;
|
||||
std::shared_ptr<Texture> texture;
|
||||
std::shared_ptr<Texture> resolve_texture;
|
||||
LoadAction load_action = LoadAction::kDontCare;
|
||||
StoreAction store_action = StoreAction::kStore;
|
||||
|
||||
|
||||
@ -59,11 +59,11 @@ class RenderPass {
|
||||
virtual bool EncodeCommands(Allocator& transients_allocator) const = 0;
|
||||
|
||||
protected:
|
||||
const RenderTarget render_target_;
|
||||
|
||||
RenderPass(RenderTarget target);
|
||||
|
||||
private:
|
||||
const RenderTarget render_target_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(RenderPass);
|
||||
};
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
#include "impeller/renderer/render_target.h"
|
||||
|
||||
#include "impeller/base/strings.h"
|
||||
#include "impeller/base/base.h"
|
||||
#include "impeller/renderer/allocator.h"
|
||||
#include "impeller/renderer/context.h"
|
||||
#include "impeller/renderer/texture.h"
|
||||
@ -15,6 +15,92 @@ RenderTarget::RenderTarget() = default;
|
||||
|
||||
RenderTarget::~RenderTarget() = default;
|
||||
|
||||
bool RenderTarget::IsValid() const {
|
||||
// Validate that there is a color attachment at zero index.
|
||||
if (!HasColorAttachment(0u)) {
|
||||
VALIDATION_LOG
|
||||
<< "Render target does not have color attachment at index 0.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate that all attachments are of the same size.
|
||||
{
|
||||
std::optional<ISize> size;
|
||||
bool sizes_are_same = true;
|
||||
auto iterator = [&](const Attachment& attachment) -> bool {
|
||||
if (!size.has_value()) {
|
||||
size = attachment.texture->GetSize();
|
||||
}
|
||||
if (size != attachment.texture->GetSize()) {
|
||||
sizes_are_same = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
IterateAllAttachments(iterator);
|
||||
if (!sizes_are_same) {
|
||||
VALIDATION_LOG
|
||||
<< "Sizes of all render target attachments are not the same.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate that all attachments are of the same type and sample counts.
|
||||
{
|
||||
std::optional<TextureType> texture_type;
|
||||
std::optional<SampleCount> sample_count;
|
||||
bool passes_type_validation = true;
|
||||
auto iterator = [&](const Attachment& attachment) -> bool {
|
||||
if (!texture_type.has_value() || !sample_count.has_value()) {
|
||||
texture_type = attachment.texture->GetTextureDescriptor().type;
|
||||
sample_count = attachment.texture->GetTextureDescriptor().sample_count;
|
||||
}
|
||||
|
||||
if (texture_type != attachment.texture->GetTextureDescriptor().type) {
|
||||
passes_type_validation = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sample_count !=
|
||||
attachment.texture->GetTextureDescriptor().sample_count) {
|
||||
passes_type_validation = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
IterateAllAttachments(iterator);
|
||||
if (!passes_type_validation) {
|
||||
VALIDATION_LOG << "Render target texture types are not of the same type "
|
||||
"and sample count.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderTarget::IterateAllAttachments(
|
||||
std::function<bool(const Attachment& attachment)> iterator) const {
|
||||
for (const auto& color : colors_) {
|
||||
if (!iterator(color.second)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (depth_.has_value()) {
|
||||
if (!iterator(depth_.value())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stencil_.has_value()) {
|
||||
if (!iterator(stencil_.value())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderTarget::HasColorAttachment(size_t index) const {
|
||||
if (auto found = colors_.find(index); found != colors_.end()) {
|
||||
return true;
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
@ -25,6 +26,8 @@ class RenderTarget {
|
||||
|
||||
~RenderTarget();
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
bool HasColorAttachment(size_t index) const;
|
||||
|
||||
ISize GetRenderTargetSize() const;
|
||||
@ -49,6 +52,9 @@ class RenderTarget {
|
||||
std::map<size_t, ColorAttachment> colors_;
|
||||
std::optional<DepthAttachment> depth_;
|
||||
std::optional<StencilAttachment> stencil_;
|
||||
|
||||
void IterateAllAttachments(
|
||||
std::function<bool(const Attachment& attachment)> iterator) const;
|
||||
};
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -13,11 +13,13 @@
|
||||
namespace impeller {
|
||||
|
||||
struct TextureDescriptor {
|
||||
TextureType type = TextureType::k2D;
|
||||
PixelFormat format = PixelFormat::kUnknown;
|
||||
ISize size;
|
||||
size_t mip_count = 1u; // Size::MipCount is usually appropriate.
|
||||
TextureUsageMask usage =
|
||||
static_cast<TextureUsageMask>(TextureUsage::kShaderRead);
|
||||
SampleCount sample_count = SampleCount::kCount1;
|
||||
|
||||
constexpr size_t GetSizeOfBaseMipLevel() const {
|
||||
if (!IsValid()) {
|
||||
@ -33,11 +35,16 @@ struct TextureDescriptor {
|
||||
return size.width * BytesPerPixelForPixelFormat(format);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
constexpr bool SamplingOptionsAreValid() const {
|
||||
const auto count = static_cast<uint64_t>(sample_count);
|
||||
return IsMultisampleCapable(type) ? count > 1 : count == 1;
|
||||
}
|
||||
|
||||
constexpr bool IsValid() const {
|
||||
return format != PixelFormat::kUnknown && //
|
||||
size.IsPositive() && //
|
||||
mip_count >= 1u //
|
||||
;
|
||||
mip_count >= 1u && //
|
||||
SamplingOptionsAreValid();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user