Add code to allow for depth buffer query (Fixes #18)

This commit is contained in:
Georg Hagen
2024-08-01 10:29:07 +02:00
parent 579c4bcca1
commit e54404ec61
8 changed files with 171 additions and 16 deletions

View File

@@ -35,5 +35,8 @@ namespace OpenVulkano
virtual Scene::UI::Ui* GetActiveUi() = 0; virtual Scene::UI::Ui* GetActiveUi() = 0;
virtual IResourceManager* GetIResourceManager() = 0; virtual IResourceManager* GetIResourceManager() = 0;
virtual float GetLastQueriedDepthValue() = 0;
virtual void SetQueryDepthValue(const Math::Vector2f& depthCoordinates) = 0;
}; };
} }

View File

@@ -0,0 +1,96 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "DepthBufferQuery.hpp"
#include "Renderer.hpp"
#include <vulkan/vulkan.hpp>
//TODO resize
namespace OpenVulkano::Vulkan
{
void DepthBufferQuery::Init()
{
auto device = renderer.GetContext().device->device;
vk::BufferCreateInfo bufferInfo = { {}, 25 * sizeof(float), vk::BufferUsageFlagBits::eTransferDst };
bufferDepth = device.createBuffer(bufferInfo);
const vk::MemoryRequirements memRequirements = device.getBufferMemoryRequirements(bufferDepth);
size_t size = memRequirements.size;
const vk::MemoryAllocateInfo memAllocInfo = { size, renderer.GetContext().device->GetMemoryType(memRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible) };
memory = device.allocateMemory(memAllocInfo);
cpuDepthBuffer = static_cast<float*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE, {}));
device.bindBufferMemory(bufferDepth, memory, 0);
}
void DepthBufferQuery::Close()
{
auto device = renderer.GetContext().device->device;
device.destroy(bufferDepth);
device.unmapMemory(memory);
device.free(memory);
cpuDepthBuffer = nullptr;
}
void DepthBufferQuery::Resize(uint32_t width, uint32_t height)
{
//TODO
}
float DepthBufferQuery::GetQueriedValue() const
{
if (cpuDepthBuffer[0] == -2) return -2;
if (cpuDepthBuffer[12] > 0 && cpuDepthBuffer[12] < 1) return cpuDepthBuffer[12];
double val = 0;
int validCount = 0;
for (int i = 0; i < 25; i++)
{
float f = cpuDepthBuffer[i];
if (f > 0 && f < 1)
{
val += f;
validCount++;
}
}
if (validCount == 0) return 1; // Prevent divide by 0
return val / validCount;
}
vk::Offset3D DepthBufferQuery::GetCopyOffset() const
{
vk::Extent3D depthExtent = renderer.GetContext().swapChain.GetCurrentDepthBuffer().extent;
int32_t x = static_cast<int32_t>(depthQueryCoordinates.x * depthExtent.width);
x = std::min<int32_t>(depthExtent.width - 5, std::max(0, x));
int32_t y = static_cast<int32_t>(depthQueryCoordinates.y * depthExtent.height);
y = std::min<int32_t>(depthExtent.height - 5, std::max(0, y));
return { x, y, 0 };
}
void DepthBufferQuery::Encode(vk::CommandBuffer& commandBuffer)
{
if (!copyDepthBuffer) return;
copyDepthBuffer = false;
std::fill(cpuDepthBuffer, cpuDepthBuffer + 25, -2.0f); // Invalidate data in buffer to allow detecting if copy is done
const vk::ImageAspectFlags aspectMask = vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil;
const Image& depthBufferImage = renderer.GetContext().swapChain.GetCurrentDepthBuffer();
constexpr vk::Extent3D copySize = { 5, 5, 1 };
const vk::ImageSubresourceLayers layout = { vk::ImageAspectFlagBits::eDepth, 0, 0, 1 };
vk::BufferImageCopy imgCopy = { 0, 5, 5, layout, GetCopyOffset(), copySize };
const vk::ImageMemoryBarrier imgMemBarrier({}, vk::AccessFlagBits::eTransferRead, vk::ImageLayout::eDepthStencilAttachmentOptimal, vk::ImageLayout::eTransferSrcOptimal, 0, 0, depthBufferImage.image, vk::ImageSubresourceRange(aspectMask, 0, 1, 0, 1));
commandBuffer.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, nullptr, nullptr, imgMemBarrier);
commandBuffer.copyImageToBuffer(depthBufferImage.image, vk::ImageLayout::eTransferSrcOptimal, bufferDepth, 1, &imgCopy);
depthBufferImage.SetLayout(commandBuffer, aspectMask, vk::ImageLayout::eDepthStencilAttachmentOptimal, vk::ImageLayout::eTransferSrcOptimal);
}
}

