Improve stability of Vulkan and D3D12 backends on large worlds

This commit is contained in:
Wojtek Figat
2021-06-10 17:01:07 +02:00
parent 14bc9501c7
commit 3d4309457b
11 changed files with 161 additions and 115 deletions

View File

@@ -153,7 +153,7 @@ void GPUContextDX12::SetResourceState(ResourceOwnerDX12* resource, D3D12_RESOURC
if (state.AreAllSubresourcesSame())
{
// Transition entire resource at once
const D3D12_RESOURCE_STATES before = state.GetSubresourceState(subresourceIndex);
const D3D12_RESOURCE_STATES before = state.GetSubresourceState(-1);
if (ResourceStateDX12::IsTransitionNeeded(before, after))
{
AddTransitionBarrier(resource, before, after, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES);
@@ -163,6 +163,7 @@ void GPUContextDX12::SetResourceState(ResourceOwnerDX12* resource, D3D12_RESOURC
else
{
// Slow path to transition each subresource
bool hadAnyTransition = false;
for (int32 i = 0; i < state.GetSubresourcesCount(); i++)
{
const D3D12_RESOURCE_STATES before = state.GetSubresourceState(i);
@@ -170,10 +171,20 @@ void GPUContextDX12::SetResourceState(ResourceOwnerDX12* resource, D3D12_RESOURC
{
AddTransitionBarrier(resource, before, after, i);
state.SetSubresourceState(i, after);
hadAnyTransition = true;
}
}
ASSERT(state.CheckResourceState(after));
state.SetResourceState(after);
if (hadAnyTransition)
{
// Try merge all subresources states into a single state
after = state.GetSubresourceState(0);
for (int32 i = 1; i < state.GetSubresourcesCount(); i++)
{
if (state.GetSubresourceState(i) != after)
return;
}
state.SetResourceState(after);
}
}
}
else
@@ -357,6 +368,21 @@ void GPUContextDX12::flushRTVs()
{
depthBuffer = _rtDepth->DSV();
auto states = _rtDepth->ReadOnlyDepthView ? D3D12_RESOURCE_STATE_DEPTH_READ : D3D12_RESOURCE_STATE_DEPTH_WRITE;
if (_currentState && _rtDepth->ReadOnlyDepthView)
{
// If read-only depth buffer is also binded as shader input then ensure it has proper state bit
const uint32 srMask = _currentState->GetUsedSRsMask();
const uint32 srCount = Math::FloorLog2(srMask) + 1;
for (uint32 i = 0; i < srCount; i++)
{
const auto handle = _srHandles[i];
if (srMask & (1 << i) && handle == _rtDepth)
{
states |= D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
break;
}
}
}
SetResourceState(_rtDepth->GetResourceOwner(), states, _rtDepth->SubresourceIndex);
}
else
@@ -483,7 +509,7 @@ void GPUContextDX12::flushPS()
}
}
void GPUContextDX12::onDrawCall()
void GPUContextDX12::OnDrawCall()
{
// Ensure state of the vertex and index buffers
for (int32 i = 0; i < _vbCount; i++)
@@ -510,7 +536,7 @@ void GPUContextDX12::onDrawCall()
if (srMask & (1 << i) && handle != nullptr && handle->GetResourceOwner())
{
const auto resourceOwner = handle->GetResourceOwner();
bool isRtv = false;
bool isRtv = _rtDepth == handle;
for (int32 j = 0; j < _rtCount; j++)
{
if (_rtHandles[j] && _rtHandles[j]->GetResourceOwner() == resourceOwner)
@@ -970,14 +996,14 @@ void GPUContextDX12::ResolveMultisample(GPUTexture* sourceMultisampleTexture, GP
void GPUContextDX12::DrawInstanced(uint32 verticesCount, uint32 instanceCount, int32 startInstance, int32 startVertex)
{
onDrawCall();
OnDrawCall();
_commandList->DrawInstanced(verticesCount, instanceCount, startVertex, startInstance);
RENDER_STAT_DRAW_CALL(verticesCount * instanceCount, verticesCount * instanceCount / 3);
}
void GPUContextDX12::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCount, int32 startInstance, int32 startVertex, int32 startIndex)
{
onDrawCall();
OnDrawCall();
_commandList->DrawIndexedInstanced(indicesCount, instanceCount, startIndex, startVertex, startInstance);
RENDER_STAT_DRAW_CALL(0, indicesCount / 3 * instanceCount);
}
@@ -990,7 +1016,7 @@ void GPUContextDX12::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offs
auto signature = _device->DrawIndirectCommandSignature->GetSignature();
SetResourceState(bufferForArgsDX12, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);
onDrawCall();
OnDrawCall();
_commandList->ExecuteIndirect(signature, 1, bufferForArgsDX12->GetResource(), (UINT64)offsetForArgs, nullptr, 0);
RENDER_STAT_DRAW_CALL(0, 0);
}
@@ -1003,7 +1029,7 @@ void GPUContextDX12::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint
auto signature = _device->DrawIndexedIndirectCommandSignature->GetSignature();
SetResourceState(bufferForArgsDX12, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);
onDrawCall();
OnDrawCall();
_commandList->ExecuteIndirect(signature, 1, bufferForArgsDX12->GetResource(), (UINT64)offsetForArgs, nullptr, 0);
RENDER_STAT_DRAW_CALL(0, 0);
}

View File

@@ -138,7 +138,7 @@ private:
void flushCBs();
void flushRBs();
void flushPS();
void onDrawCall();
void OnDrawCall();
public:

View File

@@ -33,10 +33,46 @@ static_assert(OFFSET_OF(GPUDrawIndexedIndirectArgs, StartIndex) == OFFSET_OF(VkD
static_assert(OFFSET_OF(GPUDrawIndexedIndirectArgs, StartVertex) == OFFSET_OF(VkDrawIndexedIndirectCommand, vertexOffset), "Wrong offset for GPUDrawIndexedIndirectArgs::StartVertex");
static_assert(OFFSET_OF(GPUDrawIndexedIndirectArgs, StartInstance) == OFFSET_OF(VkDrawIndexedIndirectCommand, firstInstance), "Wrong offset for GPUDrawIndexedIndirectArgs::StartInstance");
#if VK_ENABLE_BARRIERS_DEBUG
const Char* ToString(VkImageLayout layout)
{
switch (layout)
{
#define TO_STR(type) case type: return TEXT(#type)
TO_STR(VK_IMAGE_LAYOUT_UNDEFINED);
TO_STR(VK_IMAGE_LAYOUT_GENERAL);
TO_STR(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_PREINITIALIZED);
TO_STR(VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL);
TO_STR(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
TO_STR(VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR);
TO_STR(VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV);
TO_STR(VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT);
TO_STR(VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR);
TO_STR(VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR);
#undef TO_STR
default:
return TEXT("?");
}
}
#endif
void PipelineBarrierVulkan::AddImageBarrier(VkImage image, const VkImageSubresourceRange& range, VkImageLayout srcLayout, VkImageLayout dstLayout, GPUTextureViewVulkan* handle)
{
#if VK_ENABLE_BARRIERS_DEBUG
ImageBarriersDebug.Add(handle);
ImageBarriersDebug.Add(handle);
#endif
VkImageMemoryBarrier& imageBarrier = ImageBarriers.AddOne();
RenderToolsVulkan::ZeroStruct(imageBarrier, VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER);
@@ -44,21 +80,21 @@ void PipelineBarrierVulkan::AddImageBarrier(VkImage image, const VkImageSubresou
imageBarrier.subresourceRange = range;
imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
RenderToolsVulkan::SetImageBarrierInfo(srcLayout, dstLayout, imageBarrier, SourceStage, DestStage);
imageBarrier.oldLayout = srcLayout;
imageBarrier.newLayout = dstLayout;
SourceStage |= RenderToolsVulkan::GetImageBarrierFlags(srcLayout, imageBarrier.srcAccessMask);
DestStage |= RenderToolsVulkan::GetImageBarrierFlags(dstLayout, imageBarrier.dstAccessMask);
#if VK_ENABLE_BARRIERS_DEBUG
LOG(Warning, "Image Barrier: 0x{0:x}, {1} -> {2} for baseMipLevel: {3}, baseArrayLayer: {4}, levelCount: {5}, layerCount: {6} ({7})",
(int)image,
srcLayout,
dstLayout,
range.baseMipLevel,
range.baseArrayLayer,
range.levelCount,
range.layerCount,
handle && handle->Owner->AsGPUResource() ? handle->Owner->AsGPUResource()->ToString() : String::Empty
);
LOG(Warning, "Image Barrier: 0x{0:x}, {1} -> {2} for baseMipLevel: {3}, baseArrayLayer: {4}, levelCount: {5}, layerCount: {6} ({7})",
(uintptr)image,
ToString(srcLayout),
ToString(dstLayout),
range.baseMipLevel,
range.baseArrayLayer,
range.levelCount,
range.layerCount,
handle && handle->Owner->AsGPUResource() ? handle->Owner->AsGPUResource()->ToString() : String::Empty
);
#endif
}
@@ -73,16 +109,14 @@ void PipelineBarrierVulkan::AddBufferBarrier(VkBuffer buffer, VkDeviceSize offse
bufferBarrier.dstAccessMask = dstAccess;
bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
RenderToolsVulkan::SetBufferBarrierInfo(srcAccess, dstAccess, SourceStage, DestStage);
SourceStage |= RenderToolsVulkan::GetBufferBarrierFlags(srcAccess);
DestStage |= RenderToolsVulkan::GetBufferBarrierFlags(dstAccess);
}
void PipelineBarrierVulkan::Execute(CmdBufferVulkan* cmdBuffer)
{
ASSERT(cmdBuffer->IsOutsideRenderPass());
vkCmdPipelineBarrier(cmdBuffer->GetHandle(), SourceStage, DestStage, 0, 0, nullptr, BufferBarriers.Count(), BufferBarriers.Get(), ImageBarriers.Count(), ImageBarriers.Get());
Reset();
}
@@ -127,11 +161,11 @@ void GPUContextVulkan::AddImageBarrier(VkImage image, VkImageLayout srcLayout, V
_barriers.AddImageBarrier(image, subresourceRange, srcLayout, dstLayout, handle);
#if !VK_ENABLE_BARRIERS_BATCHING
// Auto-flush without batching
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
if (cmdBuffer->IsInsideRenderPass())
EndRenderPass();
_barriers.Execute(cmdBuffer);
// Auto-flush without batching
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
if (cmdBuffer->IsInsideRenderPass())
EndRenderPass();
_barriers.Execute(cmdBuffer);
#endif
}
@@ -144,15 +178,19 @@ void GPUContextVulkan::AddImageBarrier(GPUTextureViewVulkan* handle, VkImageLayo
const int32 mipLevels = state.GetSubresourcesCount() / handle->Owner->ArraySlices;
if (state.AreAllSubresourcesSame())
{
// Transition entire resource at once
const VkImageLayout srcLayout = state.GetSubresourceState(0);
VkImageSubresourceRange range;
range.aspectMask = handle->Info.subresourceRange.aspectMask;
range.baseMipLevel = 0;
range.levelCount = mipLevels;
range.baseArrayLayer = 0;
range.layerCount = handle->Owner->ArraySlices;
AddImageBarrier(handle->Image, srcLayout, dstLayout, range, handle);
const VkImageLayout srcLayout = state.GetSubresourceState(-1);
if (srcLayout != dstLayout)
{
// Transition entire resource at once
VkImageSubresourceRange range;
range.aspectMask = handle->Info.subresourceRange.aspectMask;
range.baseMipLevel = 0;
range.levelCount = mipLevels;
range.baseArrayLayer = 0;
range.layerCount = handle->Owner->ArraySlices;
AddImageBarrier(handle->Image, srcLayout, dstLayout, range, handle);
state.SetResourceState(dstLayout);
}
}
else
{
@@ -172,8 +210,8 @@ void GPUContextVulkan::AddImageBarrier(GPUTextureViewVulkan* handle, VkImageLayo
state.SetSubresourceState(i, dstLayout);
}
}
ASSERT(state.CheckResourceState(dstLayout));
}
ASSERT(state.CheckResourceState(dstLayout));
state.SetResourceState(dstLayout);
}
else
@@ -262,11 +300,11 @@ void GPUContextVulkan::AddBufferBarrier(GPUBufferVulkan* buffer, VkAccessFlags d
buffer->Access = dstAccess;
#if !VK_ENABLE_BARRIERS_BATCHING
// Auto-flush without batching
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
if (cmdBuffer->IsInsideRenderPass())
EndRenderPass();
_barriers.Execute(cmdBuffer);
// Auto-flush without batching
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
if (cmdBuffer->IsInsideRenderPass())
EndRenderPass();
_barriers.Execute(cmdBuffer);
#endif
}
@@ -628,6 +666,18 @@ void GPUContextVulkan::OnDrawCall()
UpdateDescriptorSets(pipelineState);
}
// Bind any missing vertex buffers to null if required by the current state
const auto vertexInputState = pipelineState->GetVertexInputState();
const int32 missingVBs = vertexInputState->vertexBindingDescriptionCount - _vbCount;
if (missingVBs > 0)
{
VkBuffer buffers[GPU_MAX_VB_BINDED];
VkDeviceSize offsets[GPU_MAX_VB_BINDED] = {};
for (int32 i = 0; i < missingVBs; i++)
buffers[i] = _device->HelperResources.GetDummyVertexBuffer()->GetHandle();
vkCmdBindVertexBuffers(cmdBuffer->GetHandle(), _vbCount, missingVBs, buffers, offsets);
}
// Start render pass if not during one
if (cmdBuffer->IsOutsideRenderPass())
BeginRenderPass();
@@ -652,7 +702,7 @@ void GPUContextVulkan::OnDrawCall()
_rtDirtyFlag = false;
#if VK_ENABLE_BARRIERS_DEBUG
LOG(Warning, "Draw");
LOG(Warning, "Draw");
#endif
}
@@ -668,6 +718,7 @@ void GPUContextVulkan::FrameBegin()
_srDirtyFlag = 0;
_uaDirtyFlag = 0;
_rtCount = 0;
_vbCount = 0;
_renderPass = nullptr;
_currentState = nullptr;
_rtDepth = nullptr;
@@ -922,6 +973,7 @@ void GPUContextVulkan::BindUA(int32 slot, GPUResourceView* view)
void GPUContextVulkan::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets)
{
_vbCount = vertexBuffers.Length();
if (vertexBuffers.Length() == 0)
return;
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
@@ -955,7 +1007,7 @@ void GPUContextVulkan::UpdateCB(GPUConstantBuffer* cb, const void* data)
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
// Allocate bytes for the buffer
const auto allocation = _device->UniformBufferUploader->Allocate(size, 0, cmdBuffer);
const auto allocation = _device->UniformBufferUploader->Allocate(size, 0, this);
// Copy data
Platform::MemoryCopy(allocation.CPUAddress, data, allocation.Size);
@@ -1002,7 +1054,7 @@ void GPUContextVulkan::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCo
RENDER_STAT_DISPATCH_CALL();
#if VK_ENABLE_BARRIERS_DEBUG
LOG(Warning, "Dispatch");
LOG(Warning, "Dispatch");
#endif
}
@@ -1036,7 +1088,7 @@ void GPUContextVulkan::DispatchIndirect(GPUShaderProgramCS* shader, GPUBuffer* b
RENDER_STAT_DISPATCH_CALL();
#if VK_ENABLE_BARRIERS_DEBUG
LOG(Warning, "DispatchIndirect");
LOG(Warning, "DispatchIndirect");
#endif
}

View File

@@ -35,8 +35,6 @@ class DescriptorSetLayoutVulkan;
/// </summary>
#define VK_BARRIER_BUFFER_SIZE 16
#if VK_ENABLE_BARRIERS_BATCHING
/// <summary>
/// The Vulkan pipeline resources layout barrier batching structure.
/// </summary>
@@ -81,8 +79,6 @@ public:
void Execute(CmdBufferVulkan* cmdBuffer);
};
#endif
/// <summary>
/// GPU Context for Vulkan backend.
/// </summary>
@@ -93,9 +89,7 @@ private:
GPUDeviceVulkan* _device;
QueueVulkan* _queue;
CmdBufferManagerVulkan* _cmdBufferManager;
#if VK_ENABLE_BARRIERS_BATCHING
PipelineBarrierVulkan _barriers;
#endif
int32 _psDirtyFlag : 1;
int32 _rtDirtyFlag : 1;
@@ -104,6 +98,7 @@ private:
int32 _uaDirtyFlag : 1;
int32 _rtCount;
int32 _vbCount;
RenderPassVulkan* _renderPass;
GPUPipelineStateVulkan* _currentState;

View File

@@ -270,7 +270,7 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
_descDynamic.pDynamicStates = _dynamicStates;
_dynamicStates[_descDynamic.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT;
_dynamicStates[_descDynamic.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR;
_dynamicStates[_descDynamic.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;
//_dynamicStates[_descDynamic.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;
static_assert(ARRAY_COUNT(_dynamicStates) <= 3, "Invalid dynamic states array.");
_desc.pDynamicState = &_descDynamic;

View File

@@ -152,6 +152,11 @@ public:
/// </summary>
const SpirvShaderDescriptorInfo* DescriptorInfoPerStage[DescriptorSet::GraphicsStagesCount];
const VkPipelineVertexInputStateCreateInfo* GetVertexInputState() const
{
return _desc.pVertexInputState;
}
DescriptorSetWriteContainerVulkan DSWriteContainer;
DescriptorSetWriterVulkan DSWriter[DescriptorSet::GraphicsStagesCount];

View File

@@ -3,6 +3,7 @@
#if GRAPHICS_API_VULKAN
#include "GPUShaderVulkan.h"
#include "GPUContextVulkan.h"
#include "GPUShaderProgramVulkan.h"
#include "RenderToolsVulkan.h"
#include "CmdBufferVulkan.h"
@@ -12,7 +13,7 @@
#include "Engine/Graphics/PixelFormatExtensions.h"
#if PLATFORM_DESKTOP
#define VULKAN_UNIFORM_RING_BUFFER_SIZE 16 * 1024 * 1024
#define VULKAN_UNIFORM_RING_BUFFER_SIZE 24 * 1024 * 1024
#else
#define VULKAN_UNIFORM_RING_BUFFER_SIZE 8 * 1024 * 1024
#endif
@@ -45,7 +46,7 @@ UniformBufferUploaderVulkan::UniformBufferUploaderVulkan(GPUDeviceVulkan* device
LOG_VULKAN_RESULT(result);
}
UniformBufferUploaderVulkan::Allocation UniformBufferUploaderVulkan::Allocate(uint64 size, uint32 alignment, CmdBufferVulkan* cmdBuffer)
UniformBufferUploaderVulkan::Allocation UniformBufferUploaderVulkan::Allocate(uint64 size, uint32 alignment, GPUContextVulkan* context)
{
alignment = Math::Max(_minAlignment, alignment);
uint64 offset = Math::AlignUp<uint64>(_offset, alignment);
@@ -53,16 +54,12 @@ UniformBufferUploaderVulkan::Allocation UniformBufferUploaderVulkan::Allocate(ui
// Check if wrap around ring buffer
if (offset + size >= _size)
{
if (_fenceCmdBuffer)
auto cmdBuffer = context->GetCmdBufferManager()->GetActiveCmdBuffer();
if (_fenceCmdBuffer && _fenceCounter == cmdBuffer->GetFenceSignaledCounter())
{
if (_fenceCmdBuffer == cmdBuffer && _fenceCounter == cmdBuffer->GetFenceSignaledCounter())
{
LOG(Error, "Wrapped around the ring buffer. Requested more bytes than possible in the same cmd buffer!");
}
else if (_fenceCounter == _fenceCmdBuffer->GetFenceSignaledCounter())
{
LOG(Error, "Wrapped around the ring buffer! Need to wait on the GPU!!!");
}
LOG(Error, "Wrapped around the ring buffer! Need to wait on the GPU!");
context->Flush();
cmdBuffer = context->GetCmdBufferManager()->GetActiveCmdBuffer();
}
offset = 0;

View File

@@ -62,7 +62,7 @@ public:
public:
Allocation Allocate(uint64 size, uint32 alignment, CmdBufferVulkan* cmdBuffer);
Allocation Allocate(uint64 size, uint32 alignment, GPUContextVulkan* context);
public:

View File

@@ -164,37 +164,6 @@ public:
return stageFlags;
}
static inline void SetBufferBarrierInfo(VkAccessFlags source, VkAccessFlags dest, VkPipelineStageFlags& sourceStage, VkPipelineStageFlags& destStage)
{
sourceStage |= GetBufferBarrierFlags(source);
destStage |= GetBufferBarrierFlags(dest);
}
static inline void SetImageBarrierInfo(VkImageLayout source, VkImageLayout dest, VkImageMemoryBarrier& barrier, VkPipelineStageFlags& sourceStage, VkPipelineStageFlags& destStage)
{
barrier.oldLayout = source;
barrier.newLayout = dest;
sourceStage |= GetImageBarrierFlags(source, barrier.srcAccessMask);
destStage |= GetImageBarrierFlags(dest, barrier.dstAccessMask);
}
static void ImagePipelineBarrier(VkCommandBuffer cmdBuffer, VkImage img, VkImageLayout src, VkImageLayout dest, const VkImageSubresourceRange& subresourceRange)
{
VkImageMemoryBarrier imageBarrier;
ZeroStruct(imageBarrier, VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER);
imageBarrier.image = img;
imageBarrier.subresourceRange = subresourceRange;
imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
VkPipelineStageFlags srcStages = (VkPipelineStageFlags)0;
VkPipelineStageFlags destStages = (VkPipelineStageFlags)0;
SetImageBarrierInfo(src, dest, imageBarrier, srcStages, destStages);
vkCmdPipelineBarrier(cmdBuffer, srcStages, destStages, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
}
template<class T>
static FORCE_INLINE void ZeroStruct(T& data, VkStructureType type)
{

View File

@@ -206,8 +206,10 @@ void LightPass::RenderLight(RenderContext& renderContext, GPUTextureView* lightB
// Bind output
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
GPUTextureView* depthBufferHandle = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : nullptr;
context->SetRenderTarget(depthBufferHandle, lightBuffer);
const bool depthBufferReadOnly = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView;
GPUTextureView* depthBufferRTV = depthBufferReadOnly ? depthBuffer->ViewReadOnlyDepth() : nullptr;
GPUTextureView* depthBufferSRV = depthBufferReadOnly ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
context->SetRenderTarget(depthBufferRTV, lightBuffer);
// Set per frame data
GBufferPass::SetInputs(renderContext.View, perFrame.GBuffer);
@@ -225,7 +227,7 @@ void LightPass::RenderLight(RenderContext& renderContext, GPUTextureView* lightB
context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1);
context->BindSR(2, renderContext.Buffers->GBuffer2);
context->BindSR(3, depthBuffer);
context->BindSR(3, depthBufferSRV);
context->BindSR(4, renderContext.Buffers->GBuffer3);
// Check if debug lights
@@ -274,7 +276,7 @@ void LightPass::RenderLight(RenderContext& renderContext, GPUTextureView* lightB
ShadowsPass::Instance()->RenderShadow(renderContext, light, shadowMaskView);
// Bind output
context->SetRenderTarget(depthBufferHandle, lightBuffer);
context->SetRenderTarget(depthBufferRTV, lightBuffer);
// Set shadow mask
context->BindSR(5, shadowMaskView);
@@ -329,7 +331,7 @@ void LightPass::RenderLight(RenderContext& renderContext, GPUTextureView* lightB
ShadowsPass::Instance()->RenderShadow(renderContext, light, shadowMaskView);
// Bind output
context->SetRenderTarget(depthBufferHandle, lightBuffer);
context->SetRenderTarget(depthBufferRTV, lightBuffer);
// Set shadow mask
context->BindSR(5, shadowMaskView);
@@ -370,7 +372,7 @@ void LightPass::RenderLight(RenderContext& renderContext, GPUTextureView* lightB
ShadowsPass::Instance()->RenderShadow(renderContext, light, lightIndex, shadowMaskView);
// Bind output
context->SetRenderTarget(depthBufferHandle, lightBuffer);
context->SetRenderTarget(depthBufferRTV, lightBuffer);
// Set shadow mask
context->BindSR(5, shadowMaskView);

View File

@@ -315,12 +315,12 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererPointLightD
context->ResetRenderTarget();
const Viewport viewport = renderContext.Task->GetViewport();
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
GPUTextureView* depthBufferHandle = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
GPUTextureView* depthBufferSRV = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
context->SetViewportAndScissors(viewport);
context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1);
context->BindSR(2, renderContext.Buffers->GBuffer2);
context->BindSR(3, depthBufferHandle);
context->BindSR(3, depthBufferSRV);
context->BindSR(4, renderContext.Buffers->GBuffer3);
// Setup shader data
@@ -417,12 +417,12 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererSpotLightDa
context->ResetRenderTarget();
const Viewport viewport = renderContext.Task->GetViewport();
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
GPUTextureView* depthBufferHandle = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
GPUTextureView* depthBufferSRV = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
context->SetViewportAndScissors(viewport);
context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1);
context->BindSR(2, renderContext.Buffers->GBuffer2);
context->BindSR(3, depthBufferHandle);
context->BindSR(3, depthBufferSRV);
context->BindSR(4, renderContext.Buffers->GBuffer3);
// Setup shader data
@@ -693,12 +693,12 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererDirectional
context->ResetRenderTarget();
const Viewport viewport = renderContext.Task->GetViewport();
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer;
GPUTextureView* depthBufferHandle = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
GPUTextureView* depthBufferSRV = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View();
context->SetViewportAndScissors(viewport);
context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1);
context->BindSR(2, renderContext.Buffers->GBuffer2);
context->BindSR(3, depthBufferHandle);
context->BindSR(3, depthBufferSRV);
context->BindSR(4, renderContext.Buffers->GBuffer3);
// Setup shader data