diff --git a/aster/image.cpp b/aster/image.cpp index 6d72a62..b490b0e 100644 --- a/aster/image.cpp +++ b/aster/image.cpp @@ -19,14 +19,14 @@ Image::Destroy(const Device *device) } void -Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageFormat, const bool isMipmapped, +Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageFormat, const bool isMipMapped, const cstr name) { - const u32 mipLevels = isMipmapped ? 1 + Cast(floor(log2(eastl::max(extent.width, extent.height)))) : 1; + const u32 mipLevels = isMipMapped ? 1 + Cast(floor(log2(eastl::max(extent.width, extent.height)))) : 1; assert(mipLevels <= MIP_MASK); auto usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst; - if (isMipmapped) + if (isMipMapped) { usage |= vk::ImageUsageFlagBits::eTransferSrc; } @@ -81,6 +81,59 @@ Texture::Init(const Device *device, const vk::Extent2D extent, vk::Format imageF device->SetName(m_Image, name); } +void +AttachmentImage::Init(const Device *device, vk::Extent2D extent, vk::Format imageFormat, cstr name) +{ + vk::ImageCreateInfo imageCreateInfo = { + .imageType = vk::ImageType::e2D, + .format = imageFormat, + .extent = {.width = extent.width, .height = extent.height, .depth = 1}, + .mipLevels = 1, + .arrayLayers = 1, + .samples = vk::SampleCountFlagBits::e1, + .tiling = vk::ImageTiling::eOptimal, + .usage = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, + .sharingMode = vk::SharingMode::eExclusive, + .initialLayout = vk::ImageLayout::eUndefined, + }; + constexpr VmaAllocationCreateInfo allocationCreateInfo = { + .flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT, + .usage = VMA_MEMORY_USAGE_AUTO, + }; + + VkImage image; + VmaAllocation allocation; + auto result = Cast(vmaCreateImage(device->m_Allocator, Recast(&imageCreateInfo), + &allocationCreateInfo, &image, &allocation, nullptr)); + ERROR_IF(Failed(result), "Could not allocate depth buffer. Cause: {}", result) THEN_ABORT(result); + + vk::ImageView view; + vk::ImageViewCreateInfo imageViewCreateInfo = { + .image = image, + .viewType = vk::ImageViewType::e2D, + .format = imageFormat, + .components = {}, + .subresourceRange = + { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + result = device->m_Device.createImageView(&imageViewCreateInfo, nullptr, &view); + ERROR_IF(Failed(result), "Could not create depth image view {}. Cause: {}", name, result) THEN_ABORT(result); + + m_Image = image; + m_View = view; + m_Allocation = allocation; + m_Extent = {extent.width, extent.height, 1}; + m_MipLevels_ = 1 | OWNED_BIT | VALID_BIT; + + device->SetName(m_Image, name); +} + void DepthImage::Init(const Device *device, vk::Extent2D extent, cstr name) { diff --git a/aster/image.h b/aster/image.h index 22970d6..e7048f9 100644 --- a/aster/image.h +++ b/aster/image.h @@ -9,6 +9,24 @@ struct Device; +[[nodiscard]] inline vk::Extent2D +ToExtent2D(const vk::Extent3D &extent) +{ + return {extent.width, extent.height}; +} + +[[nodiscard]] inline vk::Offset2D +ToOffset2D(const vk::Extent3D &extent) +{ + return {Cast(extent.width), Cast(extent.height)}; +} + +[[nodiscard]] inline vk::Offset3D +ToOffset3D(const vk::Extent3D &extent) +{ + return {Cast(extent.width), Cast(extent.height), Cast(extent.depth)}; +} + struct Image { vk::Image m_Image = nullptr; @@ -32,7 +50,12 @@ struct Image struct Texture : Image { - void Init(const Device *device, vk::Extent2D extent, vk::Format imageFormat, bool isMipmapped, cstr name = nullptr); + void Init(const Device *device, vk::Extent2D extent, vk::Format imageFormat, bool isMipMapped, cstr name = nullptr); +}; + +struct AttachmentImage : Image +{ + void Init(const Device *device, vk::Extent2D extent, vk::Format imageFormat, cstr name = nullptr); }; struct DepthImage : Image diff --git a/aster/swapchain.cpp b/aster/swapchain.cpp index fbe53b4..57ff233 100644 --- a/aster/swapchain.cpp +++ b/aster/swapchain.cpp @@ -110,7 +110,7 @@ Swapchain::Create(const Window *window) .imageColorSpace = swapchainColorSpace, .imageExtent = m_Extent, .imageArrayLayers = 1, - .imageUsage = vk::ImageUsageFlagBits::eColorAttachment, + .imageUsage = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferDst, .imageSharingMode = vk::SharingMode::eExclusive, .preTransform = surfaceCapabilities.currentTransform, .compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque, diff --git a/samples/03_model_render/model_render.cpp b/samples/03_model_render/model_render.cpp index cf1e624..dd26d96 100644 --- a/samples/03_model_render/model_render.cpp +++ b/samples/03_model_render/model_render.cpp @@ -79,7 +79,8 @@ main(int, char **) Model model = modelLoader.LoadModel(MODEL_FILE); - Pipeline pipeline = CreatePipeline(&device, &swapchain, &resourceManager); + vk::Format attachmentFormat = vk::Format::eR8G8B8A8Srgb; + Pipeline pipeline = CreatePipeline(&device, attachmentFormat, &resourceManager); Camera camera = { .m_View = glm::lookAt(vec3(0.0f, 2.0f, 2.0f), vec3(0.0f), vec3(0.0f, 1.0f, 0.0f)), @@ -154,14 +155,6 @@ main(int, char **) .extent = swapchain.m_Extent, }; - auto fnResizeViewportScissor = [&viewport, &scissor](vk::Extent2D extent) { - viewport.y = Cast(extent.height); - viewport.width = Cast(extent.width); - viewport.height = -Cast(extent.height); - scissor.extent = extent; - }; - swapchain.RegisterResizeCallback(fnResizeViewportScissor); - vk::ImageSubresourceRange subresourceRange = { .aspectMask = vk::ImageAspectFlagBits::eColor, .baseMipLevel = 0, @@ -176,8 +169,26 @@ main(int, char **) .dstQueueFamilyIndex = queueAllocation.m_Family, .subresourceRange = subresourceRange, }; - vk::ImageMemoryBarrier renderToPresentBarrier = { + vk::ImageMemoryBarrier renderToTransferSrcBarrier = { .oldLayout = vk::ImageLayout::eColorAttachmentOptimal, + .newLayout = vk::ImageLayout::eTransferSrcOptimal, + .srcQueueFamilyIndex = queueAllocation.m_Family, + .dstQueueFamilyIndex = queueAllocation.m_Family, + .subresourceRange = subresourceRange, + }; + vk::ImageMemoryBarrier acquireToTransferDstBarrier = { + .oldLayout = vk::ImageLayout::eUndefined, + .newLayout = vk::ImageLayout::eTransferDstOptimal, + .srcQueueFamilyIndex = queueAllocation.m_Family, + .dstQueueFamilyIndex = queueAllocation.m_Family, + .subresourceRange = subresourceRange, + }; + eastl::array postRenderBarriers = { + renderToTransferSrcBarrier, + acquireToTransferDstBarrier, + }; + vk::ImageMemoryBarrier transferDstToPresentBarrier = { + .oldLayout = vk::ImageLayout::eTransferDstOptimal, .newLayout = vk::ImageLayout::ePresentSrcKHR, .srcQueueFamilyIndex = queueAllocation.m_Family, .dstQueueFamilyIndex = queueAllocation.m_Family, @@ -186,26 +197,23 @@ main(int, char **) FrameManager frameManager = {&device, queueAllocation.m_Family, MAX_FRAMES_IN_FLIGHT}; eastl::fixed_vector depthImages(frameManager.m_FramesInFlight); + eastl::fixed_vector attachmentImages(frameManager.m_FramesInFlight); { - u32 depthImageIdx = 0; - for (auto &depthImage : depthImages) + auto depthIter = depthImages.begin(); + auto attachmentIter = attachmentImages.begin(); + for (u32 index = 0; index < frameManager.m_FramesInFlight; ++index) { - auto name = fmt::format("Depth {}", depthImageIdx++); - depthImage.Init(&device, swapchain.m_Extent, name.c_str()); + auto name = fmt::format("Depth Frame{}", index); + depthIter->Init(&device, swapchain.m_Extent, name.c_str()); + + name = fmt::format("Attachment0 Frame{}", index); + attachmentIter->Init(&device, swapchain.m_Extent, attachmentFormat, name.c_str()); + + ++depthIter; + ++attachmentIter; } } - auto fnRecreateDepthBuffers = [&device, &depthImages](vk::Extent2D extent) { - u32 depthImageIdx = 0; - for (auto &depthImage : depthImages) - { - auto name = fmt::format("Depth {}", depthImageIdx++); - depthImage.Destroy(&device); - depthImage.Init(&device, extent, name.c_str()); - } - }; - swapchain.RegisterResizeCallback(fnRecreateDepthBuffers); - Time::Init(); INFO("Starting loop"); @@ -221,13 +229,18 @@ main(int, char **) Frame *currentFrame = frameManager.GetNextFrame(&swapchain, &window); u32 imageIndex = currentFrame->m_ImageIdx; - vk::ImageView currentImageView = swapchain.m_ImageViews[imageIndex]; - vk::Image currentImage = swapchain.m_Images[imageIndex]; + vk::Image currentSwapchainImage = swapchain.m_Images[imageIndex]; vk::CommandBuffer cmd = currentFrame->m_CommandBuffer; vk::ImageView currentDepthImageView = depthImages[currentFrame->m_FrameIdx].m_View; + AttachmentImage *currentAttachment = &attachmentImages[currentFrame->m_ImageIdx]; + vk::Image currentImage = currentAttachment->m_Image; + vk::ImageView currentImageView = currentAttachment->m_View; + topOfThePipeBarrier.image = currentImage; - renderToPresentBarrier.image = currentImage; + postRenderBarriers[0].image = currentImage; + postRenderBarriers[1].image = currentSwapchainImage; + transferDstToPresentBarrier.image = currentSwapchainImage; vk::CommandBufferBeginInfo beginInfo = {.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit}; AbortIfFailed(cmd.begin(&beginInfo)); @@ -257,7 +270,7 @@ main(int, char **) }; vk::RenderingInfo renderingInfo = { - .renderArea = {.extent = swapchain.m_Extent}, + .renderArea = {.extent = ToExtent2D(currentAttachment->m_Extent)}, .layerCount = 1, .colorAttachmentCount = Cast(attachmentInfos.size()), .pColorAttachments = attachmentInfos.data(), @@ -296,8 +309,40 @@ main(int, char **) cmd.endRendering(); - cmd.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eBottomOfPipe, - {}, 0, nullptr, 0, nullptr, 1, &renderToPresentBarrier); + cmd.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eAllCommands, + {}, 0, nullptr, 0, nullptr, postRenderBarriers.size(), postRenderBarriers.data()); + + vk::ImageBlit blitRegion = { + .srcSubresource = + { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .srcOffsets = + std::array{ + vk::Offset3D{0, 0, 0}, + ToOffset3D(currentAttachment->m_Extent), + }, + .dstSubresource = + { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .dstOffsets = + std::array{ + vk::Offset3D{0, 0, 0}, + vk::Offset3D{Cast(swapchain.m_Extent.width), Cast(swapchain.m_Extent.height), 1}, + }, + }; + cmd.blitImage(currentImage, postRenderBarriers[0].newLayout, currentSwapchainImage, + postRenderBarriers[1].newLayout, 1, &blitRegion, vk::Filter::eLinear); + + cmd.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {}, 0, + nullptr, 0, nullptr, 1, &transferDstToPresentBarrier); AbortIfFailed(cmd.end()); @@ -322,6 +367,10 @@ main(int, char **) { depthImage.Destroy(&device); } + for (auto &attachmentImage : attachmentImages) + { + attachmentImage.Destroy(&device); + } ubo.Destroy(&device); device.m_Device.destroy(descriptorPool, nullptr); diff --git a/samples/03_model_render/pipeline_utils.cpp b/samples/03_model_render/pipeline_utils.cpp index e67b674..70b71b7 100644 --- a/samples/03_model_render/pipeline_utils.cpp +++ b/samples/03_model_render/pipeline_utils.cpp @@ -13,7 +13,7 @@ #include Pipeline -CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResourceManager *resourceManager) +CreatePipeline(const Device *device, vk::Format attachmentFormat, const GpuResourceManager *resourceManager) { // Pipeline Setup auto vertexShaderModule = CreateShader(device, VERTEX_SHADER_FILE); @@ -132,7 +132,7 @@ CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResour vk::PipelineRenderingCreateInfo renderingCreateInfo = { .viewMask = 0, .colorAttachmentCount = 1, - .pColorAttachmentFormats = &swapchain->m_Format, + .pColorAttachmentFormats = &attachmentFormat, .depthAttachmentFormat = vk::Format::eD24UnormS8Uint, }; diff --git a/samples/03_model_render/pipeline_utils.h b/samples/03_model_render/pipeline_utils.h index 47c40cf..df9e29f 100644 --- a/samples/03_model_render/pipeline_utils.h +++ b/samples/03_model_render/pipeline_utils.h @@ -16,4 +16,4 @@ constexpr auto VERTEX_SHADER_FILE = "shader/model.vs.hlsl.spv"; constexpr auto FRAGMENT_SHADER_FILE = "shader/model.ps.hlsl.spv"; vk::ShaderModule CreateShader(const Device *device, cstr shaderFile); -Pipeline CreatePipeline(const Device *device, const Swapchain *swapchain, const GpuResourceManager *resourceManager); +Pipeline CreatePipeline(const Device *device, vk::Format attachmentFormat, const GpuResourceManager *resourceManager);