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()) if (state.AreAllSubresourcesSame())
{ {
// Transition entire resource at once // 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)) if (ResourceStateDX12::IsTransitionNeeded(before, after))
{ {
AddTransitionBarrier(resource, before, after, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES); AddTransitionBarrier(resource, before, after, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES);
@@ -163,6 +163,7 @@ void GPUContextDX12::SetResourceState(ResourceOwnerDX12* resource, D3D12_RESOURC
else else
{ {
// Slow path to transition each subresource // Slow path to transition each subresource
bool hadAnyTransition = false;
for (int32 i = 0; i < state.GetSubresourcesCount(); i++) for (int32 i = 0; i < state.GetSubresourcesCount(); i++)
{ {
const D3D12_RESOURCE_STATES before = state.GetSubresourceState(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); AddTransitionBarrier(resource, before, after, i);
state.SetSubresourceState(i, after); state.SetSubresourceState(i, after);
hadAnyTransition = true;
} }
} }
ASSERT(state.CheckResourceState(after)); if (hadAnyTransition)
state.SetResourceState(after); {
// 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 else
@@ -357,6 +368,21 @@ void GPUContextDX12::flushRTVs()
{ {
depthBuffer = _rtDepth->DSV(); depthBuffer = _rtDepth->DSV();
auto states = _rtDepth->ReadOnlyDepthView ? D3D12_RESOURCE_STATE_DEPTH_READ : D3D12_RESOURCE_STATE_DEPTH_WRITE; 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); SetResourceState(_rtDepth->GetResourceOwner(), states, _rtDepth->SubresourceIndex);
} }
else else
@@ -483,7 +509,7 @@ void GPUContextDX12::flushPS()
} }
} }
void GPUContextDX12::onDrawCall() void GPUContextDX12::OnDrawCall()
{ {
// Ensure state of the vertex and index buffers // Ensure state of the vertex and index buffers
for (int32 i = 0; i < _vbCount; i++) for (int32 i = 0; i < _vbCount; i++)
@@ -510,7 +536,7 @@ void GPUContextDX12::onDrawCall()
if (srMask & (1 << i) && handle != nullptr && handle->GetResourceOwner()) if (srMask & (1 << i) && handle != nullptr && handle->GetResourceOwner())
{ {
const auto resourceOwner = handle->GetResourceOwner(); const auto resourceOwner = handle->GetResourceOwner();
bool isRtv = false; bool isRtv = _rtDepth == handle;
for (int32 j = 0; j < _rtCount; j++) for (int32 j = 0; j < _rtCount; j++)
{ {
if (_rtHandles[j] && _rtHandles[j]->GetResourceOwner() == resourceOwner) 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) void GPUContextDX12::DrawInstanced(uint32 verticesCount, uint32 instanceCount, int32 startInstance, int32 startVertex)
{ {
onDrawCall(); OnDrawCall();
_commandList->DrawInstanced(verticesCount, instanceCount, startVertex, startInstance); _commandList->DrawInstanced(verticesCount, instanceCount, startVertex, startInstance);
RENDER_STAT_DRAW_CALL(verticesCount * instanceCount, verticesCount * instanceCount / 3); RENDER_STAT_DRAW_CALL(verticesCount * instanceCount, verticesCount * instanceCount / 3);
} }
void GPUContextDX12::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCount, int32 startInstance, int32 startVertex, int32 startIndex) void GPUContextDX12::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCount, int32 startInstance, int32 startVertex, int32 startIndex)
{ {
onDrawCall(); OnDrawCall();
_commandList->DrawIndexedInstanced(indicesCount, instanceCount, startIndex, startVertex, startInstance); _commandList->DrawIndexedInstanced(indicesCount, instanceCount, startIndex, startVertex, startInstance);
RENDER_STAT_DRAW_CALL(0, indicesCount / 3 * instanceCount); RENDER_STAT_DRAW_CALL(0, indicesCount / 3 * instanceCount);
} }
@@ -990,7 +1016,7 @@ void GPUContextDX12::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offs
auto signature = _device->DrawIndirectCommandSignature->GetSignature(); auto signature = _device->DrawIndirectCommandSignature->GetSignature();
SetResourceState(bufferForArgsDX12, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT); SetResourceState(bufferForArgsDX12, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);
onDrawCall(); OnDrawCall();
_commandList->ExecuteIndirect(signature, 1, bufferForArgsDX12->GetResource(), (UINT64)offsetForArgs, nullptr, 0); _commandList->ExecuteIndirect(signature, 1, bufferForArgsDX12->GetResource(), (UINT64)offsetForArgs, nullptr, 0);
RENDER_STAT_DRAW_CALL(0, 0); RENDER_STAT_DRAW_CALL(0, 0);
} }
@@ -1003,7 +1029,7 @@ void GPUContextDX12::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint
auto signature = _device->DrawIndexedIndirectCommandSignature->GetSignature(); auto signature = _device->DrawIndexedIndirectCommandSignature->GetSignature();
SetResourceState(bufferForArgsDX12, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT); SetResourceState(bufferForArgsDX12, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT);
onDrawCall(); OnDrawCall();
_commandList->ExecuteIndirect(signature, 1, bufferForArgsDX12->GetResource(), (UINT64)offsetForArgs, nullptr, 0); _commandList->ExecuteIndirect(signature, 1, bufferForArgsDX12->GetResource(), (UINT64)offsetForArgs, nullptr, 0);
RENDER_STAT_DRAW_CALL(0, 0); RENDER_STAT_DRAW_CALL(0, 0);
} }

