looks like command buffers need to be externally synchronized
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include "MaterialLoader.h"
|
||||
#include "MeshLoader.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Graphics/Mesh.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "MeshAsset.h"
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Seele
|
||||
}
|
||||
allocator = other.allocator;
|
||||
}
|
||||
if(other.arraySize > allocated)
|
||||
if(_data == nullptr || other.arraySize > allocated)
|
||||
{
|
||||
if(_data != nullptr)
|
||||
{
|
||||
|
||||
@@ -502,7 +502,7 @@ private:
|
||||
if (!isValid(r))
|
||||
{
|
||||
nodeContainer.emplace(std::forward<KeyType>(key));
|
||||
return 0;
|
||||
return nodeContainer.size() - 1;
|
||||
}
|
||||
r = splay(r, key);
|
||||
Node* node = getNode(r);
|
||||
|
||||
@@ -10,6 +10,7 @@ target_sources(SeeleEngine
|
||||
Mesh.h
|
||||
Mesh.cpp
|
||||
MeshBatch.h
|
||||
MeshBatch.cpp
|
||||
RenderMaterial.h
|
||||
RenderMaterial.cpp
|
||||
ShaderCompiler.h
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "Containers/Array.h"
|
||||
#include "Containers/List.h"
|
||||
#include "GraphicsInitializer.h"
|
||||
#include "MeshBatch.h"
|
||||
#include <boost/crc.hpp>
|
||||
#include <functional>
|
||||
|
||||
@@ -17,6 +16,8 @@ namespace Seele
|
||||
struct VertexInputStream;
|
||||
struct VertexStreamComponent;
|
||||
class VertexInputType;
|
||||
struct MeshBatchElement;
|
||||
DECLARE_REF(MaterialAsset)
|
||||
namespace Gfx
|
||||
{
|
||||
DECLARE_REF(Graphics)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "MeshBatch.h"
|
||||
#include "GraphicsResources.h"
|
||||
#include "VertexShaderInput.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MeshBatchElement::MeshBatchElement()
|
||||
: uniformBuffer(nullptr)
|
||||
, indexBuffer(nullptr)
|
||||
, firstIndex(0)
|
||||
, numPrimitives(0)
|
||||
, numInstances(1)
|
||||
, baseVertexIndex(0)
|
||||
, minVertexIndex(0)
|
||||
, maxVertexIndex(0)
|
||||
, indirectArgsBuffer(nullptr)
|
||||
{}
|
||||
MeshBatch::MeshBatch()
|
||||
: useReverseCulling(false)
|
||||
, isBackfaceCullingDisabled(false)
|
||||
, isCastingShadow(true)
|
||||
, useWireframe(false)
|
||||
, topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||||
, vertexInput(nullptr)
|
||||
, material(nullptr)
|
||||
{
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
#include "GraphicsEnums.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(MaterialAsset)
|
||||
DECLARE_REF(VertexShaderInput)
|
||||
DECLARE_REF(MaterialAsset)
|
||||
DECLARE_NAME_REF(Gfx, VertexBuffer)
|
||||
DECLARE_NAME_REF(Gfx, IndexBuffer)
|
||||
DECLARE_NAME_REF(Gfx, UniformBuffer)
|
||||
@@ -29,17 +30,7 @@ public:
|
||||
|
||||
uint8 isInstanced : 1;
|
||||
Gfx::PVertexBuffer indirectArgsBuffer;
|
||||
MeshBatchElement()
|
||||
: uniformBuffer(nullptr)
|
||||
, indexBuffer(nullptr)
|
||||
, firstIndex(0)
|
||||
, numPrimitives(0)
|
||||
, numInstances(1)
|
||||
, baseVertexIndex(0)
|
||||
, minVertexIndex(0)
|
||||
, maxVertexIndex(0)
|
||||
, indirectArgsBuffer(nullptr)
|
||||
{}
|
||||
MeshBatchElement();
|
||||
};
|
||||
struct MeshBatch
|
||||
{
|
||||
@@ -76,16 +67,7 @@ struct MeshBatch
|
||||
return count;
|
||||
}
|
||||
|
||||
MeshBatch()
|
||||
: useReverseCulling(false)
|
||||
, isBackfaceCullingDisabled(false)
|
||||
, isCastingShadow(true)
|
||||
, useWireframe(false)
|
||||
, topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||||
, vertexInput(nullptr)
|
||||
, material(nullptr)
|
||||
{
|
||||
}
|
||||
MeshBatch();
|
||||
};
|
||||
DECLARE_REF(PrimitiveComponent)
|
||||
struct StaticMeshBatch : public MeshBatch
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "ShaderCompiler.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "VertexShaderInput.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Gfx;
|
||||
|
||||
@@ -131,11 +131,19 @@ void Allocation::markFree(SubAllocation *allocation)
|
||||
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
||||
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
||||
PSubAllocation allocHandle;
|
||||
PSubAllocation freeRangeToDelete;
|
||||
|
||||
std::unique_lock lck(lock);
|
||||
//Join lower bound
|
||||
for (auto freeRange : freeRanges)
|
||||
{
|
||||
PSubAllocation freeAlloc = freeRange.value;
|
||||
if (freeAlloc->allocatedOffset <= lowerBound
|
||||
&& freeAlloc->allocatedOffset + freeAlloc->allocatedSize >= upperBound)
|
||||
{
|
||||
// allocation is already in a free region
|
||||
return;
|
||||
}
|
||||
if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize == lowerBound)
|
||||
{
|
||||
//extend freeAlloc by the allocatedSize
|
||||
@@ -148,6 +156,7 @@ void Allocation::markFree(SubAllocation *allocation)
|
||||
auto foundAlloc = freeRanges.find(upperBound);
|
||||
if (foundAlloc != freeRanges.end())
|
||||
{
|
||||
freeRangeToDelete = foundAlloc->value;
|
||||
// There is a free allocation ending where the new free one ends
|
||||
if (allocHandle != nullptr)
|
||||
{
|
||||
@@ -159,22 +168,23 @@ void Allocation::markFree(SubAllocation *allocation)
|
||||
{
|
||||
// set foundAlloc back by size amount
|
||||
allocHandle = foundAlloc->value;
|
||||
// remove from offset map since key changes
|
||||
freeRanges.erase(foundAlloc->key);
|
||||
allocHandle->allocatedOffset -= allocation->allocatedSize;
|
||||
allocHandle->alignedOffset -= allocation->allocatedSize;
|
||||
// place back at correct offset
|
||||
freeRanges[allocHandle->allocatedOffset] = allocHandle;
|
||||
// remove from offset map since key changes
|
||||
freeRanges.erase(foundAlloc->key);
|
||||
}
|
||||
}
|
||||
|
||||
if (allocHandle == nullptr)
|
||||
{
|
||||
allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize);
|
||||
freeRanges[allocation->allocatedOffset] = allocHandle;
|
||||
}
|
||||
activeAllocations.erase(allocation->allocatedOffset);
|
||||
lock.unlock();
|
||||
bytesUsed -= allocation->allocatedSize;
|
||||
|
||||
// TODO: delete allocation when bytesUsed == 0
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "VulkanGraphics.h"
|
||||
#include "VulkanCommandBuffer.h"
|
||||
#include "VulkanAllocator.h"
|
||||
#include "ThreadPool.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
@@ -62,14 +63,17 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags u
|
||||
|
||||
ShaderBuffer::~ShaderBuffer()
|
||||
{
|
||||
auto cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
|
||||
auto &deletionQueue = graphics->getDeletionQueue();
|
||||
PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
|
||||
VkDevice device = graphics->getDevice();
|
||||
VkBuffer buf[Gfx::numFramesBuffered];
|
||||
auto deletionLambda = [](PCmdBuffer cmdBuffer, VkDevice device, VkBuffer buffer) -> Job
|
||||
{
|
||||
co_await cmdBuffer->asyncWait();
|
||||
vkDestroyBuffer(device, buffer, nullptr);
|
||||
co_return;
|
||||
};
|
||||
for (uint32 i = 0; i < numBuffers; ++i)
|
||||
{
|
||||
buf[i] = buffers[i].buffer;
|
||||
deletionQueue.addPendingDelete(cmdBuffer, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); });
|
||||
deletionLambda(cmdBuffer, device, buffers[i].buffer);
|
||||
buffers[i].allocation = nullptr;
|
||||
}
|
||||
graphics = nullptr;
|
||||
|
||||
@@ -25,6 +25,7 @@ CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferMa
|
||||
init::CommandBufferAllocateInfo(cmdPool,
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
1);
|
||||
std::unique_lock lock(handleLock);
|
||||
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle))
|
||||
|
||||
fence = new Fence(graphics);
|
||||
@@ -33,6 +34,7 @@ CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferMa
|
||||
|
||||
CmdBuffer::~CmdBuffer()
|
||||
{
|
||||
std::unique_lock lock(handleLock);
|
||||
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
|
||||
renderPass = nullptr;
|
||||
framebuffer = nullptr;
|
||||
@@ -44,18 +46,21 @@ void CmdBuffer::begin()
|
||||
VkCommandBufferBeginInfo beginInfo =
|
||||
init::CommandBufferBeginInfo();
|
||||
beginInfo.pInheritanceInfo = nullptr;
|
||||
std::unique_lock lock(handleLock);
|
||||
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
|
||||
state = State::InsideBegin;
|
||||
}
|
||||
|
||||
void CmdBuffer::end()
|
||||
{
|
||||
std::unique_lock lock(handleLock);
|
||||
VK_CHECK(vkEndCommandBuffer(handle));
|
||||
state = State::Ended;
|
||||
}
|
||||
|
||||
void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFramebuffer)
|
||||
{
|
||||
std::unique_lock lock(handleLock);
|
||||
renderPass = newRenderPass;
|
||||
framebuffer = newFramebuffer;
|
||||
|
||||
@@ -72,6 +77,7 @@ void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFrame
|
||||
|
||||
void CmdBuffer::endRenderPass()
|
||||
{
|
||||
std::unique_lock lock(handleLock);
|
||||
vkCmdEndRenderPass(handle);
|
||||
state = State::InsideBegin;
|
||||
}
|
||||
@@ -79,6 +85,7 @@ void CmdBuffer::endRenderPass()
|
||||
void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
|
||||
{
|
||||
assert(state == State::RenderPassActive);
|
||||
std::unique_lock lock(handleLock);
|
||||
Array<VkCommandBuffer> cmdBuffers(commands.size());
|
||||
for (uint32 i = 0; i < commands.size(); ++i)
|
||||
{
|
||||
@@ -97,6 +104,7 @@ void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
|
||||
|
||||
void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands)
|
||||
{
|
||||
std::unique_lock lock(handleLock);
|
||||
Array<VkCommandBuffer> cmdBuffers(commands.size());
|
||||
for (uint32 i = 0; i < commands.size(); ++i)
|
||||
{
|
||||
@@ -115,12 +123,14 @@ void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands)
|
||||
|
||||
void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore)
|
||||
{
|
||||
std::unique_lock lock(handleLock);
|
||||
waitSemaphores.add(semaphore);
|
||||
waitFlags.add(flags);
|
||||
}
|
||||
|
||||
void CmdBuffer::refreshFence()
|
||||
{
|
||||
std::unique_lock lock(handleLock);
|
||||
if (state == State::Submitted)
|
||||
{
|
||||
if (fence->isSignaled())
|
||||
@@ -153,10 +163,16 @@ void CmdBuffer::refreshFence()
|
||||
|
||||
void CmdBuffer::waitForCommand(uint32 timeout)
|
||||
{
|
||||
std::unique_lock lock(handleLock);
|
||||
fence->wait(timeout);
|
||||
refreshFence();
|
||||
}
|
||||
|
||||
Event CmdBuffer::asyncWait() const
|
||||
{
|
||||
return fence->asyncWait();
|
||||
}
|
||||
|
||||
|
||||
PFence CmdBuffer::getFence()
|
||||
{
|
||||
@@ -187,6 +203,7 @@ RenderCommand::~RenderCommand()
|
||||
|
||||
void RenderCommand::begin(PCmdBuffer parent)
|
||||
{
|
||||
threadId = std::this_thread::get_id();
|
||||
ready = false;
|
||||
VkCommandBufferBeginInfo beginInfo =
|
||||
init::CommandBufferBeginInfo();
|
||||
@@ -202,11 +219,13 @@ void RenderCommand::begin(PCmdBuffer parent)
|
||||
|
||||
void RenderCommand::end()
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
VK_CHECK(vkEndCommandBuffer(handle));
|
||||
}
|
||||
|
||||
void RenderCommand::reset()
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
|
||||
boundDescriptors.clear();
|
||||
ready = true;
|
||||
@@ -219,6 +238,7 @@ bool RenderCommand::isReady()
|
||||
|
||||
void RenderCommand::setViewport(Gfx::PViewport viewport)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
VkViewport vp = viewport.cast<Viewport>()->getHandle();
|
||||
VkRect2D scissors = init::Rect2D(viewport->getSizeX(), viewport->getSizeY(), viewport->getOffsetX(), viewport->getOffsetY());
|
||||
vkCmdSetViewport(handle, 0, 1, &vp);
|
||||
@@ -227,11 +247,13 @@ void RenderCommand::setViewport(Gfx::PViewport viewport)
|
||||
|
||||
void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
pipeline = gfxPipeline.cast<GraphicsPipeline>();
|
||||
pipeline->bind(handle);
|
||||
}
|
||||
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
auto descriptor = descriptorSet.cast<DescriptorSet>();
|
||||
boundDescriptors.add(descriptor.getHandle());
|
||||
descriptor->bind();
|
||||
@@ -241,6 +263,7 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
|
||||
}
|
||||
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
|
||||
for(uint32 i = 0; i < descriptorSets.size(); ++i)
|
||||
{
|
||||
@@ -255,6 +278,7 @@ void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorS
|
||||
}
|
||||
void RenderCommand::bindVertexBuffer(const Array<VertexInputStream>& streams)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
Array<VkBuffer> buffers(streams.size());
|
||||
Array<VkDeviceSize> offsets(streams.size());
|
||||
for(uint32 i = 0; i < streams.size(); ++i)
|
||||
@@ -267,16 +291,19 @@ void RenderCommand::bindVertexBuffer(const Array<VertexInputStream>& streams)
|
||||
}
|
||||
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
|
||||
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, cast(buf->getIndexType()));
|
||||
}
|
||||
void RenderCommand::draw(const MeshBatchElement& data)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
|
||||
}
|
||||
|
||||
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
vkCmdDraw(handle, vertexCount, instanceCount, firstVertex, firstInstance);
|
||||
}
|
||||
|
||||
@@ -299,6 +326,7 @@ ComputeCommand::~ComputeCommand()
|
||||
|
||||
void ComputeCommand::begin(PCmdBuffer)
|
||||
{
|
||||
threadId = std::this_thread::get_id();
|
||||
ready = false;
|
||||
VkCommandBufferBeginInfo beginInfo =
|
||||
init::CommandBufferBeginInfo();
|
||||
@@ -313,11 +341,13 @@ void ComputeCommand::begin(PCmdBuffer)
|
||||
|
||||
void ComputeCommand::end()
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
VK_CHECK(vkEndCommandBuffer(handle));
|
||||
}
|
||||
|
||||
void ComputeCommand::reset()
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
|
||||
boundDescriptors.clear();
|
||||
ready = true;
|
||||
@@ -329,12 +359,14 @@ bool ComputeCommand::isReady()
|
||||
|
||||
void ComputeCommand::bindPipeline(Gfx::PComputePipeline computePipeline)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
pipeline = computePipeline.cast<ComputePipeline>();
|
||||
pipeline->bind(handle);
|
||||
}
|
||||
|
||||
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
auto descriptor = descriptorSet.cast<DescriptorSet>();
|
||||
boundDescriptors.add(descriptor.getHandle());
|
||||
descriptor->bind();
|
||||
@@ -345,6 +377,7 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
|
||||
|
||||
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
|
||||
for(uint32 i = 0; i < descriptorSets.size(); ++i)
|
||||
{
|
||||
@@ -360,6 +393,7 @@ void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptor
|
||||
|
||||
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ)
|
||||
{
|
||||
assert(threadId == std::this_thread::get_id());
|
||||
vkCmdDispatch(handle, threadX, threadY, threadZ);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore);
|
||||
void refreshFence();
|
||||
void waitForCommand(uint32 timeToWait = 1000000u);
|
||||
Event asyncWait() const;
|
||||
PFence getFence();
|
||||
PCommandBufferManager getManager();
|
||||
enum State
|
||||
@@ -53,6 +54,7 @@ private:
|
||||
State state;
|
||||
VkViewport currentViewport;
|
||||
VkRect2D currentScissor;
|
||||
std::mutex handleLock;
|
||||
VkCommandBuffer handle;
|
||||
VkCommandPool owner;
|
||||
Array<PSemaphore> waitSemaphores;
|
||||
@@ -96,6 +98,7 @@ private:
|
||||
VkViewport currentViewport;
|
||||
VkRect2D currentScissor;
|
||||
PGraphics graphics;
|
||||
std::thread::id threadId;
|
||||
VkCommandBuffer handle;
|
||||
VkCommandPool owner;
|
||||
friend class CmdBuffer;
|
||||
@@ -126,6 +129,7 @@ private:
|
||||
VkViewport currentViewport;
|
||||
VkRect2D currentScissor;
|
||||
PGraphics graphics;
|
||||
std::thread::id threadId;
|
||||
VkCommandBuffer handle;
|
||||
VkCommandPool owner;
|
||||
friend class CmdBuffer;
|
||||
|
||||
@@ -8,7 +8,9 @@ using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRenderTargetLayout renderTargetLayout)
|
||||
: graphics(graphics), layout(renderTargetLayout), renderPass(renderPass)
|
||||
: graphics(graphics)
|
||||
, layout(renderTargetLayout)
|
||||
, renderPass(renderPass)
|
||||
{
|
||||
FramebufferDescription description;
|
||||
std::memset(&description, 0, sizeof(FramebufferDescription));
|
||||
|
||||
@@ -52,6 +52,7 @@ Gfx::PWindow Graphics::createWindow(const WindowCreateInfo &createInfo)
|
||||
Gfx::PViewport Graphics::createViewport(Gfx::PWindow owner, const ViewportCreateInfo &viewportInfo)
|
||||
{
|
||||
PViewport result = new Viewport(this, owner, viewportInfo);
|
||||
std::unique_lock lock(viewportLock);
|
||||
viewports.add(result);
|
||||
return result;
|
||||
}
|
||||
@@ -65,6 +66,8 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
|
||||
PRenderPass rp = renderPass.cast<RenderPass>();
|
||||
uint32 framebufferHash = rp->getFramebufferHash();
|
||||
PFramebuffer framebuffer;
|
||||
{
|
||||
std::unique_lock lock(allocatedFrameBufferLock);
|
||||
auto found = allocatedFramebuffers.find(framebufferHash);
|
||||
if (found == allocatedFramebuffers.end())
|
||||
{
|
||||
@@ -75,6 +78,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
|
||||
{
|
||||
framebuffer = found->value;
|
||||
}
|
||||
}
|
||||
getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer);
|
||||
}
|
||||
|
||||
@@ -275,21 +279,6 @@ void Graphics::copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture)
|
||||
}
|
||||
}
|
||||
|
||||
VkInstance Graphics::getInstance() const
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
VkDevice Graphics::getDevice() const
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
|
||||
VkPhysicalDevice Graphics::getPhysicalDevice() const
|
||||
{
|
||||
return physicalDevice;
|
||||
}
|
||||
|
||||
PCommandBufferManager Graphics::getQueueCommands(Gfx::QueueType queueType)
|
||||
{
|
||||
switch (queueType)
|
||||
@@ -360,7 +349,6 @@ PStagingManager Graphics::getStagingManager()
|
||||
return stagingManager;
|
||||
}
|
||||
|
||||
|
||||
Array<const char *> Graphics::getRequiredExtensions()
|
||||
{
|
||||
Array<const char *> extensions;
|
||||
@@ -566,6 +554,7 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
||||
deviceInfo.ppEnabledLayerNames = initializer.layers.data();
|
||||
|
||||
VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle));
|
||||
std::cout << "Vulkan handle: " << handle << std::endl;
|
||||
|
||||
graphicsQueue = new Queue(this, Gfx::QueueType::GRAPHICS, graphicsQueueInfo.familyIndex, 0);
|
||||
if (Gfx::useAsyncCompute && asyncComputeInfo.familyIndex != -1)
|
||||
|
||||
@@ -19,9 +19,9 @@ class Graphics : public Gfx::Graphics
|
||||
public:
|
||||
Graphics();
|
||||
virtual ~Graphics();
|
||||
VkInstance getInstance() const;
|
||||
VkDevice getDevice() const;
|
||||
VkPhysicalDevice getPhysicalDevice() const;
|
||||
constexpr VkInstance getInstance() const { return instance; };
|
||||
constexpr VkDevice getDevice() const { return handle; };
|
||||
constexpr VkPhysicalDevice getPhysicalDevice() const { return physicalDevice; };
|
||||
|
||||
PCommandBufferManager getQueueCommands(Gfx::QueueType queueType);
|
||||
PCommandBufferManager getGraphicsCommands();
|
||||
@@ -29,11 +29,6 @@ public:
|
||||
PCommandBufferManager getTransferCommands();
|
||||
PCommandBufferManager getDedicatedTransferCommands();
|
||||
|
||||
QueueOwnedResourceDeletion &getDeletionQueue()
|
||||
{
|
||||
return deletionQueue;
|
||||
}
|
||||
|
||||
PAllocator getAllocator();
|
||||
PStagingManager getStagingManager();
|
||||
|
||||
@@ -86,7 +81,6 @@ protected:
|
||||
PQueue computeQueue;
|
||||
PQueue transferQueue;
|
||||
PQueue dedicatedTransferQueue;
|
||||
QueueOwnedResourceDeletion deletionQueue;
|
||||
PPipelineCache pipelineCache;
|
||||
Map<std::thread::id, PCommandBufferManager> graphicsCommands;
|
||||
Map<std::thread::id, PCommandBufferManager> computeCommands;
|
||||
@@ -95,7 +89,9 @@ protected:
|
||||
VkPhysicalDeviceProperties props;
|
||||
VkPhysicalDeviceFeatures features;
|
||||
VkDebugReportCallbackEXT callback;
|
||||
std::mutex viewportLock;
|
||||
Array<PViewport> viewports;
|
||||
std::mutex allocatedFrameBufferLock;
|
||||
Map<uint32, PFramebuffer> allocatedFramebuffers;
|
||||
PAllocator allocator;
|
||||
PStagingManager stagingManager;
|
||||
|
||||
@@ -7,48 +7,6 @@
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
List<QueueOwnedResourceDeletion::PendingItem> QueueOwnedResourceDeletion::deletionQueue;
|
||||
volatile bool QueueOwnedResourceDeletion::running;
|
||||
std::mutex QueueOwnedResourceDeletion::mutex;
|
||||
std::condition_variable QueueOwnedResourceDeletion::cv;
|
||||
|
||||
QueueOwnedResourceDeletion::QueueOwnedResourceDeletion()
|
||||
{
|
||||
worker = std::thread(&run);
|
||||
running = true;
|
||||
}
|
||||
|
||||
QueueOwnedResourceDeletion::~QueueOwnedResourceDeletion()
|
||||
{
|
||||
worker.join();
|
||||
}
|
||||
|
||||
void QueueOwnedResourceDeletion::addPendingDelete(PCmdBuffer cmdbuffer, std::function<void()> func)
|
||||
{
|
||||
PendingItem item;
|
||||
item.cmdBuffer = cmdbuffer;
|
||||
item.func = func;
|
||||
deletionQueue.add(item);
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void QueueOwnedResourceDeletion::run()
|
||||
{
|
||||
while (running || !deletionQueue.empty())
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
cv.wait(lock);
|
||||
auto entry = deletionQueue.begin();
|
||||
PCmdBuffer cmdBuffer = entry->cmdBuffer;
|
||||
//cmdBuffer->getManager()->waitForCommands(cmdBuffer);
|
||||
//cmdBuffer->begin();
|
||||
|
||||
//entry->func();
|
||||
deletionQueue.remove(entry);
|
||||
}
|
||||
}
|
||||
|
||||
Semaphore::Semaphore(PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
@@ -65,7 +23,7 @@ Semaphore::~Semaphore()
|
||||
|
||||
Fence::Fence(PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
, signaled(false)
|
||||
, signaled("Fence")
|
||||
{
|
||||
VkFenceCreateInfo info =
|
||||
init::FenceCreateInfo(0);
|
||||
@@ -87,7 +45,7 @@ bool Fence::isSignaled()
|
||||
switch (res)
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
signaled = true;
|
||||
signaled.raise();
|
||||
return true;
|
||||
case VK_NOT_READY:
|
||||
break;
|
||||
@@ -102,7 +60,7 @@ void Fence::reset()
|
||||
if (signaled)
|
||||
{
|
||||
vkResetFences(graphics->getDevice(), 1, &fence);
|
||||
signaled = false;
|
||||
signaled.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +71,7 @@ void Fence::wait(uint32 timeout)
|
||||
switch (r)
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
signaled = true;
|
||||
signaled.raise();
|
||||
break;
|
||||
case VK_TIMEOUT:
|
||||
break;
|
||||
@@ -122,6 +80,11 @@ void Fence::wait(uint32 timeout)
|
||||
break;
|
||||
}
|
||||
}
|
||||
Event Fence::asyncWait() const
|
||||
{
|
||||
return signaled;
|
||||
}
|
||||
|
||||
|
||||
VertexDeclaration::VertexDeclaration(const Array<Gfx::VertexElement>& elementList)
|
||||
: elementList(elementList)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <functional>
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "VulkanAllocator.h"
|
||||
#include "ThreadPool.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -41,6 +43,7 @@ public:
|
||||
return fence;
|
||||
}
|
||||
void wait(uint32 timeout);
|
||||
Event asyncWait() const;
|
||||
bool operator<(const Fence &other) const
|
||||
{
|
||||
return fence < other.fence;
|
||||
@@ -48,7 +51,7 @@ public:
|
||||
|
||||
private:
|
||||
PGraphics graphics;
|
||||
bool signaled;
|
||||
Event signaled;
|
||||
VkFence fence;
|
||||
};
|
||||
DEFINE_REF(Fence)
|
||||
@@ -64,27 +67,6 @@ private:
|
||||
};
|
||||
DEFINE_REF(VertexDeclaration)
|
||||
|
||||
class QueueOwnedResourceDeletion
|
||||
{
|
||||
public:
|
||||
QueueOwnedResourceDeletion();
|
||||
virtual ~QueueOwnedResourceDeletion();
|
||||
static void addPendingDelete(PCmdBuffer fence, std::function<void()> function);
|
||||
|
||||
private:
|
||||
std::thread worker;
|
||||
static volatile bool running;
|
||||
static void run();
|
||||
struct PendingItem
|
||||
{
|
||||
PCmdBuffer cmdBuffer;
|
||||
std::function<void()> func;
|
||||
};
|
||||
static std::mutex mutex;
|
||||
static std::condition_variable cv;
|
||||
static List<PendingItem> deletionQueue;
|
||||
};
|
||||
|
||||
class ShaderBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -29,6 +29,7 @@ PipelineCache::PipelineCache(PGraphics graphics, const std::string& cacheFilePat
|
||||
stream.read((char*)cacheData.data(), fileSize);
|
||||
cacheCreateInfo.initialDataSize = fileSize;
|
||||
cacheCreateInfo.pInitialData = cacheData.data();
|
||||
std::cout << "Loaded " << fileSize << " bytes from pipeline cache" << std::endl;
|
||||
}
|
||||
VK_CHECK(vkCreatePipelineCache(graphics->getDevice(), &cacheCreateInfo, nullptr, &cache));
|
||||
}
|
||||
@@ -44,6 +45,7 @@ PipelineCache::~PipelineCache()
|
||||
stream.flush();
|
||||
stream.close();
|
||||
vkDestroyPipelineCache(graphics->getDevice(), cache, nullptr);
|
||||
std::cout << "Written " << cacheSize << " bytes to cache" << std::endl;
|
||||
}
|
||||
|
||||
struct PipelineCreateHashStruct
|
||||
@@ -321,6 +323,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
uint32 hash = crc.checksum();
|
||||
VkPipeline pipelineHandle;
|
||||
|
||||
std::unique_lock lock(createdPipelinesLock);
|
||||
auto foundPipeline = createdPipelines.find(hash);
|
||||
if (foundPipeline != createdPipelines.end())
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ private:
|
||||
VkPipelineCache cache;
|
||||
PGraphics graphics;
|
||||
std::string cacheFile;
|
||||
std::mutex createdPipelinesLock;
|
||||
Map<uint32, VkPipeline> createdPipelines;
|
||||
};
|
||||
DEFINE_REF(PipelineCache)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "VulkanGraphicsEnums.h"
|
||||
#include "VulkanAllocator.h"
|
||||
#include "VulkanCommandBuffer.h"
|
||||
#include "ThreadPool.h"
|
||||
#include <math.h>
|
||||
|
||||
using namespace Seele;
|
||||
@@ -161,13 +162,17 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType,
|
||||
|
||||
TextureHandle::~TextureHandle()
|
||||
{
|
||||
auto &deletionQueue = graphics->getDeletionQueue();
|
||||
auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||
VkDevice device = graphics->getDevice();
|
||||
VkImageView view = defaultView;
|
||||
VkImage img = image;
|
||||
deletionQueue.addPendingDelete(cmdBuffer, [device, view]() { vkDestroyImageView(device, view, nullptr); });
|
||||
deletionQueue.addPendingDelete(cmdBuffer, [device, img]() { vkDestroyImage(device, img, nullptr); });
|
||||
auto deletionLambda = [cmdBuffer, device, view, img]() -> Job
|
||||
{
|
||||
vkDestroyImageView(device, view, nullptr);
|
||||
vkDestroyImage(device, img, nullptr);
|
||||
co_return;
|
||||
};
|
||||
deletionLambda();
|
||||
}
|
||||
|
||||
TextureHandle* TextureBase::cast(Gfx::PTexture texture)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "MaterialAsset.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
#include "Asset/TextureAsset.h"
|
||||
#include "BRDF.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sstream>
|
||||
|
||||
@@ -38,13 +38,9 @@ public:
|
||||
: handle(ptr)
|
||||
, deleter(std::move(deleter))
|
||||
, refCount(1)
|
||||
{
|
||||
registeredObjects[ptr] = this;
|
||||
}
|
||||
inline RefObject(const RefObject &rhs)
|
||||
: handle(rhs.handle), refCount(rhs.refCount)
|
||||
{
|
||||
}
|
||||
RefObject(const RefObject &rhs) = delete;
|
||||
RefObject(RefObject &&rhs)
|
||||
: handle(std::move(rhs.handle)), refCount(std::move(rhs.refCount))
|
||||
{
|
||||
@@ -56,18 +52,11 @@ public:
|
||||
registeredObjects.erase(handle);
|
||||
}
|
||||
// #pragma warning( disable: 4150)
|
||||
//deleter(handle);
|
||||
deleter(handle);
|
||||
handle = nullptr;
|
||||
// #pragma warning( default: 4150)
|
||||
}
|
||||
RefObject &operator=(const RefObject &rhs)
|
||||
{
|
||||
if (*this != rhs)
|
||||
{
|
||||
handle = rhs.handle;
|
||||
refCount = rhs.refCount;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
RefObject &operator=(const RefObject &rhs) = delete;
|
||||
RefObject &operator=(RefObject &&rhs)
|
||||
{
|
||||
if (*this != rhs)
|
||||
@@ -131,11 +120,10 @@ public:
|
||||
if (registeredObj == registeredEnd)
|
||||
{
|
||||
object = new RefObject<T, Deleter>(ptr, std::move(deleter));
|
||||
l.unlock();
|
||||
registeredObjects[ptr] = object;
|
||||
}
|
||||
else
|
||||
{
|
||||
l.unlock();
|
||||
object = (RefObject<T, Deleter> *)registeredObj->value;
|
||||
object->addRef();
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ ThreadPool::ThreadPool(uint32 threadCount)
|
||||
|
||||
ThreadPool::~ThreadPool()
|
||||
{
|
||||
running.store(false);
|
||||
for(auto& thread : workers)
|
||||
{
|
||||
thread.join();
|
||||
@@ -74,7 +75,7 @@ void ThreadPool::notify(Event* event)
|
||||
{
|
||||
std::unique_lock lock(jobQueueLock);
|
||||
std::unique_lock lock2(waitingLock);
|
||||
while(!waitingJobs.empty())
|
||||
while(!waitingJobs[*event].empty())
|
||||
{
|
||||
//std::cout << "Waking up job " << job << std::endl;
|
||||
jobQueue.add(std::move(waitingJobs[*event].retrieve()));
|
||||
@@ -90,7 +91,6 @@ void ThreadPool::notify(Event* event)
|
||||
mainJobCV.notify_one();
|
||||
}
|
||||
}
|
||||
event->reset();
|
||||
}
|
||||
void ThreadPool::threadLoop(const bool mainThread)
|
||||
{
|
||||
|
||||
@@ -91,6 +91,10 @@ public:
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
operator bool()
|
||||
{
|
||||
return flag->load();
|
||||
}
|
||||
|
||||
void raise();
|
||||
void reset();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Element.h"
|
||||
#include "UI/System.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::UI;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "System.h"
|
||||
#include "Elements/Panel.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::UI;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "InspectorView.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Scene/Actor/Actor.h"
|
||||
#include "Window.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "SceneView.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Window.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Asset/MeshAsset.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
#include "Scene/Actor/CameraActor.h"
|
||||
#include "Scene/Components/CameraComponent.h"
|
||||
|
||||
@@ -30,6 +30,7 @@ MainJob Window::render()
|
||||
for(auto& windowView : views)
|
||||
{
|
||||
co_await windowView->updateFinished;
|
||||
windowView->updateFinished.reset();
|
||||
{
|
||||
std::unique_lock lock(windowView->workerMutex);
|
||||
windowView->view->prepareRender();
|
||||
|
||||
Reference in New Issue
Block a user