Change the folder structure of the vulkan backend to better reflect what is going on
This commit is contained in:
parent
4638cc44d2
commit
295eb252ab
37 changed files with 119 additions and 110 deletions
264
src/common/rendering/vulkan/commands/vk_commandbuffer.cpp
Normal file
264
src/common/rendering/vulkan/commands/vk_commandbuffer.cpp
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
** Vulkan backend
|
||||
** Copyright (c) 2016-2020 Magnus Norddahl
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any damages
|
||||
** arising from the use of this software.
|
||||
**
|
||||
** Permission is granted to anyone to use this software for any purpose,
|
||||
** including commercial applications, and to alter it and redistribute it
|
||||
** freely, subject to the following restrictions:
|
||||
**
|
||||
** 1. The origin of this software must not be misrepresented; you must not
|
||||
** claim that you wrote the original software. If you use this software
|
||||
** in a product, an acknowledgment in the product documentation would be
|
||||
** appreciated but is not required.
|
||||
** 2. Altered source versions must be plainly marked as such, and must not be
|
||||
** misrepresented as being the original software.
|
||||
** 3. This notice may not be removed or altered from any source distribution.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "vk_commandbuffer.h"
|
||||
#include "vulkan/vk_renderdevice.h"
|
||||
#include "vulkan/vk_renderstate.h"
|
||||
#include "vulkan/vk_postprocess.h"
|
||||
#include "vulkan/framebuffers/vk_framebuffer.h"
|
||||
#include <zvulkan/vulkanswapchain.h>
|
||||
#include <zvulkan/vulkanbuilders.h>
|
||||
#include "hw_clock.h"
|
||||
#include "v_video.h"
|
||||
|
||||
extern int rendered_commandbuffers;
|
||||
int current_rendered_commandbuffers;
|
||||
|
||||
extern bool gpuStatActive;
|
||||
extern bool keepGpuStatActive;
|
||||
extern FString gpuStatOutput;
|
||||
|
||||
VkCommandBufferManager::VkCommandBufferManager(VulkanRenderDevice* fb) : fb(fb)
|
||||
{
|
||||
mCommandPool = CommandPoolBuilder()
|
||||
.QueueFamily(fb->device->GraphicsFamily)
|
||||
.DebugName("mCommandPool")
|
||||
.Create(fb->device.get());
|
||||
|
||||
for (auto& semaphore : mSubmitSemaphore)
|
||||
semaphore.reset(new VulkanSemaphore(fb->device.get()));
|
||||
|
||||
for (auto& fence : mSubmitFence)
|
||||
fence.reset(new VulkanFence(fb->device.get()));
|
||||
|
||||
for (int i = 0; i < maxConcurrentSubmitCount; i++)
|
||||
mSubmitWaitFences[i] = mSubmitFence[i]->fence;
|
||||
|
||||
if (fb->device->GraphicsTimeQueries)
|
||||
{
|
||||
mTimestampQueryPool = QueryPoolBuilder()
|
||||
.QueryType(VK_QUERY_TYPE_TIMESTAMP, MaxTimestampQueries)
|
||||
.Create(fb->device.get());
|
||||
|
||||
GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, MaxTimestampQueries);
|
||||
}
|
||||
}
|
||||
|
||||
VkCommandBufferManager::~VkCommandBufferManager()
|
||||
{
|
||||
}
|
||||
|
||||
VulkanCommandBuffer* VkCommandBufferManager::GetTransferCommands()
|
||||
{
|
||||
if (!mTransferCommands)
|
||||
{
|
||||
mTransferCommands = mCommandPool->createBuffer();
|
||||
mTransferCommands->SetDebugName("VulkanRenderDevice.mTransferCommands");
|
||||
mTransferCommands->begin();
|
||||
}
|
||||
return mTransferCommands.get();
|
||||
}
|
||||
|
||||
VulkanCommandBuffer* VkCommandBufferManager::GetDrawCommands()
|
||||
{
|
||||
if (!mDrawCommands)
|
||||
{
|
||||
mDrawCommands = mCommandPool->createBuffer();
|
||||
mDrawCommands->SetDebugName("VulkanRenderDevice.mDrawCommands");
|
||||
mDrawCommands->begin();
|
||||
}
|
||||
return mDrawCommands.get();
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::BeginFrame()
|
||||
{
|
||||
if (mNextTimestampQuery > 0)
|
||||
{
|
||||
GetDrawCommands()->resetQueryPool(mTimestampQueryPool.get(), 0, mNextTimestampQuery);
|
||||
mNextTimestampQuery = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::FlushCommands(VulkanCommandBuffer** commands, size_t count, bool finish, bool lastsubmit)
|
||||
{
|
||||
int currentIndex = mNextSubmit % maxConcurrentSubmitCount;
|
||||
|
||||
if (mNextSubmit >= maxConcurrentSubmitCount)
|
||||
{
|
||||
vkWaitForFences(fb->device->device, 1, &mSubmitFence[currentIndex]->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
|
||||
vkResetFences(fb->device->device, 1, &mSubmitFence[currentIndex]->fence);
|
||||
}
|
||||
|
||||
QueueSubmit submit;
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
submit.AddCommandBuffer(commands[i]);
|
||||
|
||||
if (mNextSubmit > 0)
|
||||
submit.AddWait(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, mSubmitSemaphore[(mNextSubmit - 1) % maxConcurrentSubmitCount].get());
|
||||
|
||||
if (finish && fb->GetFramebufferManager()->PresentImageIndex != -1)
|
||||
{
|
||||
submit.AddWait(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, fb->GetFramebufferManager()->SwapChainImageAvailableSemaphore.get());
|
||||
submit.AddSignal(fb->GetFramebufferManager()->RenderFinishedSemaphore.get());
|
||||
}
|
||||
|
||||
if (!lastsubmit)
|
||||
submit.AddSignal(mSubmitSemaphore[currentIndex].get());
|
||||
|
||||
submit.Execute(fb->device.get(), fb->device->GraphicsQueue, mSubmitFence[currentIndex].get());
|
||||
mNextSubmit++;
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::FlushCommands(bool finish, bool lastsubmit, bool uploadOnly)
|
||||
{
|
||||
if (!uploadOnly)
|
||||
fb->GetRenderState()->EndRenderPass();
|
||||
|
||||
if ((!uploadOnly && mDrawCommands) || mTransferCommands)
|
||||
{
|
||||
VulkanCommandBuffer* commands[2];
|
||||
size_t count = 0;
|
||||
|
||||
if (mTransferCommands)
|
||||
{
|
||||
mTransferCommands->end();
|
||||
commands[count++] = mTransferCommands.get();
|
||||
TransferDeleteList->Add(std::move(mTransferCommands));
|
||||
}
|
||||
|
||||
if (!uploadOnly && mDrawCommands)
|
||||
{
|
||||
mDrawCommands->end();
|
||||
commands[count++] = mDrawCommands.get();
|
||||
DrawDeleteList->Add(std::move(mDrawCommands));
|
||||
}
|
||||
|
||||
FlushCommands(commands, count, finish, lastsubmit);
|
||||
|
||||
current_rendered_commandbuffers += (int)count;
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::WaitForCommands(bool finish, bool uploadOnly)
|
||||
{
|
||||
if (finish)
|
||||
{
|
||||
Finish.Reset();
|
||||
Finish.Clock();
|
||||
|
||||
fb->GetFramebufferManager()->AcquireImage();
|
||||
}
|
||||
|
||||
FlushCommands(finish, true, uploadOnly);
|
||||
|
||||
if (finish)
|
||||
{
|
||||
fb->FPSLimit();
|
||||
fb->GetFramebufferManager()->QueuePresent();
|
||||
}
|
||||
|
||||
int numWaitFences = min(mNextSubmit, (int)maxConcurrentSubmitCount);
|
||||
|
||||
if (numWaitFences > 0)
|
||||
{
|
||||
vkWaitForFences(fb->device->device, numWaitFences, mSubmitWaitFences, VK_TRUE, std::numeric_limits<uint64_t>::max());
|
||||
vkResetFences(fb->device->device, numWaitFences, mSubmitWaitFences);
|
||||
}
|
||||
|
||||
DeleteFrameObjects(uploadOnly);
|
||||
mNextSubmit = 0;
|
||||
|
||||
if (finish)
|
||||
{
|
||||
Finish.Unclock();
|
||||
rendered_commandbuffers = current_rendered_commandbuffers;
|
||||
current_rendered_commandbuffers = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::DeleteFrameObjects(bool uploadOnly)
|
||||
{
|
||||
TransferDeleteList = std::make_unique<DeleteList>();
|
||||
if (!uploadOnly)
|
||||
DrawDeleteList = std::make_unique<DeleteList>();
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::PushGroup(const FString& name)
|
||||
{
|
||||
if (!gpuStatActive)
|
||||
return;
|
||||
|
||||
if (mNextTimestampQuery < MaxTimestampQueries && fb->device->GraphicsTimeQueries)
|
||||
{
|
||||
TimestampQuery q;
|
||||
q.name = name;
|
||||
q.startIndex = mNextTimestampQuery++;
|
||||
q.endIndex = 0;
|
||||
GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.startIndex);
|
||||
mGroupStack.push_back(timeElapsedQueries.size());
|
||||
timeElapsedQueries.push_back(q);
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::PopGroup()
|
||||
{
|
||||
if (!gpuStatActive || mGroupStack.empty())
|
||||
return;
|
||||
|
||||
TimestampQuery& q = timeElapsedQueries[mGroupStack.back()];
|
||||
mGroupStack.pop_back();
|
||||
|
||||
if (mNextTimestampQuery < MaxTimestampQueries && fb->device->GraphicsTimeQueries)
|
||||
{
|
||||
q.endIndex = mNextTimestampQuery++;
|
||||
GetDrawCommands()->writeTimestamp(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mTimestampQueryPool.get(), q.endIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void VkCommandBufferManager::UpdateGpuStats()
|
||||
{
|
||||
uint64_t timestamps[MaxTimestampQueries];
|
||||
if (mNextTimestampQuery > 0)
|
||||
mTimestampQueryPool->getResults(0, mNextTimestampQuery, sizeof(uint64_t) * mNextTimestampQuery, timestamps, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
|
||||
|
||||
double timestampPeriod = fb->device->PhysicalDevice.Properties.Properties.limits.timestampPeriod;
|
||||
|
||||
gpuStatOutput = "";
|
||||
for (auto& q : timeElapsedQueries)
|
||||
{
|
||||
if (q.endIndex <= q.startIndex)
|
||||
continue;
|
||||
|
||||
int64_t timeElapsed = max(static_cast<int64_t>(timestamps[q.endIndex] - timestamps[q.startIndex]), (int64_t)0);
|
||||
double timeNS = timeElapsed * timestampPeriod;
|
||||
|
||||
FString out;
|
||||
out.Format("%s=%04.2f ms\n", q.name.GetChars(), timeNS / 1000000.0f);
|
||||
gpuStatOutput += out;
|
||||
}
|
||||
timeElapsedQueries.clear();
|
||||
mGroupStack.clear();
|
||||
|
||||
gpuStatActive = keepGpuStatActive;
|
||||
keepGpuStatActive = false;
|
||||
}
|
||||
89
src/common/rendering/vulkan/commands/vk_commandbuffer.h
Normal file
89
src/common/rendering/vulkan/commands/vk_commandbuffer.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
|
||||
#include <zvulkan/vulkandevice.h>
|
||||
#include <zvulkan/vulkanobjects.h>
|
||||
#include "zstring.h"
|
||||
|
||||
class VulkanRenderDevice;
|
||||
|
||||
class VkCommandBufferManager
|
||||
{
|
||||
public:
|
||||
VkCommandBufferManager(VulkanRenderDevice* fb);
|
||||
~VkCommandBufferManager();
|
||||
|
||||
void BeginFrame();
|
||||
|
||||
VulkanCommandBuffer* GetTransferCommands();
|
||||
VulkanCommandBuffer* GetDrawCommands();
|
||||
|
||||
void FlushCommands(bool finish, bool lastsubmit = false, bool uploadOnly = false);
|
||||
|
||||
void WaitForCommands(bool finish) { WaitForCommands(finish, false); }
|
||||
void WaitForCommands(bool finish, bool uploadOnly);
|
||||
|
||||
void PushGroup(const FString& name);
|
||||
void PopGroup();
|
||||
void UpdateGpuStats();
|
||||
|
||||
class DeleteList
|
||||
{
|
||||
public:
|
||||
std::vector<std::unique_ptr<VulkanBuffer>> Buffers;
|
||||
std::vector<std::unique_ptr<VulkanSampler>> Samplers;
|
||||
std::vector<std::unique_ptr<VulkanImage>> Images;
|
||||
std::vector<std::unique_ptr<VulkanImageView>> ImageViews;
|
||||
std::vector<std::unique_ptr<VulkanFramebuffer>> Framebuffers;
|
||||
std::vector<std::unique_ptr<VulkanAccelerationStructure>> AccelStructs;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorPool>> DescriptorPools;
|
||||
std::vector<std::unique_ptr<VulkanDescriptorSet>> Descriptors;
|
||||
std::vector<std::unique_ptr<VulkanShader>> Shaders;
|
||||
std::vector<std::unique_ptr<VulkanCommandBuffer>> CommandBuffers;
|
||||
size_t TotalSize = 0;
|
||||
|
||||
void Add(std::unique_ptr<VulkanBuffer> obj) { if (obj) { TotalSize += obj->size; Buffers.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanSampler> obj) { if (obj) { Samplers.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanImage> obj) { if (obj) { Images.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanImageView> obj) { if (obj) { ImageViews.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanFramebuffer> obj) { if (obj) { Framebuffers.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanAccelerationStructure> obj) { if (obj) { AccelStructs.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanDescriptorPool> obj) { if (obj) { DescriptorPools.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanDescriptorSet> obj) { if (obj) { Descriptors.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanCommandBuffer> obj) { if (obj) { CommandBuffers.push_back(std::move(obj)); } }
|
||||
void Add(std::unique_ptr<VulkanShader> obj) { if (obj) { Shaders.push_back(std::move(obj)); } }
|
||||
};
|
||||
|
||||
std::unique_ptr<DeleteList> TransferDeleteList = std::make_unique<DeleteList>();
|
||||
std::unique_ptr<DeleteList> DrawDeleteList = std::make_unique<DeleteList>();
|
||||
|
||||
void DeleteFrameObjects(bool uploadOnly = false);
|
||||
|
||||
private:
|
||||
void FlushCommands(VulkanCommandBuffer** commands, size_t count, bool finish, bool lastsubmit);
|
||||
|
||||
VulkanRenderDevice* fb = nullptr;
|
||||
|
||||
std::unique_ptr<VulkanCommandPool> mCommandPool;
|
||||
|
||||
std::unique_ptr<VulkanCommandBuffer> mTransferCommands;
|
||||
std::unique_ptr<VulkanCommandBuffer> mDrawCommands;
|
||||
|
||||
enum { maxConcurrentSubmitCount = 8 };
|
||||
std::unique_ptr<VulkanSemaphore> mSubmitSemaphore[maxConcurrentSubmitCount];
|
||||
std::unique_ptr<VulkanFence> mSubmitFence[maxConcurrentSubmitCount];
|
||||
VkFence mSubmitWaitFences[maxConcurrentSubmitCount];
|
||||
int mNextSubmit = 0;
|
||||
|
||||
struct TimestampQuery
|
||||
{
|
||||
FString name;
|
||||
uint32_t startIndex;
|
||||
uint32_t endIndex;
|
||||
};
|
||||
|
||||
enum { MaxTimestampQueries = 100 };
|
||||
std::unique_ptr<VulkanQueryPool> mTimestampQueryPool;
|
||||
int mNextTimestampQuery = 0;
|
||||
std::vector<size_t> mGroupStack;
|
||||
std::vector<TimestampQuery> timeElapsedQueries;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue