diff --git a/src/rendering/vulkan/renderer/vk_postprocess.cpp b/src/rendering/vulkan/renderer/vk_postprocess.cpp index d3d50ab97..a4ef6dc71 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/rendering/vulkan/renderer/vk_postprocess.cpp @@ -98,6 +98,87 @@ void VkPostprocess::RenderBuffersReset() void VkPostprocess::UpdateEffectTextures() { + auto fb = GetVulkanFrameBuffer(); + + TMap::Iterator it(hw_postprocess.Textures); + TMap::Pair *pair; + while (it.NextPair(pair)) + { + const auto &desc = pair->Value; + auto &vktex = mTextures[pair->Key]; + + if (vktex && (vktex->Image->width != desc.Width || vktex->Image->height != desc.Height)) + vktex.reset(); + + if (!vktex) + { + vktex.reset(new VkPPTexture()); + + VkFormat format; + int pixelsize; + switch (pair->Value.Format) + { + default: + case PixelFormat::Rgba8: format = VK_FORMAT_R8G8B8A8_UNORM; pixelsize = 4; break; + case PixelFormat::Rgba16f: format = VK_FORMAT_R16G16B16A16_SFLOAT; pixelsize = 8; break; + case PixelFormat::R32f: format = VK_FORMAT_R32_SFLOAT; pixelsize = 4; break; + case PixelFormat::Rg16f: format = VK_FORMAT_R16G16_SFLOAT; pixelsize = 4; break; + case PixelFormat::Rgba16_snorm: format = VK_FORMAT_R16G16B16A16_SNORM; pixelsize = 8; break; + } + + ImageBuilder imgbuilder; + imgbuilder.setFormat(format); + imgbuilder.setSize(desc.Width, desc.Height); + if (desc.Data) + imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + else + 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 %s\n", pair->Key.GetChars()); + vktex->Image = imgbuilder.create(fb->device); + + ImageViewBuilder viewbuilder; + viewbuilder.setImage(vktex->Image.get(), format); + vktex->View = viewbuilder.create(fb->device); + + if (desc.Data) + { + size_t totalsize = desc.Width * desc.Height * pixelsize; + BufferBuilder stagingbuilder; + stagingbuilder.setSize(totalsize); + stagingbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); + vktex->Staging = stagingbuilder.create(fb->device); + + PipelineBarrier barrier0; + barrier0.addImage(vktex->Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT); + barrier0.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + + void *data = vktex->Staging->Map(0, totalsize); + memcpy(data, desc.Data.get(), totalsize); + vktex->Staging->Unmap(); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.depth = 1; + region.imageExtent.width = desc.Width; + region.imageExtent.height = desc.Height; + fb->GetUploadCommands()->copyBufferToImage(vktex->Staging->buffer, vktex->Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + PipelineBarrier barrier1; + barrier1.addImage(vktex->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->GetUploadCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + vktex->Layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + else + { + PipelineBarrier barrier; + barrier.addImage(vktex->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->GetUploadCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + vktex->Layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + } + } } void VkPostprocess::CompileEffectShaders() @@ -112,6 +193,8 @@ void VkPostprocess::CompileEffectShaders() auto &vkshader = mShaders[pair->Key]; if (!vkshader) { + vkshader.reset(new VkPPShader()); + FString prolog; if (!desc.Uniforms.empty()) prolog = UniformBlockDecl::Create("Uniforms", desc.Uniforms, uniformbindingpoint); diff --git a/src/rendering/vulkan/renderer/vk_postprocess.h b/src/rendering/vulkan/renderer/vk_postprocess.h index 6c75ac960..4e7070e14 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.h +++ b/src/rendering/vulkan/renderer/vk_postprocess.h @@ -52,4 +52,6 @@ class VkPPTexture public: std::unique_ptr Image; std::unique_ptr View; + std::unique_ptr Staging; + VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED; };