From 9ab19d057dd4c7355aeef4bf92890a7ba375330d Mon Sep 17 00:00:00 2001 From: Magnus Norddahl <dpjudas@users.noreply.github.com> Date: Thu, 16 May 2019 18:26:47 +0200 Subject: [PATCH] - centralize how image transitions are done in the vulkan backend --- src/CMakeLists.txt | 1 + .../vulkan/renderer/vk_postprocess.cpp | 245 +++++------------- .../vulkan/renderer/vk_postprocess.h | 29 +-- .../vulkan/renderer/vk_renderbuffers.cpp | 103 ++++---- .../vulkan/renderer/vk_renderbuffers.h | 27 +- .../vulkan/renderer/vk_renderpass.cpp | 2 +- .../vulkan/renderer/vk_renderstate.cpp | 4 +- .../vulkan/system/vk_framebuffer.cpp | 36 +-- .../vulkan/textures/vk_hwtexture.cpp | 175 +++++-------- src/rendering/vulkan/textures/vk_hwtexture.h | 14 +- .../vulkan/textures/vk_imagetransition.cpp | 130 ++++++++++ .../vulkan/textures/vk_imagetransition.h | 39 +++ 12 files changed, 385 insertions(+), 420 deletions(-) create mode 100644 src/rendering/vulkan/textures/vk_imagetransition.cpp create mode 100644 src/rendering/vulkan/textures/vk_imagetransition.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a2039a3b2..463ac9092 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -918,6 +918,7 @@ set (VULKAN_SOURCES rendering/vulkan/shaders/vk_shader.cpp rendering/vulkan/textures/vk_samplers.cpp rendering/vulkan/textures/vk_hwtexture.cpp + rendering/vulkan/textures/vk_imagetransition.cpp rendering/vulkan/thirdparty/volk/volk.c rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.cpp ) diff --git a/src/rendering/vulkan/renderer/vk_postprocess.cpp b/src/rendering/vulkan/renderer/vk_postprocess.cpp index ee454a88d..78df34630 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/rendering/vulkan/renderer/vk_postprocess.cpp @@ -7,6 +7,7 @@ #include "vulkan/system/vk_buffers.h" #include "vulkan/system/vk_swapchain.h" #include "vulkan/renderer/vk_renderstate.h" +#include "vulkan/textures/vk_imagetransition.h" #include "hwrenderer/utility/hw_cvars.h" #include "hwrenderer/postprocessing/hw_postprocess.h" #include "hwrenderer/postprocessing/hw_postprocess_cvars.h" @@ -30,11 +31,11 @@ void VkPostprocess::SetActiveRenderTarget() auto fb = GetVulkanFrameBuffer(); auto buffers = fb->GetBuffers(); - VkPPImageTransition imageTransition; - imageTransition.addImage(buffers->PipelineImage[mCurrentPipelineImage].get(), &buffers->PipelineLayout[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false); + VkImageTransition imageTransition; + imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false); imageTransition.execute(fb->GetDrawCommands()); - fb->GetRenderState()->SetRenderTarget(buffers->PipelineView[mCurrentPipelineImage].get(), nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT); + fb->GetRenderState()->SetRenderTarget(buffers->PipelineImage[mCurrentPipelineImage].View.get(), nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT); } void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D) @@ -70,14 +71,14 @@ void VkPostprocess::BlitSceneToPostprocess() mCurrentPipelineImage = 0; - VkPPImageTransition imageTransition0; - imageTransition0.addImage(buffers->SceneColor.get(), &buffers->SceneColorLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false); - imageTransition0.addImage(buffers->PipelineImage[mCurrentPipelineImage].get(), &buffers->PipelineLayout[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); - imageTransition0.execute(fb->GetDrawCommands()); + VkImageTransition imageTransition; + imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false); + imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); + imageTransition.execute(fb->GetDrawCommands()); if (buffers->GetSceneSamples() != VK_SAMPLE_COUNT_1_BIT) { - auto sceneColor = buffers->SceneColor.get(); + auto sceneColor = buffers->SceneColor.Image.get(); VkImageResolve resolve = {}; resolve.srcOffset = { 0, 0, 0 }; resolve.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -92,12 +93,12 @@ void VkPostprocess::BlitSceneToPostprocess() resolve.extent = { (uint32_t)sceneColor->width, (uint32_t)sceneColor->height, 1 }; cmdbuffer->resolveImage( sceneColor->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffers->PipelineImage[mCurrentPipelineImage]->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + buffers->PipelineImage[mCurrentPipelineImage].Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolve); } else { - auto sceneColor = buffers->SceneColor.get(); + auto sceneColor = buffers->SceneColor.Image.get(); VkImageBlit blit = {}; blit.srcOffsets[0] = { 0, 0, 0 }; blit.srcOffsets[1] = { sceneColor->width, sceneColor->height, 1 }; @@ -113,7 +114,7 @@ void VkPostprocess::BlitSceneToPostprocess() blit.dstSubresource.layerCount = 1; cmdbuffer->blitImage( sceneColor->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - buffers->PipelineImage[mCurrentPipelineImage]->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + buffers->PipelineImage[mCurrentPipelineImage].Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST); } } @@ -123,51 +124,48 @@ void VkPostprocess::ImageTransitionScene(bool undefinedSrcLayout) auto fb = GetVulkanFrameBuffer(); auto buffers = fb->GetBuffers(); - VkPPImageTransition imageTransition; - imageTransition.addImage(buffers->SceneColor.get(), &buffers->SceneColorLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); - imageTransition.addImage(buffers->SceneFog.get(), &buffers->SceneFogLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); - imageTransition.addImage(buffers->SceneNormal.get(), &buffers->SceneNormalLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); - imageTransition.addImage(buffers->SceneDepthStencil.get(), &buffers->SceneDepthStencilLayout, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout); + VkImageTransition imageTransition; + imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); + imageTransition.addImage(&buffers->SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); + imageTransition.addImage(&buffers->SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); + imageTransition.addImage(&buffers->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout); imageTransition.execute(fb->GetDrawCommands()); } -void VkPostprocess::BlitCurrentToImage(VulkanImage *dstimage, VkImageLayout *dstlayout, VkImageLayout finallayout) +void VkPostprocess::BlitCurrentToImage(VkTextureImage *dstimage, VkImageLayout finallayout) { auto fb = GetVulkanFrameBuffer(); fb->GetRenderState()->EndRenderPass(); - auto srcimage = fb->GetBuffers()->PipelineImage[mCurrentPipelineImage].get(); - auto srclayout = &fb->GetBuffers()->PipelineLayout[mCurrentPipelineImage]; + auto srcimage = &fb->GetBuffers()->PipelineImage[mCurrentPipelineImage]; auto cmdbuffer = fb->GetDrawCommands(); - *dstlayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // needed by VkPPImageTransition.addImage. Actual layout is undefined. - - VkPPImageTransition imageTransition0; - imageTransition0.addImage(srcimage, srclayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false); - imageTransition0.addImage(dstimage, dstlayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); + VkImageTransition imageTransition0; + imageTransition0.addImage(srcimage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false); + imageTransition0.addImage(dstimage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); imageTransition0.execute(cmdbuffer); VkImageBlit blit = {}; blit.srcOffsets[0] = { 0, 0, 0 }; - blit.srcOffsets[1] = { srcimage->width, srcimage->height, 1 }; + blit.srcOffsets[1] = { srcimage->Image->width, srcimage->Image->height, 1 }; blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blit.srcSubresource.mipLevel = 0; blit.srcSubresource.baseArrayLayer = 0; blit.srcSubresource.layerCount = 1; blit.dstOffsets[0] = { 0, 0, 0 }; - blit.dstOffsets[1] = { dstimage->width, dstimage->height, 1 }; + blit.dstOffsets[1] = { dstimage->Image->width, dstimage->Image->height, 1 }; blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blit.dstSubresource.mipLevel = 0; blit.dstSubresource.baseArrayLayer = 0; blit.dstSubresource.layerCount = 1; cmdbuffer->blitImage( - srcimage->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dstimage->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + srcimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dstimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST); - VkPPImageTransition imageTransition1; - imageTransition1.addImage(dstimage, dstlayout, finallayout, false); + VkImageTransition imageTransition1; + imageTransition1.addImage(dstimage, finallayout, false); imageTransition1.execute(cmdbuffer); } @@ -179,7 +177,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool hw_postprocess.customShaders.Run(&renderstate, "screen"); PresentUniforms uniforms; - if (!applyGamma /*|| framebuffer->IsHWGammaActive()*/) + if (!applyGamma) { uniforms.InvGamma = 1.0f; uniforms.Contrast = 1.0f; @@ -263,8 +261,8 @@ void VkPostprocess::UpdateShadowMap() auto fb = GetVulkanFrameBuffer(); auto buffers = fb->GetBuffers(); - VkPPImageTransition imageTransition; - imageTransition.addImage(buffers->Shadowmap.get(), &buffers->ShadowmapLayout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); + VkImageTransition imageTransition; + imageTransition.addImage(&buffers->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); imageTransition.execute(fb->GetDrawCommands()); screen->mShadowMap.FinishUpdate(); @@ -345,14 +343,14 @@ VkPPTexture::VkPPTexture(PPTexture *texture) imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); if (!imgbuilder.isFormatSupported(fb->device)) I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n"); - Image = imgbuilder.create(fb->device); - Image->SetDebugName("VkPPTexture"); + TexImage.Image = imgbuilder.create(fb->device); + TexImage.Image->SetDebugName("VkPPTexture"); Format = format; ImageViewBuilder viewbuilder; - viewbuilder.setImage(Image.get(), format); - View = viewbuilder.create(fb->device); - View->SetDebugName("VkPPTextureView"); + viewbuilder.setImage(TexImage.Image.get(), format); + TexImage.View = viewbuilder.create(fb->device); + TexImage.View->SetDebugName("VkPPTextureView"); if (texture->Data) { @@ -363,9 +361,9 @@ VkPPTexture::VkPPTexture(PPTexture *texture) Staging = stagingbuilder.create(fb->device); Staging->SetDebugName("VkPPTextureStaging"); - PipelineBarrier barrier0; - barrier0.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT); - barrier0.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + VkImageTransition barrier0; + barrier0.addImage(&TexImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); + barrier0.execute(fb->GetTransferCommands()); void *data = Staging->Map(0, totalsize); memcpy(data, texture->Data.get(), totalsize); @@ -377,19 +375,17 @@ VkPPTexture::VkPPTexture(PPTexture *texture) region.imageExtent.depth = 1; region.imageExtent.width = texture->Width; region.imageExtent.height = texture->Height; - fb->GetTransferCommands()->copyBufferToImage(Staging->buffer, Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + fb->GetTransferCommands()->copyBufferToImage(Staging->buffer, TexImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - PipelineBarrier barrier1; - barrier1.addImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); - barrier1.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - Layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkImageTransition barrier1; + barrier1.addImage(&TexImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); + barrier1.execute(fb->GetTransferCommands()); } else { - PipelineBarrier barrier; - barrier.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT); - barrier.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - Layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkImageTransition barrier; + barrier.addImage(&TexImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); + barrier.execute(fb->GetTransferCommands()); } } @@ -542,16 +538,16 @@ VulkanDescriptorSet *VkPPRenderState::GetInput(VkPPRenderPassSetup *passSetup, c descriptors->SetDebugName("VkPostprocess.descriptors"); WriteDescriptors write; - VkPPImageTransition imageTransition; + VkImageTransition imageTransition; for (unsigned int index = 0; index < textures.Size(); index++) { const PPTextureInput &input = textures[index]; VulkanSampler *sampler = pp->GetSampler(input.Filter, input.Wrap); - TextureImage tex = GetTexture(input.Type, input.Texture); + VkTextureImage *tex = GetTexture(input.Type, input.Texture); - write.addCombinedImageSampler(descriptors.get(), index, tex.view, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - imageTransition.addImage(tex.image, tex.layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); + write.addCombinedImageSampler(descriptors.get(), index, tex->DepthOnlyView ? tex->DepthOnlyView.get() : tex->View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + imageTransition.addImage(tex, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); } if (bindShadowMapBuffers) @@ -573,21 +569,21 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co { auto fb = GetVulkanFrameBuffer(); - TextureImage tex = GetTexture(output.Type, output.Texture); + VkTextureImage *tex = GetTexture(output.Type, output.Texture); VkImageView view; int w, h; - if (tex.view) + if (tex) { - VkPPImageTransition imageTransition; - imageTransition.addImage(tex.image, tex.layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture); + VkImageTransition imageTransition; + imageTransition.addImage(tex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture); if (stencilTest) - imageTransition.addImage(fb->GetBuffers()->SceneDepthStencil.get(), &fb->GetBuffers()->SceneDepthStencilLayout, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false); + imageTransition.addImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false); imageTransition.execute(fb->GetDrawCommands()); - view = tex.view->view; - w = tex.image->width; - h = tex.image->height; + view = tex->View->view; + w = tex->Image->width; + h = tex->Image->height; } else { @@ -604,9 +600,8 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co builder.setSize(w, h); builder.addAttachment(view); if (stencilTest) - builder.addAttachment(fb->GetBuffers()->SceneDepthStencilView.get()); + builder.addAttachment(fb->GetBuffers()->SceneDepthStencil.View.get()); framebuffer = builder.create(GetVulkanFrameBuffer()->device); - framebuffer->SetDebugName(tex.debugname); } framebufferWidth = w; @@ -614,10 +609,9 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co return framebuffer.get(); } -VkPPRenderState::TextureImage VkPPRenderState::GetTexture(const PPTextureType &type, PPTexture *pptexture) +VkTextureImage *VkPPRenderState::GetTexture(const PPTextureType &type, PPTexture *pptexture) { auto fb = GetVulkanFrameBuffer(); - TextureImage tex = {}; if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture) { @@ -625,67 +619,42 @@ VkPPRenderState::TextureImage VkPPRenderState::GetTexture(const PPTextureType &t if (type == PPTextureType::NextPipelineTexture) idx = (idx + 1) % VkRenderBuffers::NumPipelineImages; - tex.image = fb->GetBuffers()->PipelineImage[idx].get(); - tex.view = fb->GetBuffers()->PipelineView[idx].get(); - tex.layout = &fb->GetBuffers()->PipelineLayout[idx]; - tex.debugname = "PipelineTexture"; + return &fb->GetBuffers()->PipelineImage[idx]; } else if (type == PPTextureType::PPTexture) { auto vktex = GetVkTexture(pptexture); - tex.image = vktex->Image.get(); - tex.view = vktex->View.get(); - tex.layout = &vktex->Layout; - tex.debugname = "PPTexture"; + return &vktex->TexImage; } else if (type == PPTextureType::SceneColor) { - tex.image = fb->GetBuffers()->SceneColor.get(); - tex.view = fb->GetBuffers()->SceneColorView.get(); - tex.layout = &fb->GetBuffers()->SceneColorLayout; - tex.debugname = "SceneColor"; + return &fb->GetBuffers()->SceneColor; } else if (type == PPTextureType::SceneNormal) { - tex.image = fb->GetBuffers()->SceneNormal.get(); - tex.view = fb->GetBuffers()->SceneNormalView.get(); - tex.layout = &fb->GetBuffers()->SceneNormalLayout; - tex.debugname = "SceneNormal"; + return &fb->GetBuffers()->SceneNormal; } else if (type == PPTextureType::SceneFog) { - tex.image = fb->GetBuffers()->SceneFog.get(); - tex.view = fb->GetBuffers()->SceneFogView.get(); - tex.layout = &fb->GetBuffers()->SceneFogLayout; - tex.debugname = "SceneFog"; + return &fb->GetBuffers()->SceneFog; } else if (type == PPTextureType::SceneDepth) { - tex.image = fb->GetBuffers()->SceneDepthStencil.get(); - tex.view = fb->GetBuffers()->SceneDepthView.get(); - tex.layout = &fb->GetBuffers()->SceneDepthStencilLayout; - tex.debugname = "SceneDepth"; + return &fb->GetBuffers()->SceneDepthStencil; } else if (type == PPTextureType::ShadowMap) { - tex.image = fb->GetBuffers()->Shadowmap.get(); - tex.view = fb->GetBuffers()->ShadowmapView.get(); - tex.layout = &fb->GetBuffers()->ShadowmapLayout; - tex.debugname = "Shadowmap"; + return &fb->GetBuffers()->Shadowmap; } else if (type == PPTextureType::SwapChain) { - tex.image = nullptr; - tex.view = nullptr; - tex.layout = nullptr; - tex.debugname = "SwapChain"; + return nullptr; } else { I_FatalError("VkPPRenderState::GetTexture not implemented yet for this texture type"); + return nullptr; } - - return tex; } VkPPShader *VkPPRenderState::GetVkShader(PPShader *shader) @@ -805,79 +774,3 @@ void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey &key) RenderPass = builder.create(GetVulkanFrameBuffer()->device); RenderPass->SetDebugName("VkPPRenderPassSetup.RenderPass"); } - -///////////////////////////////////////////////////////////////////////////// - -void VkPPImageTransition::addImage(VulkanImage *image, VkImageLayout *layout, VkImageLayout targetLayout, bool undefinedSrcLayout) -{ - if (*layout == targetLayout) - return; - - VkAccessFlags srcAccess = 0; - VkAccessFlags dstAccess = 0; - VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - switch (*layout) - { - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - srcAccess = VK_ACCESS_TRANSFER_READ_BIT; - srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - srcAccess = VK_ACCESS_SHADER_READ_BIT; - srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - srcAccess = VK_ACCESS_TRANSFER_WRITE_BIT; - srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - srcAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - break; - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - break; - default: - I_FatalError("Unimplemented src image layout transition\n"); - } - - switch (targetLayout) - { - case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: - dstAccess = VK_ACCESS_TRANSFER_READ_BIT; - dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - dstAccess = VK_ACCESS_SHADER_READ_BIT; - dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - dstAccess = VK_ACCESS_TRANSFER_WRITE_BIT; - dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - dstAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dstStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - break; - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - break; - default: - I_FatalError("Unimplemented dst image layout transition\n"); - } - - barrier.addImage(image, undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : *layout, targetLayout, srcAccess, dstAccess, aspectMask); - needbarrier = true; - *layout = targetLayout; -} - -void VkPPImageTransition::execute(VulkanCommandBuffer *cmdbuffer) -{ - if (needbarrier) - barrier.execute(cmdbuffer, srcStageMask, dstStageMask); -} diff --git a/src/rendering/vulkan/renderer/vk_postprocess.h b/src/rendering/vulkan/renderer/vk_postprocess.h index 667bf28b6..bc9f247c1 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.h +++ b/src/rendering/vulkan/renderer/vk_postprocess.h @@ -8,6 +8,7 @@ #include "hwrenderer/postprocessing/hw_postprocess.h" #include "vulkan/system/vk_objects.h" #include "vulkan/system/vk_builders.h" +#include "vulkan/textures/vk_imagetransition.h" class FString; @@ -34,19 +35,6 @@ public: bool operator!=(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) != 0; } }; -class VkPPImageTransition -{ -public: - void addImage(VulkanImage *image, VkImageLayout *layout, VkImageLayout targetLayout, bool undefinedSrcLayout); - void execute(VulkanCommandBuffer *cmdbuffer); - -private: - PipelineBarrier barrier; - VkPipelineStageFlags srcStageMask = 0; - VkPipelineStageFlags dstStageMask = 0; - bool needbarrier = false; -}; - class VkPostprocess { public: @@ -67,7 +55,7 @@ public: void ImageTransitionScene(bool undefinedSrcLayout); void BlitSceneToPostprocess(); - void BlitCurrentToImage(VulkanImage *image, VkImageLayout *layout, VkImageLayout finallayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + void BlitCurrentToImage(VkTextureImage *image, VkImageLayout finallayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); void DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders); private: @@ -101,10 +89,8 @@ class VkPPTexture : public PPTextureBackend public: VkPPTexture(PPTexture *texture); - std::unique_ptr<VulkanImage> Image; - std::unique_ptr<VulkanImageView> View; + VkTextureImage TexImage; std::unique_ptr<VulkanBuffer> Staging; - VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED; VkFormat Format; }; @@ -143,12 +129,5 @@ private: VkPPShader *GetVkShader(PPShader *shader); VkPPTexture *GetVkTexture(PPTexture *texture); - struct TextureImage - { - VulkanImage *image; - VulkanImageView *view; - VkImageLayout *layout; - const char *debugname; - }; - TextureImage GetTexture(const PPTextureType &type, PPTexture *tex); + VkTextureImage *GetTexture(const PPTextureType &type, PPTexture *tex); }; diff --git a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp index 29524599f..7bde9789e 100644 --- a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp @@ -71,39 +71,32 @@ void VkRenderBuffers::CreatePipeline(int width, int height) for (int i = 0; i < NumPipelineImages; i++) { PipelineImage[i].reset(); - PipelineView[i].reset(); } - PipelineBarrier barrier; + VkImageTransition barrier; for (int i = 0; i < NumPipelineImages; i++) { ImageBuilder builder; builder.setSize(width, height); builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - PipelineImage[i] = builder.create(fb->device); - PipelineImage[i]->SetDebugName("VkRenderBuffers.PipelineImage"); + PipelineImage[i].Image = builder.create(fb->device); + PipelineImage[i].Image->SetDebugName("VkRenderBuffers.PipelineImage"); ImageViewBuilder viewbuilder; - viewbuilder.setImage(PipelineImage[i].get(), VK_FORMAT_R16G16B16A16_SFLOAT); - PipelineView[i] = viewbuilder.create(fb->device); - PipelineView[i]->SetDebugName("VkRenderBuffers.PipelineView"); + viewbuilder.setImage(PipelineImage[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT); + PipelineImage[i].View = viewbuilder.create(fb->device); + PipelineImage[i].View->SetDebugName("VkRenderBuffers.PipelineView"); - barrier.addImage(PipelineImage[i].get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - PipelineLayout[i] = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + barrier.addImage(&PipelineImage[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); } - barrier.execute(fb->GetDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); + barrier.execute(fb->GetDrawCommands()); } void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits samples) { auto fb = GetVulkanFrameBuffer(); - SceneColorView.reset(); - SceneDepthStencilView.reset(); - SceneDepthView.reset(); - SceneNormalView.reset(); - SceneFogView.reset(); SceneColor.reset(); SceneDepthStencil.reset(); SceneNormal.reset(); @@ -114,14 +107,12 @@ void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits s CreateSceneNormal(width, height, samples); CreateSceneFog(width, height, samples); - PipelineBarrier barrier; - barrier.addImage(SceneColor.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - barrier.addImage(SceneDepthStencil.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - barrier.addImage(SceneNormal.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - barrier.addImage(SceneFog.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - barrier.execute(fb->GetDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); - - SceneColorLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkImageTransition barrier; + barrier.addImage(&SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); + barrier.addImage(&SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true); + barrier.addImage(&SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); + barrier.addImage(&SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); + barrier.execute(fb->GetDrawCommands()); } void VkRenderBuffers::CreateSceneColor(int width, int height, VkSampleCountFlagBits samples) @@ -133,13 +124,13 @@ void VkRenderBuffers::CreateSceneColor(int width, int height, VkSampleCountFlagB builder.setSamples(samples); builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - SceneColor = builder.create(fb->device); - SceneColor->SetDebugName("VkRenderBuffers.SceneColor"); + SceneColor.Image = builder.create(fb->device); + SceneColor.Image->SetDebugName("VkRenderBuffers.SceneColor"); ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneColor.get(), VK_FORMAT_R16G16B16A16_SFLOAT); - SceneColorView = viewbuilder.create(fb->device); - SceneColorView->SetDebugName("VkRenderBuffers.SceneColorView"); + viewbuilder.setImage(SceneColor.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT); + SceneColor.View = viewbuilder.create(fb->device); + SceneColor.View->SetDebugName("VkRenderBuffers.SceneColorView"); } void VkRenderBuffers::CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples) @@ -160,17 +151,18 @@ void VkRenderBuffers::CreateSceneDepthStencil(int width, int height, VkSampleCou I_FatalError("This device does not support any of the required depth stencil image formats."); } } - SceneDepthStencil = builder.create(fb->device); - SceneDepthStencil->SetDebugName("VkRenderBuffers.SceneDepthStencil"); + SceneDepthStencil.Image = builder.create(fb->device); + SceneDepthStencil.Image->SetDebugName("VkRenderBuffers.SceneDepthStencil"); + SceneDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneDepthStencil.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - SceneDepthStencilView = viewbuilder.create(fb->device); - SceneDepthStencilView->SetDebugName("VkRenderBuffers.SceneDepthStencilView"); + viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + SceneDepthStencil.View = viewbuilder.create(fb->device); + SceneDepthStencil.View->SetDebugName("VkRenderBuffers.SceneDepthStencilView"); - viewbuilder.setImage(SceneDepthStencil.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT); - SceneDepthView = viewbuilder.create(fb->device); - SceneDepthView->SetDebugName("VkRenderBuffers.SceneDepthView"); + viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT); + SceneDepthStencil.DepthOnlyView = viewbuilder.create(fb->device); + SceneDepthStencil.DepthOnlyView->SetDebugName("VkRenderBuffers.SceneDepthView"); } void VkRenderBuffers::CreateSceneFog(int width, int height, VkSampleCountFlagBits samples) @@ -182,13 +174,13 @@ void VkRenderBuffers::CreateSceneFog(int width, int height, VkSampleCountFlagBit builder.setSamples(samples); builder.setFormat(VK_FORMAT_R8G8B8A8_UNORM); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - SceneFog = builder.create(fb->device); - SceneFog->SetDebugName("VkRenderBuffers.SceneFog"); + SceneFog.Image = builder.create(fb->device); + SceneFog.Image->SetDebugName("VkRenderBuffers.SceneFog"); ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneFog.get(), VK_FORMAT_R8G8B8A8_UNORM); - SceneFogView = viewbuilder.create(fb->device); - SceneFogView->SetDebugName("VkRenderBuffers.SceneFogView"); + viewbuilder.setImage(SceneFog.Image.get(), VK_FORMAT_R8G8B8A8_UNORM); + SceneFog.View = viewbuilder.create(fb->device); + SceneFog.View->SetDebugName("VkRenderBuffers.SceneFogView"); } void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples) @@ -200,22 +192,21 @@ void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlag builder.setSamples(samples); builder.setFormat(VK_FORMAT_A2R10G10B10_UNORM_PACK32); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - SceneNormal = builder.create(fb->device); - SceneNormal->SetDebugName("VkRenderBuffers.SceneNormal"); + SceneNormal.Image = builder.create(fb->device); + SceneNormal.Image->SetDebugName("VkRenderBuffers.SceneNormal"); ImageViewBuilder viewbuilder; - viewbuilder.setImage(SceneNormal.get(), VK_FORMAT_A2R10G10B10_UNORM_PACK32); - SceneNormalView = viewbuilder.create(fb->device); - SceneNormalView->SetDebugName("VkRenderBuffers.SceneNormalView"); + viewbuilder.setImage(SceneNormal.Image.get(), VK_FORMAT_A2R10G10B10_UNORM_PACK32); + SceneNormal.View = viewbuilder.create(fb->device); + SceneNormal.View->SetDebugName("VkRenderBuffers.SceneNormalView"); } void VkRenderBuffers::CreateShadowmap() { - if (Shadowmap && Shadowmap->width == gl_shadowmap_quality) + if (Shadowmap.Image && Shadowmap.Image->width == gl_shadowmap_quality) return; Shadowmap.reset(); - ShadowmapView.reset(); auto fb = GetVulkanFrameBuffer(); @@ -223,17 +214,17 @@ void VkRenderBuffers::CreateShadowmap() builder.setSize(gl_shadowmap_quality, 1024); builder.setFormat(VK_FORMAT_R32_SFLOAT); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - Shadowmap = builder.create(fb->device); - Shadowmap->SetDebugName("VkRenderBuffers.Shadowmap"); + Shadowmap.Image = builder.create(fb->device); + Shadowmap.Image->SetDebugName("VkRenderBuffers.Shadowmap"); ImageViewBuilder viewbuilder; - viewbuilder.setImage(Shadowmap.get(), VK_FORMAT_R32_SFLOAT); - ShadowmapView = viewbuilder.create(fb->device); - ShadowmapView->SetDebugName("VkRenderBuffers.ShadowmapView"); + viewbuilder.setImage(Shadowmap.Image.get(), VK_FORMAT_R32_SFLOAT); + Shadowmap.View = viewbuilder.create(fb->device); + Shadowmap.View->SetDebugName("VkRenderBuffers.ShadowmapView"); - PipelineBarrier barrier; - barrier.addImage(Shadowmap.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT); - barrier.execute(fb->GetDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + VkImageTransition barrier; + barrier.addImage(&Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true); + barrier.execute(fb->GetDrawCommands()); if (!ShadowmapSampler) { diff --git a/src/rendering/vulkan/renderer/vk_renderbuffers.h b/src/rendering/vulkan/renderer/vk_renderbuffers.h index 63b84f996..b1df96b02 100644 --- a/src/rendering/vulkan/renderer/vk_renderbuffers.h +++ b/src/rendering/vulkan/renderer/vk_renderbuffers.h @@ -2,6 +2,7 @@ #pragma once #include "vulkan/system/vk_objects.h" +#include "vulkan/textures/vk_imagetransition.h" class VkRenderBuffers { @@ -17,30 +18,18 @@ public: int GetSceneHeight() const { return mSceneHeight; } VkSampleCountFlagBits GetSceneSamples() const { return mSamples; } - std::unique_ptr<VulkanImage> SceneColor; - std::unique_ptr<VulkanImage> SceneDepthStencil; - std::unique_ptr<VulkanImage> SceneNormal; - std::unique_ptr<VulkanImage> SceneFog; - std::unique_ptr<VulkanImageView> SceneColorView; - std::unique_ptr<VulkanImageView> SceneDepthStencilView; - std::unique_ptr<VulkanImageView> SceneDepthView; - std::unique_ptr<VulkanImageView> SceneNormalView; - std::unique_ptr<VulkanImageView> SceneFogView; + VkTextureImage SceneColor; + VkTextureImage SceneDepthStencil; + VkTextureImage SceneNormal; + VkTextureImage SceneFog; + VkFormat SceneDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; - VkImageLayout SceneColorLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkImageLayout SceneDepthStencilLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - VkImageLayout SceneNormalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkImageLayout SceneFogLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; static const int NumPipelineImages = 2; - std::unique_ptr<VulkanImage> PipelineImage[NumPipelineImages]; - std::unique_ptr<VulkanImageView> PipelineView[NumPipelineImages]; - VkImageLayout PipelineLayout[NumPipelineImages] = { VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; + VkTextureImage PipelineImage[NumPipelineImages]; - std::unique_ptr<VulkanImage> Shadowmap; - std::unique_ptr<VulkanImageView> ShadowmapView; + VkTextureImage Shadowmap; std::unique_ptr<VulkanSampler> ShadowmapSampler; - VkImageLayout ShadowmapLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; private: void CreatePipeline(int width, int height); diff --git a/src/rendering/vulkan/renderer/vk_renderpass.cpp b/src/rendering/vulkan/renderer/vk_renderpass.cpp index fc0669419..9fc5b9ab6 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/rendering/vulkan/renderer/vk_renderpass.cpp @@ -175,7 +175,7 @@ void VkRenderPassManager::UpdateDynamicSet() update.addBuffer(DynamicSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightBufferSSO->mBuffer.get()); update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatricesUBO->mBuffer.get(), 0, sizeof(MatricesUBO)); update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamUBO->mBuffer.get(), 0, sizeof(StreamUBO)); - update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->ShadowmapView.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->Shadowmap.View.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); update.updateSets(fb->device); } diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index dab0d64b3..e9474f092 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -568,9 +568,9 @@ void VkRenderState::BeginRenderPass(const VkRenderPassKey &key, VulkanCommandBuf builder.setSize(mRenderTarget.Width, mRenderTarget.Height); builder.addAttachment(mRenderTarget.View); if (key.DrawBuffers > 1) - builder.addAttachment(buffers->SceneFogView.get()); + builder.addAttachment(buffers->SceneFog.View.get()); if (key.DrawBuffers > 2) - builder.addAttachment(buffers->SceneNormalView.get()); + builder.addAttachment(buffers->SceneNormal.View.get()); if (key.UsesDepthStencil()) builder.addAttachment(mRenderTarget.DepthStencil); framebuffer = builder.create(GetVulkanFrameBuffer()->device); diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 2deff5223..173d5408b 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -444,7 +444,7 @@ sector_t *VulkanFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor * if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao { - mRenderState->SetRenderTarget(GetBuffers()->SceneColorView.get(), GetBuffers()->SceneDepthStencilView.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); + mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); bool useSSAO = (gl_ssao != 0); GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount()); @@ -505,33 +505,32 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint int width = mat->TextureWidth(); int height = mat->TextureHeight(); - VulkanImage *image = BaseLayer->GetImage(tex, 0, 0); - VulkanImageView *view = BaseLayer->GetImageView(tex, 0, 0); - VulkanImageView *depthStencilView = BaseLayer->GetDepthStencilView(tex); + VkTextureImage *image = BaseLayer->GetImage(tex, 0, 0); + VkTextureImage *depthStencil = BaseLayer->GetDepthStencil(tex); mRenderState->EndRenderPass(); - PipelineBarrier barrier0; - barrier0.addImage(image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - barrier0.execute(GetDrawCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + VkImageTransition barrier0; + barrier0.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); + barrier0.execute(GetDrawCommands()); - mRenderState->SetRenderTarget(view, depthStencilView, image->width, image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT); + mRenderState->SetRenderTarget(image->View.get(), depthStencil->View.get(), image->Image->width, image->Image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT); IntRect bounds; bounds.left = bounds.top = 0; - bounds.width = MIN(mat->GetWidth(), image->width); - bounds.height = MIN(mat->GetHeight(), image->height); + bounds.width = MIN(mat->GetWidth(), image->Image->width); + bounds.height = MIN(mat->GetHeight(), image->Image->height); FRenderViewpoint texvp; RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false); mRenderState->EndRenderPass(); - PipelineBarrier barrier1; - barrier1.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); - barrier1.execute(GetDrawCommands(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + VkImageTransition barrier1; + barrier1.addImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); + barrier1.execute(GetDrawCommands()); - mRenderState->SetRenderTarget(GetBuffers()->SceneColorView.get(), GetBuffers()->SceneDepthStencilView.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); + mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); tex->SetUpdated(true); } @@ -736,14 +735,15 @@ FTexture *VulkanFrameBuffer::WipeEndScreen() void VulkanFrameBuffer::CopyScreenToBuffer(int w, int h, void *data) { + VkTextureImage image; + // Convert from rgba16f to rgba8 using the GPU: ImageBuilder imgbuilder; imgbuilder.setFormat(VK_FORMAT_R8G8B8A8_UNORM); imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); imgbuilder.setSize(w, h); - auto image = imgbuilder.create(device); - VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; - GetPostprocess()->BlitCurrentToImage(image.get(), &layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + image.Image = imgbuilder.create(device); + GetPostprocess()->BlitCurrentToImage(&image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); // Staging buffer for download BufferBuilder bufbuilder; @@ -758,7 +758,7 @@ void VulkanFrameBuffer::CopyScreenToBuffer(int w, int h, void *data) region.imageExtent.depth = 1; region.imageSubresource.layerCount = 1; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - GetDrawCommands()->copyImageToBuffer(image->image, layout, staging->buffer, 1, ®ion); + GetDrawCommands()->copyImageToBuffer(image.Image->image, image.Layout, staging->buffer, 1, ®ion); // Submit command buffers and wait for device to finish the work WaitForCommands(false); diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index 755e3a8dc..57928d2b1 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -70,10 +70,12 @@ void VkHardwareTexture::Reset() ResetDescriptors(); auto &deleteList = fb->FrameDeleteList; - if (mImage) deleteList.Images.push_back(std::move(mImage)); - if (mImageView) deleteList.ImageViews.push_back(std::move(mImageView)); - if (mDepthStencil) deleteList.Images.push_back(std::move(mDepthStencil)); - if (mDepthStencilView) deleteList.ImageViews.push_back(std::move(mDepthStencilView)); + if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image)); + if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View)); + if (mDepthStencil.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image)); + if (mDepthStencil.View) deleteList.ImageViews.push_back(std::move(mDepthStencil.View)); + mImage.reset(); + mDepthStencil.reset(); } } @@ -105,12 +107,12 @@ void VkHardwareTexture::ResetAllDescriptors() void VkHardwareTexture::Precache(FMaterial *mat, int translation, int flags) { int numLayers = mat->GetLayers(); - GetImageView(mat->tex, translation, flags); + GetImage(mat->tex, translation, flags); for (int i = 1; i < numLayers; i++) { FTexture *layer; auto systex = static_cast<VkHardwareTexture*>(mat->GetLayer(i, 0, &layer)); - systex->GetImageView(layer, 0, mat->isExpanded() ? CTF_Expand : 0); + systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0); } } @@ -144,42 +146,31 @@ VulkanDescriptorSet *VkHardwareTexture::GetDescriptorSet(const FMaterialState &s VulkanSampler *sampler = fb->GetSamplerManager()->Get(clampmode); - auto baseView = GetImageView(tex, translation, flags); - WriteDescriptors update; - update.addCombinedImageSampler(descriptor.get(), 0, baseView, sampler, mImageLayout); + update.addCombinedImageSampler(descriptor.get(), 0, GetImage(tex, translation, flags)->View.get(), sampler, mImage.Layout); for (int i = 1; i < numLayers; i++) { FTexture *layer; auto systex = static_cast<VkHardwareTexture*>(mat->GetLayer(i, 0, &layer)); - update.addCombinedImageSampler(descriptor.get(), i, systex->GetImageView(layer, 0, mat->isExpanded() ? CTF_Expand : 0), sampler, systex->mImageLayout); + update.addCombinedImageSampler(descriptor.get(), i, systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0)->View.get(), sampler, systex->mImage.Layout); } update.updateSets(fb->device); mDescriptorSets.emplace_back(clampmode, flags, std::move(descriptor)); return mDescriptorSets.back().descriptor.get(); } -VulkanImage *VkHardwareTexture::GetImage(FTexture *tex, int translation, int flags) +VkTextureImage *VkHardwareTexture::GetImage(FTexture *tex, int translation, int flags) { - if (!mImage) + if (!mImage.Image) { CreateImage(tex, translation, flags); } - return mImage.get(); + return &mImage; } -VulkanImageView *VkHardwareTexture::GetImageView(FTexture *tex, int translation, int flags) +VkTextureImage *VkHardwareTexture::GetDepthStencil(FTexture *tex) { - if (!mImageView) - { - CreateImage(tex, translation, flags); - } - return mImageView.get(); -} - -VulkanImageView *VkHardwareTexture::GetDepthStencilView(FTexture *tex) -{ - if (!mDepthStencilView) + if (!mDepthStencil.View) { auto fb = GetVulkanFrameBuffer(); @@ -192,19 +183,20 @@ VulkanImageView *VkHardwareTexture::GetDepthStencilView(FTexture *tex) builder.setSamples(VK_SAMPLE_COUNT_1_BIT); builder.setFormat(format); builder.setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); - mDepthStencil = builder.create(fb->device); - mDepthStencil->SetDebugName("VkHardwareTexture.DepthStencil"); + mDepthStencil.Image = builder.create(fb->device); + mDepthStencil.Image->SetDebugName("VkHardwareTexture.DepthStencil"); + mDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; ImageViewBuilder viewbuilder; - viewbuilder.setImage(mDepthStencil.get(), format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - mDepthStencilView = viewbuilder.create(fb->device); - mDepthStencilView->SetDebugName("VkHardwareTexture.DepthStencilView"); + viewbuilder.setImage(mDepthStencil.Image.get(), format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + mDepthStencil.View = viewbuilder.create(fb->device); + mDepthStencil.View->SetDebugName("VkHardwareTexture.DepthStencilView"); - PipelineBarrier barrier; - barrier.addImage(mDepthStencil.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - barrier.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); + VkImageTransition barrier; + barrier.addImage(&mDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true); + barrier.execute(fb->GetTransferCommands()); } - return mDepthStencilView.get(); + return &mDepthStencil; } void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) @@ -236,19 +228,19 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) imgbuilder.setFormat(format); imgbuilder.setSize(w, h); imgbuilder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - mImage = imgbuilder.create(fb->device); - mImage->SetDebugName("VkHardwareTexture.mImage"); + mImage.Image = imgbuilder.create(fb->device); + mImage.Image->SetDebugName("VkHardwareTexture.mImage"); ImageViewBuilder viewbuilder; - viewbuilder.setImage(mImage.get(), format); - mImageView = viewbuilder.create(fb->device); - mImageView->SetDebugName("VkHardwareTexture.mImageView"); + viewbuilder.setImage(mImage.Image.get(), format); + mImage.View = viewbuilder.create(fb->device); + mImage.View->SetDebugName("VkHardwareTexture.mImageView"); auto cmdbuffer = fb->GetTransferCommands(); - PipelineBarrier imageTransition; - imageTransition.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT); - imageTransition.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + VkImageTransition imageTransition; + imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true); + imageTransition.execute(cmdbuffer); } } @@ -272,19 +264,19 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form imgbuilder.setFormat(format); imgbuilder.setSize(w, h, GetMipLevels(w, h)); imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); - mImage = imgbuilder.create(fb->device); - mImage->SetDebugName("VkHardwareTexture.mImage"); + mImage.Image = imgbuilder.create(fb->device); + mImage.Image->SetDebugName("VkHardwareTexture.mImage"); ImageViewBuilder viewbuilder; - viewbuilder.setImage(mImage.get(), format); - mImageView = viewbuilder.create(fb->device); - mImageView->SetDebugName("VkHardwareTexture.mImageView"); + viewbuilder.setImage(mImage.Image.get(), format); + mImage.View = viewbuilder.create(fb->device); + mImage.View->SetDebugName("VkHardwareTexture.mImageView"); auto cmdbuffer = fb->GetTransferCommands(); - PipelineBarrier imageTransition0; - imageTransition0.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT); - imageTransition0.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + VkImageTransition imageTransition; + imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); + imageTransition.execute(cmdbuffer); VkBufferImageCopy region = {}; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -292,54 +284,11 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form region.imageExtent.depth = 1; region.imageExtent.width = w; region.imageExtent.height = h; - cmdbuffer->copyBufferToImage(stagingBuffer->buffer, mImage->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + cmdbuffer->copyBufferToImage(stagingBuffer->buffer, mImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); fb->FrameDeleteList.Buffers.push_back(std::move(stagingBuffer)); - GenerateMipmaps(mImage.get(), cmdbuffer); -} - -void VkHardwareTexture::GenerateMipmaps(VulkanImage *image, VulkanCommandBuffer *cmdbuffer) -{ - int mipWidth = image->width; - int mipHeight = image->height; - int i; - for (i = 1; mipWidth > 1 || mipHeight > 1; i++) - { - PipelineBarrier barrier0; - barrier0.addImage(image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); - barrier0.addImage(image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i); - barrier0.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - - int nextWidth = std::max(mipWidth >> 1, 1); - int nextHeight = std::max(mipHeight >> 1, 1); - - VkImageBlit blit = {}; - blit.srcOffsets[0] = { 0, 0, 0 }; - blit.srcOffsets[1] = { mipWidth, mipHeight, 1 }; - blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.mipLevel = i - 1; - blit.srcSubresource.baseArrayLayer = 0; - blit.srcSubresource.layerCount = 1; - blit.dstOffsets[0] = { 0, 0, 0 }; - blit.dstOffsets[1] = { nextWidth, nextHeight, 1 }; - blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.mipLevel = i; - blit.dstSubresource.baseArrayLayer = 0; - blit.dstSubresource.layerCount = 1; - cmdbuffer->blitImage(image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR); - - PipelineBarrier barrier1; - barrier1.addImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); - barrier1.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - - mipWidth = nextWidth; - mipHeight = nextHeight; - } - - PipelineBarrier barrier2; - barrier2.addImage(image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); - barrier2.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + mImage.GenerateMipmaps(cmdbuffer); } int VkHardwareTexture::GetMipLevels(int w, int h) @@ -356,12 +305,12 @@ int VkHardwareTexture::GetMipLevels(int w, int h) void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize) { - if (mImage && (mImage->width != w || mImage->height != h || mTexelsize != texelsize)) + if (mImage.Image && (mImage.Image->width != w || mImage.Image->height != h || mTexelsize != texelsize)) { Reset(); } - if (!mImage) + if (!mImage.Image) { auto fb = GetVulkanFrameBuffer(); @@ -376,21 +325,20 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize) imgbuilder.setMemoryType( VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - mImage = imgbuilder.create(fb->device, &allocatedBytes); - mImage->SetDebugName("VkHardwareTexture.mImage"); - mImageLayout = VK_IMAGE_LAYOUT_GENERAL; + mImage.Image = imgbuilder.create(fb->device, &allocatedBytes); + mImage.Image->SetDebugName("VkHardwareTexture.mImage"); mTexelsize = texelsize; ImageViewBuilder viewbuilder; - viewbuilder.setImage(mImage.get(), format); - mImageView = viewbuilder.create(fb->device); - mImageView->SetDebugName("VkHardwareTexture.mImageView"); + viewbuilder.setImage(mImage.Image.get(), format); + mImage.View = viewbuilder.create(fb->device); + mImage.View->SetDebugName("VkHardwareTexture.mImageView"); auto cmdbuffer = fb->GetTransferCommands(); - PipelineBarrier imageTransition; - imageTransition.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, mImageLayout, 0, VK_ACCESS_SHADER_READ_BIT); - imageTransition.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + VkImageTransition imageTransition; + imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_GENERAL, true); + imageTransition.execute(cmdbuffer); bufferpitch = int(allocatedBytes / h / texelsize); } @@ -398,12 +346,12 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize) uint8_t *VkHardwareTexture::MapBuffer() { - return (uint8_t*)mImage->Map(0, mImage->width * mImage->height * mTexelsize); + return (uint8_t*)mImage.Image->Map(0, mImage.Image->width * mImage.Image->height * mTexelsize); } unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) { - mImage->Unmap(); + mImage.Image->Unmap(); return 0; } @@ -417,15 +365,14 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) imgbuilder.setFormat(format); imgbuilder.setSize(w, h); imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); - mImage = imgbuilder.create(fb->device); - mImage->SetDebugName(name); - mImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + mImage.Image = imgbuilder.create(fb->device); + mImage.Image->SetDebugName(name); mTexelsize = 4; ImageViewBuilder viewbuilder; - viewbuilder.setImage(mImage.get(), format); - mImageView = viewbuilder.create(fb->device); - mImageView->SetDebugName(name); + viewbuilder.setImage(mImage.Image.get(), format); + mImage.View = viewbuilder.create(fb->device); + mImage.View->SetDebugName(name); - fb->GetPostprocess()->BlitCurrentToImage(mImage.get(), &mImageLayout); + fb->GetPostprocess()->BlitCurrentToImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } diff --git a/src/rendering/vulkan/textures/vk_hwtexture.h b/src/rendering/vulkan/textures/vk_hwtexture.h index 2cf63b622..6d461184f 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/rendering/vulkan/textures/vk_hwtexture.h @@ -10,6 +10,7 @@ #include "tarray.h" #include "hwrenderer/textures/hw_ihwtexture.h" #include "volk/volk.h" +#include "vk_imagetransition.h" struct FMaterialState; class VulkanDescriptorSet; @@ -40,9 +41,8 @@ public: void DeleteDescriptors() override { ResetDescriptors(); } - VulkanImage *GetImage(FTexture *tex, int translation, int flags); - VulkanImageView *GetImageView(FTexture *tex, int translation, int flags); - VulkanImageView *GetDepthStencilView(FTexture *tex); + VkTextureImage *GetImage(FTexture *tex, int translation, int flags); + VkTextureImage *GetDepthStencil(FTexture *tex); static void ResetAllDescriptors(); @@ -50,7 +50,6 @@ private: void CreateImage(FTexture *tex, int translation, int flags); void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels); - void GenerateMipmaps(VulkanImage *image, VulkanCommandBuffer *cmdbuffer); static int GetMipLevels(int w, int h); void ResetDescriptors(); @@ -74,11 +73,8 @@ private: }; std::vector<DescriptorEntry> mDescriptorSets; - std::unique_ptr<VulkanImage> mImage; - std::unique_ptr<VulkanImageView> mImageView; - VkImageLayout mImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkTextureImage mImage; int mTexelsize = 4; - std::unique_ptr<VulkanImage> mDepthStencil; - std::unique_ptr<VulkanImageView> mDepthStencilView; + VkTextureImage mDepthStencil; }; diff --git a/src/rendering/vulkan/textures/vk_imagetransition.cpp b/src/rendering/vulkan/textures/vk_imagetransition.cpp new file mode 100644 index 000000000..be47576d7 --- /dev/null +++ b/src/rendering/vulkan/textures/vk_imagetransition.cpp @@ -0,0 +1,130 @@ + +#include "vk_imagetransition.h" + +void VkImageTransition::addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout) +{ + if (image->Layout == targetLayout) + return; + + VkAccessFlags srcAccess = 0; + VkAccessFlags dstAccess = 0; + VkImageAspectFlags aspectMask = image->AspectMask; + + switch (image->Layout) + { + case VK_IMAGE_LAYOUT_UNDEFINED: + srcAccess = 0; + srcStageMask |= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + srcAccess = VK_ACCESS_TRANSFER_READ_BIT; + srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + srcAccess = VK_ACCESS_SHADER_READ_BIT; + srcStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + srcAccess = VK_ACCESS_TRANSFER_WRITE_BIT; + srcStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + srcAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + break; + default: + I_FatalError("Unimplemented src image layout transition\n"); + } + + switch (targetLayout) + { + case VK_IMAGE_LAYOUT_GENERAL: + dstAccess = 0; + dstStageMask |= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + dstAccess = VK_ACCESS_TRANSFER_READ_BIT; + dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + dstAccess = VK_ACCESS_SHADER_READ_BIT; + dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + dstAccess = VK_ACCESS_TRANSFER_WRITE_BIT; + dstStageMask |= VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + dstAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dstStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + break; + default: + I_FatalError("Unimplemented dst image layout transition\n"); + } + + barrier.addImage(image->Image.get(), undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : image->Layout, targetLayout, srcAccess, dstAccess, aspectMask); + needbarrier = true; + image->Layout = targetLayout; +} + +void VkImageTransition::execute(VulkanCommandBuffer *cmdbuffer) +{ + if (needbarrier) + barrier.execute(cmdbuffer, srcStageMask, dstStageMask); +} + +///////////////////////////////////////////////////////////////////////////// + +void VkTextureImage::GenerateMipmaps(VulkanCommandBuffer *cmdbuffer) +{ + int mipWidth = Image->width; + int mipHeight = Image->height; + int i; + for (i = 1; mipWidth > 1 || mipHeight > 1; i++) + { + PipelineBarrier barrier0; + barrier0.addImage(Image.get(), Layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); + barrier0.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i); + barrier0.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + Layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + + int nextWidth = std::max(mipWidth >> 1, 1); + int nextHeight = std::max(mipHeight >> 1, 1); + + VkImageBlit blit = {}; + blit.srcOffsets[0] = { 0, 0, 0 }; + blit.srcOffsets[1] = { mipWidth, mipHeight, 1 }; + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.mipLevel = i - 1; + blit.srcSubresource.baseArrayLayer = 0; + blit.srcSubresource.layerCount = 1; + blit.dstOffsets[0] = { 0, 0, 0 }; + blit.dstOffsets[1] = { nextWidth, nextHeight, 1 }; + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.mipLevel = i; + blit.dstSubresource.baseArrayLayer = 0; + blit.dstSubresource.layerCount = 1; + cmdbuffer->blitImage(Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR); + + PipelineBarrier barrier1; + barrier1.addImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); + barrier1.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + mipWidth = nextWidth; + mipHeight = nextHeight; + } + + PipelineBarrier barrier2; + barrier2.addImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); + barrier2.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + Layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; +} diff --git a/src/rendering/vulkan/textures/vk_imagetransition.h b/src/rendering/vulkan/textures/vk_imagetransition.h new file mode 100644 index 000000000..c5b32dd50 --- /dev/null +++ b/src/rendering/vulkan/textures/vk_imagetransition.h @@ -0,0 +1,39 @@ + +#pragma once + +#include "vulkan/system/vk_objects.h" +#include "vulkan/system/vk_builders.h" + +class VkTextureImage +{ +public: + void reset() + { + AspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + Layout = VK_IMAGE_LAYOUT_UNDEFINED; + DepthOnlyView.reset(); + View.reset(); + Image.reset(); + } + + void GenerateMipmaps(VulkanCommandBuffer *cmdbuffer); + + std::unique_ptr<VulkanImage> Image; + std::unique_ptr<VulkanImageView> View; + std::unique_ptr<VulkanImageView> DepthOnlyView; + VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageAspectFlags AspectMask = VK_IMAGE_ASPECT_COLOR_BIT; +}; + +class VkImageTransition +{ +public: + void addImage(VkTextureImage *image, VkImageLayout targetLayout, bool undefinedSrcLayout); + void execute(VulkanCommandBuffer *cmdbuffer); + +private: + PipelineBarrier barrier; + VkPipelineStageFlags srcStageMask = 0; + VkPipelineStageFlags dstStageMask = 0; + bool needbarrier = false; +};