View File

@@ -0,0 +1,48 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "Math/Math.hpp"
#include "Vulkan/Image.hpp"
namespace OpenVulkano::Vulkan
{
class Renderer;
class DepthBufferQuery final
{
Renderer& renderer;
vk::DeviceMemory memory;
vk::Buffer bufferDepth;
float* cpuDepthBuffer = nullptr;
Math::Vector2f depthQueryCoordinates = { 0.5f, 0.5f };
bool copyDepthBuffer = true;
vk::Offset3D GetCopyOffset() const;
public:
DepthBufferQuery(Renderer& renderer): renderer(renderer) {}
~DepthBufferQuery() { if (cpuDepthBuffer != nullptr) Close(); }
void Init();
void Close();
void Encode(vk::CommandBuffer& commandBuffer);
void Resize(uint32_t width, uint32_t height);
float GetQueriedValue() const;
void SetQueryCoordinates(const Math::Vector2f& coords)
{
copyDepthBuffer = true;
depthQueryCoordinates = coords;
}
};
}

View File

@@ -90,5 +90,7 @@ namespace OpenVulkano::Vulkan
[[nodiscard]] const vk::Viewport& GetFullscreenViewport() const { return fullscreenViewport; } [[nodiscard]] const vk::Viewport& GetFullscreenViewport() const { return fullscreenViewport; }
[[nodiscard]] const vk::Rect2D& GetFullscreenScissor() const { return fullscreenScissor; } [[nodiscard]] const vk::Rect2D& GetFullscreenScissor() const { return fullscreenScissor; }
[[nodiscard]] const Image& GetCurrentDepthBuffer() { return depthBuffer; }
}; };
} }

View File

@@ -57,7 +57,7 @@ namespace OpenVulkano::Vulkan
if (m_frameBuffer->UseDepthBuffer()) if (m_frameBuffer->UseDepthBuffer())
{ // Depth attachment { // Depth attachment
attachments.emplace_back(vk::AttachmentDescriptionFlags(), m_frameBuffer->GetDepthFormat(), vk::SampleCountFlagBits::e1, attachments.emplace_back(vk::AttachmentDescriptionFlags(), m_frameBuffer->GetDepthFormat(), vk::SampleCountFlagBits::e1,
m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eDontCare, m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eStore, m_useClearDepth ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eDepthStencilAttachmentOptimal, vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eDepthStencilAttachmentOptimal, vk::ImageLayout::eDepthStencilAttachmentOptimal);
depthReference = new vk::AttachmentReference(1, vk::ImageLayout::eDepthStencilAttachmentOptimal); depthReference = new vk::AttachmentReference(1, vk::ImageLayout::eDepthStencilAttachmentOptimal);
} }
@@ -87,4 +87,4 @@ namespace OpenVulkano::Vulkan
{ {
renderPass = m_device.createRenderPass(renderPassCreateInfo); renderPass = m_device.createRenderPass(renderPassCreateInfo);
} }
} }

View File

@@ -18,6 +18,11 @@
namespace OpenVulkano::Vulkan namespace OpenVulkano::Vulkan
{ {
Renderer::Renderer()
: depthBufferQuery(*this)
{
}
void Renderer::Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) void Renderer::Init(IGraphicsAppManager* graphicsAppManager, IWindow* window)
{ {
logger = Logger::RENDER; logger = Logger::RENDER;
@@ -62,6 +67,8 @@ namespace OpenVulkano::Vulkan
} }
} }
depthBufferQuery.Init();
logger->info("Vulkan renderer initialized"); logger->info("Vulkan renderer initialized");
} }
@@ -87,6 +94,7 @@ namespace OpenVulkano::Vulkan
closeables.pop_back(); closeables.pop_back();
closeable->Close(); closeable->Close();
} }
depthBufferQuery.Close();
uiRenderer.Close(); uiRenderer.Close();
resourceManager.Close(); resourceManager.Close();
commands.clear(); commands.clear();
@@ -138,6 +146,7 @@ namespace OpenVulkano::Vulkan
CommandHelper* cmdHelper = GetCommandData(commands.size() - 1); CommandHelper* cmdHelper = GetCommandData(commands.size() - 1);
cmdHelper->cmdBuffer.executeCommands(submitBuffers[currentImageId].size(), submitBuffers[currentImageId].data()); cmdHelper->cmdBuffer.executeCommands(submitBuffers[currentImageId].size(), submitBuffers[currentImageId].data());
context.swapChainRenderPass.End(cmdHelper->cmdBuffer); context.swapChainRenderPass.End(cmdHelper->cmdBuffer);
depthBufferQuery.Encode(cmdHelper->cmdBuffer);
uiRenderer.DrawUiFrame(cmdHelper->cmdBuffer); uiRenderer.DrawUiFrame(cmdHelper->cmdBuffer);
cmdHelper->cmdBuffer.end(); cmdHelper->cmdBuffer.end();
std::array<vk::PipelineStageFlags, 2> stateFlags = { vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput), vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput) }; std::array<vk::PipelineStageFlags, 2> stateFlags = { vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput), vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput) };

