Improve stability of Vulkan and D3D12 backends on large worlds
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ private:
|
||||
void flushCBs();
|
||||
void flushRBs();
|
||||
void flushPS();
|
||||
void onDrawCall();
|
||||
void OnDrawCall();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -152,6 +152,11 @@ public:
|
||||
/// </summary>
|
||||
const SpirvShaderDescriptorInfo* DescriptorInfoPerStage[DescriptorSet::GraphicsStagesCount];
|
||||
|
||||
const VkPipelineVertexInputStateCreateInfo* GetVertexInputState() const
|
||||
{
|
||||
return _desc.pVertexInputState;
|
||||
}
|
||||
|
||||
DescriptorSetWriteContainerVulkan DSWriteContainer;
|
||||
DescriptorSetWriterVulkan DSWriter[DescriptorSet::GraphicsStagesCount];
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
Allocation Allocate(uint64 size, uint32 alignment, CmdBufferVulkan* cmdBuffer);
|
||||
Allocation Allocate(uint64 size, uint32 alignment, GPUContextVulkan* context);
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user