blob: a3a63e9eb3b5d0e55f5aab06831bbd3124c82406 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_UI_LIB_ESCHER_VK_IMAGE_H_
#define SRC_UI_LIB_ESCHER_VK_IMAGE_H_
#include "src/ui/lib/escher/forward_declarations.h"
#include "src/ui/lib/escher/renderer/semaphore.h"
#include "src/ui/lib/escher/resources/resource.h"
#include "src/ui/lib/escher/util/debug_print.h"
namespace escher {
// Full description of the size and layout of an Image.
#pragma pack(push, 1) // As required by escher::HashMapHasher<ImageInfo>
struct ImageInfo {
vk::Format format = vk::Format::eUndefined;
uint32_t width = 0;
uint32_t height = 0;
uint32_t sample_count = 1;
vk::ImageUsageFlags usage;
vk::MemoryPropertyFlags memory_flags = vk::MemoryPropertyFlagBits::eDeviceLocal;
vk::ImageTiling tiling = vk::ImageTiling::eOptimal;
bool is_mutable = false;
bool is_external = false;
bool operator==(const ImageInfo& other) const {
return format == other.format && width == other.width && height == other.height &&
sample_count == other.sample_count && usage == other.usage &&
memory_flags == other.memory_flags && tiling == other.tiling &&
is_mutable == other.is_mutable && is_external == other.is_external;
}
// Transient images are neither loaded nor stored by render passes. Instead
// they may be rendered into by one subpass and used as an input attachment by
// a subsequent pass. Consequently, it may be possible (not implemented yet,
// and depending on the hardware/driver) to avoid allocating any memory for
// such images, so that it exists only transiently in tile-local storage.
bool is_transient() const {
return static_cast<bool>(usage & vk::ImageUsageFlagBits::eTransientAttachment);
}
};
#pragma pack(pop)
// An Image is a Resource that encapsulates a vk::Image.
class Image : public Resource {
public:
static const ResourceTypeInfo kTypeInfo;
const ResourceTypeInfo& type_info() const override { return kTypeInfo; }
// Constructor. Wraps an existing image without claiming ownership. Useful
// when the image is owned/maintained by another system (e.g.,
// vk::SwapchainKHR).
static ImagePtr WrapVkImage(ResourceManager* image_owner, ImageInfo info, vk::Image image,
vk::ImageLayout initial_layout);
const ImageInfo& info() const { return info_; }
vk::Image vk() const { return image_; }
vk::Format format() const { return info_.format; }
// TODO(fxbug.dev/7173): decide whether to deprecate format().
vk::Format vk_format() const { return info_.format; }
uint32_t width() const { return info_.width; }
uint32_t height() const { return info_.height; }
bool has_depth() const { return has_depth_; }
bool has_stencil() const { return has_stencil_; }
bool is_transient() const { return info_.is_transient(); }
vk::DeviceSize size() const { return size_; }
uint8_t* host_ptr() const { return host_ptr_; }
// TODO(fxbug.dev/7174): how does this interact with swapchain_layout_?
// Should it be locked so that the layout can't be changed during a render-pass
// where it is used as an attachment?
vk::ImageLayout layout() const { return layout_; }
bool is_layout_initialized() const {
return layout() != vk::ImageLayout::eUndefined && layout() != vk::ImageLayout::ePreinitialized;
}
// Specify the layout that should be transitioned to when this image is used
// as a framebuffer attachment.
void set_swapchain_layout(vk::ImageLayout layout) { swapchain_layout_ = layout; }
vk::ImageLayout swapchain_layout() const { return swapchain_layout_; }
bool is_swapchain_image() const { return swapchain_layout_ != vk::ImageLayout::eUndefined; }
bool use_protected_memory() const {
return static_cast<bool>(info_.memory_flags & vk::MemoryPropertyFlagBits::eProtected);
}
// Return the number of bytes of committed memory. Unlike the similarly-named Vulkan function,
// the image's memory need not be created as lazily-allocated; if not, this will simply return
// size(). If the memory is lazily-allocated, this will return the result of
// vkGetDeviceMemoryCommitment().
//
// This method is virtual because this class doesn't have direct access to the VkDeviceMemory that
// is required to call vkGetDeviceMemoryCommitment(); each subclass implements this slightly
// differently.
virtual vk::DeviceSize GetDeviceMemoryCommitment();
protected:
// Constructor. In some cases it is necessary to wrap an un-owned vk::Image,
// which should not be destroyed when this Image is destroyed (e.g. when
// working with images associated with a vk::SwapchainKHR); this is done by
// passing nullptr as the |mem| argument.
Image(ResourceManager* image_owner, ImageInfo info, vk::Image image, vk::DeviceSize size_,
uint8_t* host_ptr_, vk::ImageLayout initial_layout);
private:
friend class CommandBuffer;
friend class impl::CommandBuffer;
// Set the image layout stored in |layout_|. This should be only used by
// friend classes like |CommandBuffer| or |impl::CommandBuffer|
// when they made transitions to image layouts, e.g. when we invoke
// |TransitionImageLayout| to manually do layout transitions in
// BatchGpuUploader.
void set_layout(vk::ImageLayout new_layout) { layout_ = new_layout; }
const ImageInfo info_;
const vk::Image image_;
const bool has_depth_;
const bool has_stencil_;
const vk::DeviceSize size_;
uint8_t* const host_ptr_;
// TODO(fxbug.dev/7174): consider allowing image to have an initial layout.
vk::ImageLayout layout_ = vk::ImageLayout::eUndefined;
vk::ImageLayout swapchain_layout_ = vk::ImageLayout::eUndefined;
FXL_DISALLOW_COPY_AND_ASSIGN(Image);
};
typedef fxl::RefPtr<Image> ImagePtr;
// Debugging.
ESCHER_DEBUG_PRINTABLE(ImageInfo);
} // namespace escher
#endif // SRC_UI_LIB_ESCHER_VK_IMAGE_H_