View File

@@ -16,6 +16,7 @@
#include "CommandHelper.hpp" #include "CommandHelper.hpp"
#include "Base/EngineConfiguration.hpp" #include "Base/EngineConfiguration.hpp"
#include "Resources/ResourceManager.hpp" #include "Resources/ResourceManager.hpp"
#include "DepthBufferQuery.hpp"
#include <vector> #include <vector>
#include <thread> #include <thread>
@@ -40,9 +41,10 @@ namespace OpenVulkano::Vulkan
std::vector<std::vector<vk::CommandBuffer>> submitBuffers; std::vector<std::vector<vk::CommandBuffer>> submitBuffers;
UiRenderer uiRenderer; UiRenderer uiRenderer;
std::vector<ICloseable*> closeables; std::vector<ICloseable*> closeables;
DepthBufferQuery depthBufferQuery;
public: public:
Renderer() = default; Renderer();
~Renderer() override = default; ~Renderer() override = default;
void Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) override; void Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) override;
@@ -86,5 +88,9 @@ namespace OpenVulkano::Vulkan
void UnregisterCloseable(ICloseable* closeable) { Utils::Remove(closeables, closeable); } void UnregisterCloseable(ICloseable* closeable) { Utils::Remove(closeables, closeable); }
IResourceManager* GetIResourceManager() override { return &resourceManager; } IResourceManager* GetIResourceManager() override { return &resourceManager; }
float GetLastQueriedDepthValue() override { return depthBufferQuery.GetQueriedValue(); }
void SetQueryDepthValue(const Math::Vector2f& depthCoordinates) override { depthBufferQuery.SetQueryCoordinates(depthCoordinates); }
}; };
} }

View File

@@ -45,7 +45,7 @@ namespace OpenVulkano
vk::PresentModeKHR presentMode; vk::PresentModeKHR presentMode;
std::vector<vk::Semaphore> imageAvailableSemaphores; std::vector<vk::Semaphore> imageAvailableSemaphores;
uint32_t currentSemaphoreId = 0; uint32_t currentSemaphoreId = 0;
vk::Extent2D size{0,0}; vk::Extent2D size{ 0, 0 };
public: public:
vk::SwapchainKHR swapChain; vk::SwapchainKHR swapChain;
@@ -59,10 +59,7 @@ namespace OpenVulkano
void Resize(uint32_t newWidth, uint32_t newHeight); void Resize(uint32_t newWidth, uint32_t newHeight);
[[nodiscard]] vk::Extent2D GetSize() const [[nodiscard]] vk::Extent2D GetSize() const { return size; }
{
return size;
}
uint32_t AcquireNextImage(const vk::Fence& fence = vk::Fence()); uint32_t AcquireNextImage(const vk::Fence& fence = vk::Fence());
@@ -81,10 +78,7 @@ namespace OpenVulkano
} }
} }
[[nodiscard]] uint32_t GetImageCount() const [[nodiscard]] uint32_t GetImageCount() const { return images.size(); }
{
return images.size();
}
vk::Semaphore& GetCurrentSemaphore() { return imageAvailableSemaphores[currentSemaphoreId]; } vk::Semaphore& GetCurrentSemaphore() { return imageAvailableSemaphores[currentSemaphoreId]; }
@@ -96,10 +90,7 @@ namespace OpenVulkano
void DestroySwapChain(); void DestroySwapChain();
protected: protected:
vk::Format FindColorFormat() override [[nodiscard]] vk::Format FindColorFormat() override { return surfaceFormat.format; }
{
return surfaceFormat.format;
}
virtual vk::PresentModeKHR ChosePresentMode(); virtual vk::PresentModeKHR ChosePresentMode();