From d78cb959a75cdfe0209174cf5bc3f7c131cc8ac3 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 13 Mar 2019 02:23:33 +0100 Subject: [PATCH] - implement wipe screen copy --- .../vulkan/renderer/vk_postprocess.cpp | 40 +++++++++++++++++++ .../vulkan/renderer/vk_postprocess.h | 1 + .../vulkan/renderer/vk_renderbuffers.cpp | 2 +- .../vulkan/system/vk_framebuffer.cpp | 26 ++++++++++++ src/rendering/vulkan/system/vk_framebuffer.h | 8 +--- .../vulkan/textures/vk_hwtexture.cpp | 25 ++++++++++++ src/rendering/vulkan/textures/vk_hwtexture.h | 3 ++ 7 files changed, 98 insertions(+), 7 deletions(-) diff --git a/src/rendering/vulkan/renderer/vk_postprocess.cpp b/src/rendering/vulkan/renderer/vk_postprocess.cpp index 5d037da696..3f372fb660 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/rendering/vulkan/renderer/vk_postprocess.cpp @@ -119,6 +119,46 @@ void VkPostprocess::BlitSceneToTexture() imageTransition1.execute(fb->GetDrawCommands()); } +void VkPostprocess::BlitCurrentToImage(VulkanImage *dstimage, VkImageLayout *dstlayout) +{ + auto fb = GetVulkanFrameBuffer(); + + fb->GetRenderState()->EndRenderPass(); + + auto srcimage = fb->GetBuffers()->PipelineImage[mCurrentPipelineImage].get(); + auto srclayout = &fb->GetBuffers()->PipelineLayout[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); + imageTransition0.execute(fb->GetDrawCommands()); + + VkImageBlit blit = {}; + blit.srcOffsets[0] = { 0, 0, 0 }; + blit.srcOffsets[1] = { srcimage->width, srcimage->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.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, + 1, &blit, VK_FILTER_NEAREST); + + VkPPImageTransition imageTransition1; + imageTransition1.addImage(dstimage, dstlayout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); + imageTransition1.execute(fb->GetDrawCommands()); +} + void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders) { auto fb = GetVulkanFrameBuffer(); diff --git a/src/rendering/vulkan/renderer/vk_postprocess.h b/src/rendering/vulkan/renderer/vk_postprocess.h index e4bd816534..5cc32247a5 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.h +++ b/src/rendering/vulkan/renderer/vk_postprocess.h @@ -61,6 +61,7 @@ public: void ClearTonemapPalette(); void BlitSceneToTexture(); + void BlitCurrentToImage(VulkanImage *image, VkImageLayout *layout); void DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders); private: diff --git a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp index a84c09a1b0..19f2dcc37b 100644 --- a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp @@ -78,7 +78,7 @@ void VkRenderBuffers::CreatePipeline(int width, int height) 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_DST_BIT); + 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"); diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 4bdf86d306..6286e939cd 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -546,6 +546,32 @@ void VulkanFrameBuffer::UpdatePalette() mPostprocess->ClearTonemapPalette(); } +FTexture *VulkanFrameBuffer::WipeStartScreen() +{ + const auto &viewport = screen->mScreenViewport; + auto tex = new FWrapperTexture(viewport.width, viewport.height, 1); + auto systex = static_cast(tex->GetSystemTexture()); + + systex->CreateWipeTexture(viewport.width, viewport.height, "WipeStartScreen"); + + return tex; +} + +FTexture *VulkanFrameBuffer::WipeEndScreen() +{ + GetPostprocess()->SetActiveRenderTarget(); + Draw2D(); + Clear2D(); + + const auto &viewport = screen->mScreenViewport; + auto tex = new FWrapperTexture(viewport.width, viewport.height, 1); + auto systex = static_cast(tex->GetSystemTexture()); + + systex->CreateWipeTexture(viewport.width, viewport.height, "WipeEndScreen"); + + return tex; +} + void VulkanFrameBuffer::BeginFrame() { SetViewportRects(nullptr); diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index 05d1ae80cc..a8525aa4c8 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -71,12 +71,8 @@ public: IIndexBuffer *CreateIndexBuffer() override; IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo) override; - /* - bool WipeStartScreen(int type); - void WipeEndScreen(); - bool WipeDo(int ticks); - void WipeCleanup(); - */ + FTexture *WipeStartScreen() override; + FTexture *WipeEndScreen() override; void SetVSync(bool vsync); diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index 6b7ccb3cf6..653e9fadfe 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -35,6 +35,7 @@ #include "vulkan/system/vk_framebuffer.h" #include "vulkan/textures/vk_samplers.h" #include "vulkan/renderer/vk_renderpass.h" +#include "vulkan/renderer/vk_postprocess.h" #include "vk_hwtexture.h" VkHardwareTexture *VkHardwareTexture::First = nullptr; @@ -282,6 +283,30 @@ unsigned int VkHardwareTexture::CreateTexture(unsigned char * buffer, int w, int return 0; } +void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name) +{ + auto fb = GetVulkanFrameBuffer(); + + VkFormat format = VK_FORMAT_B8G8R8A8_UNORM; + + ImageBuilder imgbuilder; + 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; + mTexelsize = 4; + + ImageViewBuilder viewbuilder; + viewbuilder.setImage(mImage.get(), format); + mImageView = viewbuilder.create(fb->device); + mImageView->SetDebugName(name); + + fb->GetPostprocess()->BlitCurrentToImage(mImage.get(), &mImageLayout); +} + + #if 0 //=========================================================================== diff --git a/src/rendering/vulkan/textures/vk_hwtexture.h b/src/rendering/vulkan/textures/vk_hwtexture.h index 2be0dc3051..2f8a7927af 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.h +++ b/src/rendering/vulkan/textures/vk_hwtexture.h @@ -32,6 +32,9 @@ public: uint8_t *MapBuffer() override; unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) override; + // Wipe screen + void CreateWipeTexture(int w, int h, const char *name); + static VkHardwareTexture *First; VkHardwareTexture *Prev = nullptr; VkHardwareTexture *Next = nullptr;