blob: ab1100664d4706b3f7e9750768e5e142ce5c7c3e [file] [log] [blame]
// 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/renderer/backend/vulkan/surface_vk.h"
#include "impeller/renderer/backend/vulkan/swapchain_image_vk.h"
#include "impeller/renderer/backend/vulkan/texture_vk.h"
#include "impeller/renderer/surface.h"
namespace impeller {
std::unique_ptr<SurfaceVK> SurfaceVK::WrapSwapchainImage(
const std::shared_ptr<Context>& context,
std::shared_ptr<SwapchainImageVK>& swapchain_image,
SwapCallback swap_callback) {
if (!context || !swapchain_image || !swap_callback) {
return nullptr;
}
// Some Vulkan devices may not support memoryless (lazily allocated) textures.
// In this case we will cache the MSAA texture on the swapchain image to avoid
// thrasing the VMA heap.
bool supports_memoryless =
context->GetCapabilities()->SupportsMemorylessTextures();
TextureDescriptor msaa_tex_desc;
msaa_tex_desc.storage_mode = StorageMode::kDeviceTransient;
msaa_tex_desc.type = TextureType::kTexture2DMultisample;
msaa_tex_desc.sample_count = SampleCount::kCount4;
msaa_tex_desc.format = swapchain_image->GetPixelFormat();
msaa_tex_desc.size = swapchain_image->GetSize();
msaa_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget);
std::shared_ptr<Texture> msaa_tex;
if (supports_memoryless || !swapchain_image->HasMSAATexture()) {
msaa_tex = context->GetResourceAllocator()->CreateTexture(msaa_tex_desc);
msaa_tex->SetLabel("ImpellerOnscreenColorMSAA");
if (!msaa_tex) {
VALIDATION_LOG << "Could not allocate MSAA color texture.";
return nullptr;
}
if (!supports_memoryless) {
swapchain_image->SetMSAATexture(msaa_tex);
}
} else {
msaa_tex = swapchain_image->GetMSAATexture();
}
TextureDescriptor resolve_tex_desc;
resolve_tex_desc.type = TextureType::kTexture2D;
resolve_tex_desc.format = swapchain_image->GetPixelFormat();
resolve_tex_desc.size = swapchain_image->GetSize();
resolve_tex_desc.usage =
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
resolve_tex_desc.sample_count = SampleCount::kCount1;
resolve_tex_desc.storage_mode = StorageMode::kDevicePrivate;
std::shared_ptr<Texture> resolve_tex =
std::make_shared<TextureVK>(context, //
swapchain_image //
);
if (!resolve_tex) {
VALIDATION_LOG << "Could not wrap resolve texture.";
return nullptr;
}
resolve_tex->SetLabel("ImpellerOnscreenResolve");
ColorAttachment color0;
color0.texture = msaa_tex;
color0.clear_color = Color::DarkSlateGray();
color0.load_action = LoadAction::kClear;
color0.store_action = StoreAction::kMultisampleResolve;
color0.resolve_texture = resolve_tex;
RenderTarget render_target_desc;
render_target_desc.SetColorAttachment(color0, 0u);
// The constructor is private. So make_unique may not be used.
return std::unique_ptr<SurfaceVK>(
new SurfaceVK(render_target_desc, std::move(swap_callback)));
}
SurfaceVK::SurfaceVK(const RenderTarget& target, SwapCallback swap_callback)
: Surface(target), swap_callback_(std::move(swap_callback)) {}
SurfaceVK::~SurfaceVK() = default;
bool SurfaceVK::Present() const {
return swap_callback_ ? swap_callback_() : false;
}
} // namespace impeller