vk_texture: Implement non-owning texture

* Swapchain images must not be destroyed since their cleanup is handled automatically.
This commit is contained in:
GPUCode
2022-04-30 18:45:25 +03:00
parent 2ec7f37d69
commit 4151fad10b
4 changed files with 35 additions and 19 deletions

View File

@@ -177,11 +177,8 @@ void VKSwapChain::SetupImages() {
// Create the swapchain buffers containing the image and imageview // Create the swapchain buffers containing the image and imageview
swapchain_images.resize(images.size()); swapchain_images.resize(images.size());
for (size_t i = 0; i < swapchain_images.size(); i++) for (int i = 0; i < swapchain_images.size(); i++)
{ {
swapchain_images[i].image = images[i];
// Create swapchain image view
vk::ImageViewCreateInfo color_attachment_view vk::ImageViewCreateInfo color_attachment_view
( (
{}, {},
@@ -192,11 +189,12 @@ void VKSwapChain::SetupImages() {
{ vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 } { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 }
); );
swapchain_images[i].image_view = device.createImageViewUnique(color_attachment_view); // Wrap swapchain images with VKTexture
swapchain_images[i].image.Adopt(images[i], color_attachment_view);
// Create framebuffer for each swapchain image // Create framebuffer for each swapchain image
VKFramebuffer::Info fb_info = { VKFramebuffer::Info fb_info = {
.color = // TODO .color = &swapchain_images[i].image
}; };
swapchain_images[i].framebuffer.Create(fb_info); swapchain_images[i].framebuffer.Create(fb_info);

View File

@@ -11,8 +11,7 @@
namespace Vulkan { namespace Vulkan {
struct SwapChainImage { struct SwapChainImage {
vk::Image image; VKTexture image;
vk::UniqueImageView image_view;
VKFramebuffer framebuffer; VKFramebuffer framebuffer;
}; };

View File

@@ -10,6 +10,12 @@
namespace Vulkan { namespace Vulkan {
VKTexture::~VKTexture() {
if (cleanup_image) {
g_vk_instace->GetDevice().destroyImage(texture);
}
}
void VKTexture::Create(const Info& info) { void VKTexture::Create(const Info& info) {
auto& device = g_vk_instace->GetDevice(); auto& device = g_vk_instace->GetDevice();
texture_info = info; texture_info = info;
@@ -49,22 +55,31 @@ void VKTexture::Create(const Info& info) {
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled
); );
texture = device.createImageUnique(image_info); texture = device.createImage(image_info);
// Create texture memory // Create texture memory
auto requirements = device.getImageMemoryRequirements(texture.get()); auto requirements = device.getImageMemoryRequirements(texture);
auto memory_index = VKBuffer::FindMemoryType(requirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eDeviceLocal); auto memory_index = VKBuffer::FindMemoryType(requirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eDeviceLocal);
vk::MemoryAllocateInfo alloc_info(requirements.size, memory_index); vk::MemoryAllocateInfo alloc_info(requirements.size, memory_index);
texture_memory = device.allocateMemoryUnique(alloc_info); texture_memory = device.allocateMemoryUnique(alloc_info);
device.bindImageMemory(texture.get(), texture_memory.get(), 0); device.bindImageMemory(texture, texture_memory.get(), 0);
// Create texture view // Create texture view
vk::ImageViewCreateInfo view_info({}, texture.get(), info.view_type, texture_info.format, {}, vk::ImageViewCreateInfo view_info({}, texture, info.view_type, texture_info.format, {},
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));
texture_view = device.createImageViewUnique(view_info); texture_view = device.createImageViewUnique(view_info);
} }
void VKTexture::Adopt(vk::Image image, vk::ImageViewCreateInfo view_info) {
// Prevent image cleanup at object destruction
cleanup_image = false;
texture = image;
// Create image view
texture_view = g_vk_instace->GetDevice().createImageViewUnique(view_info);
}
void VKTexture::TransitionLayout(vk::ImageLayout new_layout, vk::CommandBuffer& command_buffer) { void VKTexture::TransitionLayout(vk::ImageLayout new_layout, vk::CommandBuffer& command_buffer) {
struct LayoutInfo { struct LayoutInfo {
vk::ImageLayout layout; vk::ImageLayout layout;
@@ -135,7 +150,7 @@ void VKTexture::TransitionLayout(vk::ImageLayout new_layout, vk::CommandBuffer&
source.access, dst.access, source.access, dst.access,
source.layout, dst.layout, source.layout, dst.layout,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
texture.get(), texture,
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1) vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)
); );
@@ -172,7 +187,7 @@ void VKTexture::CopyPixels(std::span<u32> new_pixels) {
TransitionLayout(vk::ImageLayout::eTransferDstOptimal, command_buffer); TransitionLayout(vk::ImageLayout::eTransferDstOptimal, command_buffer);
auto& staging = g_vk_res_cache->GetTextureUploadBuffer(); auto& staging = g_vk_res_cache->GetTextureUploadBuffer();
command_buffer.copyBufferToImage(staging.GetBuffer(), texture.get(), vk::ImageLayout::eTransferDstOptimal, regions); command_buffer.copyBufferToImage(staging.GetBuffer(), texture, vk::ImageLayout::eTransferDstOptimal, regions);
// Prepare for shader reads // Prepare for shader reads
TransitionLayout(vk::ImageLayout::eShaderReadOnlyOptimal, command_buffer); TransitionLayout(vk::ImageLayout::eShaderReadOnlyOptimal, command_buffer);
@@ -222,7 +237,7 @@ void VKTexture::BlitTo(Common::Rectangle<u32> srect, VKTexture& dest,
dest.TransitionLayout(vk::ImageLayout::eTransferDstOptimal, command_buffer); dest.TransitionLayout(vk::ImageLayout::eTransferDstOptimal, command_buffer);
// Perform blit operation // Perform blit operation
command_buffer.blitImage(texture.get(), vk::ImageLayout::eTransferSrcOptimal, dest.texture.get(), command_buffer.blitImage(texture, vk::ImageLayout::eTransferSrcOptimal, dest.texture,
vk::ImageLayout::eTransferDstOptimal, regions, vk::Filter::eNearest); vk::ImageLayout::eTransferDstOptimal, regions, vk::Filter::eNearest);
} }

View File

@@ -39,11 +39,13 @@ public:
VKTexture() = default; VKTexture() = default;
VKTexture(VKTexture&&) = default; VKTexture(VKTexture&&) = default;
~VKTexture() = default; ~VKTexture();
/// Create a new Vulkan texture object along with its sampler /// Create a new Vulkan texture object
void Create(const Info& info); void Create(const Info& info);
bool IsValid() { return !!texture; }
/// Create a non-owning texture object
void Adopt(vk::Image image, vk::ImageViewCreateInfo view_info);
/// Copies CPU side pixel data to the GPU texture buffer /// Copies CPU side pixel data to the GPU texture buffer
void CopyPixels(std::span<u32> pixels); void CopyPixels(std::span<u32> pixels);
@@ -53,6 +55,7 @@ public:
vk::Format GetFormat() const { return texture_info.format; } vk::Format GetFormat() const { return texture_info.format; }
vk::Rect2D GetRect() const { return vk::Rect2D({}, { texture_info.width, texture_info.height }); } vk::Rect2D GetRect() const { return vk::Rect2D({}, { texture_info.width, texture_info.height }); }
u32 GetSamples() const { return texture_info.multisamples; } u32 GetSamples() const { return texture_info.multisamples; }
bool IsValid() { return texture; }
/// Used to transition the image to an optimal layout during transfers /// Used to transition the image to an optimal layout during transfers
void TransitionLayout(vk::ImageLayout new_layout, vk::CommandBuffer& command_buffer); void TransitionLayout(vk::ImageLayout new_layout, vk::CommandBuffer& command_buffer);
@@ -67,9 +70,10 @@ public:
vk::CommandBuffer& command_buffer); vk::CommandBuffer& command_buffer);
private: private:
bool cleanup_image = true;
Info texture_info; Info texture_info;
vk::ImageLayout texture_layout = vk::ImageLayout::eUndefined; vk::ImageLayout texture_layout = vk::ImageLayout::eUndefined;
vk::UniqueImage texture; vk::Image texture;
vk::UniqueImageView texture_view; vk::UniqueImageView texture_view;
vk::UniqueDeviceMemory texture_memory; vk::UniqueDeviceMemory texture_memory;
u32 channels; u32 channels;