blob: 70c048e1f459f37871fcc1ca5e31174ea6c8d58c [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/texture_vk.h"
namespace impeller {
TextureVK::TextureVK(TextureDescriptor desc,
std::weak_ptr<Context> context,
std::shared_ptr<TextureSourceVK> source)
: Texture(desc), context_(std::move(context)), source_(std::move(source)) {}
TextureVK::~TextureVK() = default;
void TextureVK::SetLabel(std::string_view label) {
auto context = context_.lock();
if (!context) {
// The context may have died.
return;
}
ContextVK::Cast(*context).SetDebugName(GetImage(), label);
}
bool TextureVK::OnSetContents(const uint8_t* contents,
size_t length,
size_t slice) {
if (!IsValid() || !contents) {
return false;
}
const auto& desc = GetTextureDescriptor();
// Out of bounds access.
if (length != desc.GetByteSizeOfBaseMipLevel()) {
VALIDATION_LOG << "illegal to set contents for invalid size";
return false;
}
return source_->SetContents(desc, contents, length, slice);
}
bool TextureVK::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
size_t slice) {
// Vulkan has no threading restrictions. So we can pass this data along to the
// client rendering API immediately.
return OnSetContents(mapping->GetMapping(), mapping->GetSize(), slice);
}
bool TextureVK::IsValid() const {
return !!source_;
}
ISize TextureVK::GetSize() const {
return GetTextureDescriptor().size;
}
vk::Image TextureVK::GetImage() const {
return source_->GetVKImage();
}
vk::ImageView TextureVK::GetImageView() const {
return source_->GetVKImageView();
}
static constexpr vk::ImageAspectFlags ToImageAspectFlags(
vk::ImageLayout layout) {
switch (layout) {
case vk::ImageLayout::eColorAttachmentOptimal:
case vk::ImageLayout::eShaderReadOnlyOptimal:
return vk::ImageAspectFlagBits::eColor;
case vk::ImageLayout::eDepthAttachmentOptimal:
return vk::ImageAspectFlagBits::eDepth;
case vk::ImageLayout::eStencilAttachmentOptimal:
return vk::ImageAspectFlagBits::eStencil;
default:
FML_DLOG(INFO) << "Unknown layout to determine aspect.";
return vk::ImageAspectFlagBits::eNone;
}
FML_UNREACHABLE();
}
vk::ImageLayout TextureVK::GetLayout() const {
ReaderLock lock(layout_mutex_);
return layout_;
}
vk::ImageLayout TextureVK::SetLayoutWithoutEncoding(
vk::ImageLayout layout) const {
WriterLock lock(layout_mutex_);
const auto old_layout = layout_;
layout_ = layout;
return old_layout;
}
bool TextureVK::SetLayout(vk::ImageLayout new_layout,
const vk::CommandBuffer& buffer) const {
const auto old_layout = SetLayoutWithoutEncoding(new_layout);
if (new_layout == old_layout) {
return true;
}
vk::ImageMemoryBarrier image_barrier;
image_barrier.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite |
vk::AccessFlagBits::eTransferWrite;
image_barrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead |
vk::AccessFlagBits::eShaderRead;
image_barrier.oldLayout = old_layout;
image_barrier.newLayout = new_layout;
image_barrier.image = GetImage();
image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_barrier.subresourceRange.aspectMask = ToImageAspectFlags(new_layout);
image_barrier.subresourceRange.baseMipLevel = 0u;
image_barrier.subresourceRange.levelCount = GetTextureDescriptor().mip_count;
image_barrier.subresourceRange.baseArrayLayer = 0u;
image_barrier.subresourceRange.layerCount = 1u;
buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics, // src stage
vk::PipelineStageFlagBits::eAllGraphics, // dst stage
{}, // dependency flags
nullptr, // memory barriers
nullptr, // buffer barriers
image_barrier // image barriers
);
return true;
}
} // namespace impeller