iwa/source/util/image_reference.cpp
2024-04-06 14:11:26 +02:00

148 lines
4.1 KiB
C++

#include "iwa/util/image_reference.hpp"
#include <mijin/util/iterators.hpp>
#include "iwa/command.hpp"
#include "iwa/device.hpp"
namespace iwa
{
ImageReference::ImageReference(ObjectPtr<Device> owner) : super_t(std::move(owner))
{
}
void ImageReference::finalize(ImageReferenceFinalizeArgs& /* args */) {}
mijin::Task<> ImageReference::c_present()
{
co_return;
}
SwapchainImageReference::SwapchainImageReference(ObjectPtr<Device> owner, SwapchainImageReferenceCreationArgs args)
: super_t(std::move(owner)), mSwapchain(std::move(args.swapchain))
{
mPresentReadySemaphores.resize(mSwapchain->getNumParallelFrames());
for (ObjectPtr<Semaphore>& semaphore : mPresentReadySemaphores)
{
semaphore = getOwner()->createChild<Semaphore>();
}
createImageViews();
mSwapchain->recreated.connect([this]()
{
createImageViews();
});
}
vk::Format SwapchainImageReference::getFormat()
{
return mSwapchain->getFormat();
}
vk::Extent2D SwapchainImageReference::getExtent()
{
return mSwapchain->getExtent();
}
ImageReferenceFrame SwapchainImageReference::getCurrentFrame()
{
return ImageReferenceFrame{
.image = mSwapchain->getCurrentImage().getRaw(),
.imageView = mImageViews[mSwapchain->getCurrentImageIdx()].getRaw()
};
}
void SwapchainImageReference::finalize(ImageReferenceFinalizeArgs& args)
{
args.waitSemaphores.push_back(*mSwapchain->getCurrentAvailableSemaphore());
args.signalSemaphores.push_back(*mPresentReadySemaphores[mSwapchain->getCurrentFrameIdx()]);
mSwapchain->getCurrentImage()->applyTransition(args.cmdBuffer, ImageTransition{
.stages = vk::PipelineStageFlagBits::eBottomOfPipe,
.layout = vk::ImageLayout::ePresentSrcKHR,
.access = {}
});
}
mijin::Task<> SwapchainImageReference::c_present()
{
// and present
co_await mSwapchain->c_present({
.queue = getOwner()->getGraphicsQueue(),
.waitSemaphores = {mPresentReadySemaphores[mSwapchain->getCurrentFrameIdx()]->getVkHandle()}
});
}
void SwapchainImageReference::createImageViews()
{
mImageViews.resize(mSwapchain->getImages().size());
for (auto [image, imageView] : mijin::zip(mSwapchain->getImages(), mImageViews))
{
imageView = image->createImageView();
}
}
DirectImageReference::DirectImageReference(ObjectPtr<Device> owner, DirectImageReferenceCreationArgs args)
: super_t(std::move(owner)), mImage(std::move(args.image)), mImageView(std::move(args.imageView))
{
}
vk::Format DirectImageReference::getFormat()
{
return mImage->getFormat();
}
vk::Extent2D DirectImageReference::getExtent()
{
return {
.width = mImage->getSize().width,
.height = mImage->getSize().height
};
}
ImageReferenceFrame DirectImageReference::getCurrentFrame()
{
return ImageReferenceFrame{
.image = mImage.getRaw(),
.imageView = mImageView.getRaw()
};
}
AutoResizeImageReference::AutoResizeImageReference(ObjectPtr<Device> owner, AutoResizeImageReferenceCreationArgs args)
: super_t(std::move(owner), DirectImageReferenceCreationArgs{}), mReferenceImageRef(std::move(args.referenceImageRef)),
mImageCreationArgs(std::move(args.imageCreationArgs)), mImageViewCreationArgs(args.imageViewCreationArgs)
{
createImage();
}
vk::Extent2D AutoResizeImageReference::getExtent()
{
return mReferenceImageRef->getExtent();
}
ImageReferenceFrame AutoResizeImageReference::getCurrentFrame()
{
const vk::Extent2D extent = mReferenceImageRef->getExtent();
if (extent.width != mImage->getSize().width || extent.height != mImage->getSize().height) {
createImage();
}
return ImageReferenceFrame{
.image = mImage.getRaw(),
.imageView = mImageView.getRaw()
};
}
void AutoResizeImageReference::createImage()
{
const vk::Extent2D extent = mReferenceImageRef->getExtent();
mImageCreationArgs.extent.width = extent.width;
mImageCreationArgs.extent.height = extent.height;
mImageCreationArgs.extent.depth = 1;
mImage = getOwner()->createChild<Image>(mImageCreationArgs);
mImage->allocateMemory();
mImageView = mImage->createImageView(mImageViewCreationArgs);
}
} // namespace iwa