Skip to content

Commit

Permalink
- centralize how image transitions are done in the vulkan backend
Browse files Browse the repository at this point in the history
  • Loading branch information
dpjudas committed May 16, 2019
1 parent 99f5885 commit 9ab19d0
Show file tree
Hide file tree
Showing 12 changed files with 385 additions and 420 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -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
)
Expand Down
245 changes: 69 additions & 176 deletions src/rendering/vulkan/renderer/vk_postprocess.cpp

Large diffs are not rendered by default.

29 changes: 4 additions & 25 deletions src/rendering/vulkan/renderer/vk_postprocess.h
Expand Up @@ -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;

Expand All @@ -34,19 +35,6 @@ class VkPPRenderPassKey
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:
Expand All @@ -67,7 +55,7 @@ class VkPostprocess
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:
Expand Down Expand Up @@ -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;
};

Expand Down Expand Up @@ -143,12 +129,5 @@ class VkPPRenderState : public PPRenderState
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);
};
103 changes: 47 additions & 56 deletions src/rendering/vulkan/renderer/vk_renderbuffers.cpp
Expand Up @@ -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();
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -200,40 +192,39 @@ 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();

ImageBuilder builder;
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)
{
Expand Down
27 changes: 8 additions & 19 deletions src/rendering/vulkan/renderer/vk_renderbuffers.h
Expand Up @@ -2,6 +2,7 @@
#pragma once

#include "vulkan/system/vk_objects.h"
#include "vulkan/textures/vk_imagetransition.h"

class VkRenderBuffers
{
Expand All @@ -17,30 +18,18 @@ class VkRenderBuffers
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);
Expand Down
2 changes: 1 addition & 1 deletion src/rendering/vulkan/renderer/vk_renderpass.cpp
Expand Up @@ -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);
}

Expand Down
4 changes: 2 additions & 2 deletions src/rendering/vulkan/renderer/vk_renderstate.cpp
Expand Up @@ -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);
Expand Down

0 comments on commit 9ab19d0

Please sign in to comment.