- centralize how image transitions are done in the vulkan backend

This commit is contained in:
Magnus Norddahl 2019-05-16 18:26:47 +02:00
parent 99f58855ad
commit 9ab19d057d
12 changed files with 385 additions and 420 deletions

View file

@ -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
)

View file

@ -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, &region);
fb->GetTransferCommands()->copyBufferToImage(Staging->buffer, TexImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
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);
}

View file

@ -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);
};

View file

@ -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)
{

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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, &region);
GetDrawCommands()->copyImageToBuffer(image.Image->image, image.Layout, staging->buffer, 1, &region);
// Submit command buffers and wait for device to finish the work
WaitForCommands(false);

View file

@ -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, &region);
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, mImage.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
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);
}

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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;
};