diff --git a/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp
index 3721abbb2..4110f86c6 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp
@@ -289,7 +289,7 @@ void CmdBufferManagerVulkan::SubmitActiveCmdBuffer(SemaphoreVulkan* signalSemaph
}
#else
for (int32 i = 0; i < _activeTimerQueries.Count(); i++)
- queries->Interrupt(_activeCmdBuffer);
+ queries[i]->Interrupt(_context);
#endif
#endif
@@ -347,7 +347,7 @@ void CmdBufferManagerVulkan::GetNewActiveCommandBuffer()
#else
for (int32 i = 0; i < _activeTimerQueries.Count(); i++)
{
- queries->Resume(_activeCmdBuffer);
+ queries[i]->Resume(_context);
}
#endif
#endif
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
index 5fc45fd22..c1f25ecab 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
@@ -437,6 +437,7 @@ void GPUContextVulkan::BeginRenderPass()
// Build render targets layout descriptor and framebuffer key
FramebufferVulkan::Key framebufferKey;
+ Platform::MemoryClear(&framebufferKey, sizeof(framebufferKey));
framebufferKey.AttachmentCount = _rtCount;
RenderTargetLayoutVulkan layout;
Platform::MemoryClear(&layout, sizeof(layout));
@@ -445,7 +446,7 @@ void GPUContextVulkan::BeginRenderPass()
layout.DepthFormat = _rtDepth ? _rtDepth->GetFormat() : PixelFormat::Unknown;
VkClearValue clearValues[GPU_MAX_RT_BINDED + 1];
PendingClear clear;
- for (int32 i = 0; i < GPU_MAX_RT_BINDED; i++)
+ for (int32 i = 0; i < _rtCount; i++)
{
auto handle = _rtTargets[i];
if (handle)
@@ -470,11 +471,6 @@ void GPUContextVulkan::BeginRenderPass()
layout.StoreDontCare |= mask;
}
}
- else
- {
- layout.RTVsFormats[i] = PixelFormat::Unknown;
- framebufferKey.Attachments[i] = VK_NULL_HANDLE;
- }
}
GPUTextureViewVulkan* handle;
if (_rtDepth)
@@ -536,6 +532,7 @@ void GPUContextVulkan::BeginRenderPass()
FlushBarriers();
cmdBuffer->BeginRenderPass(renderPass, framebuffer, ARRAY_COUNT(clearValues), clearValues);
+ _rtDirtyFlag = false;
}
void GPUContextVulkan::EndRenderPass()
@@ -802,7 +799,7 @@ void GPUContextVulkan::OnDrawCall()
}
// Allocate sets if need to
- //if (needsWrite) // TODO: write on change only?
+ if (needsWrite)
{
if (!pipelineState->CurrentTypedDescriptorPoolSet->AllocateDescriptorSets(*pipelineState->DescriptorSetsLayout, pipelineState->DescriptorSetHandles.Get()))
return;
@@ -862,7 +859,6 @@ void GPUContextVulkan::OnDrawCall()
vkCmdBindDescriptorSets(cmdBuffer->GetHandle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineState->GetLayout()->Handle, 0, descriptorSets.Count(), descriptorSets.Get(), dynamicOffsets.Count(), dynamicOffsets.Get());
}
- _rtDirtyFlag = false;
#if VK_ENABLE_BARRIERS_DEBUG
LOG(Warning, "Draw");
#endif
@@ -904,7 +900,7 @@ void GPUContextVulkan::FrameBegin()
if (_device->QueriesToReset.HasItems())
{
for (auto query : _device->QueriesToReset)
- query->Reset(cmdBuffer);
+ query->Reset(this);
_device->QueriesToReset.Clear();
}
#endif
@@ -1442,7 +1438,7 @@ uint64 GPUContextVulkan::BeginQuery(GPUQueryType type)
auto pool = _device->QueryPools[poolIndex];
uint32 index = 0;
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
- if (!pool->AcquireQuery(cmdBuffer, index))
+ if (!pool->AcquireQuery(this, index))
return 0;
GPUQueryVulkan query;
query.PoolIndex = (uint16)poolIndex;
@@ -1455,19 +1451,21 @@ uint64 GPUContextVulkan::BeginQuery(GPUQueryType type)
{
case GPUQueryType::Timer:
// Timer queries need 2 slots (begin + end)
- pool->AcquireQuery(cmdBuffer, index);
+ pool->AcquireQuery(this, index);
query.SecondQueryIndex = (uint16)index;
-
vkCmdWriteTimestamp(cmdBuffer->GetHandle(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, pool->GetHandle(), query.QueryIndex);
#if GPU_VULKAN_PAUSE_QUERIES
_cmdBufferManager->OnTimerQueryBegin(query.Raw);
#endif
break;
case GPUQueryType::Occlusion:
- vkCmdBeginQuery(cmdBuffer->GetHandle(), pool->GetHandle(), query.QueryIndex, 0);
- break;
case GPUQueryType::BinaryOcclusion:
- vkCmdBeginQuery(cmdBuffer->GetHandle(), pool->GetHandle(), query.QueryIndex, VK_QUERY_CONTROL_PRECISE_BIT);
+ // Flush render pass when starting occlusion query
+ if (_rtDirtyFlag && cmdBuffer->IsInsideRenderPass())
+ EndRenderPass();
+ if (cmdBuffer->IsOutsideRenderPass())
+ BeginRenderPass();
+ vkCmdBeginQuery(cmdBuffer->GetHandle(), pool->GetHandle(), query.QueryIndex, type == GPUQueryType::Occlusion ? VK_QUERY_CONTROL_PRECISE_BIT : 0);
break;
}
pool->MarkQueryAsStarted(query.QueryIndex);
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
index 43d37aebd..29cfb5633 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
@@ -527,7 +527,7 @@ RenderPassVulkan::RenderPassVulkan(GPUDeviceVulkan* device, const RenderTargetLa
: Device(device)
, Handle(VK_NULL_HANDLE)
, Layout(layout)
- , CanDepthWrite(true)
+ , CanDepthStencilWrite(true)
{
const int32 colorAttachmentsCount = layout.RTsCount;
const bool hasDepthStencilAttachment = layout.DepthFormat != PixelFormat::Unknown;
@@ -615,7 +615,7 @@ RenderPassVulkan::RenderPassVulkan(GPUDeviceVulkan* device, const RenderTargetLa
depthStencilReference.layout = depthStencilLayout;
subpassDesc.pDepthStencilAttachment = &depthStencilReference;
if (!layout.WriteDepth && !layout.WriteStencil)
- CanDepthWrite = false;
+ CanDepthStencilWrite = false;
}
VkRenderPassCreateInfo createInfo;
@@ -642,7 +642,7 @@ QueryPoolVulkan::QueryPoolVulkan(GPUDeviceVulkan* device, int32 capacity, GPUQue
{
VkQueryPoolCreateInfo createInfo;
RenderToolsVulkan::ZeroStruct(createInfo, VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO);
- createInfo.queryType = type != GPUQueryType::Timer ? VK_QUERY_TYPE_TIMESTAMP : VK_QUERY_TYPE_OCCLUSION;
+ createInfo.queryType = type == GPUQueryType::Timer ? VK_QUERY_TYPE_TIMESTAMP : VK_QUERY_TYPE_OCCLUSION;
createInfo.queryCount = capacity;
VALIDATE_VULKAN_RESULT(vkCreateQueryPool(device->Device, &createInfo, nullptr, &_handle));
@@ -663,11 +663,18 @@ QueryPoolVulkan::~QueryPoolVulkan()
#if VULKAN_RESET_QUERY_POOLS
-void QueryPoolVulkan::Reset(CmdBufferVulkan* cmdBuffer)
+void QueryPoolVulkan::Reset(GPUContextVulkan* context)
{
+ if (_resetRanges.IsEmpty())
+ return;
+ const auto cmdBuffer = context->GetCmdBufferManager()->GetCmdBuffer();
+ if (cmdBuffer->IsInsideRenderPass())
+ context->EndRenderPass(); // vkCmdResetQueryPool can be called only outside the render pass
+ // TODO: batch sequential reset operations
+ auto commandBuffer = cmdBuffer->GetHandle();
for (auto& range : _resetRanges)
{
- vkCmdResetQueryPool(cmdBuffer->GetHandle(), _handle, range.Start, range.Count);
+ vkCmdResetQueryPool(commandBuffer, _handle, range.Start, range.Count);
}
_resetRanges.Clear();
ResetBeforeUse = false;
@@ -684,7 +691,7 @@ BufferedQueryPoolVulkan::BufferedQueryPoolVulkan(GPUDeviceVulkan* device, int32
_readResultsBits.AddZeroed((capacity + 63) / 64);
}
-bool BufferedQueryPoolVulkan::AcquireQuery(CmdBufferVulkan* cmdBuffer, uint32& resultIndex)
+bool BufferedQueryPoolVulkan::AcquireQuery(GPUContextVulkan* context, uint32& resultIndex)
{
const uint64 allUsedMask = MAX_uint64;
for (int32 wordIndex = _lastBeginIndex / 64; wordIndex < _usedQueryBits.Count(); wordIndex++)
@@ -705,7 +712,7 @@ bool BufferedQueryPoolVulkan::AcquireQuery(CmdBufferVulkan* cmdBuffer, uint32& r
_readResultsBits[wordIndex] &= ~bit;
_lastBeginIndex = resultIndex + 1;
if (ResetBeforeUse)
- Reset(cmdBuffer);
+ Reset(context);
_lastUsedFrame = Engine::FrameCount;
return true;
}
@@ -757,6 +764,7 @@ bool BufferedQueryPoolVulkan::GetResults(uint32 index, uint64& result)
if ((_startedQueryBits[word] & bit) == 0)
{
// Query never started/ended
+ result = 0;
return true;
}
@@ -809,27 +817,23 @@ bool BufferedQueryPoolVulkan::TryExpire()
return false;
// Reset back to clean state all unfinished queries
- for (uint32 index = 0; index < _queryOutput.Count(); index++)
+ bool canUseNow = true;
+ for (uint32 index = 0; index < (uint32)_queryOutput.Count(); index++)
{
const uint64 bit = (uint64)1 << (index % 64);
const uint32 word = index / 64;
if ((_usedQueryBits[word] & bit) == 0)
continue;
+#if VULKAN_RESET_QUERY_POOLS
if ((_readResultsBits[word] & bit) == 0)
{
- const VkResult vkResult = vkGetQueryPoolResults(_device->Device, _handle, index, 1, sizeof(uint64), &_queryOutput[index], sizeof(uint64), VK_QUERY_RESULT_64_BIT);
- if (vkResult == VK_SUCCESS)
- {
- _readResultsBits[word] = _readResultsBits[word] | bit;
-
-#if VULKAN_RESET_QUERY_POOLS
- // Add to reset
- if (!_device->QueriesToReset.Contains(this))
- _device->QueriesToReset.Add(this);
- _resetRanges.Add(Range{ index, 1 });
-#endif
- }
+ // Add to reset
+ if (!_device->QueriesToReset.Contains(this))
+ _device->QueriesToReset.Add(this);
+ _resetRanges.Add(Range{ index, 1 });
+ canUseNow = false;
}
+#endif
_usedQueryBits[word] = _usedQueryBits[word] & ~bit;
}
constexpr uint64 allUsedMask = MAX_uint64;
@@ -842,7 +846,7 @@ bool BufferedQueryPoolVulkan::TryExpire()
}
}
- return HasRoom();
+ return canUseNow && HasRoom();
}
HelperResourcesVulkan::HelperResourcesVulkan(GPUDeviceVulkan* device)
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h
index b1cafeea7..dfc5b38ee 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h
@@ -260,7 +260,7 @@ public:
GPUDeviceVulkan* Device;
VkRenderPass Handle;
RenderTargetLayoutVulkan Layout;
- bool CanDepthWrite;
+ bool CanDepthStencilWrite;
#if VULKAN_USE_DEBUG_DATA
VkRenderPassCreateInfo DebugCreateInfo;
#endif
@@ -299,7 +299,7 @@ public:
#if VULKAN_RESET_QUERY_POOLS
bool ResetBeforeUse;
- void Reset(CmdBufferVulkan* cmdBuffer);
+ void Reset(GPUContextVulkan* context);
#endif
};
@@ -318,7 +318,7 @@ private:
public:
BufferedQueryPoolVulkan(GPUDeviceVulkan* device, int32 capacity, GPUQueryType type);
- bool AcquireQuery(CmdBufferVulkan* cmdBuffer, uint32& resultIndex);
+ bool AcquireQuery(GPUContextVulkan* context, uint32& resultIndex);
void ReleaseQuery(uint32 queryIndex);
void MarkQueryAsStarted(uint32 queryIndex);
bool GetResults(uint32 index, uint64& result);
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp
index ec28b4c56..ead7a1102 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp
@@ -315,10 +315,13 @@ VkPipeline GPUPipelineStateVulkan::GetState(RenderPassVulkan* renderPass, GPUVer
// Create object
auto depthWrite = _descDepthStencil.depthWriteEnable;
- _descDepthStencil.depthWriteEnable &= renderPass->CanDepthWrite ? 1 : 0;
+ auto stencilWriteMask = _descDepthStencil.front.writeMask;
+ _descDepthStencil.depthWriteEnable &= renderPass->CanDepthStencilWrite ? 1 : 0;
+ _descDepthStencil.front.writeMask &= renderPass->CanDepthStencilWrite ? MAX_uint32 : 0;
const VkResult result = vkCreateGraphicsPipelines(_device->Device, _device->PipelineCache, 1, &_desc, nullptr, &pipeline);
_device->PipelineCacheUsage++;
_descDepthStencil.depthWriteEnable = depthWrite;
+ _descDepthStencil.front.writeMask = _descDepthStencil.back.writeMask = stencilWriteMask;
LOG_VULKAN_RESULT(result);
if (result != VK_SUCCESS)
{
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp
index da2361030..1bf1ec859 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp
@@ -642,7 +642,7 @@ void GPUSwapChainVulkan::Present(bool vsync)
// Cache a command buffer to wait on its fence before drawing to this backbuffer again
auto& acquiredBackBuffer = _backBuffers[_acquiredImageIndex];
- ASSERT(acquiredBackBuffer.SubmitCmdBuffer == nullptr || !acquiredBackBuffer.SubmitCmdBuffer->IsSubmitted());
+ ASSERT(acquiredBackBuffer.SubmitCmdBuffer == nullptr || acquiredBackBuffer.SubmitCmdBuffer->IsSubmitted());
acquiredBackBuffer.SubmitCmdBuffer = context->GetCmdBufferManager()->GetActiveCmdBuffer();
context->GetCmdBufferManager()->SubmitActiveCmdBuffer(_backBuffers[_acquiredImageIndex].RenderingDoneSemaphore);
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUTimerQueryVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUTimerQueryVulkan.cpp
index ecd0dbdfe..38ea8be12 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUTimerQueryVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUTimerQueryVulkan.cpp
@@ -83,16 +83,16 @@ float GPUTimerQueryVulkan::GetResult()
#else
-void GPUTimerQueryVulkan::Interrupt(CmdBufferVulkan* cmdBuffer)
+void GPUTimerQueryVulkan::Interrupt(GPUContextVulkan* context)
{
if (!_interrupted)
{
_interrupted = true;
- WriteTimestamp(cmdBuffer, _queries[_queryIndex].End, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
+ WriteTimestamp(context, _queries[_queryIndex].End, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
}
}
-void GPUTimerQueryVulkan::Resume(CmdBufferVulkan* cmdBuffer)
+void GPUTimerQueryVulkan::Resume(GPUContextVulkan* context)
{
ASSERT(_interrupted);
@@ -100,7 +100,7 @@ void GPUTimerQueryVulkan::Resume(CmdBufferVulkan* cmdBuffer)
e.End.Pool = nullptr;
_interrupted = false;
- WriteTimestamp(cmdBuffer, e.Begin, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
+ WriteTimestamp(context, e.Begin, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
_queries.Add(e);
_queryIndex++;
@@ -127,13 +127,13 @@ bool GPUTimerQueryVulkan::GetResult(Query& query)
return false;
}
-void GPUTimerQueryVulkan::WriteTimestamp(CmdBufferVulkan* cmdBuffer, Query& query, VkPipelineStageFlagBits stage) const
+void GPUTimerQueryVulkan::WriteTimestamp(GPUContextVulkan* context, Query& query, VkPipelineStageFlagBits stage) const
{
auto pool = _device->QueryPools[_device->GetOrCreateQueryPool(GPUQueryType::Timer)];
uint32 index;
- if (pool->AcquireQuery(cmdBuffer, index))
+ if (pool->AcquireQuery(context, index))
{
- vkCmdWriteTimestamp(cmdBuffer->GetHandle(), stage, pool->GetHandle(), index);
+ vkCmdWriteTimestamp(context->GetCmdBufferManager()->GetCmdBuffer()->GetHandle(), stage, pool->GetHandle(), index);
pool->MarkQueryAsStarted(index);
query.Pool = pool;
query.Index = index;
@@ -215,14 +215,13 @@ void GPUTimerQueryVulkan::Begin()
if (UseQueries())
{
const auto context = (GPUContextVulkan*)_device->GetMainContext();
- const auto cmdBuffer = context->GetCmdBufferManager()->GetCmdBuffer();
QueryPair e;
e.End.Pool = nullptr;
_queryIndex = 0;
_interrupted = false;
- WriteTimestamp(cmdBuffer, e.Begin, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
+ WriteTimestamp(context, e.Begin, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
context->GetCmdBufferManager()->OnTimerQueryBegin(this);
ASSERT(_queries.IsEmpty());
@@ -241,11 +240,10 @@ void GPUTimerQueryVulkan::End()
if (UseQueries())
{
const auto context = (GPUContextVulkan*)_device->GetMainContext();
- const auto cmdBuffer = context->GetCmdBufferManager()->GetCmdBuffer();
if (!_interrupted)
{
- WriteTimestamp(cmdBuffer, _queries[_queryIndex].End, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
+ WriteTimestamp(context, _queries[_queryIndex].End, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
}
context->GetCmdBufferManager()->OnTimerQueryEnd(this);
}
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUTimerQueryVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUTimerQueryVulkan.h
index 07a263fe3..372cfc084 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUTimerQueryVulkan.h
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUTimerQueryVulkan.h
@@ -51,20 +51,20 @@ public:
#if !GPU_VULKAN_QUERY_NEW
public:
///
- /// Interrupts an in-progress query, allowing the command buffer to submitted. Interrupted queries must be resumed using Resume().
+ /// Interrupts an in-progress query, allowing the command buffer to submit. Interrupted queries must be resumed using Resume().
///
- /// The GPU commands buffer.
- void Interrupt(CmdBufferVulkan* cmdBuffer);
+ /// The GPU context.
+ void Interrupt(GPUContextVulkan* context);
///
/// Resumes an interrupted query, restoring it back to its original in-progress state.
///
- /// The GPU commands buffer.
- void Resume(CmdBufferVulkan* cmdBuffer);
+ /// The GPU context.
+ void Resume(GPUContextVulkan* context);
private:
bool GetResult(Query& query);
- void WriteTimestamp(CmdBufferVulkan* cmdBuffer, Query& query, VkPipelineStageFlagBits stage) const;
+ void WriteTimestamp(GPUContextVulkan* context, Query& query, VkPipelineStageFlagBits stage) const;
bool TryGetResult();
bool UseQueries();
#endif