Adding nlohmanns json library

This commit is contained in:
Dynamitos
2020-05-05 01:52:07 +02:00
parent 3ef8342247
commit bb5b48698a
83 changed files with 2426 additions and 646 deletions
@@ -18,6 +18,12 @@ target_sources(SeeleEngine
VulkanInitializer.cpp
VulkanRenderPass.h
VulkanRenderPass.cpp
VulkanPipeline.h
VulkanPipeline.cpp
VulkanPipelineCache.h
VulkanPipelineCache.cpp
VulkanShader.h
VulkanShader.cpp
VulkanTexture.cpp
VulkanQueue.h
VulkanQueue.cpp
+41 -58
View File
@@ -5,12 +5,8 @@
using namespace Seele::Vulkan;
SubAllocation::SubAllocation(Allocation* owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize)
: owner(owner)
, size(size)
, allocatedOffset(allocatedOffset)
, alignedOffset(alignedOffset)
, allocatedSize(allocatedSize)
SubAllocation::SubAllocation(Allocation *owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize)
: owner(owner), size(size), allocatedOffset(allocatedOffset), alignedOffset(alignedOffset), allocatedSize(allocatedSize)
{
}
@@ -29,9 +25,9 @@ bool SubAllocation::isReadable() const
return owner->isReadable();
}
void* SubAllocation::getMappedPointer()
void *SubAllocation::getMappedPointer()
{
return (uint8*)owner->getMappedPointer() + alignedOffset;
return (uint8 *)owner->getMappedPointer() + alignedOffset;
}
void SubAllocation::flushMemory()
@@ -44,15 +40,9 @@ void SubAllocation::invalidateMemory()
owner->invalidateMemory();
}
Allocation::Allocation(PGraphics graphics, Allocator* allocator, VkDeviceSize size, uint8 memoryTypeIndex,
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo* dedicatedInfo)
: device(graphics->getDevice())
, allocator(allocator)
, bytesAllocated(0)
, bytesUsed(0)
, readable(properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
, properties(properties)
, memoryTypeIndex(memoryTypeIndex)
Allocation::Allocation(PGraphics graphics, Allocator *allocator, VkDeviceSize size, uint8 memoryTypeIndex,
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
: device(graphics->getDevice()), allocator(allocator), bytesAllocated(0), bytesUsed(0), readable(properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), properties(properties), memoryTypeIndex(memoryTypeIndex)
{
VkMemoryAllocateInfo allocInfo =
init::MemoryAllocateInfo();
@@ -110,8 +100,8 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
{
freeAllocation->size -= size;
freeAllocation->allocatedSize -= size;
freeAllocation->allocatedOffset += allocatedOffset;
freeAllocation->alignedOffset += allocatedOffset;
freeAllocation->allocatedOffset += size;
freeAllocation->alignedOffset += size;
PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size);
activeAllocations[allocatedOffset] = subAlloc.getHandle();
freeRanges.erase(allocatedOffset);
@@ -123,15 +113,15 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
return nullptr;
}
void Allocation::markFree(SubAllocation* allocation)
void Allocation::markFree(SubAllocation *allocation)
{
VkDeviceSize lowerBound = allocation->allocatedOffset;
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
PSubAllocation allocHandle;
for(auto freeRange : freeRanges)
for (auto freeRange : freeRanges)
{
PSubAllocation freeAlloc = freeRange.value;
if(freeAlloc->allocatedOffset + freeAlloc->allocatedSize + 1 == lowerBound)
if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize + 1 == lowerBound)
{
freeAlloc->allocatedSize += allocation->allocatedSize;
allocHandle = freeAlloc;
@@ -139,9 +129,9 @@ void Allocation::markFree(SubAllocation* allocation)
}
}
auto foundAlloc = freeRanges.find(upperBound + 1);
if(foundAlloc != freeRanges.end())
if (foundAlloc != freeRanges.end())
{
if(allocHandle == nullptr)
if (allocHandle == nullptr)
{
allocHandle->allocatedSize += foundAlloc->value->allocatedSize;
freeRanges.erase(foundAlloc->key);
@@ -153,7 +143,7 @@ void Allocation::markFree(SubAllocation* allocation)
allocHandle->alignedOffset -= allocation->allocatedSize;
}
}
if(allocHandle == nullptr)
if (allocHandle == nullptr)
{
allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize);
freeRanges[allocation->allocatedOffset] = allocHandle;
@@ -170,16 +160,16 @@ Allocator::Allocator(PGraphics graphics)
for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
{
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
HeapInfo& heapInfo = heaps[i];
HeapInfo &heapInfo = heaps[i];
heapInfo.maxSize = memoryHeap.size;
}
}
Allocator::~Allocator()
{
for(auto heap : heaps)
for (auto heap : heaps)
{
for(auto alloc : heap.allocations)
for (auto alloc : heap.allocations)
{
assert(alloc->activeAllocations.empty());
assert(alloc->freeRanges.size() == 1);
@@ -189,45 +179,45 @@ Allocator::~Allocator()
graphics = nullptr;
}
PSubAllocation Allocator::allocate(const VkMemoryRequirements2& memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo* dedicatedInfo)
PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
{
const VkMemoryRequirements& requirements = memRequirements2.memoryRequirements;
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
uint8 memoryTypeIndex;
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
if(memRequirements2.pNext != nullptr)
if (memRequirements2.pNext != nullptr)
{
VkMemoryDedicatedRequirements* dedicatedReq = (VkMemoryDedicatedRequirements*)memRequirements2.pNext;
if(dedicatedReq->prefersDedicatedAllocation)
VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext;
if (dedicatedReq->prefersDedicatedAllocation)
{
PAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
heaps[heapIndex].allocations.add(newAllocation);
return newAllocation->getSuballocation(requirements.size, requirements.alignment);
}
}
for(auto alloc : heaps[heapIndex].allocations)
for (auto alloc : heaps[heapIndex].allocations)
{
PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
if(suballoc != nullptr)
if (suballoc != nullptr)
{
return suballoc;
}
}
// no suitable allocations found, allocate new block
PAllocation newAllocation = new Allocation(graphics, this, (requirements.size > MemoryBlockSize) ? requirements.size : MemoryBlockSize, memoryTypeIndex, properties, nullptr);
heaps[heapIndex].allocations.add(newAllocation);
return newAllocation->getSuballocation(requirements.size, requirements.alignment);
}
void Allocator::free(Allocation* allocation)
void Allocator::free(Allocation *allocation)
{
for(auto heap : heaps)
for (auto heap : heaps)
{
for(uint32 i = 0; i < heap.allocations.size(); ++i)
for (uint32 i = 0; i < heap.allocations.size(); ++i)
{
if(heap.allocations[i] == allocation)
if (heap.allocations[i] == allocation)
{
heap.allocations.remove(i, false);
return;
@@ -236,7 +226,7 @@ void Allocator::free(Allocation* allocation)
}
}
VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8* typeIndex)
VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex)
{
for (uint8 memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex)
{
@@ -250,43 +240,37 @@ VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags proper
}
typeBits >>= 1;
}
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
StagingBuffer::StagingBuffer()
{
}
StagingBuffer::~StagingBuffer()
{
}
StagingManager::StagingManager(PGraphics graphics, PAllocator allocator)
: graphics(graphics)
, allocator(allocator)
: graphics(graphics), allocator(allocator)
{
}
StagingManager::~StagingManager()
{
}
void StagingManager::clearPending()
{
}
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
{
for(auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
{
for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
{
auto freeBuffer = *it;
if(freeBuffer->allocation->getSize() == size && freeBuffer->allocation->isReadable() == bCPURead)
if (freeBuffer->allocation->getSize() == size && freeBuffer->allocation->isReadable() == bCPURead)
{
activeBuffers.add(freeBuffer.getHandle());
freeBuffers.remove(it, false);
@@ -311,14 +295,13 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF
bufferQuery.buffer = stagingBuffer->buffer;
vkGetBufferMemoryRequirements2(vulkanDevice, &bufferQuery, &memReqs);
memReqs.memoryRequirements.alignment =
(16 > memReqs.memoryRequirements.alignment) ?
16 : memReqs.memoryRequirements.alignment;
memReqs.memoryRequirements.alignment =
(16 > memReqs.memoryRequirements.alignment) ? 16 : memReqs.memoryRequirements.alignment;
stagingBuffer->allocation = allocator->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | (bCPURead ? VK_MEMORY_PROPERTY_HOST_CACHED_BIT : VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), stagingBuffer->buffer);
stagingBuffer->allocation = allocator->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | (bCPURead ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : VK_MEMORY_PROPERTY_HOST_CACHED_BIT), stagingBuffer->buffer);
stagingBuffer->bReadable = bCPURead;
vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset());
activeBuffers.add(stagingBuffer.getHandle());
return stagingBuffer;
}
+17 -11
View File
@@ -58,9 +58,14 @@ Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::Q
Buffer::~Buffer()
{
auto fence = getCommands()->getCommands()->getFence();
auto &deletionQueue = graphics->getDeletionQueue();
VkDevice device = graphics->getDevice();
VkBuffer buf[Gfx::numFramesBuffered];
for (uint32 i = 0; i < numBuffers; ++i)
{
vkDestroyBuffer(graphics->getDevice(), buffers[i].buffer, nullptr);
buf[i] = buffers[i].buffer;
deletionQueue.addPendingDelete(fence, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); });
buffers[i].allocation = nullptr;
}
}
@@ -221,10 +226,9 @@ void Buffer::unlock()
std::memset(&region, 0, sizeof(VkBufferCopy));
region.size = size;
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
graphics->getStagingManager()->releaseStagingBuffer(stagingBuffer);
}
transferOwnership(pending.prevQueue);
graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer);
}
}
@@ -278,13 +282,14 @@ VkAccessFlags StructuredBuffer::getDestAccessMask()
return VK_ACCESS_MEMORY_READ_BIT;
}
VertexBuffer::VertexBuffer(PGraphics graphics, const BulkResourceData &resourceData)
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.owner)
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData)
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner)
, Gfx::VertexBuffer(resourceData.numVertices, resourceData.vertexSize)
{
if (resourceData.data != nullptr)
if (resourceData.resourceData.data != nullptr)
{
void *data = lock();
std::memcpy(data, resourceData.data, resourceData.size);
std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size);
unlock();
}
}
@@ -303,13 +308,14 @@ VkAccessFlags VertexBuffer::getDestAccessMask()
return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
}
IndexBuffer::IndexBuffer(PGraphics graphics, const BulkResourceData &resourceData)
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.owner)
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData)
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner)
, Gfx::IndexBuffer(resourceData.resourceData.size, resourceData.indexType)
{
if (resourceData.data != nullptr)
if (resourceData.resourceData.data != nullptr)
{
void *data = lock();
std::memcpy(data, resourceData.data, resourceData.size);
std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size);
unlock();
}
}
@@ -1,9 +1,12 @@
#include "VulkanCommandBuffer.h"
#include "VulkanInitializer.h"
#include "VulkanGraphics.h"
#include "VulkanPipeline.h"
#include "VulkanGraphicsEnums.h"
#include "VulkanFramebuffer.h"
#include "VulkanRenderPass.h"
#include "VulkanPipeline.h"
#include "VulkanDescriptorSets.h"
using namespace Seele;
using namespace Seele::Vulkan;
@@ -74,7 +77,6 @@ void CmdBuffer::endRenderPass()
{
vkCmdEndRenderPass(handle);
state = State::InsideBegin;
}
void CmdBuffer::executeCommands(Array<PSecondaryCmdBuffer> commands)
@@ -112,6 +114,11 @@ void CmdBuffer::refreshFence()
}
}
PFence CmdBuffer::getFence()
{
return fence;
}
SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool)
: CmdBufferBase(graphics, cmdPool)
{
@@ -145,6 +152,33 @@ void SecondaryCmdBuffer::end()
VK_CHECK(vkEndCommandBuffer(handle));
}
void SecondaryCmdBuffer::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline)
{
pipeline = gfxPipeline.cast<GraphicsPipeline>();
pipeline->bind(handle);
}
void SecondaryCmdBuffer::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
{
VkDescriptorSet setHandle = descriptorSet.cast<DescriptorSet>()->getHandle();
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr);
}
void SecondaryCmdBuffer::bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer)
{
PVertexBuffer buf = vertexBuffer.cast<VertexBuffer>();
const VkBuffer bufHandle[1] = {buf->getHandle()};
const VkDeviceSize offsets[1] = {0};
vkCmdBindVertexBuffers(handle, 0, 1, bufHandle, offsets);
}
void SecondaryCmdBuffer::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
{
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, VK_INDEX_TYPE_UINT16);
}
void SecondaryCmdBuffer::draw(DrawInstance data)
{
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, data.firstInstance);
}
CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue)
: graphics(graphics), queue(queue)
{
@@ -220,4 +254,4 @@ void CommandBufferManager::waitForCommands(PCmdBuffer cmdBuffer, uint32 timeout)
{
cmdBuffer->fence->wait(timeout);
cmdBuffer->refreshFence();
}
}
@@ -8,7 +8,7 @@ namespace Vulkan
{
DECLARE_REF(RenderPass);
DECLARE_REF(Framebuffer);
class CmdBufferBase : public Gfx::RenderCommandBase
class CmdBufferBase
{
public:
CmdBufferBase(PGraphics graphics, VkCommandPool cmdPool);
@@ -41,6 +41,7 @@ public:
void executeCommands(Array<PSecondaryCmdBuffer> secondaryCommands);
void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore);
void refreshFence();
PFence getFence();
enum State
{
ReadyBegin,
@@ -64,15 +65,22 @@ private:
};
DEFINE_REF(CmdBuffer);
class SecondaryCmdBuffer : public CmdBufferBase
DECLARE_REF(GraphicsPipeline);
class SecondaryCmdBuffer : public CmdBufferBase, public Gfx::RenderCommand
{
public:
SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool);
virtual ~SecondaryCmdBuffer();
void begin(PCmdBuffer parent);
void end();
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override;
virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override;
virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) override;
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
virtual void draw(DrawInstance data) override;
private:
PGraphicsPipeline pipeline;
};
DEFINE_REF(SecondaryCmdBuffer);
@@ -23,7 +23,6 @@ private:
PGraphics graphics;
Array<VkDescriptorSetLayoutBinding> bindings;
VkDescriptorSetLayout layoutHandle;
friend class PipelineStateCacheManager;
};
DEFINE_REF(DescriptorLayout);
class PipelineLayout : public Gfx::PipelineLayout
@@ -49,10 +48,33 @@ private:
uint32 layoutHash;
VkPipelineLayout layoutHandle;
PGraphics graphics;
friend class PipelineStateCacheManager;
};
DEFINE_REF(PipelineLayout);
class DescriptorAllocator : public Gfx::DescriptorAllocator
{
public:
DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout);
virtual ~DescriptorAllocator();
virtual void allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet);
inline VkDescriptorPool getHandle() const
{
return poolHandle;
}
inline DescriptorLayout getLayout() const
{
return layout;
}
private:
PGraphics graphics;
int maxSets = 512;
VkDescriptorPool poolHandle;
DescriptorLayout &layout;
};
DEFINE_REF(DescriptorAllocator);
class DescriptorSet : public Gfx::DescriptorSet
{
public:
@@ -70,6 +92,10 @@ public:
{
return setHandle;
}
virtual uint32 getSetIndex() const
{
return owner->getLayout().getSetIndex();
}
private:
virtual void writeChanges();
@@ -83,24 +109,5 @@ private:
};
DEFINE_REF(DescriptorSet);
class DescriptorAllocator : public Gfx::DescriptorAllocator
{
public:
DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout);
virtual ~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);
} // namespace Vulkan
} // namespace Seele
@@ -8,9 +8,7 @@ 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));
@@ -27,6 +27,7 @@ public:
{
return hash;
}
private:
uint32 hash;
PGraphics graphics;
+31 -5
View File
@@ -6,6 +6,7 @@
#include "VulkanCommandBuffer.h"
#include "VulkanRenderPass.h"
#include "VulkanFramebuffer.h"
#include "VulkanPipelineCache.h"
#include "Graphics/GraphicsResources.h"
#include <glfw/glfw3.h>
@@ -42,6 +43,7 @@ void Graphics::init(GraphicsInitializer initInfo)
computeCommands = new CommandBufferManager(this, computeQueue);
transferCommands = new CommandBufferManager(this, transferQueue);
dedicatedTransferCommands = new CommandBufferManager(this, dedicatedTransferQueue);
pipelineCache = new PipelineCache(this, "pipeline.cache");
}
Gfx::PWindow Graphics::createWindow(const WindowCreateInfo &createInfo)
@@ -67,7 +69,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
uint32 framebufferHash = rp->getFramebufferHash();
PFramebuffer framebuffer;
auto found = allocatedFramebuffers.find(framebufferHash);
if(found == allocatedFramebuffers.end())
if (found == allocatedFramebuffers.end())
{
framebuffer = new Framebuffer(this, rp, rp->getLayout());
}
@@ -83,6 +85,18 @@ void Graphics::endRenderPass()
graphicsCommands->getCommands()->endRenderPass();
}
void Graphics::executeCommands(Array<Gfx::PRenderCommand> commands)
{
Array<VkCommandBuffer> cmdBuffers(commands.size());
for (uint32 i = 0; i < commands.size(); ++i)
{
PSecondaryCmdBuffer buf = commands[i].cast<SecondaryCmdBuffer>();
buf->end();
cmdBuffers[i] = buf->getHandle();
}
vkCmdExecuteCommands(graphicsCommands->getCommands()->getHandle(), cmdBuffers.size(), cmdBuffers.data());
}
Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo)
{
PTexture2D result = new Texture2D(this, createInfo.width, createInfo.height, createInfo.bArray,
@@ -91,28 +105,39 @@ Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo)
return result;
}
Gfx::PUniformBuffer Graphics::createUniformBuffer(const BulkResourceData &bulkData)
Gfx::PUniformBuffer Graphics::createUniformBuffer(const BulkResourceData &bulkData)
{
PUniformBuffer uniformBuffer = new UniformBuffer(this, bulkData);
return uniformBuffer;
}
Gfx::PStructuredBuffer Graphics::createStructuredBuffer(const BulkResourceData &bulkData)
Gfx::PStructuredBuffer Graphics::createStructuredBuffer(const BulkResourceData &bulkData)
{
PStructuredBuffer structuredBuffer = new StructuredBuffer(this, bulkData);
return structuredBuffer;
}
Gfx::PVertexBuffer Graphics::createVertexBuffer(const BulkResourceData &bulkData)
Gfx::PVertexBuffer Graphics::createVertexBuffer(const VertexBufferCreateInfo &bulkData)
{
PVertexBuffer vertexBuffer = new VertexBuffer(this, bulkData);
return vertexBuffer;
}
Gfx::PIndexBuffer Graphics::createIndexBuffer(const BulkResourceData &bulkData)
Gfx::PIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkData)
{
PIndexBuffer indexBuffer = new IndexBuffer(this, bulkData);
return indexBuffer;
}
Gfx::PRenderCommand Graphics::createRenderCommand()
{
PSecondaryCmdBuffer cmdBuffer = graphicsCommands->createSecondaryCmdBuffer();
cmdBuffer->begin(getGraphicsCommands()->getCommands());
return cmdBuffer;
}
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo)
{
PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo);
return pipeline;
}
VkInstance Graphics::getInstance() const
{
@@ -173,6 +198,7 @@ Array<const char *> Graphics::getRequiredExtensions()
}
void Graphics::initInstance(GraphicsInitializer initInfo)
{
glfwInit();
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = initInfo.applicationName;
+14 -2
View File
@@ -11,6 +11,8 @@ DECLARE_REF(StagingManager);
DECLARE_REF(CommandBufferManager);
DECLARE_REF(Queue);
DECLARE_REF(Framebuffer);
DECLARE_REF(RenderCommand);
DECLARE_REF(PipelineCache);
class Graphics : public Gfx::Graphics
{
public:
@@ -29,6 +31,10 @@ public:
{
return queueMapping;
}
QueueOwnedResourceDeletion &getDeletionQueue()
{
return deletionQueue;
}
PAllocator getAllocator();
PStagingManager getStagingManager();
@@ -42,11 +48,15 @@ public:
virtual void beginRenderPass(Gfx::PRenderPass renderPass) override;
virtual void endRenderPass() override;
virtual void executeCommands(Array<Gfx::PRenderCommand> commands) override;
virtual Gfx::PTexture2D createTexture2D(const TextureCreateInfo &createInfo) override;
virtual Gfx::PUniformBuffer createUniformBuffer(const BulkResourceData &bulkData) override;
virtual Gfx::PStructuredBuffer createStructuredBuffer(const BulkResourceData &bulkData) override;
virtual Gfx::PVertexBuffer createVertexBuffer(const BulkResourceData &bulkData) override;
virtual Gfx::PIndexBuffer createIndexBuffer(const BulkResourceData &bulkData) override;
virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override;
virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override;
virtual Gfx::PRenderCommand createRenderCommand() override;
virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override;
protected:
Array<const char *> getRequiredExtensions();
@@ -64,6 +74,8 @@ protected:
PQueue transferQueue;
PQueue dedicatedTransferQueue;
QueueFamilyMapping queueMapping;
QueueOwnedResourceDeletion deletionQueue;
PPipelineCache pipelineCache;
PCommandBufferManager graphicsCommands;
PCommandBufferManager computeCommands;
PCommandBufferManager transferCommands;
@@ -1145,3 +1145,166 @@ Gfx::SeAttachmentLoadOp Seele::Vulkan::cast(const VkAttachmentLoadOp &loadOp)
return SE_ATTACHMENT_LOAD_OP_MAX_ENUM;
}
}
VkIndexType Seele::Vulkan::cast(const Gfx::SeIndexType &indexType)
{
switch (indexType)
{
case Gfx::SE_INDEX_TYPE_UINT16:
return VK_INDEX_TYPE_UINT16;
case Gfx::SE_INDEX_TYPE_UINT32:
return VK_INDEX_TYPE_UINT32;
default:
return VK_INDEX_TYPE_MAX_ENUM;
}
}
Gfx::SeIndexType Seele::Vulkan::cast(const VkIndexType &indexType)
{
switch (indexType)
{
case VK_INDEX_TYPE_UINT16:
return Gfx::SE_INDEX_TYPE_UINT16;
case VK_INDEX_TYPE_UINT32:
return Gfx::SE_INDEX_TYPE_UINT32;
default:
return Gfx::SE_INDEX_TYPE_MAX_ENUM;
}
}
VkPrimitiveTopology Seele::Vulkan::cast(const Gfx::SePrimitiveTopology &topology)
{
switch (topology)
{
case SE_PRIMITIVE_TOPOLOGY_POINT_LIST:
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
case SE_PRIMITIVE_TOPOLOGY_LINE_LIST:
return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
case SE_PRIMITIVE_TOPOLOGY_LINE_STRIP:
return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
case SE_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
case SE_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
case SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
case SE_PRIMITIVE_TOPOLOGY_PATCH_LIST:
return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
default:
return VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
}
}
Gfx::SePrimitiveTopology Seele::Vulkan::cast(const VkPrimitiveTopology &topology)
{
switch (topology)
{
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
return SE_PRIMITIVE_TOPOLOGY_POINT_LIST;
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
return SE_PRIMITIVE_TOPOLOGY_LINE_LIST;
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
return SE_PRIMITIVE_TOPOLOGY_LINE_STRIP;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
return SE_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
return SE_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
return SE_PRIMITIVE_TOPOLOGY_PATCH_LIST;
default:
return SE_PRIMITIVE_TOPOLOGY_MAX_ENUM;
}
}
VkPolygonMode Seele::Vulkan::cast(const Gfx::SePolygonMode &mode)
{
switch (mode)
{
case SE_POLYGON_MODE_FILL:
return VK_POLYGON_MODE_FILL;
case SE_POLYGON_MODE_LINE:
return VK_POLYGON_MODE_LINE;
case SE_POLYGON_MODE_POINT:
return VK_POLYGON_MODE_POINT;
default:
return VK_POLYGON_MODE_MAX_ENUM;
}
}
Gfx::SePolygonMode Seele::Vulkan::cast(const VkPolygonMode &mode)
{
switch (mode)
{
case VK_POLYGON_MODE_FILL:
return SE_POLYGON_MODE_FILL;
case VK_POLYGON_MODE_LINE:
return SE_POLYGON_MODE_LINE;
case VK_POLYGON_MODE_POINT:
return SE_POLYGON_MODE_POINT;
default:
return SE_POLYGON_MODE_MAX_ENUM;
}
}
VkCompareOp Seele::Vulkan::cast(const Gfx::SeCompareOp &op)
{
switch (op)
{
case SE_COMPARE_OP_NEVER:
return VK_COMPARE_OP_NEVER;
case SE_COMPARE_OP_LESS:
return VK_COMPARE_OP_LESS;
case SE_COMPARE_OP_EQUAL:
return VK_COMPARE_OP_EQUAL;
case SE_COMPARE_OP_LESS_OR_EQUAL:
return VK_COMPARE_OP_LESS_OR_EQUAL;
case SE_COMPARE_OP_GREATER:
return VK_COMPARE_OP_GREATER;
case SE_COMPARE_OP_NOT_EQUAL:
return VK_COMPARE_OP_NOT_EQUAL;
case SE_COMPARE_OP_GREATER_OR_EQUAL:
return VK_COMPARE_OP_GREATER_OR_EQUAL;
case SE_COMPARE_OP_ALWAYS:
return VK_COMPARE_OP_ALWAYS;
default:
return VK_COMPARE_OP_MAX_ENUM;
}
}
Gfx::SeCompareOp Seele::Vulkan::cast(const VkCompareOp &op)
{
switch (op)
{
case VK_COMPARE_OP_NEVER:
return SE_COMPARE_OP_NEVER;
case VK_COMPARE_OP_LESS:
return SE_COMPARE_OP_LESS;
case VK_COMPARE_OP_EQUAL:
return SE_COMPARE_OP_EQUAL;
case VK_COMPARE_OP_LESS_OR_EQUAL:
return SE_COMPARE_OP_LESS_OR_EQUAL;
case VK_COMPARE_OP_GREATER:
return SE_COMPARE_OP_GREATER;
case VK_COMPARE_OP_NOT_EQUAL:
return SE_COMPARE_OP_NOT_EQUAL;
case VK_COMPARE_OP_GREATER_OR_EQUAL:
return SE_COMPARE_OP_GREATER_OR_EQUAL;
case VK_COMPARE_OP_ALWAYS:
return SE_COMPARE_OP_ALWAYS;
default:
return SE_COMPARE_OP_MAX_ENUM;
}
}
@@ -16,6 +16,17 @@ namespace Seele
{
namespace Vulkan
{
enum class ShaderType
{
VERTEX = 0,
CONTROL = 1,
EVALUATION = 2,
GEOMETRY = 3,
FRAGMENT = 4,
COMPUTE = 5,
};
VkDescriptorType cast(const Gfx::SeDescriptorType &descriptorType);
Gfx::SeDescriptorType cast(const VkDescriptorType &descriptorType);
VkShaderStageFlagBits cast(const Gfx::SeShaderStageFlagBits &stage);
@@ -26,5 +37,13 @@ VkAttachmentStoreOp cast(const Gfx::SeAttachmentStoreOp &storeOp);
Gfx::SeAttachmentStoreOp cast(const VkAttachmentStoreOp &storeOp);
VkAttachmentLoadOp cast(const Gfx::SeAttachmentLoadOp &loadOp);
Gfx::SeAttachmentLoadOp cast(const VkAttachmentLoadOp &loadOp);
VkIndexType cast(const Gfx::SeIndexType &indexType);
Gfx::SeIndexType cast(const VkIndexType &indexType);
VkPrimitiveTopology cast(const Gfx::SePrimitiveTopology &topology);
Gfx::SePrimitiveTopology cast(const VkPrimitiveTopology &topology);
VkPolygonMode cast(const Gfx::SePolygonMode &mode);
Gfx::SePolygonMode cast(const VkPolygonMode &mode);
VkCompareOp cast(const Gfx::SeCompareOp &op);
Gfx::SeCompareOp cast(const VkCompareOp &op);
} // namespace Vulkan
} // namespace Seele
@@ -7,6 +7,49 @@
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(PFence fence, std::function<void()> func)
{
PendingItem item;
item.fence = fence;
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();
PFence fence = entry->fence;
fence->wait(1000ull);
if (fence->isSignaled())
{
entry->func();
deletionQueue.remove(entry);
}
}
}
QueueOwnedResource::QueueOwnedResource(PGraphics graphics, Gfx::QueueType startQueueType)
: graphics(graphics), currentOwner(startQueueType)
{
@@ -1,5 +1,8 @@
#pragma once
#include "Graphics/GraphicsResources.h"
#include <thread>
#include <functional>
#include <condition_variable>
#include <vulkan/vulkan.h>
namespace Seele
@@ -39,6 +42,10 @@ public:
return fence;
}
void wait(uint32 timeout);
bool operator<(const Fence &other) const
{
return fence < other.fence;
}
private:
bool signaled;
@@ -76,6 +83,26 @@ struct QueueFamilyMapping
return srcIndex != dstIndex;
}
};
class QueueOwnedResourceDeletion
{
public:
QueueOwnedResourceDeletion();
virtual ~QueueOwnedResourceDeletion();
static void addPendingDelete(PFence fence, std::function<void()> function);
private:
std::thread worker;
static volatile bool running;
static void run();
struct PendingItem
{
PFence fence;
std::function<void()> func;
};
static std::mutex mutex;
static std::condition_variable cv;
static List<PendingItem> deletionQueue;
};
class QueueOwnedResource
{
public:
@@ -154,7 +181,7 @@ DEFINE_REF(StructuredBuffer);
class VertexBuffer : public Buffer, public Gfx::VertexBuffer
{
public:
VertexBuffer(PGraphics graphics, const BulkResourceData &resourceData);
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData);
virtual ~VertexBuffer();
protected:
@@ -166,7 +193,7 @@ DEFINE_REF(VertexBuffer);
class IndexBuffer : public Buffer, public Gfx::IndexBuffer
{
public:
IndexBuffer(PGraphics graphics, const BulkResourceData &resourceData);
IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData);
virtual ~IndexBuffer();
protected:
@@ -251,7 +278,8 @@ class Texture2D : public TextureBase, public Gfx::Texture2D
public:
Texture2D(PGraphics graphics, uint32 sizeX, uint32 sizeY,
bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format,
uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE);
uint32 samples, Gfx::SeImageUsageFlags usage,
Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE);
virtual ~Texture2D();
inline uint32 getSizeX() const
{
@@ -334,6 +362,7 @@ public:
virtual ~Viewport();
virtual void resize(uint32 newX, uint32 newY);
virtual void move(uint32 newOffsetX, uint32 newOffsetY);
protected:
private:
PGraphics graphics;
@@ -0,0 +1,28 @@
#include "VulkanPipeline.h"
#include "VulkanDescriptorSets.h"
#include "VulkanGraphics.h"
using namespace Seele;
using namespace Seele::Vulkan;
GraphicsPipeline::GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo)
: Gfx::GraphicsPipeline(createInfo)
, graphics(graphics)
, layout(pipelineLayout)
, pipeline(handle)
{
}
GraphicsPipeline::~GraphicsPipeline()
{
}
void GraphicsPipeline::bind(VkCommandBuffer handle)
{
vkCmdBindPipeline(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
}
VkPipelineLayout GraphicsPipeline::getLayout() const
{
return layout->getHandle();
}
@@ -0,0 +1,24 @@
#pragma once
#include "VulkanGraphicsResources.h"
namespace Seele
{
namespace Vulkan
{
DECLARE_REF(PipelineLayout);
DECLARE_REF(Graphics);
class GraphicsPipeline : public Gfx::GraphicsPipeline
{
public:
GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo);
virtual ~GraphicsPipeline();
void bind(VkCommandBuffer handle);
VkPipelineLayout getLayout() const;
private:
VkPipeline pipeline;
PPipelineLayout layout;
PGraphics graphics;
};
DEFINE_REF(GraphicsPipeline);
} // namespace Vulkan
} // namespace Seele
@@ -0,0 +1,240 @@
#include "VulkanPipelineCache.h"
#include "VulkanGraphics.h"
#include "VulkanGraphicsEnums.h"
#include "VulkanInitializer.h"
#include "VulkanRenderPass.h"
#include "VulkanDescriptorSets.h"
#include "VulkanShader.h"
using namespace Seele;
using namespace Seele::Vulkan;
PipelineCache::PipelineCache(PGraphics graphics, const std::string& cacheFilePath)
: graphics(graphics)
, cacheFile(cacheFilePath)
{
std::ifstream stream(cacheFilePath, std::ios::binary | std::ios::ate);
VkPipelineCacheCreateInfo cacheCreateInfo;
cacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
cacheCreateInfo.pNext = nullptr;
cacheCreateInfo.flags = 0;
cacheCreateInfo.initialDataSize = 0;
if(stream.good())
{
Array<uint8> cacheData;
uint32 fileSize = static_cast<uint32>(stream.tellg());
cacheData.resize(fileSize);
stream.seekg(0);
stream.read((char*)cacheData.data(), fileSize);
cacheCreateInfo.initialDataSize = fileSize;
cacheCreateInfo.pInitialData = cacheData.data();
}
VK_CHECK(vkCreatePipelineCache(graphics->getDevice(), &cacheCreateInfo, nullptr, &cache));
}
PipelineCache::~PipelineCache()
{
VkDeviceSize cacheSize;
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, nullptr);
Array<uint8> cacheData;
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, cacheData.data());
std::ofstream stream(cacheFile, std::ios::binary);
stream.write((char*)cacheData.data(), cacheSize);
stream.flush();
stream.close();
vkDestroyPipelineCache(graphics->getDevice(), cache, nullptr);
}
PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo& gfxInfo)
{
VkGraphicsPipelineCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
createInfo.pNext = 0;
createInfo.flags = 0;
createInfo.stageCount = 0;
VkPipelineTessellationStateCreateInfo tessInfo;
VkPipelineShaderStageCreateInfo stageInfos[5];
std::memset(stageInfos, 0, sizeof(stageInfos));
if(gfxInfo.vertexShader != nullptr)
{
PVertexShader shader = gfxInfo.vertexShader.cast<VertexShader>();
VkPipelineShaderStageCreateInfo& vertInfo = stageInfos[createInfo.stageCount++];
vertInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertInfo.module = shader->getModuleHandle();
vertInfo.pName = shader->getEntryPointName();
}
if(gfxInfo.controlShader != nullptr)
{
assert(gfxInfo.evalShader != nullptr);
PControlShader control = gfxInfo.controlShader.cast<ControlShader>();
PEvaluationShader eval = gfxInfo.evalShader.cast<EvaluationShader>();
VkPipelineShaderStageCreateInfo& controlInfo = stageInfos[createInfo.stageCount++];
controlInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
controlInfo.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
controlInfo.module = control->getModuleHandle();
controlInfo.pName = control->getEntryPointName();
VkPipelineShaderStageCreateInfo& evalInfo = stageInfos[createInfo.stageCount++];
evalInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
evalInfo.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
evalInfo.module = eval->getModuleHandle();
evalInfo.pName = eval->getEntryPointName();
tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
tessInfo.pNext = 0;
tessInfo.flags = 0;
tessInfo.patchControlPoints = control->getNumPatches();
}
if(gfxInfo.geometryShader != nullptr)
{
PGeometryShader geometry = gfxInfo.geometryShader.cast<GeometryShader>();
VkPipelineShaderStageCreateInfo& geometryInfo = stageInfos[createInfo.stageCount++];
geometryInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
geometryInfo.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
geometryInfo.module = geometry->getModuleHandle();
geometryInfo.pName = geometry->getEntryPointName();
}
if(gfxInfo.fragmentShader != nullptr)
{
PFragmentShader fragment = gfxInfo.fragmentShader.cast<FragmentShader>();
VkPipelineShaderStageCreateInfo& fragmentInfo = stageInfos[createInfo.stageCount++];
fragmentInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragmentInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragmentInfo.module = fragment->getModuleHandle();
fragmentInfo.pName = fragment->getEntryPointName();
}
VkPipelineVertexInputStateCreateInfo vertexInput =
init::PipelineVertexInputStateCreateInfo();
Gfx::PVertexDeclaration vertexDecl = gfxInfo.vertexDeclaration;
auto vertexStreams = vertexDecl->getVertexStreams();
Array<VkVertexInputBindingDescription> bindingDesc(vertexStreams.size());
Array<VkVertexInputAttributeDescription> attribDesc;
uint32 bindingNum = 0;
for(auto vertexBinding : vertexStreams)
{
uint32 stride = vertexBinding.getVertexBuffer()->getVertexSize();
for(auto vertexAttrib : vertexBinding.getVertexDescriptions())
{
auto attrib = attribDesc.add();
attrib.binding = bindingNum;
attrib.format = cast(vertexAttrib.vertexFormat);
attrib.location = vertexAttrib.location;
attrib.offset = vertexAttrib.offset;
}
bindingDesc[bindingNum].binding = bindingNum;
bindingDesc[bindingNum].stride = stride;
bindingDesc[bindingNum].inputRate = vertexBinding.isInstanced() ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
bindingNum++;
}
vertexInput.pVertexBindingDescriptions = bindingDesc.data();
vertexInput.vertexBindingDescriptionCount = bindingDesc.size();
vertexInput.pVertexAttributeDescriptions = attribDesc.data();
vertexInput.vertexAttributeDescriptionCount = attribDesc.size();
VkPipelineInputAssemblyStateCreateInfo assemblyInfo =
init::PipelineInputAssemblyStateCreateInfo(
cast(gfxInfo.topology),
0,
false
);
VkPipelineViewportStateCreateInfo viewportInfo =
init::PipelineViewportStateCreateInfo(
1,
1,
0
);
VkPipelineRasterizationStateCreateInfo rasterizationState =
init::PipelineRasterizationStateCreateInfo(
cast(gfxInfo.rasterizationState.polygonMode),
gfxInfo.rasterizationState.cullMode,
(VkFrontFace)gfxInfo.rasterizationState.frontFace,
0
);
rasterizationState.depthBiasEnable = gfxInfo.rasterizationState.depthBiasEnable;
rasterizationState.depthBiasClamp = gfxInfo.rasterizationState.depthBiasClamp;
rasterizationState.depthBiasConstantFactor = gfxInfo.rasterizationState.depthBoasConstantFactor;
rasterizationState.depthBiasSlopeFactor = gfxInfo.rasterizationState.depthBiasSlopeFactor;
rasterizationState.depthClampEnable = gfxInfo.rasterizationState.depthClampEnable;
rasterizationState.lineWidth = gfxInfo.rasterizationState.lineWidth;
rasterizationState.rasterizerDiscardEnable = gfxInfo.rasterizationState.rasterizerDiscardEnable;
VkPipelineMultisampleStateCreateInfo multisampleState =
init::PipelineMultisampleStateCreateInfo((VkSampleCountFlagBits)gfxInfo.multisampleState.samples, 0);
multisampleState.alphaToCoverageEnable = gfxInfo.multisampleState.alphaCoverageEnable;
multisampleState.alphaToOneEnable = gfxInfo.multisampleState.alphaToOneEnable;
multisampleState.minSampleShading = gfxInfo.multisampleState.minSampleShading;
multisampleState.sampleShadingEnable = gfxInfo.multisampleState.sampleShadingEnable;
VkPipelineDepthStencilStateCreateInfo depthStencilState =
init::PipelineDepthStencilStateCreateInfo(
gfxInfo.depthStencilState.depthTestEnable,
gfxInfo.depthStencilState.depthWriteEnable,
cast(gfxInfo.depthStencilState.depthCompareOp)
);
const auto colorAttachments = gfxInfo.renderPass->getLayout()->colorAttachments;
Array<VkPipelineColorBlendAttachmentState> blendAttachments(colorAttachments.size());
for(uint32 i = 0; i < colorAttachments.size(); ++i)
{
const Gfx::ColorBlendState::BlendAttachment& attachment = gfxInfo.colorBlend.blendAttachments[i];
VkPipelineColorBlendAttachmentState& blendAttachment = blendAttachments[i];
blendAttachment.alphaBlendOp = (VkBlendOp)attachment.alphaBlendOp;
blendAttachment.blendEnable = attachment.blendEnable;
blendAttachment.colorBlendOp = (VkBlendOp)attachment.colorBlendOp;
blendAttachment.colorWriteMask = attachment.colorWriteMask;
blendAttachment.dstAlphaBlendFactor = (VkBlendFactor)attachment.dstAlphaBlendFactor;
blendAttachment.srcAlphaBlendFactor = (VkBlendFactor)attachment.srcAlphaBlendFactor;
blendAttachment.dstColorBlendFactor = (VkBlendFactor)attachment.dstColorBlendFactor;
blendAttachment.srcColorBlendFactor = (VkBlendFactor)attachment.srcColorBlendFactor;
}
VkPipelineColorBlendStateCreateInfo blendState =
init::PipelineColorBlendStateCreateInfo(
blendAttachments.size(),
blendAttachments.data()
);
blendState.logicOpEnable = gfxInfo.colorBlend.logicOpEnable;
blendState.logicOp = (VkLogicOp)gfxInfo.colorBlend.logicOp;
std::memcpy(blendState.blendConstants, gfxInfo.colorBlend.blendConstants, sizeof(float)*4);
uint32 numDynamicEnabled = 0;
StaticArray<VkDynamicState, VK_DYNAMIC_STATE_RANGE_SIZE> dynamicEnabled;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_VIEWPORT;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_SCISSOR;
VkPipelineDynamicStateCreateInfo dynamicState =
init::PipelineDynamicStateCreateInfo(
dynamicEnabled.data(),
numDynamicEnabled,
0
);
createInfo.pStages = stageInfos;
createInfo.pVertexInputState = &vertexInput;
createInfo.pInputAssemblyState = &assemblyInfo;
createInfo.pTessellationState = &tessInfo;
createInfo.pViewportState = &viewportInfo;
createInfo.pRasterizationState = &rasterizationState;
createInfo.pMultisampleState = &multisampleState;
createInfo.pDepthStencilState = &depthStencilState;
createInfo.pColorBlendState = &blendState;
createInfo.pDynamicState = &dynamicState;
createInfo.renderPass = gfxInfo.renderPass.cast<RenderPass>()->getHandle();
createInfo.layout = gfxInfo.pipelineLayout.cast<PipelineLayout>()->getHandle();
createInfo.subpass = 0;
VkPipeline pipelineHandle;
auto beginTime = std::chrono::high_resolution_clock::now();
VK_CHECK(vkCreateGraphicsPipelines(graphics->getDevice(), cache, 1, &createInfo, nullptr, &pipelineHandle));
auto endTime = std::chrono::high_resolution_clock::now();
int64 delta = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - beginTime).count();
std::cout << "Gfx creation time: " << delta << std::endl;
PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, gfxInfo.pipelineLayout.cast<PipelineLayout>(), gfxInfo);
return result;
}
@@ -0,0 +1,21 @@
#pragma once
#include "VulkanPipeline.h"
namespace Seele
{
namespace Vulkan
{
class PipelineCache
{
public:
PipelineCache(PGraphics graphics, const std::string& cacheFilePath);
~PipelineCache();
PGraphicsPipeline createPipeline(const GraphicsPipelineCreateInfo& createInfo);
private:
VkPipelineCache cache;
PGraphics graphics;
std::string cacheFile;
};
DEFINE_REF(PipelineCache);
} // namespace Vulkan
} // namespace Seele
+7 -10
View File
@@ -9,22 +9,19 @@ using namespace Seele;
using namespace Seele::Vulkan;
Queue::Queue(PGraphics graphics, Gfx::QueueType queueType, uint32 familyIndex, uint32 queueIndex)
: familyIndex(familyIndex)
, graphics(graphics)
, queueType(queueType)
{
: familyIndex(familyIndex), graphics(graphics), queueType(queueType)
{
vkGetDeviceQueue(graphics->getDevice(), familyIndex, queueIndex, &queue);
}
Queue::~Queue()
{
}
void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore* signalSemaphores)
void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore *signalSemaphores)
{
assert(cmdBuffer->state == CmdBuffer::State::Ended);
PFence fence = cmdBuffer->fence;
assert(!fence->isSignaled());
@@ -38,9 +35,9 @@ void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores
submitInfo.pSignalSemaphores = signalSemaphores;
Array<VkSemaphore> waitSemaphores;
if(cmdBuffer->waitSemaphores.size() > 0)
if (cmdBuffer->waitSemaphores.size() > 0)
{
for(PSemaphore semaphore : cmdBuffer->waitSemaphores)
for (PSemaphore semaphore : cmdBuffer->waitSemaphores)
{
waitSemaphores.add(semaphore->getHandle());
}
@@ -55,7 +52,7 @@ void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores
cmdBuffer->waitFlags.clear();
cmdBuffer->waitSemaphores.clear();
if(Gfx::waitIdleOnSubmit)
if (Gfx::waitIdleOnSubmit)
{
fence->wait(200 * 1000ull);
}
@@ -8,7 +8,8 @@ using namespace Seele;
using namespace Seele::Vulkan;
RenderPass::RenderPass(PGraphics graphics, Gfx::PRenderTargetLayout layout)
: layout(layout), graphics(graphics)
: Gfx::RenderPass(layout)
, graphics(graphics)
{
Array<VkAttachmentDescription> attachments;
Array<VkAttachmentReference> inputRefs;
@@ -108,17 +109,17 @@ uint32 RenderPass::getFramebufferHash()
{
FramebufferDescription description;
std::memset(&description, 0, sizeof(FramebufferDescription));
for(auto inputAttachment : layout->inputAttachments)
for (auto inputAttachment : layout->inputAttachments)
{
PTexture2D tex = inputAttachment->getTexture().cast<Texture2D>();
description.inputAttachments[description.numInputAttachments++] = tex->getView();
}
for(auto colorAttachment : layout->colorAttachments)
for (auto colorAttachment : layout->colorAttachments)
{
PTexture2D tex = colorAttachment->getTexture().cast<Texture2D>();
description.colorAttachments[description.numColorAttachments++] = tex->getView();
description.colorAttachments[description.numColorAttachments++] = tex->getView();
}
if(layout->depthAttachment != nullptr)
if (layout->depthAttachment != nullptr)
{
PTexture2D tex = layout->depthAttachment->getTexture().cast<Texture2D>();
description.depthAttachment = tex->getView();
@@ -30,13 +30,8 @@ public:
{
return subpassContents;
}
inline Gfx::PRenderTargetLayout getLayout()
{
return layout;
}
private:
PGraphics graphics;
Gfx::PRenderTargetLayout layout;
VkRenderPass renderPass;
Array<VkClearValue> clearValues;
VkRect2D renderArea;
@@ -0,0 +1,4 @@
#include "VulkanShader.h"
using namespace Seele;
using namespace Seele::Vulkan;
+57
View File
@@ -0,0 +1,57 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "VulkanGraphicsEnums.h"
namespace Seele
{
namespace Vulkan
{
class Shader
{
public:
Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage);
virtual ~Shader();
VkShaderModule getModuleHandle() const
{
return module;
}
const char* getEntryPointName() const
{
return entryPointName.c_str();
}
private:
VkShaderModule module;
std::string entryPointName;
};
DEFINE_REF(Shader);
template <typename Base, ShaderType shaderType, VkShaderStageFlags stage>
class ShaderBase : public Base, public Shader
{
public:
ShaderBase(PGraphics graphics)
: Shader(graphics, shaderType, stage)
{
}
virtual ~ShaderBase()
{
}
};
typedef ShaderBase<Gfx::VertexShader, ShaderType::VERTEX, VK_SHADER_STAGE_VERTEX_BIT> VertexShader;
typedef ShaderBase<Gfx::ControlShader, ShaderType::CONTROL, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT> ControlShader;
typedef ShaderBase<Gfx::EvaluationShader, ShaderType::EVALUATION, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT> EvaluationShader;
typedef ShaderBase<Gfx::GeometryShader, ShaderType::GEOMETRY, VK_SHADER_STAGE_GEOMETRY_BIT> GeometryShader;
typedef ShaderBase<Gfx::FragmentShader, ShaderType::FRAGMENT, VK_SHADER_STAGE_FRAGMENT_BIT> FragmentShader;
typedef ShaderBase<Gfx::ComputeShader, ShaderType::COMPUTE, VK_SHADER_STAGE_COMPUTE_BIT> ComputeShader;
DEFINE_REF(VertexShader);
DEFINE_REF(ControlShader);
DEFINE_REF(EvaluationShader);
DEFINE_REF(GeometryShader);
DEFINE_REF(FragmentShader);
DEFINE_REF(ComputeShader);
} // namespace Vulkan
}
+9 -4
View File
@@ -32,7 +32,7 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format)
TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint32 sizeX, uint32 sizeY, uint32 sizeZ,
bool bArray, uint32 arraySize, uint32 mipLevel,
Gfx::SeFormat format, uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner, VkImage existingImage)
: QueueOwnedResource(graphics, owner), graphics(graphics), sizeX(sizeX), sizeY(sizeY), sizeZ(sizeZ), mipLevels(mipLevel), format(format), samples(samples), usage(usage), arrayCount(bArray ? arraySize : 1), aspect(getAspectFromFormat(format))
: QueueOwnedResource(graphics, owner), graphics(graphics), sizeX(sizeX), sizeY(sizeY), sizeZ(sizeZ), mipLevels(mipLevel), format(format), samples(samples), usage(usage), arrayCount(bArray ? arraySize : 1), aspect(getAspectFromFormat(format)), image(existingImage), layout(VK_IMAGE_LAYOUT_UNDEFINED)
{
if (existingImage == VK_NULL_HANDLE)
{
@@ -105,8 +105,13 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
TextureHandle::~TextureHandle()
{
vkDestroyImageView(graphics->getDevice(), defaultView, nullptr);
vkDestroyImage(graphics->getDevice(), image, nullptr);
auto &deletionQueue = graphics->getDeletionQueue();
auto fence = getCommands()->getCommands()->getFence();
VkDevice device = graphics->getDevice();
VkImageView view = defaultView;
VkImage img = image;
deletionQueue.addPendingDelete(fence, [device, view]() { vkDestroyImageView(device, view, nullptr); });
deletionQueue.addPendingDelete(fence, [device, img]() { vkDestroyImage(device, img, nullptr); });
}
void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
@@ -145,7 +150,7 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstManager = graphics->getTransferCommands();
}
else if(currentOwner == Gfx::QueueType::DEDICATED_TRANSFER)
else if (currentOwner == Gfx::QueueType::DEDICATED_TRANSFER)
{
imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+30 -12
View File
@@ -9,7 +9,7 @@ using namespace Seele;
using namespace Seele::Vulkan;
Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo)
: Gfx::Window(createInfo), graphics(graphics), instance(graphics->getInstance())
: Gfx::Window(createInfo), graphics(graphics), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE)
{
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow *handle = glfwCreateWindow(createInfo.width, createInfo.height, createInfo.title, createInfo.bFullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr);
@@ -19,7 +19,28 @@ Window::Window(PGraphics graphics, const WindowCreateInfo &createInfo)
glfwCreateWindowSurface(instance, handle, nullptr, &surface);
createSwapchain();
uint32_t numQueueFamilies = 0;
vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, nullptr);
Array<VkQueueFamilyProperties> queueProperties(numQueueFamilies);
vkGetPhysicalDeviceQueueFamilyProperties(graphics->getPhysicalDevice(), &numQueueFamilies, queueProperties.data());
bool viableDevice = false;
for (uint32 i = 0; i < numQueueFamilies; ++i)
{
VkBool32 supportsPresent;
vkGetPhysicalDeviceSurfaceSupportKHR(graphics->getPhysicalDevice(), i, surface, &supportsPresent);
if (supportsPresent)
{
viableDevice = true;
break;
}
}
if (!viableDevice)
{
std::cerr << "Device not suitable for presenting to surface " << surface << ", use a different one" << std::endl;
}
recreateSwapchain(createInfo);
}
Window::~Window()
@@ -30,6 +51,7 @@ Window::~Window()
void Window::beginFrame()
{
glfwPollEvents();
advanceBackBuffer();
}
@@ -75,16 +97,9 @@ void Window::advanceBackBuffer()
imageAcquiredSemaphore = imageAcquired[semaphoreIndex];
currentImageIndex = imageIndex;
VkImageMemoryBarrier barrier =
init::ImageMemoryBarrier(
backBufferImages[currentImageIndex]->getHandle(),
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
backBufferImages[currentImageIndex]->changeLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands();
vkCmdPipelineBarrier(cmdBuffer->getHandle(),
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
0, 0, nullptr, 0, nullptr, 1, &barrier);
cmdBuffer->addWaitSemaphore(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, imageAcquiredSemaphore);
graphics->getGraphicsCommands()->getCommands()->addWaitSemaphore(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, imageAcquiredSemaphore);
graphics->getGraphicsCommands()->submitCommands();
}
@@ -187,7 +202,10 @@ void Window::createSwapchain()
void Window::destroySwapchain()
{
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
if (swapchain != VK_NULL_HANDLE)
{
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
}
for (uint32 i = 0; i < Gfx::numFramesBuffered; ++i)
{
imageAcquired[i] = nullptr;