vk_texture: Implement non-owning texture
* Swapchain images must not be destroyed since their cleanup is handled automatically.
This commit is contained in:
@@ -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);
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user