View File

@@ -138,7 +138,7 @@ private:
void flushCBs(); void flushCBs();
void flushRBs(); void flushRBs();
void flushPS(); void flushPS();
void onDrawCall(); void OnDrawCall();
public: 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, 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"); 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) void PipelineBarrierVulkan::AddImageBarrier(VkImage image, const VkImageSubresourceRange& range, VkImageLayout srcLayout, VkImageLayout dstLayout, GPUTextureViewVulkan* handle)
{ {
#if VK_ENABLE_BARRIERS_DEBUG #if VK_ENABLE_BARRIERS_DEBUG
ImageBarriersDebug.Add(handle); ImageBarriersDebug.Add(handle);
#endif #endif
VkImageMemoryBarrier& imageBarrier = ImageBarriers.AddOne(); VkImageMemoryBarrier& imageBarrier = ImageBarriers.AddOne();
RenderToolsVulkan::ZeroStruct(imageBarrier, VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER); RenderToolsVulkan::ZeroStruct(imageBarrier, VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER);
@@ -44,21 +80,21 @@ void PipelineBarrierVulkan::AddImageBarrier(VkImage image, const VkImageSubresou
imageBarrier.subresourceRange = range; imageBarrier.subresourceRange = range;
imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageBarrier.oldLayout = srcLayout;
RenderToolsVulkan::SetImageBarrierInfo(srcLayout, dstLayout, imageBarrier, SourceStage, DestStage); imageBarrier.newLayout = dstLayout;
SourceStage |= RenderToolsVulkan::GetImageBarrierFlags(srcLayout, imageBarrier.srcAccessMask);
DestStage |= RenderToolsVulkan::GetImageBarrierFlags(dstLayout, imageBarrier.dstAccessMask);
#if VK_ENABLE_BARRIERS_DEBUG #if VK_ENABLE_BARRIERS_DEBUG
LOG(Warning, "Image Barrier: 0x{0:x}, {1} -> {2} for baseMipLevel: {3}, baseArrayLayer: {4}, levelCount: {5}, layerCount: {6} ({7})", LOG(Warning, "Image Barrier: 0x{0:x}, {1} -> {2} for baseMipLevel: {3}, baseArrayLayer: {4}, levelCount: {5}, layerCount: {6} ({7})",
(int)image, (uintptr)image,
srcLayout, ToString(srcLayout),
dstLayout, ToString(dstLayout),
range.baseMipLevel, range.baseMipLevel,
range.baseArrayLayer, range.baseArrayLayer,
range.levelCount, range.levelCount,
range.layerCount, range.layerCount,
handle && handle->Owner->AsGPUResource() ? handle->Owner->AsGPUResource()->ToString() : String::Empty
handle && handle->Owner->AsGPUResource() ? handle->Owner->AsGPUResource()->ToString() : String::Empty );
);
#endif #endif
} }
@@ -73,16 +109,14 @@ void PipelineBarrierVulkan::AddBufferBarrier(VkBuffer buffer, VkDeviceSize offse
bufferBarrier.dstAccessMask = dstAccess; bufferBarrier.dstAccessMask = dstAccess;
bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
SourceStage |= RenderToolsVulkan::GetBufferBarrierFlags(srcAccess);
RenderToolsVulkan::SetBufferBarrierInfo(srcAccess, dstAccess, SourceStage, DestStage); DestStage |= RenderToolsVulkan::GetBufferBarrierFlags(dstAccess);
} }
void PipelineBarrierVulkan::Execute(CmdBufferVulkan* cmdBuffer) void PipelineBarrierVulkan::Execute(CmdBufferVulkan* cmdBuffer)
{ {
ASSERT(cmdBuffer->IsOutsideRenderPass()); ASSERT(cmdBuffer->IsOutsideRenderPass());
vkCmdPipelineBarrier(cmdBuffer->GetHandle(), SourceStage, DestStage, 0, 0, nullptr, BufferBarriers.Count(), BufferBarriers.Get(), ImageBarriers.Count(), ImageBarriers.Get()); vkCmdPipelineBarrier(cmdBuffer->GetHandle(), SourceStage, DestStage, 0, 0, nullptr, BufferBarriers.Count(), BufferBarriers.Get(), ImageBarriers.Count(), ImageBarriers.Get());
Reset(); Reset();
} }
@@ -127,11 +161,11 @@ void GPUContextVulkan::AddImageBarrier(VkImage image, VkImageLayout srcLayout, V
_barriers.AddImageBarrier(image, subresourceRange, srcLayout, dstLayout, handle); _barriers.AddImageBarrier(image, subresourceRange, srcLayout, dstLayout, handle);
#if !VK_ENABLE_BARRIERS_BATCHING #if !VK_ENABLE_BARRIERS_BATCHING
// Auto-flush without batching // Auto-flush without batching
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer(); const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
if (cmdBuffer->IsInsideRenderPass()) if (cmdBuffer->IsInsideRenderPass())
EndRenderPass(); EndRenderPass();
_barriers.Execute(cmdBuffer); _barriers.Execute(cmdBuffer);
#endif #endif
} }
@@ -144,15 +178,19 @@ void GPUContextVulkan::AddImageBarrier(GPUTextureViewVulkan* handle, VkImageLayo
const int32 mipLevels = state.GetSubresourcesCount() / handle->Owner->ArraySlices; const int32 mipLevels = state.GetSubresourcesCount() / handle->Owner->ArraySlices;
if (state.AreAllSubresourcesSame()) if (state.AreAllSubresourcesSame())
{ {
// Transition entire resource at once const VkImageLayout srcLayout = state.GetSubresourceState(-1);
const VkImageLayout srcLayout = state.GetSubresourceState(0); if (srcLayout != dstLayout)
VkImageSubresourceRange range; {
range.aspectMask = handle->Info.subresourceRange.aspectMask; // Transition entire resource at once
range.baseMipLevel = 0; VkImageSubresourceRange range;
range.levelCount = mipLevels; range.aspectMask = handle->Info.subresourceRange.aspectMask;
range.baseArrayLayer = 0; range.baseMipLevel = 0;
range.layerCount = handle->Owner->ArraySlices; range.levelCount = mipLevels;
AddImageBarrier(handle->Image, srcLayout, dstLayout, range, handle); range.baseArrayLayer = 0;
range.layerCount = handle->Owner->ArraySlices;
AddImageBarrier(handle->Image, srcLayout, dstLayout, range, handle);
state.SetResourceState(dstLayout);
}
} }
else else
{ {
@@ -172,8 +210,8 @@ void GPUContextVulkan::AddImageBarrier(GPUTextureViewVulkan* handle, VkImageLayo
state.SetSubresourceState(i, dstLayout); state.SetSubresourceState(i, dstLayout);
} }
} }
ASSERT(state.CheckResourceState(dstLayout));
} }
ASSERT(state.CheckResourceState(dstLayout));
state.SetResourceState(dstLayout); state.SetResourceState(dstLayout);
} }
else else
@@ -262,11 +300,11 @@ void GPUContextVulkan::AddBufferBarrier(GPUBufferVulkan* buffer, VkAccessFlags d
buffer->Access = dstAccess; buffer->Access = dstAccess;
#if !VK_ENABLE_BARRIERS_BATCHING #if !VK_ENABLE_BARRIERS_BATCHING
// Auto-flush without batching // Auto-flush without batching
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer(); const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
if (cmdBuffer->IsInsideRenderPass()) if (cmdBuffer->IsInsideRenderPass())
EndRenderPass(); EndRenderPass();
_barriers.Execute(cmdBuffer); _barriers.Execute(cmdBuffer);
#endif #endif
} }
@@ -628,6 +666,18 @@ void GPUContextVulkan::OnDrawCall()
UpdateDescriptorSets(pipelineState); 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 // Start render pass if not during one
if (cmdBuffer->IsOutsideRenderPass()) if (cmdBuffer->IsOutsideRenderPass())
BeginRenderPass(); BeginRenderPass();
@@ -652,7 +702,7 @@ void GPUContextVulkan::OnDrawCall()
_rtDirtyFlag = false; _rtDirtyFlag = false;
#if VK_ENABLE_BARRIERS_DEBUG #if VK_ENABLE_BARRIERS_DEBUG
LOG(Warning, "Draw"); LOG(Warning, "Draw");
#endif #endif
} }
@@ -668,6 +718,7 @@ void GPUContextVulkan::FrameBegin()
_srDirtyFlag = 0; _srDirtyFlag = 0;
_uaDirtyFlag = 0; _uaDirtyFlag = 0;
_rtCount = 0; _rtCount = 0;
_vbCount = 0;
_renderPass = nullptr; _renderPass = nullptr;
_currentState = nullptr; _currentState = nullptr;
_rtDepth = nullptr; _rtDepth = nullptr;
@@ -922,6 +973,7 @@ void GPUContextVulkan::BindUA(int32 slot, GPUResourceView* view)
void GPUContextVulkan::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets) void GPUContextVulkan::BindVB(const Span<GPUBuffer*>& vertexBuffers, const uint32* vertexBuffersOffsets)
{ {
_vbCount = vertexBuffers.Length();
if (vertexBuffers.Length() == 0) if (vertexBuffers.Length() == 0)
return; return;
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer(); const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
@@ -955,7 +1007,7 @@ void GPUContextVulkan::UpdateCB(GPUConstantBuffer* cb, const void* data)
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer(); const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
// Allocate bytes for the buffer // 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 // Copy data
Platform::MemoryCopy(allocation.CPUAddress, data, allocation.Size); Platform::MemoryCopy(allocation.CPUAddress, data, allocation.Size);
@@ -1002,7 +1054,7 @@ void GPUContextVulkan::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCo
RENDER_STAT_DISPATCH_CALL(); RENDER_STAT_DISPATCH_CALL();
#if VK_ENABLE_BARRIERS_DEBUG #if VK_ENABLE_BARRIERS_DEBUG
LOG(Warning, "Dispatch"); LOG(Warning, "Dispatch");
#endif #endif
} }
@@ -1036,7 +1088,7 @@ void GPUContextVulkan::DispatchIndirect(GPUShaderProgramCS* shader, GPUBuffer* b
RENDER_STAT_DISPATCH_CALL(); RENDER_STAT_DISPATCH_CALL();
#if VK_ENABLE_BARRIERS_DEBUG #if VK_ENABLE_BARRIERS_DEBUG
LOG(Warning, "DispatchIndirect"); LOG(Warning, "DispatchIndirect");
#endif #endif
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -164,37 +164,6 @@ public:
return stageFlags; 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> template<class T>
static FORCE_INLINE void ZeroStruct(T& data, VkStructureType type) static FORCE_INLINE void ZeroStruct(T& data, VkStructureType type)
{ {

View File

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

View File

@@ -315,12 +315,12 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererPointLightD
context->ResetRenderTarget(); context->ResetRenderTarget();
const Viewport viewport = renderContext.Task->GetViewport(); const Viewport viewport = renderContext.Task->GetViewport();
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer; 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->SetViewportAndScissors(viewport);
context->BindSR(0, renderContext.Buffers->GBuffer0); context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1); context->BindSR(1, renderContext.Buffers->GBuffer1);
context->BindSR(2, renderContext.Buffers->GBuffer2); context->BindSR(2, renderContext.Buffers->GBuffer2);
context->BindSR(3, depthBufferHandle); context->BindSR(3, depthBufferSRV);
context->BindSR(4, renderContext.Buffers->GBuffer3); context->BindSR(4, renderContext.Buffers->GBuffer3);
// Setup shader data // Setup shader data
@@ -417,12 +417,12 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererSpotLightDa
context->ResetRenderTarget(); context->ResetRenderTarget();
const Viewport viewport = renderContext.Task->GetViewport(); const Viewport viewport = renderContext.Task->GetViewport();
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer; 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->SetViewportAndScissors(viewport);
context->BindSR(0, renderContext.Buffers->GBuffer0); context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1); context->BindSR(1, renderContext.Buffers->GBuffer1);
context->BindSR(2, renderContext.Buffers->GBuffer2); context->BindSR(2, renderContext.Buffers->GBuffer2);
context->BindSR(3, depthBufferHandle); context->BindSR(3, depthBufferSRV);
context->BindSR(4, renderContext.Buffers->GBuffer3); context->BindSR(4, renderContext.Buffers->GBuffer3);
// Setup shader data // Setup shader data
@@ -693,12 +693,12 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererDirectional
context->ResetRenderTarget(); context->ResetRenderTarget();
const Viewport viewport = renderContext.Task->GetViewport(); const Viewport viewport = renderContext.Task->GetViewport();
GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer; 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->SetViewportAndScissors(viewport);
context->BindSR(0, renderContext.Buffers->GBuffer0); context->BindSR(0, renderContext.Buffers->GBuffer0);
context->BindSR(1, renderContext.Buffers->GBuffer1); context->BindSR(1, renderContext.Buffers->GBuffer1);
context->BindSR(2, renderContext.Buffers->GBuffer2); context->BindSR(2, renderContext.Buffers->GBuffer2);
context->BindSR(3, depthBufferHandle); context->BindSR(3, depthBufferSRV);
context->BindSR(4, renderContext.Buffers->GBuffer3); context->BindSR(4, renderContext.Buffers->GBuffer3);
// Setup shader data // Setup shader data