Implementing Commandbuffers

This commit is contained in:
Dynamitos
2020-03-24 21:05:32 +01:00
parent fda46a7ab8
commit ae92439164
27 changed files with 779 additions and 311 deletions
+8
View File
@@ -0,0 +1,8 @@
{
"C_Cpp.default.configurationProvider": "go2sh.cmake-integration",
"telemetry.enableTelemetry": false,
"cmake.buildDirectory": "${workspaceFolder}/bin/${buildType}",
"files.associations": {
"xstring": "cpp"
}
}
+1
View File
@@ -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)
+2
View File
@@ -4,6 +4,8 @@ namespace Seele
{
namespace Gfx
{
static bool useAsyncCompute = true;
typedef uint32_t SeFlags;
typedef uint32_t SeBool32;
typedef uint64_t SeDeviceSize;
-3
View File
@@ -54,9 +54,6 @@ namespace Seele
uint32_t offset;
uint32_t size;
};
class RenderCommandBase
{
-5
View File
@@ -21,11 +21,6 @@ void Seele::RenderCore::init()
void Seele::RenderCore::renderLoop()
{
while (true)
{
windowManager->beginFrame();
windowManager->endFrame();
}
}
void Seele::RenderCore::shutdown()
+10 -1
View File
@@ -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);
+3 -3
View File
@@ -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);
+2 -64
View File
@@ -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);
}
}
+123 -18
View File
@@ -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();
}
+22 -1
View File
@@ -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()
{
}
+36
View File
@@ -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);
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
Seele::WindowManager::WindowManager()
{
graphics = new VulkanGraphics();
graphics = new Vulkan::Graphics();
GraphicsInitializer initializer;
graphics->init(initializer);
}
+19 -8
View File
@@ -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