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