Implementing Commandbuffers
This commit is contained in:
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"C_Cpp.default.configurationProvider": "go2sh.cmake-integration",
|
||||
"telemetry.enableTelemetry": false,
|
||||
"cmake.buildDirectory": "${workspaceFolder}/bin/${buildType}",
|
||||
"files.associations": {
|
||||
"xstring": "cpp"
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ set(GLFW_ROOT ${EXTERNAL_ROOT}/glfw)
|
||||
set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE})
|
||||
set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
|
||||
set(Boost_DETAILED_FAILURE_MSG TRUE)
|
||||
|
||||
# Configuration types
|
||||
SET(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE)
|
||||
|
||||
@@ -4,6 +4,8 @@ namespace Seele
|
||||
{
|
||||
namespace Gfx
|
||||
{
|
||||
static bool useAsyncCompute = true;
|
||||
|
||||
typedef uint32_t SeFlags;
|
||||
typedef uint32_t SeBool32;
|
||||
typedef uint64_t SeDeviceSize;
|
||||
|
||||
@@ -54,9 +54,6 @@ namespace Seele
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class RenderCommandBase
|
||||
{
|
||||
|
||||
|
||||
@@ -21,11 +21,6 @@ void Seele::RenderCore::init()
|
||||
|
||||
void Seele::RenderCore::renderLoop()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
windowManager->beginFrame();
|
||||
windowManager->endFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void Seele::RenderCore::shutdown()
|
||||
|
||||
@@ -2,12 +2,21 @@ target_sources(SeeleEngine
|
||||
PRIVATE
|
||||
VulkanAllocator.h
|
||||
VulkanAllocator.cpp
|
||||
VulkanCommandBuffer.h
|
||||
VulkanCommandBuffer.cpp
|
||||
VulkanBuffer.cpp
|
||||
VulkanFramebuffer.h
|
||||
VulkanFramebuffer.cpp
|
||||
VulkanGraphics.h
|
||||
VulkanGraphics.cpp
|
||||
VulkanGraphicsResources.h
|
||||
VulkanGraphicsResources.cpp
|
||||
VulkanDescriptorSets.cpp
|
||||
VulkanGraphicsEnums.h
|
||||
VulkanGraphicsEnums.cpp
|
||||
VulkanInitializer.h
|
||||
VulkanInitializer.cpp)
|
||||
VulkanInitializer.cpp
|
||||
VulkanRenderPass.h
|
||||
VulkanRenderPass.cpp
|
||||
VulkanQueue.h
|
||||
VulkanQueue.cpp)
|
||||
@@ -14,7 +14,7 @@ SubAllocation::SubAllocation(Allocation* owner, uint32 allocatedOffset, uint32 s
|
||||
{
|
||||
}
|
||||
|
||||
Allocation::Allocation(PGraphics graphics, Allocator* allocator, uint32 size, uint32 memoryTypeIndex, VkMemoryPropertyFlags properties, bool isDedicated)
|
||||
Allocation::Allocation(WGraphics graphics, Allocator* allocator, uint32 size, uint32 memoryTypeIndex, VkMemoryPropertyFlags properties, bool isDedicated)
|
||||
: device(graphics->getDevice())
|
||||
, allocator(allocator)
|
||||
, bytesAllocated(0)
|
||||
@@ -32,13 +32,13 @@ Allocation::Allocation(PGraphics graphics, Allocator* allocator, uint32 size, ui
|
||||
freeRanges.add(freeRange);
|
||||
}
|
||||
|
||||
PSubAllocation Allocation::getSuballocation(uint32 size, uint32 alignment)
|
||||
PSubAllocation Allocation::getSuballocation(uint32 requestedSize, uint32 alignment)
|
||||
{
|
||||
if (isDedicated)
|
||||
{
|
||||
if (activeAllocations.size() == 0)
|
||||
{
|
||||
assert(size == bytesAllocated);
|
||||
assert(requestedSize == bytesAllocated);
|
||||
activeAllocations.add(freeRanges.back());
|
||||
freeRanges.clear();
|
||||
}
|
||||
@@ -53,7 +53,7 @@ PSubAllocation Allocation::getSuballocation(uint32 size, uint32 alignment)
|
||||
uint32 allocatedOffset = freeAllocation->allocatedOffset;
|
||||
uint32 alignedOffset = align(allocatedOffset, alignment);
|
||||
uint32 alignmentAdjustment = alignedOffset - allocatedOffset;
|
||||
uint32 size = alignmentAdjustment + size;
|
||||
uint32 size = alignmentAdjustment + requestedSize;
|
||||
if (freeAllocation->size == size)
|
||||
{
|
||||
freeRanges.remove(i);
|
||||
@@ -66,7 +66,7 @@ PSubAllocation Allocation::getSuballocation(uint32 size, uint32 alignment)
|
||||
freeAllocation->allocatedSize -= size;
|
||||
freeAllocation->allocatedOffset += allocatedOffset;
|
||||
freeAllocation->alignedOffset += allocatedOffset;
|
||||
PSubAllocation subAlloc = new VulkanSubAllocation(this, allocatedOffset, size, alignedOffset, size);
|
||||
PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size);
|
||||
activeAllocations.add(subAlloc);
|
||||
return subAlloc;
|
||||
}
|
||||
@@ -74,7 +74,7 @@ PSubAllocation Allocation::getSuballocation(uint32 size, uint32 alignment)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Allocator::Allocator(PGraphics graphics)
|
||||
Allocator::Allocator(WGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Seele
|
||||
class Allocation
|
||||
{
|
||||
public:
|
||||
Allocation(PGraphics graphics, Allocator* allocator, uint32 size, uint32 memoryTypeIndex, VkMemoryPropertyFlags properties, bool isDedicated);
|
||||
Allocation(WGraphics graphics, Allocator* allocator, uint32 size, uint32 memoryTypeIndex, VkMemoryPropertyFlags properties, bool isDedicated);
|
||||
PSubAllocation getSuballocation(uint32 size, uint32 alignment);
|
||||
private:
|
||||
Allocator* allocator;
|
||||
@@ -50,7 +50,7 @@ namespace Seele
|
||||
class Allocator
|
||||
{
|
||||
public:
|
||||
Allocator(PGraphics graphics);
|
||||
Allocator(WGraphics graphics);
|
||||
~Allocator();
|
||||
PSubAllocation allocate(uint64 size, const VkMemoryRequirements2& requirements, VkMemoryPropertyFlags props);
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Seele
|
||||
};
|
||||
Array<HeapInfo> heaps;
|
||||
VkResult findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint32* typeIndex);
|
||||
PGraphics graphics;
|
||||
WGraphics graphics;
|
||||
VkPhysicalDeviceMemoryProperties memProperties;
|
||||
};
|
||||
DEFINE_REF(Allocator);
|
||||
|
||||
@@ -1,67 +1,5 @@
|
||||
#include "VulkanGraphicsResources.h"
|
||||
#include "VulkanInitializer.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
void Buffer::executeOwnershipBarrier(QueueType newOwner)
|
||||
{
|
||||
VkBufferMemoryBarrier barrier =
|
||||
init::BufferMemoryBarrier();
|
||||
CommandBufferManager* sourceManager = getCommands();
|
||||
CommandBufferManager* dstManager = nullptr;
|
||||
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
if (currentOwner == QueueType::TRANSFER)
|
||||
{
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.srcQueueFamilyIndex = device->getTransferQueue()->getFamilyIndex();
|
||||
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
}
|
||||
else if (currentOwner == QueueType::COMPUTE)
|
||||
{
|
||||
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
||||
barrier.srcQueueFamilyIndex = device->getComputeQueue()->getFamilyIndex();
|
||||
srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||
}
|
||||
else if (currentOwner == QueueType::GRAPHICS)
|
||||
{
|
||||
barrier.srcAccessMask = getSourceAccessMask();
|
||||
barrier.srcQueueFamilyIndex = device->getGraphicsQueue()->getFamilyIndex();
|
||||
srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
|
||||
}
|
||||
if (newOwner == QueueType::TRANSFER)
|
||||
{
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barrier.dstQueueFamilyIndex = device->getTransferQueue()->getFamilyIndex();
|
||||
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
dstManager = device->getRHIDevice().getTransferCommands();
|
||||
}
|
||||
else if (newOwner == QueueType::COMPUTE)
|
||||
{
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
barrier.dstQueueFamilyIndex = device->getComputeQueue()->getFamilyIndex();
|
||||
dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||
dstManager = device->getRHIDevice().getComputeCommands();
|
||||
}
|
||||
else if (newOwner == QueueType::GRAPHICS)
|
||||
{
|
||||
barrier.dstAccessMask = getDestAccessMask();
|
||||
barrier.dstQueueFamilyIndex = device->getGraphicsQueue()->getFamilyIndex();
|
||||
dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
|
||||
dstManager = device->getRHIDevice().getGraphicsCommands();
|
||||
}
|
||||
VkCommandBuffer srcCommand = sourceManager->getCmdBuffer()->getHandle();
|
||||
VkCommandBuffer dstCommand = dstManager->getCmdBuffer()->getHandle();
|
||||
const bool bDynamic = (rhiUsage & BUF_Dynamic) != 0;
|
||||
uint32_t numBuffers = bDynamic ? NUM_BUFFERS : 1;
|
||||
VkBufferMemoryBarrier dynamicBarriers[NUM_BUFFERS];
|
||||
for (uint32_t i = 0; i < numBuffers; ++i)
|
||||
{
|
||||
dynamicBarriers[i] = barrier;
|
||||
dynamicBarriers[i].buffer = buffers[i]->getHandle();
|
||||
dynamicBarriers[i].offset = buffers[i]->getOffset();
|
||||
dynamicBarriers[i].size = buffers[i]->getSize();
|
||||
}
|
||||
vkCmdPipelineBarrier(srcCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
|
||||
vkCmdPipelineBarrier(dstCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
|
||||
sourceManager->submitCommands();
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
#include "VulkanCommandBuffer.h"
|
||||
#include "VulkanInitializer.h"
|
||||
#include "VulkanGraphics.h"
|
||||
#include "VulkanGraphicsEnums.h"
|
||||
#include "VulkanFramebuffer.h"
|
||||
#include "VulkanRenderPass.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
CmdBufferBase::CmdBufferBase(WGraphics graphics, VkCommandPool cmdPool)
|
||||
: graphics(graphics)
|
||||
, owner(cmdPool)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CmdBufferBase::~CmdBufferBase()
|
||||
{
|
||||
}
|
||||
|
||||
CmdBuffer::CmdBuffer(WGraphics graphics, VkCommandPool cmdPool)
|
||||
: CmdBufferBase(graphics, cmdPool)
|
||||
, renderPass(nullptr)
|
||||
, framebuffer(nullptr)
|
||||
, subpassIndex(0)
|
||||
{
|
||||
VkCommandBufferAllocateInfo allocInfo =
|
||||
init::CommandBufferAllocateInfo(cmdPool,
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
1);
|
||||
|
||||
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle))
|
||||
state = State::ReadyBegin;
|
||||
}
|
||||
|
||||
CmdBuffer::~CmdBuffer()
|
||||
{
|
||||
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
|
||||
}
|
||||
|
||||
void CmdBuffer::begin()
|
||||
{
|
||||
VkCommandBufferBeginInfo beginInfo =
|
||||
init::CommandBufferBeginInfo();
|
||||
beginInfo.pInheritanceInfo = nullptr;
|
||||
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
|
||||
state = State::InsideBegin;
|
||||
}
|
||||
|
||||
void CmdBuffer::end()
|
||||
{
|
||||
VK_CHECK(vkEndCommandBuffer(handle));
|
||||
state = State::Ended;
|
||||
}
|
||||
|
||||
void CmdBuffer::beginRenderPass(WRenderPass renderPass, WFramebuffer framebuffer)
|
||||
{
|
||||
VkRenderPassBeginInfo beginInfo =
|
||||
init::RenderPassBeginInfo();
|
||||
beginInfo.clearValueCount = renderPass->getClearValueCount();
|
||||
beginInfo.pClearValues = renderPass->getClearValues();
|
||||
beginInfo.renderArea = renderPass->getRenderArea();
|
||||
beginInfo.renderPass = renderPass->getHandle();
|
||||
beginInfo.framebuffer = framebuffer->getHandle();
|
||||
vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents());
|
||||
}
|
||||
|
||||
void CmdBuffer::endRenderPass()
|
||||
{
|
||||
vkCmdEndRenderPass(handle);
|
||||
}
|
||||
|
||||
SecondaryCmdBuffer::SecondaryCmdBuffer(WGraphics graphics, VkCommandPool cmdPool)
|
||||
: CmdBufferBase(graphics, cmdPool)
|
||||
{
|
||||
VkCommandBufferAllocateInfo allocInfo =
|
||||
init::CommandBufferAllocateInfo(cmdPool,
|
||||
VK_COMMAND_BUFFER_LEVEL_SECONDARY,
|
||||
1);
|
||||
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle));
|
||||
}
|
||||
|
||||
SecondaryCmdBuffer::~SecondaryCmdBuffer()
|
||||
{
|
||||
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
|
||||
}
|
||||
|
||||
void SecondaryCmdBuffer::begin(WCmdBuffer parent)
|
||||
{
|
||||
VkCommandBufferBeginInfo beginInfo =
|
||||
init::CommandBufferBeginInfo();
|
||||
VkCommandBufferInheritanceInfo inheritanceInfo =
|
||||
init::CommandBufferInheritanceInfo();
|
||||
inheritanceInfo.framebuffer = parent->framebuffer->getHandle();
|
||||
inheritanceInfo.renderPass = parent->renderPass->getHandle();
|
||||
inheritanceInfo.subpass = parent->subpassIndex;
|
||||
beginInfo.pInheritanceInfo = &inheritanceInfo;
|
||||
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
|
||||
}
|
||||
|
||||
void SecondaryCmdBuffer::end()
|
||||
{
|
||||
VK_CHECK(vkEndCommandBuffer(handle));
|
||||
}
|
||||
|
||||
CommandBufferManager::CommandBufferManager(WGraphics graphics, WQueue queue)
|
||||
: graphics(graphics)
|
||||
, queue(queue)
|
||||
{
|
||||
VkCommandPoolCreateInfo info =
|
||||
init::CommandPoolCreateInfo();
|
||||
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
info.queueFamilyIndex = queue->getFamilyIndex();
|
||||
|
||||
VK_CHECK(vkCreateCommandPool(graphics->getDevice(), &info, nullptr, &commandPool));
|
||||
|
||||
activeCmdBuffer = new CmdBuffer(graphics, commandPool);
|
||||
activeCmdBuffer->begin();
|
||||
}
|
||||
|
||||
CommandBufferManager::~CommandBufferManager()
|
||||
{
|
||||
vkDestroyCommandPool(graphics->getDevice(), commandPool, nullptr);
|
||||
}
|
||||
|
||||
PCmdBuffer CommandBufferManager::getCommands()
|
||||
{
|
||||
return activeCmdBuffer;
|
||||
}
|
||||
|
||||
PSecondaryCmdBuffer CommandBufferManager::createSecondaryCmdBuffer()
|
||||
{
|
||||
return PSecondaryCmdBuffer();
|
||||
}
|
||||
|
||||
void Seele::Vulkan::CommandBufferManager::submitCommands(PSemaphore signalSemaphore)
|
||||
{
|
||||
}
|
||||
@@ -1,38 +1,90 @@
|
||||
#pragma once
|
||||
#include "VulkanGraphicsResources.h"
|
||||
#include "VulkanQueue.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Vulkan
|
||||
{
|
||||
class CmdBufferBase : public RenderCommandBase
|
||||
DECLARE_REF(RenderPass);
|
||||
DECLARE_REF(Framebuffer);
|
||||
class CmdBufferBase : public Gfx::RenderCommandBase
|
||||
{
|
||||
public:
|
||||
private:
|
||||
CmdBufferBase(WGraphics graphics, VkCommandPool cmdPool);
|
||||
virtual ~CmdBufferBase();
|
||||
inline VkCommandBuffer getHandle()
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
void reset();
|
||||
VkViewport currentViewport;
|
||||
VkRect2D currentScissor;
|
||||
protected:
|
||||
WGraphics graphics;
|
||||
VkCommandBuffer handle;
|
||||
VkCommandPool owner;
|
||||
};
|
||||
DEFINE_REF(CmdBuffer);
|
||||
DEFINE_REF(CmdBufferBase);
|
||||
|
||||
DECLARE_REF(SecondaryCmdBuffer);
|
||||
class CmdBuffer : public CmdBufferBase
|
||||
{
|
||||
public:
|
||||
CmdBuffer(WGraphics graphics, VkCommandPool cmdPool);
|
||||
virtual ~CmdBuffer();
|
||||
void begin();
|
||||
void end();
|
||||
void beginRenderPass(WRenderPass renderPass, WFramebuffer framebuffer);
|
||||
void endRenderPass();
|
||||
void executeCommands(Array<WSecondaryCmdBuffer> secondaryCommands);
|
||||
void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore);
|
||||
enum State
|
||||
{
|
||||
ReadyBegin,
|
||||
InsideBegin,
|
||||
RenderPassActive,
|
||||
Ended,
|
||||
Submitted,
|
||||
};
|
||||
|
||||
private:
|
||||
WRenderPass renderPass;
|
||||
WFramebuffer framebuffer;
|
||||
uint32 subpassIndex;
|
||||
State state;
|
||||
friend class SecondaryCmdBuffer;
|
||||
};
|
||||
DEFINE_REF(CmdBuffer);
|
||||
|
||||
class SecondaryCmdBuffer : public CmdBufferBase
|
||||
{
|
||||
public:
|
||||
SecondaryCmdBuffer(WGraphics graphics, VkCommandPool cmdPool);
|
||||
virtual ~SecondaryCmdBuffer();
|
||||
void begin(WCmdBuffer parent);
|
||||
void end();
|
||||
private:
|
||||
};
|
||||
DEFINE_REF(SecondaryCmdBuffer);
|
||||
|
||||
class CommandBufferManager
|
||||
{
|
||||
public:
|
||||
CommandBufferManager(Vulkan::PGraphics graphics, PVulkanQueue queue);
|
||||
CommandBufferManager(WGraphics graphics, WQueue queue);
|
||||
virtual ~CommandBufferManager();
|
||||
PCmdBuffer getCommands();
|
||||
PSecondaryCommandBuffer createSecondaryCmdBuffer();
|
||||
PSecondaryCmdBuffer createSecondaryCmdBuffer();
|
||||
void submitCommands(PSemaphore signalSemaphore = nullptr);
|
||||
void waitForBuffer(PCommandbuffer cmdBuffer, float timeToWait = 1.0f);
|
||||
void waitForCommands(PCmdBuffer cmdBuffer, float timeToWait = 1.0f);
|
||||
private:
|
||||
WGraphics graphics;
|
||||
VkCommandPool commandPool;
|
||||
QueueType queueType;
|
||||
WQueue queue;
|
||||
uint32 queueFamilyIndex;
|
||||
Array<Vulkan::PCmdBuffer> allocatedBuffers;
|
||||
PCmdBuffer activeCmdBuffer;
|
||||
Array<PCmdBuffer> allocatedBuffers;
|
||||
};
|
||||
DEFINE_REF(VulkanCommandBufferManager);
|
||||
DEFINE_REF(CommandBufferManager);
|
||||
}
|
||||
}
|
||||
@@ -149,7 +149,7 @@ void DescriptorSet::writeChanges()
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout& layout)
|
||||
DescriptorAllocator::DescriptorAllocator(WGraphics graphics, DescriptorLayout& layout)
|
||||
: layout(layout)
|
||||
, graphics(graphics)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "VulkanGraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Vulkan
|
||||
{
|
||||
class Framebuffer
|
||||
{
|
||||
public:
|
||||
Framebuffer(WGraphics graphics);
|
||||
virtual ~Framebuffer();
|
||||
inline VkFramebuffer getHandle() const
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
private:
|
||||
WGraphics graphics;
|
||||
VkFramebuffer handle;
|
||||
};
|
||||
DEFINE_REF(Framebuffer);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
#include "VulkanGraphics.h"
|
||||
#include "VulkanAllocator.h"
|
||||
#include "VulkanQueue.h"
|
||||
#include "Containers/Array.h"
|
||||
#include "VulkanInitializer.h"
|
||||
#include "VulkanCommandBuffer.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
Graphics::Graphics()
|
||||
: callback(VK_NULL_HANDLE)
|
||||
, handle(VK_NULL_HANDLE)
|
||||
, instance(VK_NULL_HANDLE)
|
||||
, physicalDevice(VK_NULL_HANDLE)
|
||||
: callback(VK_NULL_HANDLE), handle(VK_NULL_HANDLE), instance(VK_NULL_HANDLE), physicalDevice(VK_NULL_HANDLE)
|
||||
{
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
@@ -18,6 +17,9 @@ Graphics::Graphics()
|
||||
|
||||
Graphics::~Graphics()
|
||||
{
|
||||
vkDestroyDevice(handle, nullptr);
|
||||
DestroyDebugReportCallbackEXT(instance, nullptr, callback);
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
@@ -26,23 +28,28 @@ void Graphics::init(GraphicsInitializer initInfo)
|
||||
initInstance(initInfo);
|
||||
setupDebugCallback();
|
||||
pickPhysicalDevice();
|
||||
allocator = new VulkanAllocator(this);
|
||||
createDevice(initInfo);
|
||||
allocator = new Allocator(this);
|
||||
graphicsCommands = new CommandBufferManager(this, graphicsQueue);
|
||||
computeCommands = new CommandBufferManager(this, computeQueue);
|
||||
transferCommands = new CommandBufferManager(this, transferQueue);
|
||||
dedicatedTransferCommands = new CommandBufferManager(this, dedicatedTransferQueue);
|
||||
}
|
||||
|
||||
void Graphics::beginFrame(void* windowHandle)
|
||||
void Graphics::beginFrame(void *windowHandle)
|
||||
{
|
||||
GLFWwindow* window = static_cast<GLFWwindow*>(windowHandle);
|
||||
GLFWwindow *window = static_cast<GLFWwindow *>(windowHandle);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
void Graphics::endFrame(void* windowHandle)
|
||||
void Graphics::endFrame(void *windowHandle)
|
||||
{
|
||||
GLFWwindow* window = static_cast<GLFWwindow*>(windowHandle);
|
||||
GLFWwindow *window = static_cast<GLFWwindow *>(windowHandle);
|
||||
}
|
||||
|
||||
void* Graphics::createWindow(const WindowCreateInfo& createInfo)
|
||||
void *Graphics::createWindow(const WindowCreateInfo &createInfo)
|
||||
{
|
||||
GLFWwindow* window = glfwCreateWindow(createInfo.width, createInfo.height, createInfo.title, createInfo.bFullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr);
|
||||
GLFWwindow *window = glfwCreateWindow(createInfo.width, createInfo.height, createInfo.title, createInfo.bFullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr);
|
||||
return window;
|
||||
}
|
||||
|
||||
@@ -56,14 +63,15 @@ VkPhysicalDevice Graphics::getPhysicalDevice() const
|
||||
return physicalDevice;
|
||||
}
|
||||
|
||||
Array<const char*> Graphics::getRequiredExtensions()
|
||||
Array<const char *> Graphics::getRequiredExtensions()
|
||||
{
|
||||
Array<const char*> extensions;
|
||||
Array<const char *> extensions;
|
||||
|
||||
unsigned int glfwExtensionCount = 0;
|
||||
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
||||
const char **glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
||||
|
||||
for (unsigned int i = 0; i < glfwExtensionCount; i++) {
|
||||
for (unsigned int i = 0; i < glfwExtensionCount; i++)
|
||||
{
|
||||
extensions.add(glfwExtensions[i]);
|
||||
}
|
||||
#ifdef ENABLE_VALIDATION
|
||||
@@ -84,7 +92,7 @@ void Graphics::initInstance(GraphicsInitializer initInfo)
|
||||
VkInstanceCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
info.pApplicationInfo = &appInfo;
|
||||
Array<const char*> extensions = getRequiredExtensions();
|
||||
Array<const char *> extensions = getRequiredExtensions();
|
||||
for (uint32 i = 0; i < initInfo.instanceExtensions.size(); ++i)
|
||||
{
|
||||
extensions.add(initInfo.instanceExtensions[i]);
|
||||
@@ -119,8 +127,8 @@ void Graphics::pickPhysicalDevice()
|
||||
for (auto physicalDevice : physicalDevices)
|
||||
{
|
||||
uint32 currentRating = 0;
|
||||
VkPhysicalDeviceProperties props;
|
||||
vkGetPhysicalDeviceProperties(physicalDevice, &props);
|
||||
vkGetPhysicalDeviceFeatures(physicalDevice, &features);
|
||||
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
||||
{
|
||||
currentRating += 100;
|
||||
@@ -138,7 +146,104 @@ void Graphics::pickPhysicalDevice()
|
||||
this->physicalDevice = bestDevice;
|
||||
}
|
||||
|
||||
void Graphics::createDevice()
|
||||
void Graphics::createDevice(GraphicsInitializer initializer)
|
||||
{
|
||||
uint32_t numQueueFamilies = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueueFamilies, nullptr);
|
||||
Array<VkQueueFamilyProperties> queueProperties(numQueueFamilies);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueueFamilies, queueProperties.data());
|
||||
|
||||
Array<VkDeviceQueueCreateInfo> queueInfos;
|
||||
int32_t graphicsQueueFamilyIndex = -1;
|
||||
int32_t transferQueueFamilyIndex = -1;
|
||||
int32_t dedicatedTransferQueueFamilyIndex = -1;
|
||||
int32_t computeQueueFamilyIndex = -1;
|
||||
int32_t asyncComputeFamilyIndex = -1;
|
||||
for (int32_t familyIndex = 0; familyIndex < queueProperties.size(); ++familyIndex)
|
||||
{
|
||||
const VkQueueFamilyProperties currProps = queueProperties[familyIndex];
|
||||
if ((currProps.queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT)
|
||||
{
|
||||
if (graphicsQueueFamilyIndex == -1)
|
||||
{
|
||||
graphicsQueueFamilyIndex = familyIndex;
|
||||
}
|
||||
}
|
||||
if ((currProps.queueFlags & VK_QUEUE_COMPUTE_BIT) == VK_QUEUE_COMPUTE_BIT)
|
||||
{
|
||||
if (computeQueueFamilyIndex == -1)
|
||||
{
|
||||
computeQueueFamilyIndex = familyIndex;
|
||||
}
|
||||
if (Gfx::useAsyncCompute)
|
||||
{
|
||||
if (asyncComputeFamilyIndex == -1)
|
||||
{
|
||||
if (familyIndex == graphicsQueueFamilyIndex)
|
||||
{
|
||||
if (currProps.queueCount > 1)
|
||||
{
|
||||
asyncComputeFamilyIndex = familyIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
asyncComputeFamilyIndex = familyIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((currProps.queueFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT)
|
||||
{
|
||||
if (transferQueueFamilyIndex == -1)
|
||||
{
|
||||
transferQueueFamilyIndex = familyIndex;
|
||||
}
|
||||
if ((currProps.queueFlags ^ VK_QUEUE_TRANSFER_BIT) == 0)
|
||||
{
|
||||
dedicatedTransferQueueFamilyIndex = familyIndex;
|
||||
}
|
||||
}
|
||||
VkDeviceQueueCreateInfo info =
|
||||
init::DeviceQueueCreateInfo(familyIndex, 1);
|
||||
queueInfos.add(info);
|
||||
}
|
||||
VkDeviceCreateInfo deviceInfo = init::DeviceCreateInfo(
|
||||
queueInfos.data(),
|
||||
(uint32)queueInfos.size(),
|
||||
&features);
|
||||
deviceInfo.enabledExtensionCount = (uint32)initializer.deviceExtensions.size();
|
||||
deviceInfo.ppEnabledExtensionNames = initializer.deviceExtensions.data();
|
||||
deviceInfo.enabledLayerCount = (uint32_t)initializer.layers.size();
|
||||
deviceInfo.ppEnabledLayerNames = initializer.layers.data();
|
||||
|
||||
VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle));
|
||||
|
||||
graphicsQueue = new Queue(this, QueueType::GRAPHICS, graphicsQueueFamilyIndex, 0);
|
||||
if (Gfx::useAsyncCompute && asyncComputeFamilyIndex != -1)
|
||||
{
|
||||
if (asyncComputeFamilyIndex == graphicsQueueFamilyIndex)
|
||||
{
|
||||
// Same family as graphics, but different queue
|
||||
computeQueue = new Queue(this, QueueType::COMPUTE, asyncComputeFamilyIndex, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Different family
|
||||
computeQueue = new Queue(this, QueueType::COMPUTE, asyncComputeFamilyIndex, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
computeQueue = new Queue(this, QueueType::COMPUTE, computeQueueFamilyIndex, 0);
|
||||
}
|
||||
transferQueue = new Queue(this, QueueType::TRANSFER, transferQueueFamilyIndex, 0);
|
||||
if (dedicatedTransferQueueFamilyIndex != -1)
|
||||
{
|
||||
dedicatedTransferQueue = new Queue(this, QueueType::DEDICATED_TRANSFER, dedicatedTransferQueueFamilyIndex, 0);
|
||||
}
|
||||
queueMapping.graphicsFamily = graphicsQueue->getFamilyIndex();
|
||||
queueMapping.computeFamily = computeQueue->getFamilyIndex();
|
||||
queueMapping.transferFamily = transferQueue->getFamilyIndex();
|
||||
queueMapping.dedicatedTransferFamily = dedicatedTransferQueue->getFamilyIndex();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "VulkanGraphicsResources.h"
|
||||
|
||||
@@ -6,6 +7,8 @@ namespace Seele
|
||||
namespace Vulkan
|
||||
{
|
||||
DECLARE_REF(Allocator);
|
||||
DECLARE_REF(CommandBufferManager);
|
||||
DECLARE_REF(Queue);
|
||||
class Graphics : public Gfx::Graphics
|
||||
{
|
||||
public:
|
||||
@@ -14,6 +17,11 @@ namespace Seele
|
||||
VkDevice getDevice() const;
|
||||
VkPhysicalDevice getPhysicalDevice() const;
|
||||
|
||||
PCommandBufferManager getGraphicsCommands();
|
||||
PCommandBufferManager getComputeCommands();
|
||||
PCommandBufferManager getTransferCommands();
|
||||
PCommandBufferManager getDedicatedTransferCommands();
|
||||
|
||||
// Inherited via Graphics
|
||||
virtual void init(GraphicsInitializer initializer) override;
|
||||
virtual void beginFrame(void* windowHandle) override;
|
||||
@@ -24,14 +32,27 @@ namespace Seele
|
||||
void initInstance(GraphicsInitializer initInfo);
|
||||
void setupDebugCallback();
|
||||
void pickPhysicalDevice();
|
||||
void createDevice();
|
||||
void createDevice(GraphicsInitializer initInfo);
|
||||
|
||||
VkDevice handle;
|
||||
VkPhysicalDevice physicalDevice;
|
||||
VkInstance instance;
|
||||
|
||||
WQueue graphicsQueue;
|
||||
WQueue computeQueue;
|
||||
WQueue transferQueue;
|
||||
WQueue dedicatedTransferQueue;
|
||||
QueueFamilyMapping queueMapping;
|
||||
PCommandBufferManager graphicsCommands;
|
||||
PCommandBufferManager computeCommands;
|
||||
PCommandBufferManager transferCommands;
|
||||
PCommandBufferManager dedicatedTransferCommands;
|
||||
VkPhysicalDeviceProperties props;
|
||||
VkPhysicalDeviceFeatures features;
|
||||
VkDebugReportCallbackEXT callback;
|
||||
Array<PViewport> viewports;
|
||||
PAllocator allocator;
|
||||
|
||||
friend class Window;
|
||||
};
|
||||
DEFINE_REF(Graphics);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
using namespace Seele::Vulkan;
|
||||
using namespace Seele::Gfx;
|
||||
|
||||
VkDescriptorType cast(const Seele::Gfx::SeDescriptorType& descriptorType)
|
||||
VkDescriptorType Seele::Vulkan::cast(const Seele::Gfx::SeDescriptorType& descriptorType)
|
||||
{
|
||||
switch (descriptorType)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ VkDescriptorType cast(const Seele::Gfx::SeDescriptorType& descriptorType)
|
||||
return VK_DESCRIPTOR_TYPE_MAX_ENUM;
|
||||
}
|
||||
|
||||
Seele::Gfx::SeDescriptorType cast(const VkDescriptorType& descriptorType)
|
||||
Seele::Gfx::SeDescriptorType Seele::Vulkan::cast(const VkDescriptorType& descriptorType)
|
||||
{
|
||||
switch (descriptorType)
|
||||
{
|
||||
@@ -80,7 +80,7 @@ Seele::Gfx::SeDescriptorType cast(const VkDescriptorType& descriptorType)
|
||||
return SE_DESCRIPTOR_TYPE_MAX_ENUM;
|
||||
}
|
||||
|
||||
VkShaderStageFlagBits cast(const Seele::Gfx::SeShaderStageFlagBits& stage)
|
||||
VkShaderStageFlagBits Seele::Vulkan::cast(const Seele::Gfx::SeShaderStageFlagBits& stage)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
@@ -125,7 +125,7 @@ VkShaderStageFlagBits cast(const Seele::Gfx::SeShaderStageFlagBits& stage)
|
||||
return VK_SHADER_STAGE_ALL;
|
||||
}
|
||||
|
||||
Seele::Gfx::SeShaderStageFlagBits cast(const VkShaderStageFlagBits& stage)
|
||||
Seele::Gfx::SeShaderStageFlagBits Seele::Vulkan::cast(const VkShaderStageFlagBits& stage)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "VulkanGraphicsResources.h"
|
||||
#include "VulkanInitializer.h"
|
||||
#include "VulkanGraphics.h"
|
||||
#include "VulkanGraphicsEnums.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
Semaphore::Semaphore(WGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
VkSemaphoreCreateInfo info =
|
||||
init::SemaphoreCreateInfo();
|
||||
VK_CHECK(vkCreateSemaphore(graphics->getDevice(), &info, nullptr, &handle));
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -4,189 +4,240 @@
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Vulkan
|
||||
namespace Vulkan
|
||||
{
|
||||
|
||||
DECLARE_REF(DescriptorAllocator);
|
||||
DECLARE_REF(CommandBufferManager);
|
||||
DECLARE_REF(Graphics);
|
||||
class Semaphore
|
||||
{
|
||||
public:
|
||||
Semaphore(WGraphics graphics);
|
||||
virtual ~Semaphore();
|
||||
|
||||
private:
|
||||
VkSemaphore handle;
|
||||
WGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(Semaphore);
|
||||
|
||||
class DescriptorLayout : public Gfx::DescriptorLayout
|
||||
{
|
||||
public:
|
||||
DescriptorLayout(WGraphics graphics)
|
||||
: graphics(graphics), layoutHandle(VK_NULL_HANDLE)
|
||||
{
|
||||
DECLARE_REF(DescriptorAllocator);
|
||||
DECLARE_REF(Graphics);
|
||||
class DescriptorLayout : public Gfx::DescriptorLayout
|
||||
{
|
||||
public:
|
||||
DescriptorLayout(PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
, layoutHandle(VK_NULL_HANDLE)
|
||||
{}
|
||||
virtual ~DescriptorLayout();
|
||||
virtual void create();
|
||||
inline VkDescriptorSetLayout getHandle() const
|
||||
{
|
||||
return layoutHandle;
|
||||
}
|
||||
private:
|
||||
PGraphics graphics;
|
||||
Array<VkDescriptorSetLayoutBinding> bindings;
|
||||
VkDescriptorSetLayout layoutHandle;
|
||||
friend class PipelineStateCacheManager;
|
||||
};
|
||||
DEFINE_REF(DescriptorLayout);
|
||||
class PipelineLayout : public Gfx::PipelineLayout
|
||||
{
|
||||
public:
|
||||
PipelineLayout(PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
, layoutHash(0)
|
||||
, layoutHandle(VK_NULL_HANDLE)
|
||||
{}
|
||||
virtual ~PipelineLayout();
|
||||
virtual void create();
|
||||
inline VkPipelineLayout getHandle() const
|
||||
{
|
||||
return layoutHandle;
|
||||
}
|
||||
virtual uint32 getHash() const
|
||||
{
|
||||
return layoutHash;
|
||||
}
|
||||
private:
|
||||
Array<VkDescriptorSetLayout> vulkanDescriptorLayouts;
|
||||
uint32 layoutHash;
|
||||
VkPipelineLayout layoutHandle;
|
||||
PGraphics graphics;
|
||||
friend class PipelineStateCacheManager;
|
||||
};
|
||||
DEFINE_REF(PipelineLayout);
|
||||
|
||||
class DescriptorSet : public Gfx::DescriptorSet
|
||||
{
|
||||
public:
|
||||
DescriptorSet(PGraphics graphics, PDescriptorAllocator owner)
|
||||
: graphics(graphics)
|
||||
, owner(owner)
|
||||
, setHandle(VK_NULL_HANDLE)
|
||||
{}
|
||||
virtual ~DescriptorSet();
|
||||
virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer);
|
||||
virtual void updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer);
|
||||
virtual void updateSampler(uint32_t binding, Gfx::PSamplerState samplerState);
|
||||
virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState sampler = nullptr);
|
||||
virtual bool operator<(Gfx::PDescriptorSet other);
|
||||
inline VkDescriptorSet getHandle() const
|
||||
{
|
||||
return setHandle;
|
||||
}
|
||||
private:
|
||||
virtual void writeChanges();
|
||||
Array<VkDescriptorImageInfo> imageInfos;
|
||||
Array<VkDescriptorBufferInfo> bufferInfos;
|
||||
Array<VkWriteDescriptorSet> writeDescriptors;
|
||||
VkDescriptorSet setHandle;
|
||||
PDescriptorAllocator owner;
|
||||
PGraphics graphics;
|
||||
friend class DescriptorAllocator;
|
||||
};
|
||||
DEFINE_REF(DescriptorSet);
|
||||
|
||||
class DescriptorAllocator : public Gfx::DescriptorAllocator
|
||||
{
|
||||
public:
|
||||
DescriptorAllocator(PGraphics graphics, DescriptorLayout& layout);
|
||||
~DescriptorAllocator();
|
||||
virtual void allocateDescriptorSet(Gfx::PDescriptorSet& descriptorSet);
|
||||
|
||||
inline VkDescriptorPool getHandle()
|
||||
{
|
||||
return poolHandle;
|
||||
}
|
||||
private:
|
||||
PGraphics graphics;
|
||||
int maxSets = 512;
|
||||
VkDescriptorPool poolHandle;
|
||||
DescriptorLayout& layout;
|
||||
};
|
||||
DEFINE_REF(DescriptorAllocator);
|
||||
enum class QueueType
|
||||
{
|
||||
GRAPHICS = 1,
|
||||
COMPUTE = 2,
|
||||
TRANSFER = 3
|
||||
};
|
||||
class QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
QueueOwnedResource(PGraphics graphics, QueueType startQueueType);
|
||||
~QueueOwnedResource();
|
||||
CommandBufferManager* getCommands();
|
||||
//Preliminary checks to see if the barrier should be executed at all
|
||||
void transferOwnership(QueueType newOwner);
|
||||
protected:
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
QueueType currentOwner;
|
||||
PGraphics graphics;
|
||||
CommandBufferManager* cachedCmdBufferManager;
|
||||
};
|
||||
DEFINE_REF(QueueOwnedResource);
|
||||
|
||||
class Buffer : public QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage);
|
||||
virtual ~Buffer();
|
||||
private:
|
||||
virtual VkAccessFlags getSourceAccessMask() = 0;
|
||||
virtual VkAccessFlags getDestAccessMask() = 0;
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner);
|
||||
};
|
||||
DEFINE_REF(Buffer);
|
||||
|
||||
class UniformBuffer : public Gfx::UniformBuffer
|
||||
{
|
||||
|
||||
};
|
||||
DEFINE_REF(UniformBuffer);
|
||||
|
||||
class StructuredBuffer : public Gfx::StructuredBuffer
|
||||
{
|
||||
|
||||
};
|
||||
DEFINE_REF(StructuredBuffer);
|
||||
|
||||
class TextureBase
|
||||
{
|
||||
private:
|
||||
uint32 sizeX;
|
||||
uint32 sizeY;
|
||||
uint32 sizeZ;
|
||||
uint32 arrayCount;
|
||||
uint32 layerCount;
|
||||
};
|
||||
DEFINE_REF(TextureBase);
|
||||
|
||||
class Texture2D : public Gfx::Texture2D
|
||||
{
|
||||
public:
|
||||
private:
|
||||
PTextureBase textureHandle;
|
||||
};
|
||||
DEFINE_REF(Texture2D);
|
||||
|
||||
class SamplerState
|
||||
{
|
||||
public:
|
||||
VkSampler sampler;
|
||||
};
|
||||
DEFINE_REF(SamplerState);
|
||||
|
||||
class Viewport : public Gfx::Viewport
|
||||
{
|
||||
public:
|
||||
private:
|
||||
uint32 sizeX;
|
||||
uint32 sizeY;
|
||||
uint32 offsetX;
|
||||
uint32 offsetY;
|
||||
VkSwapchainKHR swapchain;
|
||||
void* windowHandle;
|
||||
};
|
||||
DECLARE_REF(Viewport);
|
||||
}
|
||||
}
|
||||
virtual ~DescriptorLayout();
|
||||
virtual void create();
|
||||
inline VkDescriptorSetLayout getHandle() const
|
||||
{
|
||||
return layoutHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
WGraphics graphics;
|
||||
Array<VkDescriptorSetLayoutBinding> bindings;
|
||||
VkDescriptorSetLayout layoutHandle;
|
||||
friend class PipelineStateCacheManager;
|
||||
};
|
||||
DEFINE_REF(DescriptorLayout);
|
||||
class PipelineLayout : public Gfx::PipelineLayout
|
||||
{
|
||||
public:
|
||||
PipelineLayout(WGraphics graphics)
|
||||
: graphics(graphics), layoutHash(0), layoutHandle(VK_NULL_HANDLE)
|
||||
{
|
||||
}
|
||||
virtual ~PipelineLayout();
|
||||
virtual void create();
|
||||
inline VkPipelineLayout getHandle() const
|
||||
{
|
||||
return layoutHandle;
|
||||
}
|
||||
virtual uint32 getHash() const
|
||||
{
|
||||
return layoutHash;
|
||||
}
|
||||
|
||||
private:
|
||||
Array<VkDescriptorSetLayout> vulkanDescriptorLayouts;
|
||||
uint32 layoutHash;
|
||||
VkPipelineLayout layoutHandle;
|
||||
WGraphics graphics;
|
||||
friend class PipelineStateCacheManager;
|
||||
};
|
||||
DEFINE_REF(PipelineLayout);
|
||||
|
||||
class DescriptorSet : public Gfx::DescriptorSet
|
||||
{
|
||||
public:
|
||||
DescriptorSet(WGraphics graphics, PDescriptorAllocator owner)
|
||||
: graphics(graphics), owner(owner), setHandle(VK_NULL_HANDLE)
|
||||
{
|
||||
}
|
||||
virtual ~DescriptorSet();
|
||||
virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer);
|
||||
virtual void updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer);
|
||||
virtual void updateSampler(uint32_t binding, Gfx::PSamplerState samplerState);
|
||||
virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState sampler = nullptr);
|
||||
virtual bool operator<(Gfx::PDescriptorSet other);
|
||||
inline VkDescriptorSet getHandle() const
|
||||
{
|
||||
return setHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void writeChanges();
|
||||
Array<VkDescriptorImageInfo> imageInfos;
|
||||
Array<VkDescriptorBufferInfo> bufferInfos;
|
||||
Array<VkWriteDescriptorSet> writeDescriptors;
|
||||
VkDescriptorSet setHandle;
|
||||
PDescriptorAllocator owner;
|
||||
WGraphics graphics;
|
||||
friend class DescriptorAllocator;
|
||||
};
|
||||
DEFINE_REF(DescriptorSet);
|
||||
|
||||
class DescriptorAllocator : public Gfx::DescriptorAllocator
|
||||
{
|
||||
public:
|
||||
DescriptorAllocator(WGraphics graphics, DescriptorLayout &layout);
|
||||
~DescriptorAllocator();
|
||||
virtual void allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet);
|
||||
|
||||
inline VkDescriptorPool getHandle()
|
||||
{
|
||||
return poolHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
WGraphics graphics;
|
||||
int maxSets = 512;
|
||||
VkDescriptorPool poolHandle;
|
||||
DescriptorLayout &layout;
|
||||
};
|
||||
DEFINE_REF(DescriptorAllocator);
|
||||
enum class QueueType
|
||||
{
|
||||
GRAPHICS = 1,
|
||||
COMPUTE = 2,
|
||||
TRANSFER = 3,
|
||||
DEDICATED_TRANSFER = 4
|
||||
};
|
||||
|
||||
struct QueueFamilyMapping
|
||||
{
|
||||
uint32 graphicsFamily;
|
||||
uint32 computeFamily;
|
||||
uint32 transferFamily;
|
||||
uint32 dedicatedTransferFamily;
|
||||
uint32 getQueueTypeFamilyIndex(QueueType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case QueueType::GRAPHICS:
|
||||
return graphicsFamily;
|
||||
case QueueType::COMPUTE:
|
||||
return computeFamily;
|
||||
case QueueType::TRANSFER:
|
||||
return transferFamily;
|
||||
case QueueType::DEDICATED_TRANSFER:
|
||||
return dedicatedTransferFamily;
|
||||
default:
|
||||
return VK_QUEUE_FAMILY_IGNORED;
|
||||
}
|
||||
}
|
||||
bool needsTransfer(QueueType src, QueueType dst)
|
||||
{
|
||||
uint32 srcIndex = getQueueTypeFamilyIndex(src);
|
||||
uint32 dstIndex = getQueueTypeFamilyIndex(dst);
|
||||
return srcIndex != dstIndex;
|
||||
}
|
||||
};
|
||||
class QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
QueueOwnedResource(WGraphics graphics, QueueType startQueueType);
|
||||
~QueueOwnedResource();
|
||||
PCommandBufferManager getCommands();
|
||||
//Preliminary checks to see if the barrier should be executed at all
|
||||
void transferOwnership(QueueType newOwner);
|
||||
|
||||
protected:
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
QueueType currentOwner;
|
||||
WGraphics graphics;
|
||||
CommandBufferManager *cachedCmdBufferManager;
|
||||
};
|
||||
DEFINE_REF(QueueOwnedResource);
|
||||
|
||||
class Buffer : public QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
Buffer(WGraphics graphics, uint32 size, VkBufferUsageFlags usage);
|
||||
virtual ~Buffer();
|
||||
|
||||
private:
|
||||
virtual VkAccessFlags getSourceAccessMask() = 0;
|
||||
virtual VkAccessFlags getDestAccessMask() = 0;
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner);
|
||||
};
|
||||
DEFINE_REF(Buffer);
|
||||
|
||||
class UniformBuffer : public Buffer, public Gfx::UniformBuffer
|
||||
{
|
||||
};
|
||||
DEFINE_REF(UniformBuffer);
|
||||
|
||||
class StructuredBuffer : public Buffer, public Gfx::StructuredBuffer
|
||||
{
|
||||
};
|
||||
DEFINE_REF(StructuredBuffer);
|
||||
|
||||
class TextureBase
|
||||
{
|
||||
public:
|
||||
TextureBase();
|
||||
virtual ~TextureBase();
|
||||
private:
|
||||
uint32 sizeX;
|
||||
uint32 sizeY;
|
||||
uint32 sizeZ;
|
||||
uint32 arrayCount;
|
||||
uint32 layerCount;
|
||||
VkImage image;
|
||||
};
|
||||
DEFINE_REF(TextureBase);
|
||||
|
||||
class Texture2D : public Gfx::Texture2D
|
||||
{
|
||||
public:
|
||||
private:
|
||||
PTextureBase textureHandle;
|
||||
};
|
||||
DEFINE_REF(Texture2D);
|
||||
|
||||
class SamplerState
|
||||
{
|
||||
public:
|
||||
VkSampler sampler;
|
||||
};
|
||||
DEFINE_REF(SamplerState);
|
||||
|
||||
class Viewport : public Gfx::Viewport
|
||||
{
|
||||
public:
|
||||
private:
|
||||
uint32 sizeX;
|
||||
uint32 sizeY;
|
||||
uint32 offsetX;
|
||||
uint32 offsetY;
|
||||
VkSwapchainKHR swapchain;
|
||||
void *windowHandle;
|
||||
};
|
||||
DECLARE_REF(Viewport);
|
||||
} // namespace Vulkan
|
||||
} // namespace Seele
|
||||
@@ -743,11 +743,11 @@ VkPipelineShaderStageCreateInfo init::PipelineShaderStageCreateInfo(VkShaderStag
|
||||
}
|
||||
|
||||
|
||||
VkBool32 debugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t obj, size_t location, int32_t code, const char* layerPrefix, const char* msg, void* userDataManager) {
|
||||
VkBool32 Seele::Vulkan::debugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t obj, size_t location, int32_t code, const char* layerPrefix, const char* msg, void* userDataManager) {
|
||||
std::cerr << layerPrefix << ": " << msg << std::endl;
|
||||
return VK_FALSE;
|
||||
}
|
||||
VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback) {
|
||||
VkResult Seele::Vulkan::CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback) {
|
||||
auto func = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT");
|
||||
if (func != nullptr) {
|
||||
return func(instance, pCreateInfo, pAllocator, pCallback);
|
||||
@@ -757,7 +757,7 @@ VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCa
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyDebugReportCallbackEXT(VkInstance instance, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT pCallback)
|
||||
void Seele::Vulkan::DestroyDebugReportCallbackEXT(VkInstance instance, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT pCallback)
|
||||
{
|
||||
auto func = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT");
|
||||
if (func != nullptr) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
#include "Containers/Array.h"
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "VulkanQueue.h"
|
||||
#include "VulkanInitializer.h"
|
||||
#include "VulkanGraphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
Queue::Queue(WGraphics graphics, QueueType queueType, uint32 familyIndex, uint32 queueIndex)
|
||||
: familyIndex(familyIndex)
|
||||
, graphics(graphics)
|
||||
, queueType(queueType)
|
||||
{
|
||||
vkGetDeviceQueue(graphics->getDevice(), familyIndex, queueIndex, &queue);
|
||||
}
|
||||
|
||||
Queue::~Queue()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include "VulkanGraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Vulkan
|
||||
{
|
||||
DECLARE_REF(CmdBuffer);
|
||||
DECLARE_REF(Graphics);
|
||||
class Queue
|
||||
{
|
||||
public:
|
||||
Queue(WGraphics graphics, QueueType queueType, uint32 familyIndex, uint32 queueIndex);
|
||||
virtual ~Queue();
|
||||
void submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores = 0, VkSemaphore* signalSemaphore = nullptr);
|
||||
inline void submitCommandBuffer(PCmdBuffer cmdBuffer, VkSemaphore signalSemaphore)
|
||||
{
|
||||
submitCommandBuffer(cmdBuffer, 1, &signalSemaphore);
|
||||
}
|
||||
uint32 getFamilyIndex() const
|
||||
{
|
||||
return familyIndex;
|
||||
}
|
||||
inline VkQueue getHandle() const
|
||||
{
|
||||
return queue;
|
||||
}
|
||||
private:
|
||||
WGraphics graphics;
|
||||
VkQueue queue;
|
||||
uint32 familyIndex;
|
||||
QueueType queueType;
|
||||
};
|
||||
DEFINE_REF(Queue)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "VulkanGraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Vulkan
|
||||
{
|
||||
class RenderPass
|
||||
{
|
||||
public:
|
||||
RenderPass();
|
||||
virtual ~RenderPass();
|
||||
inline VkRenderPass getHandle() const
|
||||
{
|
||||
return renderPass;
|
||||
}
|
||||
inline uint32 getClearValueCount() const
|
||||
{
|
||||
return clearValues.size();
|
||||
}
|
||||
inline VkClearValue* getClearValues() const
|
||||
{
|
||||
return clearValues.data();
|
||||
}
|
||||
inline VkRect2D getRenderArea() const
|
||||
{
|
||||
return renderArea;
|
||||
}
|
||||
inline VkSubpassContents getSubpassContents() const
|
||||
{
|
||||
return subpassContents;
|
||||
}
|
||||
private:
|
||||
VkRenderPass renderPass;
|
||||
Array<VkClearValue> clearValues;
|
||||
VkRect2D renderArea;
|
||||
VkSubpassContents subpassContents;
|
||||
};
|
||||
DEFINE_REF(RenderPass);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
Seele::WindowManager::WindowManager()
|
||||
{
|
||||
graphics = new VulkanGraphics();
|
||||
graphics = new Vulkan::Graphics();
|
||||
GraphicsInitializer initializer;
|
||||
graphics->init(initializer);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ namespace Seele
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~RefObject()
|
||||
{}
|
||||
bool operator==(const RefObject& other) const
|
||||
@@ -81,6 +80,10 @@ namespace Seele
|
||||
{
|
||||
object = nullptr;
|
||||
}
|
||||
RefPtr(nullptr_t)
|
||||
{
|
||||
object = nullptr;
|
||||
}
|
||||
RefPtr(T* ptr)
|
||||
{
|
||||
object = new RefObject<T>(ptr);
|
||||
@@ -160,14 +163,19 @@ namespace Seele
|
||||
private:
|
||||
RefObject<T>* object;
|
||||
};
|
||||
//A weak pointer has no ownership over an object and thus cant delete it
|
||||
template<typename T>
|
||||
class WeakPtr
|
||||
{
|
||||
public:
|
||||
WeakPtr()
|
||||
: pointer(nullptr)
|
||||
{}
|
||||
WeakPtr(T* ptr)
|
||||
: pointer(ptr)
|
||||
{}
|
||||
WeakPtr(RefPtr<T>& sharedPtr)
|
||||
: pointer(sharedPtr.object)
|
||||
: pointer(sharedPtr.object->handle)
|
||||
{}
|
||||
WeakPtr& operator=(WeakPtr<T>& weakPtr)
|
||||
{
|
||||
@@ -176,17 +184,20 @@ namespace Seele
|
||||
}
|
||||
WeakPtr& operator=(RefPtr<T>& sharedPtr)
|
||||
{
|
||||
pointer = sharedPtr;
|
||||
pointer = sharedPtr.object->handle;
|
||||
return *this;
|
||||
}
|
||||
RefPtr<T>& lock()
|
||||
WeakPtr& operator=(T* ptr)
|
||||
{
|
||||
RefPtr<T> temp;
|
||||
temp.object = pointer;
|
||||
return temp;
|
||||
pointer = ptr;
|
||||
return *this;
|
||||
}
|
||||
inline T* operator->()
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
private:
|
||||
RefObject<T>* pointer;
|
||||
T* pointer;
|
||||
};
|
||||
template<typename T>
|
||||
class UniquePtr
|
||||
|
||||
Reference in New Issue
Block a user