diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 4ed6759ee..51ea0e5e2 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -177,11 +177,8 @@ void VKSwapChain::SetupImages() { // Create the swapchain buffers containing the image and imageview 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 ( {}, @@ -192,11 +189,12 @@ void VKSwapChain::SetupImages() { { 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 VKFramebuffer::Info fb_info = { - .color = // TODO + .color = &swapchain_images[i].image }; swapchain_images[i].framebuffer.Create(fb_info); diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index 5821510a1..a5f533e13 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h @@ -11,8 +11,7 @@ namespace Vulkan { struct SwapChainImage { - vk::Image image; - vk::UniqueImageView image_view; + VKTexture image; VKFramebuffer framebuffer; }; diff --git a/src/video_core/renderer_vulkan/vk_texture.cpp b/src/video_core/renderer_vulkan/vk_texture.cpp index 17aac1e5b..fd69d9da3 100644 --- a/src/video_core/renderer_vulkan/vk_texture.cpp +++ b/src/video_core/renderer_vulkan/vk_texture.cpp @@ -10,6 +10,12 @@ namespace Vulkan { +VKTexture::~VKTexture() { + if (cleanup_image) { + g_vk_instace->GetDevice().destroyImage(texture); + } +} + void VKTexture::Create(const Info& info) { auto& device = g_vk_instace->GetDevice(); texture_info = info; @@ -49,22 +55,31 @@ void VKTexture::Create(const Info& info) { vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled ); - texture = device.createImageUnique(image_info); + texture = device.createImage(image_info); // Create texture memory - auto requirements = device.getImageMemoryRequirements(texture.get()); + auto requirements = device.getImageMemoryRequirements(texture); auto memory_index = VKBuffer::FindMemoryType(requirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eDeviceLocal); vk::MemoryAllocateInfo alloc_info(requirements.size, memory_index); texture_memory = device.allocateMemoryUnique(alloc_info); - device.bindImageMemory(texture.get(), texture_memory.get(), 0); + device.bindImageMemory(texture, texture_memory.get(), 0); // 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)); 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) { struct LayoutInfo { vk::ImageLayout layout; @@ -135,7 +150,7 @@ void VKTexture::TransitionLayout(vk::ImageLayout new_layout, vk::CommandBuffer& source.access, dst.access, source.layout, dst.layout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - texture.get(), + texture, vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1) ); @@ -172,7 +187,7 @@ void VKTexture::CopyPixels(std::span new_pixels) { TransitionLayout(vk::ImageLayout::eTransferDstOptimal, command_buffer); 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 TransitionLayout(vk::ImageLayout::eShaderReadOnlyOptimal, command_buffer); @@ -222,7 +237,7 @@ void VKTexture::BlitTo(Common::Rectangle srect, VKTexture& dest, dest.TransitionLayout(vk::ImageLayout::eTransferDstOptimal, command_buffer); // 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); } diff --git a/src/video_core/renderer_vulkan/vk_texture.h b/src/video_core/renderer_vulkan/vk_texture.h index 7266a80e5..5b5ebcdda 100644 --- a/src/video_core/renderer_vulkan/vk_texture.h +++ b/src/video_core/renderer_vulkan/vk_texture.h @@ -39,11 +39,13 @@ public: 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); - 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 void CopyPixels(std::span pixels); @@ -53,6 +55,7 @@ public: vk::Format GetFormat() const { return texture_info.format; } vk::Rect2D GetRect() const { return vk::Rect2D({}, { texture_info.width, texture_info.height }); } u32 GetSamples() const { return texture_info.multisamples; } + bool IsValid() { return texture; } /// Used to transition the image to an optimal layout during transfers void TransitionLayout(vk::ImageLayout new_layout, vk::CommandBuffer& command_buffer); @@ -67,9 +70,10 @@ public: vk::CommandBuffer& command_buffer); private: + bool cleanup_image = true; Info texture_info; vk::ImageLayout texture_layout = vk::ImageLayout::eUndefined; - vk::UniqueImage texture; + vk::Image texture; vk::UniqueImageView texture_view; vk::UniqueDeviceMemory texture_memory; u32 channels;