- 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/shaders/vk_shader.cpp
rendering/vulkan/textures/vk_samplers.cpp rendering/vulkan/textures/vk_samplers.cpp
rendering/vulkan/textures/vk_hwtexture.cpp rendering/vulkan/textures/vk_hwtexture.cpp
rendering/vulkan/textures/vk_imagetransition.cpp
rendering/vulkan/thirdparty/volk/volk.c rendering/vulkan/thirdparty/volk/volk.c
rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.cpp 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_buffers.h"
#include "vulkan/system/vk_swapchain.h" #include "vulkan/system/vk_swapchain.h"
#include "vulkan/renderer/vk_renderstate.h" #include "vulkan/renderer/vk_renderstate.h"
#include "vulkan/textures/vk_imagetransition.h"
#include "hwrenderer/utility/hw_cvars.h" #include "hwrenderer/utility/hw_cvars.h"
#include "hwrenderer/postprocessing/hw_postprocess.h" #include "hwrenderer/postprocessing/hw_postprocess.h"
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h" #include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
@ -30,11 +31,11 @@ void VkPostprocess::SetActiveRenderTarget()
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
auto buffers = fb->GetBuffers(); auto buffers = fb->GetBuffers();
VkPPImageTransition imageTransition; VkImageTransition imageTransition;
imageTransition.addImage(buffers->PipelineImage[mCurrentPipelineImage].get(), &buffers->PipelineLayout[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false); imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false);
imageTransition.execute(fb->GetDrawCommands()); 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) void VkPostprocess::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
@ -70,14 +71,14 @@ void VkPostprocess::BlitSceneToPostprocess()
mCurrentPipelineImage = 0; mCurrentPipelineImage = 0;
VkPPImageTransition imageTransition0; VkImageTransition imageTransition;
imageTransition0.addImage(buffers->SceneColor.get(), &buffers->SceneColorLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false); imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
imageTransition0.addImage(buffers->PipelineImage[mCurrentPipelineImage].get(), &buffers->PipelineLayout[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); imageTransition.addImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
imageTransition0.execute(fb->GetDrawCommands()); imageTransition.execute(fb->GetDrawCommands());
if (buffers->GetSceneSamples() != VK_SAMPLE_COUNT_1_BIT) if (buffers->GetSceneSamples() != VK_SAMPLE_COUNT_1_BIT)
{ {
auto sceneColor = buffers->SceneColor.get(); auto sceneColor = buffers->SceneColor.Image.get();
VkImageResolve resolve = {}; VkImageResolve resolve = {};
resolve.srcOffset = { 0, 0, 0 }; resolve.srcOffset = { 0, 0, 0 };
resolve.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 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 }; resolve.extent = { (uint32_t)sceneColor->width, (uint32_t)sceneColor->height, 1 };
cmdbuffer->resolveImage( cmdbuffer->resolveImage(
sceneColor->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 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); 1, &resolve);
} }
else else
{ {
auto sceneColor = buffers->SceneColor.get(); auto sceneColor = buffers->SceneColor.Image.get();
VkImageBlit blit = {}; VkImageBlit blit = {};
blit.srcOffsets[0] = { 0, 0, 0 }; blit.srcOffsets[0] = { 0, 0, 0 };
blit.srcOffsets[1] = { sceneColor->width, sceneColor->height, 1 }; blit.srcOffsets[1] = { sceneColor->width, sceneColor->height, 1 };
@ -113,7 +114,7 @@ void VkPostprocess::BlitSceneToPostprocess()
blit.dstSubresource.layerCount = 1; blit.dstSubresource.layerCount = 1;
cmdbuffer->blitImage( cmdbuffer->blitImage(
sceneColor->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 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); 1, &blit, VK_FILTER_NEAREST);
} }
} }
@ -123,51 +124,48 @@ void VkPostprocess::ImageTransitionScene(bool undefinedSrcLayout)
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
auto buffers = fb->GetBuffers(); auto buffers = fb->GetBuffers();
VkPPImageTransition imageTransition; VkImageTransition imageTransition;
imageTransition.addImage(buffers->SceneColor.get(), &buffers->SceneColorLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); imageTransition.addImage(&buffers->SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
imageTransition.addImage(buffers->SceneFog.get(), &buffers->SceneFogLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); imageTransition.addImage(&buffers->SceneFog, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
imageTransition.addImage(buffers->SceneNormal.get(), &buffers->SceneNormalLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); imageTransition.addImage(&buffers->SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
imageTransition.addImage(buffers->SceneDepthStencil.get(), &buffers->SceneDepthStencilLayout, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout); imageTransition.addImage(&buffers->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout);
imageTransition.execute(fb->GetDrawCommands()); imageTransition.execute(fb->GetDrawCommands());
} }
void VkPostprocess::BlitCurrentToImage(VulkanImage *dstimage, VkImageLayout *dstlayout, VkImageLayout finallayout) void VkPostprocess::BlitCurrentToImage(VkTextureImage *dstimage, VkImageLayout finallayout)
{ {
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
fb->GetRenderState()->EndRenderPass(); fb->GetRenderState()->EndRenderPass();
auto srcimage = fb->GetBuffers()->PipelineImage[mCurrentPipelineImage].get(); auto srcimage = &fb->GetBuffers()->PipelineImage[mCurrentPipelineImage];
auto srclayout = &fb->GetBuffers()->PipelineLayout[mCurrentPipelineImage];
auto cmdbuffer = fb->GetDrawCommands(); auto cmdbuffer = fb->GetDrawCommands();
*dstlayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // needed by VkPPImageTransition.addImage. Actual layout is undefined. VkImageTransition imageTransition0;
imageTransition0.addImage(srcimage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
VkPPImageTransition imageTransition0; imageTransition0.addImage(dstimage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
imageTransition0.addImage(srcimage, srclayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false);
imageTransition0.addImage(dstimage, dstlayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
imageTransition0.execute(cmdbuffer); imageTransition0.execute(cmdbuffer);
VkImageBlit blit = {}; VkImageBlit blit = {};
blit.srcOffsets[0] = { 0, 0, 0 }; 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.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit.srcSubresource.mipLevel = 0; blit.srcSubresource.mipLevel = 0;
blit.srcSubresource.baseArrayLayer = 0; blit.srcSubresource.baseArrayLayer = 0;
blit.srcSubresource.layerCount = 1; blit.srcSubresource.layerCount = 1;
blit.dstOffsets[0] = { 0, 0, 0 }; 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.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
blit.dstSubresource.mipLevel = 0; blit.dstSubresource.mipLevel = 0;
blit.dstSubresource.baseArrayLayer = 0; blit.dstSubresource.baseArrayLayer = 0;
blit.dstSubresource.layerCount = 1; blit.dstSubresource.layerCount = 1;
cmdbuffer->blitImage( cmdbuffer->blitImage(
srcimage->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, srcimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstimage->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dstimage->Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &blit, VK_FILTER_NEAREST); 1, &blit, VK_FILTER_NEAREST);
VkPPImageTransition imageTransition1; VkImageTransition imageTransition1;
imageTransition1.addImage(dstimage, dstlayout, finallayout, false); imageTransition1.addImage(dstimage, finallayout, false);
imageTransition1.execute(cmdbuffer); imageTransition1.execute(cmdbuffer);
} }
@ -179,7 +177,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
hw_postprocess.customShaders.Run(&renderstate, "screen"); hw_postprocess.customShaders.Run(&renderstate, "screen");
PresentUniforms uniforms; PresentUniforms uniforms;
if (!applyGamma /*|| framebuffer->IsHWGammaActive()*/) if (!applyGamma)
{ {
uniforms.InvGamma = 1.0f; uniforms.InvGamma = 1.0f;
uniforms.Contrast = 1.0f; uniforms.Contrast = 1.0f;
@ -263,8 +261,8 @@ void VkPostprocess::UpdateShadowMap()
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
auto buffers = fb->GetBuffers(); auto buffers = fb->GetBuffers();
VkPPImageTransition imageTransition; VkImageTransition imageTransition;
imageTransition.addImage(buffers->Shadowmap.get(), &buffers->ShadowmapLayout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); imageTransition.addImage(&buffers->Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
imageTransition.execute(fb->GetDrawCommands()); imageTransition.execute(fb->GetDrawCommands());
screen->mShadowMap.FinishUpdate(); screen->mShadowMap.FinishUpdate();
@ -345,14 +343,14 @@ VkPPTexture::VkPPTexture(PPTexture *texture)
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
if (!imgbuilder.isFormatSupported(fb->device)) if (!imgbuilder.isFormatSupported(fb->device))
I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n"); I_FatalError("Vulkan device does not support the image format required by a postprocess texture\n");
Image = imgbuilder.create(fb->device); TexImage.Image = imgbuilder.create(fb->device);
Image->SetDebugName("VkPPTexture"); TexImage.Image->SetDebugName("VkPPTexture");
Format = format; Format = format;
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(Image.get(), format); viewbuilder.setImage(TexImage.Image.get(), format);
View = viewbuilder.create(fb->device); TexImage.View = viewbuilder.create(fb->device);
View->SetDebugName("VkPPTextureView"); TexImage.View->SetDebugName("VkPPTextureView");
if (texture->Data) if (texture->Data)
{ {
@ -363,9 +361,9 @@ VkPPTexture::VkPPTexture(PPTexture *texture)
Staging = stagingbuilder.create(fb->device); Staging = stagingbuilder.create(fb->device);
Staging->SetDebugName("VkPPTextureStaging"); Staging->SetDebugName("VkPPTextureStaging");
PipelineBarrier barrier0; VkImageTransition barrier0;
barrier0.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT); barrier0.addImage(&TexImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
barrier0.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); barrier0.execute(fb->GetTransferCommands());
void *data = Staging->Map(0, totalsize); void *data = Staging->Map(0, totalsize);
memcpy(data, texture->Data.get(), totalsize); memcpy(data, texture->Data.get(), totalsize);
@ -377,19 +375,17 @@ VkPPTexture::VkPPTexture(PPTexture *texture)
region.imageExtent.depth = 1; region.imageExtent.depth = 1;
region.imageExtent.width = texture->Width; region.imageExtent.width = texture->Width;
region.imageExtent.height = texture->Height; 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; VkImageTransition 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.addImage(&TexImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
barrier1.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); barrier1.execute(fb->GetTransferCommands());
Layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
} }
else else
{ {
PipelineBarrier barrier; VkImageTransition 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.addImage(&TexImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
barrier.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); barrier.execute(fb->GetTransferCommands());
Layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
} }
} }
@ -542,16 +538,16 @@ VulkanDescriptorSet *VkPPRenderState::GetInput(VkPPRenderPassSetup *passSetup, c
descriptors->SetDebugName("VkPostprocess.descriptors"); descriptors->SetDebugName("VkPostprocess.descriptors");
WriteDescriptors write; WriteDescriptors write;
VkPPImageTransition imageTransition; VkImageTransition imageTransition;
for (unsigned int index = 0; index < textures.Size(); index++) for (unsigned int index = 0; index < textures.Size(); index++)
{ {
const PPTextureInput &input = textures[index]; const PPTextureInput &input = textures[index];
VulkanSampler *sampler = pp->GetSampler(input.Filter, input.Wrap); 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); write.addCombinedImageSampler(descriptors.get(), index, tex->DepthOnlyView ? tex->DepthOnlyView.get() : tex->View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
imageTransition.addImage(tex.image, tex.layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); imageTransition.addImage(tex, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
} }
if (bindShadowMapBuffers) if (bindShadowMapBuffers)
@ -573,21 +569,21 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
{ {
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
TextureImage tex = GetTexture(output.Type, output.Texture); VkTextureImage *tex = GetTexture(output.Type, output.Texture);
VkImageView view; VkImageView view;
int w, h; int w, h;
if (tex.view) if (tex)
{ {
VkPPImageTransition imageTransition; VkImageTransition imageTransition;
imageTransition.addImage(tex.image, tex.layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture); imageTransition.addImage(tex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture);
if (stencilTest) 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()); imageTransition.execute(fb->GetDrawCommands());
view = tex.view->view; view = tex->View->view;
w = tex.image->width; w = tex->Image->width;
h = tex.image->height; h = tex->Image->height;
} }
else else
{ {
@ -604,9 +600,8 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
builder.setSize(w, h); builder.setSize(w, h);
builder.addAttachment(view); builder.addAttachment(view);
if (stencilTest) if (stencilTest)
builder.addAttachment(fb->GetBuffers()->SceneDepthStencilView.get()); builder.addAttachment(fb->GetBuffers()->SceneDepthStencil.View.get());
framebuffer = builder.create(GetVulkanFrameBuffer()->device); framebuffer = builder.create(GetVulkanFrameBuffer()->device);
framebuffer->SetDebugName(tex.debugname);
} }
framebufferWidth = w; framebufferWidth = w;
@ -614,10 +609,9 @@ VulkanFramebuffer *VkPPRenderState::GetOutput(VkPPRenderPassSetup *passSetup, co
return framebuffer.get(); return framebuffer.get();
} }
VkPPRenderState::TextureImage VkPPRenderState::GetTexture(const PPTextureType &type, PPTexture *pptexture) VkTextureImage *VkPPRenderState::GetTexture(const PPTextureType &type, PPTexture *pptexture)
{ {
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
TextureImage tex = {};
if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture) if (type == PPTextureType::CurrentPipelineTexture || type == PPTextureType::NextPipelineTexture)
{ {
@ -625,67 +619,42 @@ VkPPRenderState::TextureImage VkPPRenderState::GetTexture(const PPTextureType &t
if (type == PPTextureType::NextPipelineTexture) if (type == PPTextureType::NextPipelineTexture)
idx = (idx + 1) % VkRenderBuffers::NumPipelineImages; idx = (idx + 1) % VkRenderBuffers::NumPipelineImages;
tex.image = fb->GetBuffers()->PipelineImage[idx].get(); return &fb->GetBuffers()->PipelineImage[idx];
tex.view = fb->GetBuffers()->PipelineView[idx].get();
tex.layout = &fb->GetBuffers()->PipelineLayout[idx];
tex.debugname = "PipelineTexture";
} }
else if (type == PPTextureType::PPTexture) else if (type == PPTextureType::PPTexture)
{ {
auto vktex = GetVkTexture(pptexture); auto vktex = GetVkTexture(pptexture);
tex.image = vktex->Image.get(); return &vktex->TexImage;
tex.view = vktex->View.get();
tex.layout = &vktex->Layout;
tex.debugname = "PPTexture";
} }
else if (type == PPTextureType::SceneColor) else if (type == PPTextureType::SceneColor)
{ {
tex.image = fb->GetBuffers()->SceneColor.get(); return &fb->GetBuffers()->SceneColor;
tex.view = fb->GetBuffers()->SceneColorView.get();
tex.layout = &fb->GetBuffers()->SceneColorLayout;
tex.debugname = "SceneColor";
} }
else if (type == PPTextureType::SceneNormal) else if (type == PPTextureType::SceneNormal)
{ {
tex.image = fb->GetBuffers()->SceneNormal.get(); return &fb->GetBuffers()->SceneNormal;
tex.view = fb->GetBuffers()->SceneNormalView.get();
tex.layout = &fb->GetBuffers()->SceneNormalLayout;
tex.debugname = "SceneNormal";
} }
else if (type == PPTextureType::SceneFog) else if (type == PPTextureType::SceneFog)
{ {
tex.image = fb->GetBuffers()->SceneFog.get(); return &fb->GetBuffers()->SceneFog;
tex.view = fb->GetBuffers()->SceneFogView.get();
tex.layout = &fb->GetBuffers()->SceneFogLayout;
tex.debugname = "SceneFog";
} }
else if (type == PPTextureType::SceneDepth) else if (type == PPTextureType::SceneDepth)
{ {
tex.image = fb->GetBuffers()->SceneDepthStencil.get(); return &fb->GetBuffers()->SceneDepthStencil;
tex.view = fb->GetBuffers()->SceneDepthView.get();
tex.layout = &fb->GetBuffers()->SceneDepthStencilLayout;
tex.debugname = "SceneDepth";
} }
else if (type == PPTextureType::ShadowMap) else if (type == PPTextureType::ShadowMap)
{ {
tex.image = fb->GetBuffers()->Shadowmap.get(); return &fb->GetBuffers()->Shadowmap;
tex.view = fb->GetBuffers()->ShadowmapView.get();
tex.layout = &fb->GetBuffers()->ShadowmapLayout;
tex.debugname = "Shadowmap";
} }
else if (type == PPTextureType::SwapChain) else if (type == PPTextureType::SwapChain)
{ {
tex.image = nullptr; return nullptr;
tex.view = nullptr;
tex.layout = nullptr;
tex.debugname = "SwapChain";
} }
else else
{ {
I_FatalError("VkPPRenderState::GetTexture not implemented yet for this texture type"); I_FatalError("VkPPRenderState::GetTexture not implemented yet for this texture type");
return nullptr;
} }
return tex;
} }
VkPPShader *VkPPRenderState::GetVkShader(PPShader *shader) VkPPShader *VkPPRenderState::GetVkShader(PPShader *shader)
@ -805,79 +774,3 @@ void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey &key)
RenderPass = builder.create(GetVulkanFrameBuffer()->device); RenderPass = builder.create(GetVulkanFrameBuffer()->device);
RenderPass->SetDebugName("VkPPRenderPassSetup.RenderPass"); 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 "hwrenderer/postprocessing/hw_postprocess.h"
#include "vulkan/system/vk_objects.h" #include "vulkan/system/vk_objects.h"
#include "vulkan/system/vk_builders.h" #include "vulkan/system/vk_builders.h"
#include "vulkan/textures/vk_imagetransition.h"
class FString; class FString;
@ -34,19 +35,6 @@ public:
bool operator!=(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) != 0; } 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 class VkPostprocess
{ {
public: public:
@ -67,7 +55,7 @@ public:
void ImageTransitionScene(bool undefinedSrcLayout); void ImageTransitionScene(bool undefinedSrcLayout);
void BlitSceneToPostprocess(); 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); void DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders);
private: private:
@ -101,10 +89,8 @@ class VkPPTexture : public PPTextureBackend
public: public:
VkPPTexture(PPTexture *texture); VkPPTexture(PPTexture *texture);
std::unique_ptr<VulkanImage> Image; VkTextureImage TexImage;
std::unique_ptr<VulkanImageView> View;
std::unique_ptr<VulkanBuffer> Staging; std::unique_ptr<VulkanBuffer> Staging;
VkImageLayout Layout = VK_IMAGE_LAYOUT_UNDEFINED;
VkFormat Format; VkFormat Format;
}; };
@ -143,12 +129,5 @@ private:
VkPPShader *GetVkShader(PPShader *shader); VkPPShader *GetVkShader(PPShader *shader);
VkPPTexture *GetVkTexture(PPTexture *texture); VkPPTexture *GetVkTexture(PPTexture *texture);
struct TextureImage VkTextureImage *GetTexture(const PPTextureType &type, PPTexture *tex);
{
VulkanImage *image;
VulkanImageView *view;
VkImageLayout *layout;
const char *debugname;
};
TextureImage 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++) for (int i = 0; i < NumPipelineImages; i++)
{ {
PipelineImage[i].reset(); PipelineImage[i].reset();
PipelineView[i].reset();
} }
PipelineBarrier barrier; VkImageTransition barrier;
for (int i = 0; i < NumPipelineImages; i++) for (int i = 0; i < NumPipelineImages; i++)
{ {
ImageBuilder builder; ImageBuilder builder;
builder.setSize(width, height); builder.setSize(width, height);
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT); 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); 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].Image = builder.create(fb->device);
PipelineImage[i]->SetDebugName("VkRenderBuffers.PipelineImage"); PipelineImage[i].Image->SetDebugName("VkRenderBuffers.PipelineImage");
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(PipelineImage[i].get(), VK_FORMAT_R16G16B16A16_SFLOAT); viewbuilder.setImage(PipelineImage[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
PipelineView[i] = viewbuilder.create(fb->device); PipelineImage[i].View = viewbuilder.create(fb->device);
PipelineView[i]->SetDebugName("VkRenderBuffers.PipelineView"); 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); barrier.addImage(&PipelineImage[i], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
PipelineLayout[i] = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
} }
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) void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits samples)
{ {
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
SceneColorView.reset();
SceneDepthStencilView.reset();
SceneDepthView.reset();
SceneNormalView.reset();
SceneFogView.reset();
SceneColor.reset(); SceneColor.reset();
SceneDepthStencil.reset(); SceneDepthStencil.reset();
SceneNormal.reset(); SceneNormal.reset();
@ -114,14 +107,12 @@ void VkRenderBuffers::CreateScene(int width, int height, VkSampleCountFlagBits s
CreateSceneNormal(width, height, samples); CreateSceneNormal(width, height, samples);
CreateSceneFog(width, height, samples); CreateSceneFog(width, height, samples);
PipelineBarrier barrier; VkImageTransition 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(&SceneColor, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
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(&SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true);
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(&SceneNormal, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
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.addImage(&SceneFog, 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());
SceneColorLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
} }
void VkRenderBuffers::CreateSceneColor(int width, int height, VkSampleCountFlagBits samples) 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.setSamples(samples);
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT); 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); 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.Image = builder.create(fb->device);
SceneColor->SetDebugName("VkRenderBuffers.SceneColor"); SceneColor.Image->SetDebugName("VkRenderBuffers.SceneColor");
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(SceneColor.get(), VK_FORMAT_R16G16B16A16_SFLOAT); viewbuilder.setImage(SceneColor.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
SceneColorView = viewbuilder.create(fb->device); SceneColor.View = viewbuilder.create(fb->device);
SceneColorView->SetDebugName("VkRenderBuffers.SceneColorView"); SceneColor.View->SetDebugName("VkRenderBuffers.SceneColorView");
} }
void VkRenderBuffers::CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples) 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."); I_FatalError("This device does not support any of the required depth stencil image formats.");
} }
} }
SceneDepthStencil = builder.create(fb->device); SceneDepthStencil.Image = builder.create(fb->device);
SceneDepthStencil->SetDebugName("VkRenderBuffers.SceneDepthStencil"); SceneDepthStencil.Image->SetDebugName("VkRenderBuffers.SceneDepthStencil");
SceneDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(SceneDepthStencil.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
SceneDepthStencilView = viewbuilder.create(fb->device); SceneDepthStencil.View = viewbuilder.create(fb->device);
SceneDepthStencilView->SetDebugName("VkRenderBuffers.SceneDepthStencilView"); SceneDepthStencil.View->SetDebugName("VkRenderBuffers.SceneDepthStencilView");
viewbuilder.setImage(SceneDepthStencil.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT); viewbuilder.setImage(SceneDepthStencil.Image.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
SceneDepthView = viewbuilder.create(fb->device); SceneDepthStencil.DepthOnlyView = viewbuilder.create(fb->device);
SceneDepthView->SetDebugName("VkRenderBuffers.SceneDepthView"); SceneDepthStencil.DepthOnlyView->SetDebugName("VkRenderBuffers.SceneDepthView");
} }
void VkRenderBuffers::CreateSceneFog(int width, int height, VkSampleCountFlagBits samples) 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.setSamples(samples);
builder.setFormat(VK_FORMAT_R8G8B8A8_UNORM); builder.setFormat(VK_FORMAT_R8G8B8A8_UNORM);
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
SceneFog = builder.create(fb->device); SceneFog.Image = builder.create(fb->device);
SceneFog->SetDebugName("VkRenderBuffers.SceneFog"); SceneFog.Image->SetDebugName("VkRenderBuffers.SceneFog");
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(SceneFog.get(), VK_FORMAT_R8G8B8A8_UNORM); viewbuilder.setImage(SceneFog.Image.get(), VK_FORMAT_R8G8B8A8_UNORM);
SceneFogView = viewbuilder.create(fb->device); SceneFog.View = viewbuilder.create(fb->device);
SceneFogView->SetDebugName("VkRenderBuffers.SceneFogView"); SceneFog.View->SetDebugName("VkRenderBuffers.SceneFogView");
} }
void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples) 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.setSamples(samples);
builder.setFormat(VK_FORMAT_A2R10G10B10_UNORM_PACK32); builder.setFormat(VK_FORMAT_A2R10G10B10_UNORM_PACK32);
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
SceneNormal = builder.create(fb->device); SceneNormal.Image = builder.create(fb->device);
SceneNormal->SetDebugName("VkRenderBuffers.SceneNormal"); SceneNormal.Image->SetDebugName("VkRenderBuffers.SceneNormal");
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(SceneNormal.get(), VK_FORMAT_A2R10G10B10_UNORM_PACK32); viewbuilder.setImage(SceneNormal.Image.get(), VK_FORMAT_A2R10G10B10_UNORM_PACK32);
SceneNormalView = viewbuilder.create(fb->device); SceneNormal.View = viewbuilder.create(fb->device);
SceneNormalView->SetDebugName("VkRenderBuffers.SceneNormalView"); SceneNormal.View->SetDebugName("VkRenderBuffers.SceneNormalView");
} }
void VkRenderBuffers::CreateShadowmap() void VkRenderBuffers::CreateShadowmap()
{ {
if (Shadowmap && Shadowmap->width == gl_shadowmap_quality) if (Shadowmap.Image && Shadowmap.Image->width == gl_shadowmap_quality)
return; return;
Shadowmap.reset(); Shadowmap.reset();
ShadowmapView.reset();
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
@ -223,17 +214,17 @@ void VkRenderBuffers::CreateShadowmap()
builder.setSize(gl_shadowmap_quality, 1024); builder.setSize(gl_shadowmap_quality, 1024);
builder.setFormat(VK_FORMAT_R32_SFLOAT); builder.setFormat(VK_FORMAT_R32_SFLOAT);
builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
Shadowmap = builder.create(fb->device); Shadowmap.Image = builder.create(fb->device);
Shadowmap->SetDebugName("VkRenderBuffers.Shadowmap"); Shadowmap.Image->SetDebugName("VkRenderBuffers.Shadowmap");
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(Shadowmap.get(), VK_FORMAT_R32_SFLOAT); viewbuilder.setImage(Shadowmap.Image.get(), VK_FORMAT_R32_SFLOAT);
ShadowmapView = viewbuilder.create(fb->device); Shadowmap.View = viewbuilder.create(fb->device);
ShadowmapView->SetDebugName("VkRenderBuffers.ShadowmapView"); Shadowmap.View->SetDebugName("VkRenderBuffers.ShadowmapView");
PipelineBarrier barrier; VkImageTransition barrier;
barrier.addImage(Shadowmap.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT); barrier.addImage(&Shadowmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
barrier.execute(fb->GetDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); barrier.execute(fb->GetDrawCommands());
if (!ShadowmapSampler) if (!ShadowmapSampler)
{ {

View file

@ -2,6 +2,7 @@
#pragma once #pragma once
#include "vulkan/system/vk_objects.h" #include "vulkan/system/vk_objects.h"
#include "vulkan/textures/vk_imagetransition.h"
class VkRenderBuffers class VkRenderBuffers
{ {
@ -17,30 +18,18 @@ public:
int GetSceneHeight() const { return mSceneHeight; } int GetSceneHeight() const { return mSceneHeight; }
VkSampleCountFlagBits GetSceneSamples() const { return mSamples; } VkSampleCountFlagBits GetSceneSamples() const { return mSamples; }
std::unique_ptr<VulkanImage> SceneColor; VkTextureImage SceneColor;
std::unique_ptr<VulkanImage> SceneDepthStencil; VkTextureImage SceneDepthStencil;
std::unique_ptr<VulkanImage> SceneNormal; VkTextureImage SceneNormal;
std::unique_ptr<VulkanImage> SceneFog; VkTextureImage 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;
VkFormat SceneDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; 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; static const int NumPipelineImages = 2;
std::unique_ptr<VulkanImage> PipelineImage[NumPipelineImages]; VkTextureImage PipelineImage[NumPipelineImages];
std::unique_ptr<VulkanImageView> PipelineView[NumPipelineImages];
VkImageLayout PipelineLayout[NumPipelineImages] = { VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
std::unique_ptr<VulkanImage> Shadowmap; VkTextureImage Shadowmap;
std::unique_ptr<VulkanImageView> ShadowmapView;
std::unique_ptr<VulkanSampler> ShadowmapSampler; std::unique_ptr<VulkanSampler> ShadowmapSampler;
VkImageLayout ShadowmapLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
private: private:
void CreatePipeline(int width, int height); 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(), 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(), 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.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); update.updateSets(fb->device);
} }

View file

@ -568,9 +568,9 @@ void VkRenderState::BeginRenderPass(const VkRenderPassKey &key, VulkanCommandBuf
builder.setSize(mRenderTarget.Width, mRenderTarget.Height); builder.setSize(mRenderTarget.Width, mRenderTarget.Height);
builder.addAttachment(mRenderTarget.View); builder.addAttachment(mRenderTarget.View);
if (key.DrawBuffers > 1) if (key.DrawBuffers > 1)
builder.addAttachment(buffers->SceneFogView.get()); builder.addAttachment(buffers->SceneFog.View.get());
if (key.DrawBuffers > 2) if (key.DrawBuffers > 2)
builder.addAttachment(buffers->SceneNormalView.get()); builder.addAttachment(buffers->SceneNormal.View.get());
if (key.UsesDepthStencil()) if (key.UsesDepthStencil())
builder.addAttachment(mRenderTarget.DepthStencil); builder.addAttachment(mRenderTarget.DepthStencil);
framebuffer = builder.create(GetVulkanFrameBuffer()->device); 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 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); bool useSSAO = (gl_ssao != 0);
GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount()); GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount());
@ -505,33 +505,32 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint
int width = mat->TextureWidth(); int width = mat->TextureWidth();
int height = mat->TextureHeight(); int height = mat->TextureHeight();
VulkanImage *image = BaseLayer->GetImage(tex, 0, 0); VkTextureImage *image = BaseLayer->GetImage(tex, 0, 0);
VulkanImageView *view = BaseLayer->GetImageView(tex, 0, 0); VkTextureImage *depthStencil = BaseLayer->GetDepthStencil(tex);
VulkanImageView *depthStencilView = BaseLayer->GetDepthStencilView(tex);
mRenderState->EndRenderPass(); mRenderState->EndRenderPass();
PipelineBarrier barrier0; VkImageTransition 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.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
barrier0.execute(GetDrawCommands(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); 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; IntRect bounds;
bounds.left = bounds.top = 0; bounds.left = bounds.top = 0;
bounds.width = MIN(mat->GetWidth(), image->width); bounds.width = MIN(mat->GetWidth(), image->Image->width);
bounds.height = MIN(mat->GetHeight(), image->height); bounds.height = MIN(mat->GetHeight(), image->Image->height);
FRenderViewpoint texvp; FRenderViewpoint texvp;
RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false); RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false);
mRenderState->EndRenderPass(); mRenderState->EndRenderPass();
PipelineBarrier barrier1; VkImageTransition 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.addImage(image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
barrier1.execute(GetDrawCommands(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); 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); tex->SetUpdated(true);
} }
@ -736,14 +735,15 @@ FTexture *VulkanFrameBuffer::WipeEndScreen()
void VulkanFrameBuffer::CopyScreenToBuffer(int w, int h, void *data) void VulkanFrameBuffer::CopyScreenToBuffer(int w, int h, void *data)
{ {
VkTextureImage image;
// Convert from rgba16f to rgba8 using the GPU: // Convert from rgba16f to rgba8 using the GPU:
ImageBuilder imgbuilder; ImageBuilder imgbuilder;
imgbuilder.setFormat(VK_FORMAT_R8G8B8A8_UNORM); imgbuilder.setFormat(VK_FORMAT_R8G8B8A8_UNORM);
imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); imgbuilder.setUsage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
imgbuilder.setSize(w, h); imgbuilder.setSize(w, h);
auto image = imgbuilder.create(device); image.Image = imgbuilder.create(device);
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED; GetPostprocess()->BlitCurrentToImage(&image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
GetPostprocess()->BlitCurrentToImage(image.get(), &layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
// Staging buffer for download // Staging buffer for download
BufferBuilder bufbuilder; BufferBuilder bufbuilder;
@ -758,7 +758,7 @@ void VulkanFrameBuffer::CopyScreenToBuffer(int w, int h, void *data)
region.imageExtent.depth = 1; region.imageExtent.depth = 1;
region.imageSubresource.layerCount = 1; region.imageSubresource.layerCount = 1;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 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 // Submit command buffers and wait for device to finish the work
WaitForCommands(false); WaitForCommands(false);

View file

@ -70,10 +70,12 @@ void VkHardwareTexture::Reset()
ResetDescriptors(); ResetDescriptors();
auto &deleteList = fb->FrameDeleteList; auto &deleteList = fb->FrameDeleteList;
if (mImage) deleteList.Images.push_back(std::move(mImage)); if (mImage.Image) deleteList.Images.push_back(std::move(mImage.Image));
if (mImageView) deleteList.ImageViews.push_back(std::move(mImageView)); if (mImage.View) deleteList.ImageViews.push_back(std::move(mImage.View));
if (mDepthStencil) deleteList.Images.push_back(std::move(mDepthStencil)); if (mDepthStencil.Image) deleteList.Images.push_back(std::move(mDepthStencil.Image));
if (mDepthStencilView) deleteList.ImageViews.push_back(std::move(mDepthStencilView)); 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) void VkHardwareTexture::Precache(FMaterial *mat, int translation, int flags)
{ {
int numLayers = mat->GetLayers(); int numLayers = mat->GetLayers();
GetImageView(mat->tex, translation, flags); GetImage(mat->tex, translation, flags);
for (int i = 1; i < numLayers; i++) for (int i = 1; i < numLayers; i++)
{ {
FTexture *layer; FTexture *layer;
auto systex = static_cast<VkHardwareTexture*>(mat->GetLayer(i, 0, &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); VulkanSampler *sampler = fb->GetSamplerManager()->Get(clampmode);
auto baseView = GetImageView(tex, translation, flags);
WriteDescriptors update; 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++) for (int i = 1; i < numLayers; i++)
{ {
FTexture *layer; FTexture *layer;
auto systex = static_cast<VkHardwareTexture*>(mat->GetLayer(i, 0, &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); update.updateSets(fb->device);
mDescriptorSets.emplace_back(clampmode, flags, std::move(descriptor)); mDescriptorSets.emplace_back(clampmode, flags, std::move(descriptor));
return mDescriptorSets.back().descriptor.get(); 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); 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) if (!mDepthStencil.View)
{
CreateImage(tex, translation, flags);
}
return mImageView.get();
}
VulkanImageView *VkHardwareTexture::GetDepthStencilView(FTexture *tex)
{
if (!mDepthStencilView)
{ {
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
@ -192,19 +183,20 @@ VulkanImageView *VkHardwareTexture::GetDepthStencilView(FTexture *tex)
builder.setSamples(VK_SAMPLE_COUNT_1_BIT); builder.setSamples(VK_SAMPLE_COUNT_1_BIT);
builder.setFormat(format); builder.setFormat(format);
builder.setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); builder.setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
mDepthStencil = builder.create(fb->device); mDepthStencil.Image = builder.create(fb->device);
mDepthStencil->SetDebugName("VkHardwareTexture.DepthStencil"); mDepthStencil.Image->SetDebugName("VkHardwareTexture.DepthStencil");
mDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(mDepthStencil.get(), format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); viewbuilder.setImage(mDepthStencil.Image.get(), format, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
mDepthStencilView = viewbuilder.create(fb->device); mDepthStencil.View = viewbuilder.create(fb->device);
mDepthStencilView->SetDebugName("VkHardwareTexture.DepthStencilView"); mDepthStencil.View->SetDebugName("VkHardwareTexture.DepthStencilView");
PipelineBarrier barrier; VkImageTransition 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.addImage(&mDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true);
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); barrier.execute(fb->GetTransferCommands());
} }
return mDepthStencilView.get(); return &mDepthStencil;
} }
void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) 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.setFormat(format);
imgbuilder.setSize(w, h); imgbuilder.setSize(w, h);
imgbuilder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); imgbuilder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
mImage = imgbuilder.create(fb->device); mImage.Image = imgbuilder.create(fb->device);
mImage->SetDebugName("VkHardwareTexture.mImage"); mImage.Image->SetDebugName("VkHardwareTexture.mImage");
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(mImage.get(), format); viewbuilder.setImage(mImage.Image.get(), format);
mImageView = viewbuilder.create(fb->device); mImage.View = viewbuilder.create(fb->device);
mImageView->SetDebugName("VkHardwareTexture.mImageView"); mImage.View->SetDebugName("VkHardwareTexture.mImageView");
auto cmdbuffer = fb->GetTransferCommands(); auto cmdbuffer = fb->GetTransferCommands();
PipelineBarrier imageTransition; VkImageTransition imageTransition;
imageTransition.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT); imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
imageTransition.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); imageTransition.execute(cmdbuffer);
} }
} }
@ -272,19 +264,19 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form
imgbuilder.setFormat(format); imgbuilder.setFormat(format);
imgbuilder.setSize(w, h, GetMipLevels(w, h)); 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); 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.Image = imgbuilder.create(fb->device);
mImage->SetDebugName("VkHardwareTexture.mImage"); mImage.Image->SetDebugName("VkHardwareTexture.mImage");
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(mImage.get(), format); viewbuilder.setImage(mImage.Image.get(), format);
mImageView = viewbuilder.create(fb->device); mImage.View = viewbuilder.create(fb->device);
mImageView->SetDebugName("VkHardwareTexture.mImageView"); mImage.View->SetDebugName("VkHardwareTexture.mImageView");
auto cmdbuffer = fb->GetTransferCommands(); auto cmdbuffer = fb->GetTransferCommands();
PipelineBarrier imageTransition0; VkImageTransition imageTransition;
imageTransition0.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT); imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
imageTransition0.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); imageTransition.execute(cmdbuffer);
VkBufferImageCopy region = {}; VkBufferImageCopy region = {};
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 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.depth = 1;
region.imageExtent.width = w; region.imageExtent.width = w;
region.imageExtent.height = h; 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)); fb->FrameDeleteList.Buffers.push_back(std::move(stagingBuffer));
GenerateMipmaps(mImage.get(), cmdbuffer); mImage.GenerateMipmaps(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);
} }
int VkHardwareTexture::GetMipLevels(int w, int h) 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) 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(); Reset();
} }
if (!mImage) if (!mImage.Image)
{ {
auto fb = GetVulkanFrameBuffer(); auto fb = GetVulkanFrameBuffer();
@ -376,21 +325,20 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
imgbuilder.setMemoryType( 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_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_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.Image = imgbuilder.create(fb->device, &allocatedBytes);
mImage->SetDebugName("VkHardwareTexture.mImage"); mImage.Image->SetDebugName("VkHardwareTexture.mImage");
mImageLayout = VK_IMAGE_LAYOUT_GENERAL;
mTexelsize = texelsize; mTexelsize = texelsize;
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(mImage.get(), format); viewbuilder.setImage(mImage.Image.get(), format);
mImageView = viewbuilder.create(fb->device); mImage.View = viewbuilder.create(fb->device);
mImageView->SetDebugName("VkHardwareTexture.mImageView"); mImage.View->SetDebugName("VkHardwareTexture.mImageView");
auto cmdbuffer = fb->GetTransferCommands(); auto cmdbuffer = fb->GetTransferCommands();
PipelineBarrier imageTransition; VkImageTransition imageTransition;
imageTransition.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, mImageLayout, 0, VK_ACCESS_SHADER_READ_BIT); imageTransition.addImage(&mImage, VK_IMAGE_LAYOUT_GENERAL, true);
imageTransition.execute(cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); imageTransition.execute(cmdbuffer);
bufferpitch = int(allocatedBytes / h / texelsize); bufferpitch = int(allocatedBytes / h / texelsize);
} }
@ -398,12 +346,12 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
uint8_t *VkHardwareTexture::MapBuffer() 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) 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; return 0;
} }
@ -417,15 +365,14 @@ void VkHardwareTexture::CreateWipeTexture(int w, int h, const char *name)
imgbuilder.setFormat(format); imgbuilder.setFormat(format);
imgbuilder.setSize(w, h); imgbuilder.setSize(w, h);
imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); imgbuilder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
mImage = imgbuilder.create(fb->device); mImage.Image = imgbuilder.create(fb->device);
mImage->SetDebugName(name); mImage.Image->SetDebugName(name);
mImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
mTexelsize = 4; mTexelsize = 4;
ImageViewBuilder viewbuilder; ImageViewBuilder viewbuilder;
viewbuilder.setImage(mImage.get(), format); viewbuilder.setImage(mImage.Image.get(), format);
mImageView = viewbuilder.create(fb->device); mImage.View = viewbuilder.create(fb->device);
mImageView->SetDebugName(name); 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 "tarray.h"
#include "hwrenderer/textures/hw_ihwtexture.h" #include "hwrenderer/textures/hw_ihwtexture.h"
#include "volk/volk.h" #include "volk/volk.h"
#include "vk_imagetransition.h"
struct FMaterialState; struct FMaterialState;
class VulkanDescriptorSet; class VulkanDescriptorSet;
@ -40,9 +41,8 @@ public:
void DeleteDescriptors() override { ResetDescriptors(); } void DeleteDescriptors() override { ResetDescriptors(); }
VulkanImage *GetImage(FTexture *tex, int translation, int flags); VkTextureImage *GetImage(FTexture *tex, int translation, int flags);
VulkanImageView *GetImageView(FTexture *tex, int translation, int flags); VkTextureImage *GetDepthStencil(FTexture *tex);
VulkanImageView *GetDepthStencilView(FTexture *tex);
static void ResetAllDescriptors(); static void ResetAllDescriptors();
@ -50,7 +50,6 @@ private:
void CreateImage(FTexture *tex, int translation, int flags); void CreateImage(FTexture *tex, int translation, int flags);
void CreateTexture(int w, int h, int pixelsize, VkFormat format, const void *pixels); 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); static int GetMipLevels(int w, int h);
void ResetDescriptors(); void ResetDescriptors();
@ -74,11 +73,8 @@ private:
}; };
std::vector<DescriptorEntry> mDescriptorSets; std::vector<DescriptorEntry> mDescriptorSets;
std::unique_ptr<VulkanImage> mImage; VkTextureImage mImage;
std::unique_ptr<VulkanImageView> mImageView;
VkImageLayout mImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
int mTexelsize = 4; int mTexelsize = 4;
std::unique_ptr<VulkanImage> mDepthStencil; VkTextureImage mDepthStencil;
std::unique_ptr<VulkanImageView> mDepthStencilView;
}; };

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