looks like command buffers need to be externally synchronized

This commit is contained in:
2021-11-14 20:36:53 +01:00
parent ad09492e3e
commit 42b0d5034c
29 changed files with 1121 additions and 1114 deletions
+1
View File
@@ -5,6 +5,7 @@
#include "MaterialLoader.h" #include "MaterialLoader.h"
#include "MeshLoader.h" #include "MeshLoader.h"
#include "Material/MaterialAsset.h" #include "Material/MaterialAsset.h"
#include "Graphics/Mesh.h"
#include "Graphics/Graphics.h" #include "Graphics/Graphics.h"
#include "Window/WindowManager.h" #include "Window/WindowManager.h"
#include "MeshAsset.h" #include "MeshAsset.h"
+1 -1
View File
@@ -179,7 +179,7 @@ namespace Seele
} }
allocator = other.allocator; allocator = other.allocator;
} }
if(other.arraySize > allocated) if(_data == nullptr || other.arraySize > allocated)
{ {
if(_data != nullptr) if(_data != nullptr)
{ {
+1 -1
View File
@@ -502,7 +502,7 @@ private:
if (!isValid(r)) if (!isValid(r))
{ {
nodeContainer.emplace(std::forward<KeyType>(key)); nodeContainer.emplace(std::forward<KeyType>(key));
return 0; return nodeContainer.size() - 1;
} }
r = splay(r, key); r = splay(r, key);
Node* node = getNode(r); Node* node = getNode(r);
+1
View File
@@ -10,6 +10,7 @@ target_sources(SeeleEngine
Mesh.h Mesh.h
Mesh.cpp Mesh.cpp
MeshBatch.h MeshBatch.h
MeshBatch.cpp
RenderMaterial.h RenderMaterial.h
RenderMaterial.cpp RenderMaterial.cpp
ShaderCompiler.h ShaderCompiler.h
+2 -1
View File
@@ -3,7 +3,6 @@
#include "Containers/Array.h" #include "Containers/Array.h"
#include "Containers/List.h" #include "Containers/List.h"
#include "GraphicsInitializer.h" #include "GraphicsInitializer.h"
#include "MeshBatch.h"
#include <boost/crc.hpp> #include <boost/crc.hpp>
#include <functional> #include <functional>
@@ -17,6 +16,8 @@ namespace Seele
struct VertexInputStream; struct VertexInputStream;
struct VertexStreamComponent; struct VertexStreamComponent;
class VertexInputType; class VertexInputType;
struct MeshBatchElement;
DECLARE_REF(MaterialAsset)
namespace Gfx namespace Gfx
{ {
DECLARE_REF(Graphics) DECLARE_REF(Graphics)
+28
View File
@@ -0,0 +1,28 @@
#include "MeshBatch.h"
#include "GraphicsResources.h"
#include "VertexShaderInput.h"
#include "Material/MaterialAsset.h"
using namespace Seele;
MeshBatchElement::MeshBatchElement()
: uniformBuffer(nullptr)
, indexBuffer(nullptr)
, firstIndex(0)
, numPrimitives(0)
, numInstances(1)
, baseVertexIndex(0)
, minVertexIndex(0)
, maxVertexIndex(0)
, indirectArgsBuffer(nullptr)
{}
MeshBatch::MeshBatch()
: useReverseCulling(false)
, isBackfaceCullingDisabled(false)
, isCastingShadow(true)
, useWireframe(false)
, topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
, vertexInput(nullptr)
, material(nullptr)
{
}
+4 -22
View File
@@ -1,9 +1,10 @@
#pragma once #pragma once
#include "GraphicsEnums.h"
namespace Seele namespace Seele
{ {
DECLARE_REF(MaterialAsset)
DECLARE_REF(VertexShaderInput) DECLARE_REF(VertexShaderInput)
DECLARE_REF(MaterialAsset)
DECLARE_NAME_REF(Gfx, VertexBuffer) DECLARE_NAME_REF(Gfx, VertexBuffer)
DECLARE_NAME_REF(Gfx, IndexBuffer) DECLARE_NAME_REF(Gfx, IndexBuffer)
DECLARE_NAME_REF(Gfx, UniformBuffer) DECLARE_NAME_REF(Gfx, UniformBuffer)
@@ -29,17 +30,7 @@ public:
uint8 isInstanced : 1; uint8 isInstanced : 1;
Gfx::PVertexBuffer indirectArgsBuffer; Gfx::PVertexBuffer indirectArgsBuffer;
MeshBatchElement() MeshBatchElement();
: uniformBuffer(nullptr)
, indexBuffer(nullptr)
, firstIndex(0)
, numPrimitives(0)
, numInstances(1)
, baseVertexIndex(0)
, minVertexIndex(0)
, maxVertexIndex(0)
, indirectArgsBuffer(nullptr)
{}
}; };
struct MeshBatch struct MeshBatch
{ {
@@ -76,16 +67,7 @@ struct MeshBatch
return count; return count;
} }
MeshBatch() MeshBatch();
: useReverseCulling(false)
, isBackfaceCullingDisabled(false)
, isCastingShadow(true)
, useWireframe(false)
, topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
, vertexInput(nullptr)
, material(nullptr)
{
}
}; };
DECLARE_REF(PrimitiveComponent) DECLARE_REF(PrimitiveComponent)
struct StaticMeshBatch : public MeshBatch struct StaticMeshBatch : public MeshBatch
+1
View File
@@ -1,6 +1,7 @@
#include "ShaderCompiler.h" #include "ShaderCompiler.h"
#include "Material/MaterialAsset.h" #include "Material/MaterialAsset.h"
#include "VertexShaderInput.h" #include "VertexShaderInput.h"
#include "Graphics.h"
using namespace Seele; using namespace Seele;
using namespace Seele::Gfx; using namespace Seele::Gfx;
+252 -242
View File
@@ -5,67 +5,67 @@
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
SubAllocation::SubAllocation(Allocation *owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize) SubAllocation::SubAllocation(Allocation *owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize)
: owner(owner) : owner(owner)
, size(size) , size(size)
, allocatedOffset(allocatedOffset) , allocatedOffset(allocatedOffset)
, alignedOffset(alignedOffset) , alignedOffset(alignedOffset)
, allocatedSize(allocatedSize) , allocatedSize(allocatedSize)
{ {
} }
SubAllocation::~SubAllocation() SubAllocation::~SubAllocation()
{ {
owner->markFree(this); owner->markFree(this);
} }
VkDeviceMemory SubAllocation::getHandle() const VkDeviceMemory SubAllocation::getHandle() const
{ {
return owner->getHandle(); return owner->getHandle();
} }
bool SubAllocation::isReadable() const bool SubAllocation::isReadable() const
{ {
return owner->isReadable(); return owner->isReadable();
} }
void *SubAllocation::getMappedPointer() void *SubAllocation::getMappedPointer()
{ {
return (uint8 *)owner->getMappedPointer() + alignedOffset; return (uint8 *)owner->getMappedPointer() + alignedOffset;
} }
void SubAllocation::flushMemory() void SubAllocation::flushMemory()
{ {
owner->flushMemory(); owner->flushMemory();
} }
void SubAllocation::invalidateMemory() void SubAllocation::invalidateMemory()
{ {
owner->invalidateMemory(); owner->invalidateMemory();
} }
Allocation::Allocation(PGraphics graphics, Allocator *allocator, VkDeviceSize size, uint8 memoryTypeIndex, Allocation::Allocation(PGraphics graphics, Allocator *allocator, VkDeviceSize size, uint8 memoryTypeIndex,
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
: device(graphics->getDevice()) : device(graphics->getDevice())
, allocator(allocator) , allocator(allocator)
, bytesAllocated(0) , bytesAllocated(0)
, bytesUsed(0) , bytesUsed(0)
, readable(properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) , readable(properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
, properties(properties) , properties(properties)
, memoryTypeIndex(memoryTypeIndex) , memoryTypeIndex(memoryTypeIndex)
{ {
VkMemoryAllocateInfo allocInfo = VkMemoryAllocateInfo allocInfo =
init::MemoryAllocateInfo(); init::MemoryAllocateInfo();
allocInfo.allocationSize = size; allocInfo.allocationSize = size;
allocInfo.memoryTypeIndex = memoryTypeIndex; allocInfo.memoryTypeIndex = memoryTypeIndex;
isDedicated = dedicatedInfo != nullptr; isDedicated = dedicatedInfo != nullptr;
allocInfo.pNext = dedicatedInfo; allocInfo.pNext = dedicatedInfo;
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory)); VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
bytesAllocated = size; bytesAllocated = size;
PSubAllocation freeRange = new SubAllocation(this, 0, size, 0, size); PSubAllocation freeRange = new SubAllocation(this, 0, size, 0, size);
freeRanges[0] = freeRange; freeRanges[0] = freeRange;
canMap = (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; canMap = (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
isMapped = false; isMapped = false;
} }
Allocation::~Allocation() Allocation::~Allocation()
@@ -74,203 +74,213 @@ Allocation::~Allocation()
PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment) PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
{ {
std::unique_lock lck(lock); std::unique_lock lck(lock);
if (isDedicated) if (isDedicated)
{ {
if (activeAllocations.empty() && requestedSize == bytesAllocated) if (activeAllocations.empty() && requestedSize == bytesAllocated)
{ {
PSubAllocation suballoc = freeRanges[0]; PSubAllocation suballoc = freeRanges[0];
activeAllocations[0] = suballoc.getHandle(); activeAllocations[0] = suballoc.getHandle();
freeRanges.clear(); freeRanges.clear();
bytesUsed += requestedSize; bytesUsed += requestedSize;
return suballoc; return suballoc;
} }
else else
{ {
return nullptr; return nullptr;
} }
} }
for (auto it : freeRanges) for (auto it : freeRanges)
{ {
PSubAllocation freeAllocation = it.value; PSubAllocation freeAllocation = it.value;
VkDeviceSize allocatedOffset = freeAllocation->allocatedOffset; VkDeviceSize allocatedOffset = freeAllocation->allocatedOffset;
VkDeviceSize alignedOffset = align(allocatedOffset, alignment); VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset; VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
VkDeviceSize size = alignmentAdjustment + requestedSize; VkDeviceSize size = alignmentAdjustment + requestedSize;
if (freeAllocation->size == size) if (freeAllocation->size == size)
{ {
freeRanges.erase(allocatedOffset); freeRanges.erase(allocatedOffset);
activeAllocations[allocatedOffset] = freeAllocation.getHandle(); activeAllocations[allocatedOffset] = freeAllocation.getHandle();
bytesUsed += size; bytesUsed += size;
return freeAllocation; return freeAllocation;
} }
else if (size < freeAllocation->allocatedSize) else if (size < freeAllocation->allocatedSize)
{ {
freeAllocation->size -= size; freeAllocation->size -= size;
freeAllocation->allocatedSize -= size; freeAllocation->allocatedSize -= size;
freeAllocation->allocatedOffset += size; freeAllocation->allocatedOffset += size;
freeAllocation->alignedOffset += size; freeAllocation->alignedOffset += size;
PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size); PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size);
activeAllocations[allocatedOffset] = subAlloc.getHandle(); activeAllocations[allocatedOffset] = subAlloc.getHandle();
freeRanges.erase(allocatedOffset); freeRanges.erase(allocatedOffset);
freeRanges[freeAllocation->allocatedOffset] = freeAllocation; freeRanges[freeAllocation->allocatedOffset] = freeAllocation;
bytesUsed += size; bytesUsed += size;
return subAlloc; return subAlloc;
} }
} }
return nullptr; return nullptr;
} }
void Allocation::markFree(SubAllocation *allocation) void Allocation::markFree(SubAllocation *allocation)
{ {
// Dont free if it is already a free allocation, since they also mark themselves on deletion // Dont free if it is already a free allocation, since they also mark themselves on deletion
if (freeRanges.find(allocation->allocatedOffset) != freeRanges.end()) if (freeRanges.find(allocation->allocatedOffset) != freeRanges.end())
{ {
return; return;
} }
VkDeviceSize lowerBound = allocation->allocatedOffset; VkDeviceSize lowerBound = allocation->allocatedOffset;
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize; VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
PSubAllocation allocHandle; PSubAllocation allocHandle;
std::unique_lock lck(lock); PSubAllocation freeRangeToDelete;
//Join lower bound
for (auto freeRange : freeRanges)
{
PSubAllocation freeAlloc = freeRange.value;
if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize == lowerBound)
{
//extend freeAlloc by the allocatedSize
freeAlloc->allocatedSize += allocation->allocatedSize;
allocHandle = freeAlloc;
break;
}
}
//Join upper bound
auto foundAlloc = freeRanges.find(upperBound);
if (foundAlloc != freeRanges.end())
{
// There is a free allocation ending where the new free one ends
if (allocHandle != nullptr)
{
// extend allocHandle by another foundAlloc->allocatedSize bytes
allocHandle->allocatedSize += foundAlloc->value->allocatedSize;
freeRanges.erase(foundAlloc->key);
}
else
{
// set foundAlloc back by size amount
allocHandle = foundAlloc->value;
// remove from offset map since key changes
freeRanges.erase(foundAlloc->key);
allocHandle->allocatedOffset -= allocation->allocatedSize;
allocHandle->alignedOffset -= allocation->allocatedSize;
// place back at correct offset
freeRanges[allocHandle->allocatedOffset] = allocHandle;
}
}
if (allocHandle == nullptr)
{
allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize);
freeRanges[allocation->allocatedOffset] = allocHandle;
}
activeAllocations.erase(allocation->allocatedOffset);
bytesUsed -= allocation->allocatedSize;
// TODO: delete allocation when bytesUsed == 0 std::unique_lock lck(lock);
//Join lower bound
for (auto freeRange : freeRanges)
{
PSubAllocation freeAlloc = freeRange.value;
if (freeAlloc->allocatedOffset <= lowerBound
&& freeAlloc->allocatedOffset + freeAlloc->allocatedSize >= upperBound)
{
// allocation is already in a free region
return;
}
if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize == lowerBound)
{
//extend freeAlloc by the allocatedSize
freeAlloc->allocatedSize += allocation->allocatedSize;
allocHandle = freeAlloc;
break;
}
}
//Join upper bound
auto foundAlloc = freeRanges.find(upperBound);
if (foundAlloc != freeRanges.end())
{
freeRangeToDelete = foundAlloc->value;
// There is a free allocation ending where the new free one ends
if (allocHandle != nullptr)
{
// extend allocHandle by another foundAlloc->allocatedSize bytes
allocHandle->allocatedSize += foundAlloc->value->allocatedSize;
freeRanges.erase(foundAlloc->key);
}
else
{
// set foundAlloc back by size amount
allocHandle = foundAlloc->value;
allocHandle->allocatedOffset -= allocation->allocatedSize;
allocHandle->alignedOffset -= allocation->allocatedSize;
// place back at correct offset
freeRanges[allocHandle->allocatedOffset] = allocHandle;
// remove from offset map since key changes
freeRanges.erase(foundAlloc->key);
}
}
if (allocHandle == nullptr)
{
allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize);
freeRanges[allocation->allocatedOffset] = allocHandle;
}
activeAllocations.erase(allocation->allocatedOffset);
lock.unlock();
bytesUsed -= allocation->allocatedSize;
// TODO: delete allocation when bytesUsed == 0
} }
Allocator::Allocator(PGraphics graphics) Allocator::Allocator(PGraphics graphics)
: graphics(graphics) : graphics(graphics)
{ {
vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties); vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
heaps.resize(memProperties.memoryHeapCount); heaps.resize(memProperties.memoryHeapCount);
for (size_t i = 0; i < memProperties.memoryHeapCount; ++i) for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
{ {
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i]; VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
HeapInfo &heapInfo = heaps[i]; HeapInfo &heapInfo = heaps[i];
heapInfo.maxSize = memoryHeap.size; heapInfo.maxSize = memoryHeap.size;
} }
} }
Allocator::~Allocator() Allocator::~Allocator()
{ {
std::unique_lock lck(lock); std::unique_lock lck(lock);
for (auto heap : heaps) for (auto heap : heaps)
{ {
for (auto alloc : heap.allocations) for (auto alloc : heap.allocations)
{ {
assert(alloc->activeAllocations.empty()); assert(alloc->activeAllocations.empty());
assert(alloc->freeRanges.size() == 1); assert(alloc->freeRanges.size() == 1);
} }
heap.allocations.clear(); heap.allocations.clear();
} }
graphics = nullptr; graphics = nullptr;
} }
PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
{ {
std::unique_lock lck(lock); std::unique_lock lck(lock);
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements; const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
uint8 memoryTypeIndex; uint8 memoryTypeIndex;
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex)); VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex; uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
if (memRequirements2.pNext != nullptr) if (memRequirements2.pNext != nullptr)
{ {
VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext; VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext;
if (dedicatedReq->prefersDedicatedAllocation) if (dedicatedReq->prefersDedicatedAllocation)
{ {
PAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo); PAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
heaps[heapIndex].allocations.add(newAllocation); heaps[heapIndex].allocations.add(newAllocation);
return newAllocation->getSuballocation(requirements.size, requirements.alignment); 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); PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
if (suballoc != nullptr) if (suballoc != nullptr)
{ {
return suballoc; return suballoc;
} }
} }
// no suitable allocations found, allocate new block // no suitable allocations found, allocate new block
PAllocation newAllocation = new Allocation(graphics, this, (requirements.size > MemoryBlockSize) ? requirements.size : (VkDeviceSize)MemoryBlockSize, memoryTypeIndex, properties, nullptr); PAllocation newAllocation = new Allocation(graphics, this, (requirements.size > MemoryBlockSize) ? requirements.size : (VkDeviceSize)MemoryBlockSize, memoryTypeIndex, properties, nullptr);
heaps[heapIndex].allocations.add(newAllocation); heaps[heapIndex].allocations.add(newAllocation);
return newAllocation->getSuballocation(requirements.size, requirements.alignment); return newAllocation->getSuballocation(requirements.size, requirements.alignment);
} }
void Allocator::free(Allocation *allocation) void Allocator::free(Allocation *allocation)
{ {
std::unique_lock lck(lock); std::unique_lock lck(lock);
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); heap.allocations.remove(i, false);
return; return;
} }
} }
} }
} }
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) for (uint8 memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex)
{ {
if ((typeBits & 1) == 1) if ((typeBits & 1) == 1)
{ {
if ((memProperties.memoryTypes[memoryIndex].propertyFlags & properties) == properties) if ((memProperties.memoryTypes[memoryIndex].propertyFlags & properties) == properties)
{ {
*typeIndex = memoryIndex; *typeIndex = memoryIndex;
return VK_SUCCESS; return VK_SUCCESS;
} }
} }
typeBits >>= 1; typeBits >>= 1;
} }
return VK_ERROR_FORMAT_NOT_SUPPORTED; return VK_ERROR_FORMAT_NOT_SUPPORTED;
} }
StagingBuffer::StagingBuffer() StagingBuffer::StagingBuffer()
@@ -282,7 +292,7 @@ StagingBuffer::~StagingBuffer()
} }
StagingManager::StagingManager(PGraphics graphics, PAllocator allocator) StagingManager::StagingManager(PGraphics graphics, PAllocator allocator)
: graphics(graphics), allocator(allocator) : graphics(graphics), allocator(allocator)
{ {
} }
@@ -296,55 +306,55 @@ void StagingManager::clearPending()
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead) PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
{ {
std::unique_lock l(lock); std::unique_lock l(lock);
for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it) for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
{ {
auto freeBuffer = *it; auto freeBuffer = *it;
if (freeBuffer->getSize() == size && freeBuffer->isReadable() == bCPURead && freeBuffer->usage == usage) if (freeBuffer->getSize() == size && freeBuffer->isReadable() == bCPURead && freeBuffer->usage == usage)
{ {
//std::cout << "Reusing staging buffer" << std::endl; //std::cout << "Reusing staging buffer" << std::endl;
activeBuffers.add(freeBuffer.getHandle()); activeBuffers.add(freeBuffer.getHandle());
freeBuffers.remove(it, false); freeBuffers.remove(it, false);
return freeBuffer; return freeBuffer;
} }
} }
//std::cout << "Creating new stagingbuffer" << std::endl; //std::cout << "Creating new stagingbuffer" << std::endl;
PStagingBuffer stagingBuffer = new StagingBuffer(); PStagingBuffer stagingBuffer = new StagingBuffer();
VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size); VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size);
stagingBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; stagingBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkDevice vulkanDevice = graphics->getDevice(); VkDevice vulkanDevice = graphics->getDevice();
VK_CHECK(vkCreateBuffer(vulkanDevice, &stagingBufferCreateInfo, nullptr, &stagingBuffer->buffer)); VK_CHECK(vkCreateBuffer(vulkanDevice, &stagingBufferCreateInfo, nullptr, &stagingBuffer->buffer));
VkMemoryDedicatedRequirements dedicatedReqs; VkMemoryDedicatedRequirements dedicatedReqs;
dedicatedReqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; dedicatedReqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
dedicatedReqs.pNext = nullptr; dedicatedReqs.pNext = nullptr;
VkMemoryRequirements2 memReqs; VkMemoryRequirements2 memReqs;
memReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; memReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
memReqs.pNext = &dedicatedReqs; memReqs.pNext = &dedicatedReqs;
VkBufferMemoryRequirementsInfo2 bufferQuery; VkBufferMemoryRequirementsInfo2 bufferQuery;
bufferQuery.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2; bufferQuery.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
bufferQuery.pNext = nullptr; bufferQuery.pNext = nullptr;
bufferQuery.buffer = stagingBuffer->buffer; bufferQuery.buffer = stagingBuffer->buffer;
vkGetBufferMemoryRequirements2(vulkanDevice, &bufferQuery, &memReqs); vkGetBufferMemoryRequirements2(vulkanDevice, &bufferQuery, &memReqs);
memReqs.memoryRequirements.alignment = memReqs.memoryRequirements.alignment =
(16 > memReqs.memoryRequirements.alignment) ? 16 : 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_COHERENT_BIT : VK_MEMORY_PROPERTY_HOST_CACHED_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; stagingBuffer->bReadable = bCPURead;
stagingBuffer->size = size; stagingBuffer->size = size;
stagingBuffer->usage = usage; stagingBuffer->usage = usage;
vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset()); vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset());
activeBuffers.add(stagingBuffer.getHandle()); activeBuffers.add(stagingBuffer.getHandle());
return stagingBuffer; return stagingBuffer;
} }
void StagingManager::releaseStagingBuffer(PStagingBuffer buffer) void StagingManager::releaseStagingBuffer(PStagingBuffer buffer)
{ {
std::unique_lock l(lock); std::unique_lock l(lock);
freeBuffers.add(buffer); freeBuffers.add(buffer);
activeBuffers.remove(activeBuffers.find(buffer.getHandle())); activeBuffers.remove(activeBuffers.find(buffer.getHandle()));
} }
+9 -5
View File
@@ -3,6 +3,7 @@
#include "VulkanGraphics.h" #include "VulkanGraphics.h"
#include "VulkanCommandBuffer.h" #include "VulkanCommandBuffer.h"
#include "VulkanAllocator.h" #include "VulkanAllocator.h"
#include "ThreadPool.h"
using namespace Seele; using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
@@ -62,14 +63,17 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags u
ShaderBuffer::~ShaderBuffer() ShaderBuffer::~ShaderBuffer()
{ {
auto cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
auto &deletionQueue = graphics->getDeletionQueue();
VkDevice device = graphics->getDevice(); VkDevice device = graphics->getDevice();
VkBuffer buf[Gfx::numFramesBuffered]; auto deletionLambda = [](PCmdBuffer cmdBuffer, VkDevice device, VkBuffer buffer) -> Job
{
co_await cmdBuffer->asyncWait();
vkDestroyBuffer(device, buffer, nullptr);
co_return;
};
for (uint32 i = 0; i < numBuffers; ++i) for (uint32 i = 0; i < numBuffers; ++i)
{ {
buf[i] = buffers[i].buffer; deletionLambda(cmdBuffer, device, buffers[i].buffer);
deletionQueue.addPendingDelete(cmdBuffer, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); });
buffers[i].allocation = nullptr; buffers[i].allocation = nullptr;
} }
graphics = nullptr; graphics = nullptr;
@@ -25,6 +25,7 @@ CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferMa
init::CommandBufferAllocateInfo(cmdPool, init::CommandBufferAllocateInfo(cmdPool,
VK_COMMAND_BUFFER_LEVEL_PRIMARY, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1); 1);
std::unique_lock lock(handleLock);
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle)) VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle))
fence = new Fence(graphics); fence = new Fence(graphics);
@@ -33,6 +34,7 @@ CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferMa
CmdBuffer::~CmdBuffer() CmdBuffer::~CmdBuffer()
{ {
std::unique_lock lock(handleLock);
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
renderPass = nullptr; renderPass = nullptr;
framebuffer = nullptr; framebuffer = nullptr;
@@ -44,18 +46,21 @@ void CmdBuffer::begin()
VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo beginInfo =
init::CommandBufferBeginInfo(); init::CommandBufferBeginInfo();
beginInfo.pInheritanceInfo = nullptr; beginInfo.pInheritanceInfo = nullptr;
std::unique_lock lock(handleLock);
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo)); VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
state = State::InsideBegin; state = State::InsideBegin;
} }
void CmdBuffer::end() void CmdBuffer::end()
{ {
std::unique_lock lock(handleLock);
VK_CHECK(vkEndCommandBuffer(handle)); VK_CHECK(vkEndCommandBuffer(handle));
state = State::Ended; state = State::Ended;
} }
void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFramebuffer) void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFramebuffer)
{ {
std::unique_lock lock(handleLock);
renderPass = newRenderPass; renderPass = newRenderPass;
framebuffer = newFramebuffer; framebuffer = newFramebuffer;
@@ -72,6 +77,7 @@ void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFrame
void CmdBuffer::endRenderPass() void CmdBuffer::endRenderPass()
{ {
std::unique_lock lock(handleLock);
vkCmdEndRenderPass(handle); vkCmdEndRenderPass(handle);
state = State::InsideBegin; state = State::InsideBegin;
} }
@@ -79,6 +85,7 @@ void CmdBuffer::endRenderPass()
void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands) void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
{ {
assert(state == State::RenderPassActive); assert(state == State::RenderPassActive);
std::unique_lock lock(handleLock);
Array<VkCommandBuffer> cmdBuffers(commands.size()); Array<VkCommandBuffer> cmdBuffers(commands.size());
for (uint32 i = 0; i < commands.size(); ++i) for (uint32 i = 0; i < commands.size(); ++i)
{ {
@@ -97,6 +104,7 @@ void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands) void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands)
{ {
std::unique_lock lock(handleLock);
Array<VkCommandBuffer> cmdBuffers(commands.size()); Array<VkCommandBuffer> cmdBuffers(commands.size());
for (uint32 i = 0; i < commands.size(); ++i) for (uint32 i = 0; i < commands.size(); ++i)
{ {
@@ -115,12 +123,14 @@ void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands)
void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore) void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore)
{ {
std::unique_lock lock(handleLock);
waitSemaphores.add(semaphore); waitSemaphores.add(semaphore);
waitFlags.add(flags); waitFlags.add(flags);
} }
void CmdBuffer::refreshFence() void CmdBuffer::refreshFence()
{ {
std::unique_lock lock(handleLock);
if (state == State::Submitted) if (state == State::Submitted)
{ {
if (fence->isSignaled()) if (fence->isSignaled())
@@ -153,10 +163,16 @@ void CmdBuffer::refreshFence()
void CmdBuffer::waitForCommand(uint32 timeout) void CmdBuffer::waitForCommand(uint32 timeout)
{ {
std::unique_lock lock(handleLock);
fence->wait(timeout); fence->wait(timeout);
refreshFence(); refreshFence();
} }
Event CmdBuffer::asyncWait() const
{
return fence->asyncWait();
}
PFence CmdBuffer::getFence() PFence CmdBuffer::getFence()
{ {
@@ -187,6 +203,7 @@ RenderCommand::~RenderCommand()
void RenderCommand::begin(PCmdBuffer parent) void RenderCommand::begin(PCmdBuffer parent)
{ {
threadId = std::this_thread::get_id();
ready = false; ready = false;
VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo beginInfo =
init::CommandBufferBeginInfo(); init::CommandBufferBeginInfo();
@@ -202,11 +219,13 @@ void RenderCommand::begin(PCmdBuffer parent)
void RenderCommand::end() void RenderCommand::end()
{ {
assert(threadId == std::this_thread::get_id());
VK_CHECK(vkEndCommandBuffer(handle)); VK_CHECK(vkEndCommandBuffer(handle));
} }
void RenderCommand::reset() void RenderCommand::reset()
{ {
assert(threadId == std::this_thread::get_id());
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
boundDescriptors.clear(); boundDescriptors.clear();
ready = true; ready = true;
@@ -219,6 +238,7 @@ bool RenderCommand::isReady()
void RenderCommand::setViewport(Gfx::PViewport viewport) void RenderCommand::setViewport(Gfx::PViewport viewport)
{ {
assert(threadId == std::this_thread::get_id());
VkViewport vp = viewport.cast<Viewport>()->getHandle(); VkViewport vp = viewport.cast<Viewport>()->getHandle();
VkRect2D scissors = init::Rect2D(viewport->getSizeX(), viewport->getSizeY(), viewport->getOffsetX(), viewport->getOffsetY()); VkRect2D scissors = init::Rect2D(viewport->getSizeX(), viewport->getSizeY(), viewport->getOffsetX(), viewport->getOffsetY());
vkCmdSetViewport(handle, 0, 1, &vp); vkCmdSetViewport(handle, 0, 1, &vp);
@@ -227,11 +247,13 @@ void RenderCommand::setViewport(Gfx::PViewport viewport)
void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline) void RenderCommand::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline)
{ {
assert(threadId == std::this_thread::get_id());
pipeline = gfxPipeline.cast<GraphicsPipeline>(); pipeline = gfxPipeline.cast<GraphicsPipeline>();
pipeline->bind(handle); pipeline->bind(handle);
} }
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
{ {
assert(threadId == std::this_thread::get_id());
auto descriptor = descriptorSet.cast<DescriptorSet>(); auto descriptor = descriptorSet.cast<DescriptorSet>();
boundDescriptors.add(descriptor.getHandle()); boundDescriptors.add(descriptor.getHandle());
descriptor->bind(); descriptor->bind();
@@ -241,6 +263,7 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
} }
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets) void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets)
{ {
assert(threadId == std::this_thread::get_id());
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()]; VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
for(uint32 i = 0; i < descriptorSets.size(); ++i) for(uint32 i = 0; i < descriptorSets.size(); ++i)
{ {
@@ -255,6 +278,7 @@ void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorS
} }
void RenderCommand::bindVertexBuffer(const Array<VertexInputStream>& streams) void RenderCommand::bindVertexBuffer(const Array<VertexInputStream>& streams)
{ {
assert(threadId == std::this_thread::get_id());
Array<VkBuffer> buffers(streams.size()); Array<VkBuffer> buffers(streams.size());
Array<VkDeviceSize> offsets(streams.size()); Array<VkDeviceSize> offsets(streams.size());
for(uint32 i = 0; i < streams.size(); ++i) for(uint32 i = 0; i < streams.size(); ++i)
@@ -267,16 +291,19 @@ void RenderCommand::bindVertexBuffer(const Array<VertexInputStream>& streams)
} }
void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
{ {
assert(threadId == std::this_thread::get_id());
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>(); PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, cast(buf->getIndexType())); vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, cast(buf->getIndexType()));
} }
void RenderCommand::draw(const MeshBatchElement& data) void RenderCommand::draw(const MeshBatchElement& data)
{ {
assert(threadId == std::this_thread::get_id());
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0); vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
} }
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance)
{ {
assert(threadId == std::this_thread::get_id());
vkCmdDraw(handle, vertexCount, instanceCount, firstVertex, firstInstance); vkCmdDraw(handle, vertexCount, instanceCount, firstVertex, firstInstance);
} }
@@ -299,6 +326,7 @@ ComputeCommand::~ComputeCommand()
void ComputeCommand::begin(PCmdBuffer) void ComputeCommand::begin(PCmdBuffer)
{ {
threadId = std::this_thread::get_id();
ready = false; ready = false;
VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo beginInfo =
init::CommandBufferBeginInfo(); init::CommandBufferBeginInfo();
@@ -313,11 +341,13 @@ void ComputeCommand::begin(PCmdBuffer)
void ComputeCommand::end() void ComputeCommand::end()
{ {
assert(threadId == std::this_thread::get_id());
VK_CHECK(vkEndCommandBuffer(handle)); VK_CHECK(vkEndCommandBuffer(handle));
} }
void ComputeCommand::reset() void ComputeCommand::reset()
{ {
assert(threadId == std::this_thread::get_id());
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
boundDescriptors.clear(); boundDescriptors.clear();
ready = true; ready = true;
@@ -329,12 +359,14 @@ bool ComputeCommand::isReady()
void ComputeCommand::bindPipeline(Gfx::PComputePipeline computePipeline) void ComputeCommand::bindPipeline(Gfx::PComputePipeline computePipeline)
{ {
assert(threadId == std::this_thread::get_id());
pipeline = computePipeline.cast<ComputePipeline>(); pipeline = computePipeline.cast<ComputePipeline>();
pipeline->bind(handle); pipeline->bind(handle);
} }
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
{ {
assert(threadId == std::this_thread::get_id());
auto descriptor = descriptorSet.cast<DescriptorSet>(); auto descriptor = descriptorSet.cast<DescriptorSet>();
boundDescriptors.add(descriptor.getHandle()); boundDescriptors.add(descriptor.getHandle());
descriptor->bind(); descriptor->bind();
@@ -345,6 +377,7 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets) void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets)
{ {
assert(threadId == std::this_thread::get_id());
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()]; VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
for(uint32 i = 0; i < descriptorSets.size(); ++i) for(uint32 i = 0; i < descriptorSets.size(); ++i)
{ {
@@ -360,6 +393,7 @@ void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptor
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ)
{ {
assert(threadId == std::this_thread::get_id());
vkCmdDispatch(handle, threadX, threadY, threadZ); vkCmdDispatch(handle, threadX, threadY, threadZ);
} }
@@ -32,6 +32,7 @@ public:
void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore); void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore);
void refreshFence(); void refreshFence();
void waitForCommand(uint32 timeToWait = 1000000u); void waitForCommand(uint32 timeToWait = 1000000u);
Event asyncWait() const;
PFence getFence(); PFence getFence();
PCommandBufferManager getManager(); PCommandBufferManager getManager();
enum State enum State
@@ -53,6 +54,7 @@ private:
State state; State state;
VkViewport currentViewport; VkViewport currentViewport;
VkRect2D currentScissor; VkRect2D currentScissor;
std::mutex handleLock;
VkCommandBuffer handle; VkCommandBuffer handle;
VkCommandPool owner; VkCommandPool owner;
Array<PSemaphore> waitSemaphores; Array<PSemaphore> waitSemaphores;
@@ -96,6 +98,7 @@ private:
VkViewport currentViewport; VkViewport currentViewport;
VkRect2D currentScissor; VkRect2D currentScissor;
PGraphics graphics; PGraphics graphics;
std::thread::id threadId;
VkCommandBuffer handle; VkCommandBuffer handle;
VkCommandPool owner; VkCommandPool owner;
friend class CmdBuffer; friend class CmdBuffer;
@@ -126,6 +129,7 @@ private:
VkViewport currentViewport; VkViewport currentViewport;
VkRect2D currentScissor; VkRect2D currentScissor;
PGraphics graphics; PGraphics graphics;
std::thread::id threadId;
VkCommandBuffer handle; VkCommandBuffer handle;
VkCommandPool owner; VkCommandPool owner;
friend class CmdBuffer; friend class CmdBuffer;
@@ -8,7 +8,9 @@ using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRenderTargetLayout renderTargetLayout) Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRenderTargetLayout renderTargetLayout)
: graphics(graphics), layout(renderTargetLayout), renderPass(renderPass) : graphics(graphics)
, layout(renderTargetLayout)
, renderPass(renderPass)
{ {
FramebufferDescription description; FramebufferDescription description;
std::memset(&description, 0, sizeof(FramebufferDescription)); std::memset(&description, 0, sizeof(FramebufferDescription));
+399 -410
View File
@@ -15,587 +15,576 @@
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
Graphics::Graphics() Graphics::Graphics()
: instance(VK_NULL_HANDLE) : instance(VK_NULL_HANDLE)
, handle(VK_NULL_HANDLE) , handle(VK_NULL_HANDLE)
, physicalDevice(VK_NULL_HANDLE) , physicalDevice(VK_NULL_HANDLE)
, callback(VK_NULL_HANDLE) , callback(VK_NULL_HANDLE)
{ {
} }
Graphics::~Graphics() Graphics::~Graphics()
{ {
viewports.clear(); viewports.clear();
vkDestroyDevice(handle, nullptr); vkDestroyDevice(handle, nullptr);
DestroyDebugReportCallbackEXT(instance, nullptr, callback); DestroyDebugReportCallbackEXT(instance, nullptr, callback);
vkDestroyInstance(instance, nullptr); vkDestroyInstance(instance, nullptr);
} }
void Graphics::init(GraphicsInitializer initInfo) void Graphics::init(GraphicsInitializer initInfo)
{ {
initInstance(initInfo); initInstance(initInfo);
#if ENABLE_VALIDATION #if ENABLE_VALIDATION
setupDebugCallback(); setupDebugCallback();
#endif #endif
pickPhysicalDevice(); pickPhysicalDevice();
createDevice(initInfo); createDevice(initInfo);
allocator = new Allocator(this); allocator = new Allocator(this);
stagingManager = new StagingManager(this, allocator); stagingManager = new StagingManager(this, allocator);
pipelineCache = new PipelineCache(this, "pipeline.cache"); pipelineCache = new PipelineCache(this, "pipeline.cache");
} }
Gfx::PWindow Graphics::createWindow(const WindowCreateInfo &createInfo) Gfx::PWindow Graphics::createWindow(const WindowCreateInfo &createInfo)
{ {
PWindow result = new Window(this, createInfo); PWindow result = new Window(this, createInfo);
return result; return result;
} }
Gfx::PViewport Graphics::createViewport(Gfx::PWindow owner, const ViewportCreateInfo &viewportInfo) Gfx::PViewport Graphics::createViewport(Gfx::PWindow owner, const ViewportCreateInfo &viewportInfo)
{ {
PViewport result = new Viewport(this, owner, viewportInfo); PViewport result = new Viewport(this, owner, viewportInfo);
viewports.add(result); std::unique_lock lock(viewportLock);
return result; viewports.add(result);
return result;
} }
Gfx::PRenderPass Graphics::createRenderPass(Gfx::PRenderTargetLayout layout, Gfx::PViewport renderArea) Gfx::PRenderPass Graphics::createRenderPass(Gfx::PRenderTargetLayout layout, Gfx::PViewport renderArea)
{ {
PRenderPass result = new RenderPass(this, layout, renderArea); PRenderPass result = new RenderPass(this, layout, renderArea);
return result; return result;
} }
void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
{ {
PRenderPass rp = renderPass.cast<RenderPass>(); PRenderPass rp = renderPass.cast<RenderPass>();
uint32 framebufferHash = rp->getFramebufferHash(); uint32 framebufferHash = rp->getFramebufferHash();
PFramebuffer framebuffer; PFramebuffer framebuffer;
auto found = allocatedFramebuffers.find(framebufferHash); {
if (found == allocatedFramebuffers.end()) std::unique_lock lock(allocatedFrameBufferLock);
{ auto found = allocatedFramebuffers.find(framebufferHash);
framebuffer = new Framebuffer(this, rp, rp->getLayout()); if (found == allocatedFramebuffers.end())
allocatedFramebuffers[framebufferHash] = framebuffer; {
} framebuffer = new Framebuffer(this, rp, rp->getLayout());
else allocatedFramebuffers[framebufferHash] = framebuffer;
{ }
framebuffer = found->value; else
} {
getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer); framebuffer = found->value;
}
}
getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer);
} }
void Graphics::endRenderPass() void Graphics::endRenderPass()
{ {
getGraphicsCommands()->getCommands()->endRenderPass(); getGraphicsCommands()->getCommands()->endRenderPass();
getGraphicsCommands()->submitCommands(); getGraphicsCommands()->submitCommands();
} }
void Graphics::executeCommands(const Array<Gfx::PRenderCommand>& commands) void Graphics::executeCommands(const Array<Gfx::PRenderCommand>& commands)
{ {
getGraphicsCommands()->getCommands()->executeCommands(commands); getGraphicsCommands()->getCommands()->executeCommands(commands);
} }
void Graphics::executeCommands(const Array<Gfx::PComputeCommand>& commands) void Graphics::executeCommands(const Array<Gfx::PComputeCommand>& commands)
{ {
getComputeCommands()->getCommands()->executeCommands(commands); getComputeCommands()->getCommands()->executeCommands(commands);
} }
Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo) Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo)
{ {
PTexture2D result = new Texture2D(this, createInfo); PTexture2D result = new Texture2D(this, createInfo);
return result; return result;
} }
Gfx::PUniformBuffer Graphics::createUniformBuffer(const UniformBufferCreateInfo &bulkData) Gfx::PUniformBuffer Graphics::createUniformBuffer(const UniformBufferCreateInfo &bulkData)
{ {
PUniformBuffer uniformBuffer = new UniformBuffer(this, bulkData); PUniformBuffer uniformBuffer = new UniformBuffer(this, bulkData);
return uniformBuffer; return uniformBuffer;
} }
Gfx::PStructuredBuffer Graphics::createStructuredBuffer(const StructuredBufferCreateInfo &bulkData) Gfx::PStructuredBuffer Graphics::createStructuredBuffer(const StructuredBufferCreateInfo &bulkData)
{ {
PStructuredBuffer structuredBuffer = new StructuredBuffer(this, bulkData); PStructuredBuffer structuredBuffer = new StructuredBuffer(this, bulkData);
return structuredBuffer; return structuredBuffer;
} }
Gfx::PVertexBuffer Graphics::createVertexBuffer(const VertexBufferCreateInfo &bulkData) Gfx::PVertexBuffer Graphics::createVertexBuffer(const VertexBufferCreateInfo &bulkData)
{ {
PVertexBuffer vertexBuffer = new VertexBuffer(this, bulkData); PVertexBuffer vertexBuffer = new VertexBuffer(this, bulkData);
return vertexBuffer; return vertexBuffer;
} }
Gfx::PIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkData) Gfx::PIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkData)
{ {
PIndexBuffer indexBuffer = new IndexBuffer(this, bulkData); PIndexBuffer indexBuffer = new IndexBuffer(this, bulkData);
return indexBuffer; return indexBuffer;
} }
Gfx::PRenderCommand Graphics::createRenderCommand(const std::string& name) Gfx::PRenderCommand Graphics::createRenderCommand(const std::string& name)
{ {
PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(name); PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(name);
return cmdBuffer; return cmdBuffer;
} }
Gfx::PComputeCommand Graphics::createComputeCommand(const std::string& name) Gfx::PComputeCommand Graphics::createComputeCommand(const std::string& name)
{ {
PComputeCommand cmdBuffer = getComputeCommands()->createComputeCommand(name); PComputeCommand cmdBuffer = getComputeCommands()->createComputeCommand(name);
return cmdBuffer; return cmdBuffer;
} }
Gfx::PVertexDeclaration Graphics::createVertexDeclaration(const Array<Gfx::VertexElement>& element) Gfx::PVertexDeclaration Graphics::createVertexDeclaration(const Array<Gfx::VertexElement>& element)
{ {
PVertexDeclaration declaration = new VertexDeclaration(element); PVertexDeclaration declaration = new VertexDeclaration(element);
return declaration; return declaration;
} }
Gfx::PVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo) Gfx::PVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo)
{ {
PVertexShader shader = new VertexShader(this); PVertexShader shader = new VertexShader(this);
shader->create(createInfo); shader->create(createInfo);
return shader; return shader;
} }
Gfx::PControlShader Graphics::createControlShader(const ShaderCreateInfo& createInfo) Gfx::PControlShader Graphics::createControlShader(const ShaderCreateInfo& createInfo)
{ {
PControlShader shader = new ControlShader(this); PControlShader shader = new ControlShader(this);
shader->create(createInfo); shader->create(createInfo);
return shader; return shader;
} }
Gfx::PEvaluationShader Graphics::createEvaluationShader(const ShaderCreateInfo& createInfo) Gfx::PEvaluationShader Graphics::createEvaluationShader(const ShaderCreateInfo& createInfo)
{ {
PEvaluationShader shader = new EvaluationShader(this); PEvaluationShader shader = new EvaluationShader(this);
shader->create(createInfo); shader->create(createInfo);
return shader; return shader;
} }
Gfx::PGeometryShader Graphics::createGeometryShader(const ShaderCreateInfo& createInfo) Gfx::PGeometryShader Graphics::createGeometryShader(const ShaderCreateInfo& createInfo)
{ {
PGeometryShader shader = new GeometryShader(this); PGeometryShader shader = new GeometryShader(this);
shader->create(createInfo); shader->create(createInfo);
return shader; return shader;
} }
Gfx::PFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& createInfo) Gfx::PFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& createInfo)
{ {
PFragmentShader shader = new FragmentShader(this); PFragmentShader shader = new FragmentShader(this);
shader->create(createInfo); shader->create(createInfo);
return shader; return shader;
} }
Gfx::PComputeShader Graphics::createComputeShader(const ShaderCreateInfo& createInfo) Gfx::PComputeShader Graphics::createComputeShader(const ShaderCreateInfo& createInfo)
{ {
PComputeShader shader = new ComputeShader(this); PComputeShader shader = new ComputeShader(this);
shader->create(createInfo); shader->create(createInfo);
return shader; return shader;
} }
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo)
{ {
PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo); PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo);
return pipeline; return pipeline;
} }
Gfx::PComputePipeline Graphics::createComputePipeline(const ComputePipelineCreateInfo& createInfo) Gfx::PComputePipeline Graphics::createComputePipeline(const ComputePipelineCreateInfo& createInfo)
{ {
PComputePipeline pipeline = pipelineCache->createPipeline(createInfo); PComputePipeline pipeline = pipelineCache->createPipeline(createInfo);
return pipeline; return pipeline;
} }
Gfx::PSamplerState Graphics::createSamplerState(const SamplerCreateInfo&) Gfx::PSamplerState Graphics::createSamplerState(const SamplerCreateInfo&)
{ {
PSamplerState sampler = new SamplerState(); // TODO: proper sampler creation PSamplerState sampler = new SamplerState(); // TODO: proper sampler creation
VkSamplerCreateInfo vkInfo = VkSamplerCreateInfo vkInfo =
init::SamplerCreateInfo(); init::SamplerCreateInfo();
VK_CHECK(vkCreateSampler(handle, &vkInfo, nullptr, &sampler->sampler)); VK_CHECK(vkCreateSampler(handle, &vkInfo, nullptr, &sampler->sampler));
return sampler; return sampler;
} }
Gfx::PDescriptorLayout Graphics::createDescriptorLayout(const std::string& name) Gfx::PDescriptorLayout Graphics::createDescriptorLayout(const std::string& name)
{ {
PDescriptorLayout layout = new DescriptorLayout(this, name); PDescriptorLayout layout = new DescriptorLayout(this, name);
return layout; return layout;
} }
Gfx::PPipelineLayout Graphics::createPipelineLayout() Gfx::PPipelineLayout Graphics::createPipelineLayout()
{ {
PPipelineLayout layout = new PipelineLayout(this); PPipelineLayout layout = new PipelineLayout(this);
return layout; return layout;
} }
void Graphics::copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) void Graphics::copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture)
{ {
Texture2D* src = (Texture2D*)srcTexture->getTexture2D(); Texture2D* src = (Texture2D*)srcTexture->getTexture2D();
Texture2D* dst = (Texture2D*)dstTexture->getTexture2D(); Texture2D* dst = (Texture2D*)dstTexture->getTexture2D();
TextureHandle* srcHandle = (TextureHandle*)src->getNativeHandle(); TextureHandle* srcHandle = (TextureHandle*)src->getNativeHandle();
TextureHandle* dstHandle = (TextureHandle*)dst->getNativeHandle(); TextureHandle* dstHandle = (TextureHandle*)dst->getNativeHandle();
Gfx::SeImageLayout srcLayout = srcHandle->getLayout(); Gfx::SeImageLayout srcLayout = srcHandle->getLayout();
Gfx::SeImageLayout dstLayout = dstHandle->getLayout(); Gfx::SeImageLayout dstLayout = dstHandle->getLayout();
Gfx::QueueType dstOwner = dstHandle->currentOwner; Gfx::QueueType dstOwner = dstHandle->currentOwner;
src->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); src->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
dst->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); dst->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
dstTexture->transferOwnership(srcHandle->currentOwner); dstTexture->transferOwnership(srcHandle->currentOwner);
PCmdBuffer cmdBuffer = getQueueCommands(srcHandle->currentOwner)->getCommands(); PCmdBuffer cmdBuffer = getQueueCommands(srcHandle->currentOwner)->getCommands();
if(srcHandle->getAspect() != dstHandle->getAspect()) if(srcHandle->getAspect() != dstHandle->getAspect())
{ {
/*VkMemoryRequirements imageRequirements; /*VkMemoryRequirements imageRequirements;
vkGetImageMemoryRequirements(handle, srcHandle->getImage(), &imageRequirements); vkGetImageMemoryRequirements(handle, srcHandle->getImage(), &imageRequirements);
PStructuredBuffer tempBuffer = createStructuredBuffer(); PStructuredBuffer tempBuffer = createStructuredBuffer();
VkBufferImageCopy bufferImageCopy; VkBufferImageCopy bufferImageCopy;
bufferImageCopy.bufferOffset = 0; bufferImageCopy.bufferOffset = 0;
bufferImageCopy.bufferRowLength = srcTexture->getSizeX(); bufferImageCopy.bufferRowLength = srcTexture->getSizeX();
bufferImageCopy.bufferImageHeight = srcTexture->getSizeY(); bufferImageCopy.bufferImageHeight = srcTexture->getSizeY();
bufferImageCopy.imageExtent.width = srcTexture->getSizeX(); bufferImageCopy.imageExtent.width = srcTexture->getSizeX();
bufferImageCopy.imageExtent.height = srcTexture->getSizeY(); bufferImageCopy.imageExtent.height = srcTexture->getSizeY();
bufferImageCopy.imageExtent.depth = 1; bufferImageCopy.imageExtent.depth = 1;
bufferImageCopy.imageOffset.x = 0; bufferImageCopy.imageOffset.x = 0;
bufferImageCopy.imageOffset.y = 0; bufferImageCopy.imageOffset.y = 0;
bufferImageCopy.imageOffset.z = 0; bufferImageCopy.imageOffset.z = 0;
bufferImageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; bufferImageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
bufferImageCopy.imageSubresource.baseArrayLayer = 0; bufferImageCopy.imageSubresource.baseArrayLayer = 0;
bufferImageCopy.imageSubresource.layerCount = 1; bufferImageCopy.imageSubresource.layerCount = 1;
bufferImageCopy.imageSubresource.mipLevel = 0; bufferImageCopy.imageSubresource.mipLevel = 0;
vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), srcHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, tempBufferAllocation->getHandle(), 1, &bufferImageCopy); vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), srcHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, tempBufferAllocation->getHandle(), 1, &bufferImageCopy);
bufferImageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferImageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vkCmdCopyBufferToImage(cmdBuffer->getHandle(), tempBufferAllocation->getHandle(), dstHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferImageCopy); vkCmdCopyBufferToImage(cmdBuffer->getHandle(), tempBufferAllocation->getHandle(), dstHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferImageCopy);
delete tempBufferAllocation;*/ delete tempBufferAllocation;*/
throw new std::logic_error("Not yet implemented!"); throw new std::logic_error("Not yet implemented!");
} }
else if (src->getSizeX() != dst->getSizeX() else if (src->getSizeX() != dst->getSizeX()
|| src->getSizeY() != dst->getSizeY()) || src->getSizeY() != dst->getSizeY())
{ {
throw new std::logic_error("Not yet implemented!"); throw new std::logic_error("Not yet implemented!");
} }
else else
{ {
VkImageCopy copy; VkImageCopy copy;
std::memset(&copy, 0, sizeof(VkImageCopy)); std::memset(&copy, 0, sizeof(VkImageCopy));
copy.extent.width = srcTexture->getSizeX(); copy.extent.width = srcTexture->getSizeX();
copy.extent.height = srcTexture->getSizeY(); copy.extent.height = srcTexture->getSizeY();
copy.extent.depth = 1; copy.extent.depth = 1;
copy.srcSubresource.aspectMask = srcHandle->getAspect(); copy.srcSubresource.aspectMask = srcHandle->getAspect();
copy.srcSubresource.layerCount = 1; copy.srcSubresource.layerCount = 1;
copy.dstSubresource.aspectMask = dstHandle->getAspect(); copy.dstSubresource.aspectMask = dstHandle->getAspect();
copy.dstSubresource.layerCount = 1; copy.dstSubresource.layerCount = 1;
vkCmdCopyImage(cmdBuffer->getHandle(), vkCmdCopyImage(cmdBuffer->getHandle(),
srcHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, srcHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dstHandle->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &copy); 1, &copy);
src->changeLayout(srcLayout); src->changeLayout(srcLayout);
dst->changeLayout(dstLayout); dst->changeLayout(dstLayout);
dstTexture->transferOwnership(dstOwner); dstTexture->transferOwnership(dstOwner);
} }
}
VkInstance Graphics::getInstance() const
{
return instance;
}
VkDevice Graphics::getDevice() const
{
return handle;
}
VkPhysicalDevice Graphics::getPhysicalDevice() const
{
return physicalDevice;
} }
PCommandBufferManager Graphics::getQueueCommands(Gfx::QueueType queueType) PCommandBufferManager Graphics::getQueueCommands(Gfx::QueueType queueType)
{ {
switch (queueType) switch (queueType)
{ {
case Gfx::QueueType::GRAPHICS: case Gfx::QueueType::GRAPHICS:
return getGraphicsCommands(); return getGraphicsCommands();
case Gfx::QueueType::COMPUTE: case Gfx::QueueType::COMPUTE:
return getComputeCommands(); return getComputeCommands();
case Gfx::QueueType::TRANSFER: case Gfx::QueueType::TRANSFER:
return getTransferCommands(); return getTransferCommands();
case Gfx::QueueType::DEDICATED_TRANSFER: case Gfx::QueueType::DEDICATED_TRANSFER:
return getDedicatedTransferCommands(); return getDedicatedTransferCommands();
default: default:
throw new std::logic_error("invalid queue type"); throw new std::logic_error("invalid queue type");
} }
} }
std::mutex graphicsCommandLock; std::mutex graphicsCommandLock;
PCommandBufferManager Graphics::getGraphicsCommands() PCommandBufferManager Graphics::getGraphicsCommands()
{ {
std::unique_lock lock(graphicsCommandLock); std::unique_lock lock(graphicsCommandLock);
auto id = std::this_thread::get_id(); auto id = std::this_thread::get_id();
if(graphicsCommands.find(id) == graphicsCommands.end()) if(graphicsCommands.find(id) == graphicsCommands.end())
{ {
graphicsCommands[id] = new CommandBufferManager(this, graphicsQueue); graphicsCommands[id] = new CommandBufferManager(this, graphicsQueue);
} }
return graphicsCommands[id]; return graphicsCommands[id];
} }
std::mutex computeCommandLock; std::mutex computeCommandLock;
PCommandBufferManager Graphics::getComputeCommands() PCommandBufferManager Graphics::getComputeCommands()
{ {
std::unique_lock lock(computeCommandLock); std::unique_lock lock(computeCommandLock);
auto id = std::this_thread::get_id(); auto id = std::this_thread::get_id();
if(computeCommands.find(id) == computeCommands.end()) if(computeCommands.find(id) == computeCommands.end())
{ {
computeCommands[id] = new CommandBufferManager(this, computeQueue); computeCommands[id] = new CommandBufferManager(this, computeQueue);
} }
return computeCommands[id]; return computeCommands[id];
} }
std::mutex transferCommandLock; std::mutex transferCommandLock;
PCommandBufferManager Graphics::getTransferCommands() PCommandBufferManager Graphics::getTransferCommands()
{ {
std::unique_lock lock(transferCommandLock); std::unique_lock lock(transferCommandLock);
auto id = std::this_thread::get_id(); auto id = std::this_thread::get_id();
if(transferCommands.find(id) == transferCommands.end()) if(transferCommands.find(id) == transferCommands.end())
{ {
transferCommands[id] = new CommandBufferManager(this, transferQueue); transferCommands[id] = new CommandBufferManager(this, transferQueue);
} }
return transferCommands[id]; return transferCommands[id];
} }
std::mutex dedicatedCommandLock; std::mutex dedicatedCommandLock;
PCommandBufferManager Graphics::getDedicatedTransferCommands() PCommandBufferManager Graphics::getDedicatedTransferCommands()
{ {
std::unique_lock lock(dedicatedCommandLock); std::unique_lock lock(dedicatedCommandLock);
auto id = std::this_thread::get_id(); auto id = std::this_thread::get_id();
if(dedicatedTransferCommands.find(id) == dedicatedTransferCommands.end()) if(dedicatedTransferCommands.find(id) == dedicatedTransferCommands.end())
{ {
dedicatedTransferCommands[id] = new CommandBufferManager(this, dedicatedTransferQueue); dedicatedTransferCommands[id] = new CommandBufferManager(this, dedicatedTransferQueue);
} }
return dedicatedTransferCommands[id]; return dedicatedTransferCommands[id];
} }
PAllocator Graphics::getAllocator() PAllocator Graphics::getAllocator()
{ {
return allocator; return allocator;
} }
PStagingManager Graphics::getStagingManager() PStagingManager Graphics::getStagingManager()
{ {
return stagingManager; return stagingManager;
} }
Array<const char *> Graphics::getRequiredExtensions() Array<const char *> Graphics::getRequiredExtensions()
{ {
Array<const char *> extensions; Array<const char *> extensions;
unsigned int glfwExtensionCount = 0; 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]); extensions.add(glfwExtensions[i]);
} }
#if ENABLE_VALIDATION #if ENABLE_VALIDATION
extensions.add(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); extensions.add(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
#endif // ENABLE_VALIDATION #endif // ENABLE_VALIDATION
return extensions; return extensions;
} }
void Graphics::initInstance(GraphicsInitializer initInfo) void Graphics::initInstance(GraphicsInitializer initInfo)
{ {
glfwInit(); glfwInit();
VkApplicationInfo appInfo = {}; VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = initInfo.applicationName; appInfo.pApplicationName = initInfo.applicationName;
appInfo.applicationVersion = VK_MAKE_VERSION(0, 0, 1); appInfo.applicationVersion = VK_MAKE_VERSION(0, 0, 1);
appInfo.pEngineName = initInfo.engineName; appInfo.pEngineName = initInfo.engineName;
appInfo.engineVersion = VK_MAKE_VERSION(0, 0, 1); appInfo.engineVersion = VK_MAKE_VERSION(0, 0, 1);
appInfo.apiVersion = VK_API_VERSION_1_2; appInfo.apiVersion = VK_API_VERSION_1_2;
VkInstanceCreateInfo info = {}; VkInstanceCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
info.pApplicationInfo = &appInfo; info.pApplicationInfo = &appInfo;
Array<const char *> extensions = getRequiredExtensions(); Array<const char *> extensions = getRequiredExtensions();
for (uint32 i = 0; i < initInfo.instanceExtensions.size(); ++i) for (uint32 i = 0; i < initInfo.instanceExtensions.size(); ++i)
{ {
extensions.add(initInfo.instanceExtensions[i]); extensions.add(initInfo.instanceExtensions[i]);
} }
info.enabledExtensionCount = (uint32)extensions.size(); info.enabledExtensionCount = (uint32)extensions.size();
info.ppEnabledExtensionNames = extensions.data(); info.ppEnabledExtensionNames = extensions.data();
#if ENABLE_VALIDATION #if ENABLE_VALIDATION
info.enabledLayerCount = (uint32)initInfo.layers.size(); info.enabledLayerCount = (uint32)initInfo.layers.size();
info.ppEnabledLayerNames = initInfo.layers.data(); info.ppEnabledLayerNames = initInfo.layers.data();
#else #else
info.enabledLayerCount = 0; info.enabledLayerCount = 0;
#endif #endif
VK_CHECK(vkCreateInstance(&info, nullptr, &instance)); VK_CHECK(vkCreateInstance(&info, nullptr, &instance));
} }
void Graphics::setupDebugCallback() void Graphics::setupDebugCallback()
{ {
VkDebugReportCallbackCreateInfoEXT createInfo = VkDebugReportCallbackCreateInfoEXT createInfo =
init::DebugReportCallbackCreateInfo( init::DebugReportCallbackCreateInfo(
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT); VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT);
VK_CHECK(CreateDebugReportCallbackEXT(instance, &createInfo, nullptr, &callback)); VK_CHECK(CreateDebugReportCallbackEXT(instance, &createInfo, nullptr, &callback));
crashTracker.Initialize(); crashTracker.Initialize();
} }
void Graphics::pickPhysicalDevice() void Graphics::pickPhysicalDevice()
{ {
uint32 physicalDeviceCount; uint32 physicalDeviceCount;
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr); vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr);
Array<VkPhysicalDevice> physicalDevices(physicalDeviceCount); Array<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()); vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data());
VkPhysicalDevice bestDevice = VK_NULL_HANDLE; VkPhysicalDevice bestDevice = VK_NULL_HANDLE;
uint32 deviceRating = 0; uint32 deviceRating = 0;
for (auto dev : physicalDevices) for (auto dev : physicalDevices)
{ {
uint32 currentRating = 0; uint32 currentRating = 0;
vkGetPhysicalDeviceProperties(dev, &props); vkGetPhysicalDeviceProperties(dev, &props);
vkGetPhysicalDeviceFeatures(dev, &features); vkGetPhysicalDeviceFeatures(dev, &features);
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
{ {
std::cout << "found dedicated gpu " << props.deviceName << std::endl; std::cout << "found dedicated gpu " << props.deviceName << std::endl;
currentRating += 100; currentRating += 100;
} }
else if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) else if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
{ {
std::cout << "found integrated gpu " << props.deviceName << std::endl; std::cout << "found integrated gpu " << props.deviceName << std::endl;
currentRating += 10; currentRating += 10;
} }
if (currentRating > deviceRating) if (currentRating > deviceRating)
{ {
deviceRating = currentRating; deviceRating = currentRating;
bestDevice = dev; bestDevice = dev;
std::cout << "bestDevice: " << props.deviceName << std::endl; std::cout << "bestDevice: " << props.deviceName << std::endl;
} }
} }
physicalDevice = bestDevice; physicalDevice = bestDevice;
vkGetPhysicalDeviceProperties(physicalDevice, &props); vkGetPhysicalDeviceProperties(physicalDevice, &props);
vkGetPhysicalDeviceFeatures(physicalDevice, &features); vkGetPhysicalDeviceFeatures(physicalDevice, &features);
} }
void Graphics::createDevice(GraphicsInitializer initializer) void Graphics::createDevice(GraphicsInitializer initializer)
{ {
uint32_t numQueueFamilies = 0; uint32_t numQueueFamilies = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueueFamilies, nullptr); vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueueFamilies, nullptr);
Array<VkQueueFamilyProperties> queueProperties(numQueueFamilies); Array<VkQueueFamilyProperties> queueProperties(numQueueFamilies);
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueueFamilies, queueProperties.data()); vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &numQueueFamilies, queueProperties.data());
Array<VkDeviceQueueCreateInfo> queueInfos; Array<VkDeviceQueueCreateInfo> queueInfos;
struct QueueCreateInfo struct QueueCreateInfo
{ {
int32 familyIndex = -1; int32 familyIndex = -1;
int32 queueIndex = -1; int32 queueIndex = -1;
}; };
QueueCreateInfo graphicsQueueInfo; QueueCreateInfo graphicsQueueInfo;
QueueCreateInfo transferQueueInfo; QueueCreateInfo transferQueueInfo;
QueueCreateInfo dedicatedTransferQueueInfo; QueueCreateInfo dedicatedTransferQueueInfo;
QueueCreateInfo computeQueueInfo; QueueCreateInfo computeQueueInfo;
QueueCreateInfo asyncComputeInfo; QueueCreateInfo asyncComputeInfo;
uint32 numPriorities = 0; uint32 numPriorities = 0;
auto checkFamilyProperty = [](VkQueueFamilyProperties currProps, uint32 checkBit){ auto checkFamilyProperty = [](VkQueueFamilyProperties currProps, uint32 checkBit){
return (currProps.queueFlags & checkBit) == checkBit; return (currProps.queueFlags & checkBit) == checkBit;
}; };
for (uint32 familyIndex = 0; familyIndex < queueProperties.size(); ++familyIndex) for (uint32 familyIndex = 0; familyIndex < queueProperties.size(); ++familyIndex)
{ {
uint32 numQueuesForFamily = 0; uint32 numQueuesForFamily = 0;
VkQueueFamilyProperties currProps = queueProperties[familyIndex]; VkQueueFamilyProperties currProps = queueProperties[familyIndex];
if (checkFamilyProperty(currProps, VK_QUEUE_GRAPHICS_BIT)) if (checkFamilyProperty(currProps, VK_QUEUE_GRAPHICS_BIT))
{ {
if (graphicsQueueInfo.familyIndex == -1) if (graphicsQueueInfo.familyIndex == -1)
{ {
graphicsQueueInfo.familyIndex = familyIndex; graphicsQueueInfo.familyIndex = familyIndex;
numQueuesForFamily++; numQueuesForFamily++;
} }
} }
if ((currProps.queueFlags & VK_QUEUE_COMPUTE_BIT) == VK_QUEUE_COMPUTE_BIT) if ((currProps.queueFlags & VK_QUEUE_COMPUTE_BIT) == VK_QUEUE_COMPUTE_BIT)
{ {
if (computeQueueInfo.familyIndex == -1) if (computeQueueInfo.familyIndex == -1)
{ {
computeQueueInfo.familyIndex = familyIndex; computeQueueInfo.familyIndex = familyIndex;
} }
if (Gfx::useAsyncCompute && numQueueFamilies > 1) if (Gfx::useAsyncCompute && numQueueFamilies > 1)
{ {
if (asyncComputeInfo.familyIndex == -1) if (asyncComputeInfo.familyIndex == -1)
{ {
if (familyIndex == (uint32)graphicsQueueInfo.familyIndex) if (familyIndex == (uint32)graphicsQueueInfo.familyIndex)
{ {
if (currProps.queueCount > 1) if (currProps.queueCount > 1)
{ {
asyncComputeInfo.familyIndex = familyIndex; asyncComputeInfo.familyIndex = familyIndex;
numQueuesForFamily++; numQueuesForFamily++;
} }
} }
else else
{ {
asyncComputeInfo.familyIndex = familyIndex; asyncComputeInfo.familyIndex = familyIndex;
} }
} }
} }
} }
if ((currProps.queueFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT) if ((currProps.queueFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT)
{ {
if (transferQueueInfo.familyIndex == -1) if (transferQueueInfo.familyIndex == -1)
{ {
transferQueueInfo.familyIndex = familyIndex; transferQueueInfo.familyIndex = familyIndex;
numQueuesForFamily++; numQueuesForFamily++;
} }
if ((currProps.queueFlags ^ VK_QUEUE_TRANSFER_BIT) == 0) if ((currProps.queueFlags ^ VK_QUEUE_TRANSFER_BIT) == 0)
{ {
dedicatedTransferQueueInfo.familyIndex = familyIndex; dedicatedTransferQueueInfo.familyIndex = familyIndex;
numQueuesForFamily++; numQueuesForFamily++;
} }
} }
if (numQueuesForFamily > 0) if (numQueuesForFamily > 0)
{ {
VkDeviceQueueCreateInfo info = VkDeviceQueueCreateInfo info =
init::DeviceQueueCreateInfo(familyIndex, numQueuesForFamily); init::DeviceQueueCreateInfo(familyIndex, numQueuesForFamily);
numPriorities += numQueuesForFamily; numPriorities += numQueuesForFamily;
queueInfos.add(info); queueInfos.add(info);
} }
} }
Array<float> queuePriorities; Array<float> queuePriorities;
queuePriorities.resize(numPriorities); queuePriorities.resize(numPriorities);
float *currentPriority = queuePriorities.data(); float *currentPriority = queuePriorities.data();
for (uint32 index = 0; index < queueInfos.size(); ++index) for (uint32 index = 0; index < queueInfos.size(); ++index)
{ {
VkDeviceQueueCreateInfo &currQueue = queueInfos[index]; VkDeviceQueueCreateInfo &currQueue = queueInfos[index];
currQueue.pQueuePriorities = currentPriority; currQueue.pQueuePriorities = currentPriority;
for (int32_t queueIndex = 0; queueIndex < (int32_t)currQueue.queueCount; ++queueIndex) for (int32_t queueIndex = 0; queueIndex < (int32_t)currQueue.queueCount; ++queueIndex)
{ {
*currentPriority++ = 1.0f; *currentPriority++ = 1.0f;
} }
} }
VkDeviceCreateInfo deviceInfo = init::DeviceCreateInfo( VkDeviceCreateInfo deviceInfo = init::DeviceCreateInfo(
queueInfos.data(), queueInfos.data(),
(uint32)queueInfos.size(), (uint32)queueInfos.size(),
&features); &features);
#if ENABLE_VALIDATION #if ENABLE_VALIDATION
VkDeviceDiagnosticsConfigCreateInfoNV crashDiagInfo; VkDeviceDiagnosticsConfigCreateInfoNV crashDiagInfo;
crashDiagInfo.sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV; crashDiagInfo.sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV;
crashDiagInfo.pNext = nullptr; crashDiagInfo.pNext = nullptr;
crashDiagInfo.flags = crashDiagInfo.flags =
VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV | VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV |
VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV | VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV |
VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV; VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV;
deviceInfo.pNext = &crashDiagInfo; deviceInfo.pNext = &crashDiagInfo;
#endif #endif
deviceInfo.enabledExtensionCount = (uint32)initializer.deviceExtensions.size(); deviceInfo.enabledExtensionCount = (uint32)initializer.deviceExtensions.size();
deviceInfo.ppEnabledExtensionNames = initializer.deviceExtensions.data(); deviceInfo.ppEnabledExtensionNames = initializer.deviceExtensions.data();
deviceInfo.enabledLayerCount = (uint32_t)initializer.layers.size(); deviceInfo.enabledLayerCount = (uint32_t)initializer.layers.size();
deviceInfo.ppEnabledLayerNames = initializer.layers.data(); deviceInfo.ppEnabledLayerNames = initializer.layers.data();
VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle)); VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle));
std::cout << "Vulkan handle: " << handle << std::endl;
graphicsQueue = new Queue(this, Gfx::QueueType::GRAPHICS, graphicsQueueInfo.familyIndex, 0); graphicsQueue = new Queue(this, Gfx::QueueType::GRAPHICS, graphicsQueueInfo.familyIndex, 0);
if (Gfx::useAsyncCompute && asyncComputeInfo.familyIndex != -1) if (Gfx::useAsyncCompute && asyncComputeInfo.familyIndex != -1)
{ {
if (asyncComputeInfo.familyIndex == graphicsQueueInfo.familyIndex) if (asyncComputeInfo.familyIndex == graphicsQueueInfo.familyIndex)
{ {
// Same family as graphics, but different queue // Same family as graphics, but different queue
computeQueue = new Queue(this, Gfx::QueueType::COMPUTE, asyncComputeInfo.familyIndex, 1); computeQueue = new Queue(this, Gfx::QueueType::COMPUTE, asyncComputeInfo.familyIndex, 1);
} }
else else
{ {
// Different family // Different family
computeQueue = new Queue(this, Gfx::QueueType::COMPUTE, asyncComputeInfo.familyIndex, 0); computeQueue = new Queue(this, Gfx::QueueType::COMPUTE, asyncComputeInfo.familyIndex, 0);
} }
} }
else else
{ {
computeQueue = new Queue(this, Gfx::QueueType::COMPUTE, computeQueueInfo.familyIndex, 0); computeQueue = new Queue(this, Gfx::QueueType::COMPUTE, computeQueueInfo.familyIndex, 0);
} }
transferQueue = new Queue(this, Gfx::QueueType::TRANSFER, transferQueueInfo.familyIndex, 0); transferQueue = new Queue(this, Gfx::QueueType::TRANSFER, transferQueueInfo.familyIndex, 0);
if (dedicatedTransferQueueInfo.familyIndex != -1) if (dedicatedTransferQueueInfo.familyIndex != -1)
{ {
dedicatedTransferQueue = new Queue(this, Gfx::QueueType::DEDICATED_TRANSFER, dedicatedTransferQueueInfo.familyIndex, 0); dedicatedTransferQueue = new Queue(this, Gfx::QueueType::DEDICATED_TRANSFER, dedicatedTransferQueueInfo.familyIndex, 0);
} }
else else
{ {
dedicatedTransferQueue = transferQueue; dedicatedTransferQueue = transferQueue;
} }
queueMapping.graphicsFamily = graphicsQueue->getFamilyIndex(); queueMapping.graphicsFamily = graphicsQueue->getFamilyIndex();
queueMapping.computeFamily = computeQueue->getFamilyIndex(); queueMapping.computeFamily = computeQueue->getFamilyIndex();
queueMapping.transferFamily = transferQueue->getFamilyIndex(); queueMapping.transferFamily = transferQueue->getFamilyIndex();
queueMapping.dedicatedTransferFamily = dedicatedTransferQueue->getFamilyIndex(); queueMapping.dedicatedTransferFamily = dedicatedTransferQueue->getFamilyIndex();
} }
+61 -65
View File
@@ -17,91 +17,87 @@ DECLARE_REF(PipelineCache)
class Graphics : public Gfx::Graphics class Graphics : public Gfx::Graphics
{ {
public: public:
Graphics(); Graphics();
virtual ~Graphics(); virtual ~Graphics();
VkInstance getInstance() const; constexpr VkInstance getInstance() const { return instance; };
VkDevice getDevice() const; constexpr VkDevice getDevice() const { return handle; };
VkPhysicalDevice getPhysicalDevice() const; constexpr VkPhysicalDevice getPhysicalDevice() const { return physicalDevice; };
PCommandBufferManager getQueueCommands(Gfx::QueueType queueType); PCommandBufferManager getQueueCommands(Gfx::QueueType queueType);
PCommandBufferManager getGraphicsCommands(); PCommandBufferManager getGraphicsCommands();
PCommandBufferManager getComputeCommands(); PCommandBufferManager getComputeCommands();
PCommandBufferManager getTransferCommands(); PCommandBufferManager getTransferCommands();
PCommandBufferManager getDedicatedTransferCommands(); PCommandBufferManager getDedicatedTransferCommands();
QueueOwnedResourceDeletion &getDeletionQueue() PAllocator getAllocator();
{ PStagingManager getStagingManager();
return deletionQueue;
}
PAllocator getAllocator(); // Inherited via Graphics
PStagingManager getStagingManager(); virtual void init(GraphicsInitializer initializer) override;
virtual Gfx::PWindow createWindow(const WindowCreateInfo &createInfo) override;
virtual Gfx::PViewport createViewport(Gfx::PWindow owner, const ViewportCreateInfo &createInfo) override;
// Inherited via Graphics virtual Gfx::PRenderPass createRenderPass(Gfx::PRenderTargetLayout layout, Gfx::PViewport renderArea) override;
virtual void init(GraphicsInitializer initializer) override; virtual void beginRenderPass(Gfx::PRenderPass renderPass) override;
virtual Gfx::PWindow createWindow(const WindowCreateInfo &createInfo) override; virtual void endRenderPass() override;
virtual Gfx::PViewport createViewport(Gfx::PWindow owner, const ViewportCreateInfo &createInfo) override;
virtual Gfx::PRenderPass createRenderPass(Gfx::PRenderTargetLayout layout, Gfx::PViewport renderArea) override; virtual void executeCommands(const Array<Gfx::PRenderCommand>& commands) override;
virtual void beginRenderPass(Gfx::PRenderPass renderPass) override;
virtual void endRenderPass() override;
virtual void executeCommands(const Array<Gfx::PRenderCommand>& commands) override;
virtual void executeCommands(const Array<Gfx::PComputeCommand>& commands) override; virtual void executeCommands(const Array<Gfx::PComputeCommand>& commands) override;
virtual Gfx::PTexture2D createTexture2D(const TextureCreateInfo &createInfo) override; virtual Gfx::PTexture2D createTexture2D(const TextureCreateInfo &createInfo) override;
virtual Gfx::PUniformBuffer createUniformBuffer(const UniformBufferCreateInfo &bulkData) override; virtual Gfx::PUniformBuffer createUniformBuffer(const UniformBufferCreateInfo &bulkData) override;
virtual Gfx::PStructuredBuffer createStructuredBuffer(const StructuredBufferCreateInfo &bulkData) override; virtual Gfx::PStructuredBuffer createStructuredBuffer(const StructuredBufferCreateInfo &bulkData) override;
virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override; virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override;
virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override; virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override;
virtual Gfx::PRenderCommand createRenderCommand(const std::string& name) override; virtual Gfx::PRenderCommand createRenderCommand(const std::string& name) override;
virtual Gfx::PComputeCommand createComputeCommand(const std::string& name) override; virtual Gfx::PComputeCommand createComputeCommand(const std::string& name) override;
virtual Gfx::PVertexDeclaration createVertexDeclaration(const Array<Gfx::VertexElement>& element) override; virtual Gfx::PVertexDeclaration createVertexDeclaration(const Array<Gfx::VertexElement>& element) override;
virtual Gfx::PVertexShader createVertexShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PVertexShader createVertexShader(const ShaderCreateInfo& createInfo) override;
virtual Gfx::PControlShader createControlShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PControlShader createControlShader(const ShaderCreateInfo& createInfo) override;
virtual Gfx::PEvaluationShader createEvaluationShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PEvaluationShader createEvaluationShader(const ShaderCreateInfo& createInfo) override;
virtual Gfx::PGeometryShader createGeometryShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PGeometryShader createGeometryShader(const ShaderCreateInfo& createInfo) override;
virtual Gfx::PFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) override;
virtual Gfx::PComputeShader createComputeShader(const ShaderCreateInfo& createInfo) override; virtual Gfx::PComputeShader createComputeShader(const ShaderCreateInfo& createInfo) override;
virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override; virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override;
virtual Gfx::PComputePipeline createComputePipeline(const ComputePipelineCreateInfo& createInfo) override; virtual Gfx::PComputePipeline createComputePipeline(const ComputePipelineCreateInfo& createInfo) override;
virtual Gfx::PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) override; virtual Gfx::PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) override;
virtual Gfx::PDescriptorLayout createDescriptorLayout(const std::string& name = "") override; virtual Gfx::PDescriptorLayout createDescriptorLayout(const std::string& name = "") override;
virtual Gfx::PPipelineLayout createPipelineLayout() override; virtual Gfx::PPipelineLayout createPipelineLayout() override;
virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override; virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override;
protected: protected:
Array<const char *> getRequiredExtensions(); Array<const char *> getRequiredExtensions();
void initInstance(GraphicsInitializer initInfo); void initInstance(GraphicsInitializer initInfo);
void setupDebugCallback(); void setupDebugCallback();
void pickPhysicalDevice(); void pickPhysicalDevice();
void createDevice(GraphicsInitializer initInfo); void createDevice(GraphicsInitializer initInfo);
VkInstance instance; VkInstance instance;
VkDevice handle; VkDevice handle;
VkPhysicalDevice physicalDevice; VkPhysicalDevice physicalDevice;
PQueue graphicsQueue; PQueue graphicsQueue;
PQueue computeQueue; PQueue computeQueue;
PQueue transferQueue; PQueue transferQueue;
PQueue dedicatedTransferQueue; PQueue dedicatedTransferQueue;
QueueOwnedResourceDeletion deletionQueue; PPipelineCache pipelineCache;
PPipelineCache pipelineCache; Map<std::thread::id, PCommandBufferManager> graphicsCommands;
Map<std::thread::id, PCommandBufferManager> graphicsCommands; Map<std::thread::id, PCommandBufferManager> computeCommands;
Map<std::thread::id, PCommandBufferManager> computeCommands; Map<std::thread::id, PCommandBufferManager> transferCommands;
Map<std::thread::id, PCommandBufferManager> transferCommands; Map<std::thread::id, PCommandBufferManager> dedicatedTransferCommands;
Map<std::thread::id, PCommandBufferManager> dedicatedTransferCommands; VkPhysicalDeviceProperties props;
VkPhysicalDeviceProperties props; VkPhysicalDeviceFeatures features;
VkPhysicalDeviceFeatures features; VkDebugReportCallbackEXT callback;
VkDebugReportCallbackEXT callback; std::mutex viewportLock;
Array<PViewport> viewports; Array<PViewport> viewports;
Map<uint32, PFramebuffer> allocatedFramebuffers; std::mutex allocatedFrameBufferLock;
PAllocator allocator; Map<uint32, PFramebuffer> allocatedFramebuffers;
PStagingManager stagingManager; PAllocator allocator;
GpuCrashTracker crashTracker; PStagingManager stagingManager;
GpuCrashTracker crashTracker;
friend class Window; friend class Window;
}; };
DEFINE_REF(Graphics) DEFINE_REF(Graphics)
} // namespace Vulkan } // namespace Vulkan
@@ -7,48 +7,6 @@
using namespace Seele; using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
List<QueueOwnedResourceDeletion::PendingItem> QueueOwnedResourceDeletion::deletionQueue;
volatile bool QueueOwnedResourceDeletion::running;
std::mutex QueueOwnedResourceDeletion::mutex;
std::condition_variable QueueOwnedResourceDeletion::cv;
QueueOwnedResourceDeletion::QueueOwnedResourceDeletion()
{
worker = std::thread(&run);
running = true;
}
QueueOwnedResourceDeletion::~QueueOwnedResourceDeletion()
{
worker.join();
}
void QueueOwnedResourceDeletion::addPendingDelete(PCmdBuffer cmdbuffer, std::function<void()> func)
{
PendingItem item;
item.cmdBuffer = cmdbuffer;
item.func = func;
deletionQueue.add(item);
std::unique_lock<std::mutex> lock(mutex);
cv.notify_all();
}
void QueueOwnedResourceDeletion::run()
{
while (running || !deletionQueue.empty())
{
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock);
auto entry = deletionQueue.begin();
PCmdBuffer cmdBuffer = entry->cmdBuffer;
//cmdBuffer->getManager()->waitForCommands(cmdBuffer);
//cmdBuffer->begin();
//entry->func();
deletionQueue.remove(entry);
}
}
Semaphore::Semaphore(PGraphics graphics) Semaphore::Semaphore(PGraphics graphics)
: graphics(graphics) : graphics(graphics)
{ {
@@ -65,7 +23,7 @@ Semaphore::~Semaphore()
Fence::Fence(PGraphics graphics) Fence::Fence(PGraphics graphics)
: graphics(graphics) : graphics(graphics)
, signaled(false) , signaled("Fence")
{ {
VkFenceCreateInfo info = VkFenceCreateInfo info =
init::FenceCreateInfo(0); init::FenceCreateInfo(0);
@@ -87,7 +45,7 @@ bool Fence::isSignaled()
switch (res) switch (res)
{ {
case VK_SUCCESS: case VK_SUCCESS:
signaled = true; signaled.raise();
return true; return true;
case VK_NOT_READY: case VK_NOT_READY:
break; break;
@@ -102,7 +60,7 @@ void Fence::reset()
if (signaled) if (signaled)
{ {
vkResetFences(graphics->getDevice(), 1, &fence); vkResetFences(graphics->getDevice(), 1, &fence);
signaled = false; signaled.reset();
} }
} }
@@ -113,7 +71,7 @@ void Fence::wait(uint32 timeout)
switch (r) switch (r)
{ {
case VK_SUCCESS: case VK_SUCCESS:
signaled = true; signaled.raise();
break; break;
case VK_TIMEOUT: case VK_TIMEOUT:
break; break;
@@ -122,6 +80,11 @@ void Fence::wait(uint32 timeout)
break; break;
} }
} }
Event Fence::asyncWait() const
{
return signaled;
}
VertexDeclaration::VertexDeclaration(const Array<Gfx::VertexElement>& elementList) VertexDeclaration::VertexDeclaration(const Array<Gfx::VertexElement>& elementList)
: elementList(elementList) : elementList(elementList)
@@ -2,6 +2,8 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <functional> #include <functional>
#include "Graphics/GraphicsResources.h" #include "Graphics/GraphicsResources.h"
#include "VulkanAllocator.h"
#include "ThreadPool.h"
namespace Seele namespace Seele
{ {
@@ -16,117 +18,97 @@ DECLARE_REF(SubAllocation)
class Semaphore class Semaphore
{ {
public: public:
Semaphore(PGraphics graphics); Semaphore(PGraphics graphics);
virtual ~Semaphore(); virtual ~Semaphore();
inline VkSemaphore getHandle() const inline VkSemaphore getHandle() const
{ {
return handle; return handle;
} }
private: private:
VkSemaphore handle; VkSemaphore handle;
PGraphics graphics; PGraphics graphics;
}; };
DEFINE_REF(Semaphore) DEFINE_REF(Semaphore)
class Fence class Fence
{ {
public: public:
Fence(PGraphics graphics); Fence(PGraphics graphics);
~Fence(); ~Fence();
bool isSignaled(); bool isSignaled();
void reset(); void reset();
inline VkFence getHandle() const inline VkFence getHandle() const
{ {
return fence; return fence;
} }
void wait(uint32 timeout); void wait(uint32 timeout);
bool operator<(const Fence &other) const Event asyncWait() const;
{ bool operator<(const Fence &other) const
return fence < other.fence; {
} return fence < other.fence;
}
private: private:
PGraphics graphics; PGraphics graphics;
bool signaled; Event signaled;
VkFence fence; VkFence fence;
}; };
DEFINE_REF(Fence) DEFINE_REF(Fence)
class VertexDeclaration : public Gfx::VertexDeclaration class VertexDeclaration : public Gfx::VertexDeclaration
{ {
public: public:
Array<Gfx::VertexElement> elementList; Array<Gfx::VertexElement> elementList;
VertexDeclaration(const Array<Gfx::VertexElement>& elementList); VertexDeclaration(const Array<Gfx::VertexElement>& elementList);
virtual ~VertexDeclaration(); virtual ~VertexDeclaration();
private: private:
}; };
DEFINE_REF(VertexDeclaration) DEFINE_REF(VertexDeclaration)
class QueueOwnedResourceDeletion
{
public:
QueueOwnedResourceDeletion();
virtual ~QueueOwnedResourceDeletion();
static void addPendingDelete(PCmdBuffer fence, std::function<void()> function);
private:
std::thread worker;
static volatile bool running;
static void run();
struct PendingItem
{
PCmdBuffer cmdBuffer;
std::function<void()> func;
};
static std::mutex mutex;
static std::condition_variable cv;
static List<PendingItem> deletionQueue;
};
class ShaderBuffer class ShaderBuffer
{ {
public: public:
ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false); ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false);
virtual ~ShaderBuffer(); virtual ~ShaderBuffer();
VkBuffer getHandle() const VkBuffer getHandle() const
{ {
return buffers[currentBuffer].buffer; return buffers[currentBuffer].buffer;
} }
uint32 getSize() const uint32 getSize() const
{ {
return size; return size;
} }
VkDeviceSize getOffset() const; VkDeviceSize getOffset() const;
void advanceBuffer() void advanceBuffer()
{ {
currentBuffer = (currentBuffer + 1) % numBuffers; currentBuffer = (currentBuffer + 1) % numBuffers;
} }
virtual void *lock(bool bWriteOnly = true); virtual void *lock(bool bWriteOnly = true);
virtual void unlock(); virtual void unlock();
protected: protected:
struct BufferAllocation struct BufferAllocation
{ {
VkBuffer buffer; VkBuffer buffer;
PSubAllocation allocation; PSubAllocation allocation;
}; };
PGraphics graphics; PGraphics graphics;
uint32 currentBuffer; uint32 currentBuffer;
uint32 size; uint32 size;
Gfx::QueueType& owner; Gfx::QueueType& owner;
BufferAllocation buffers[Gfx::numFramesBuffered]; BufferAllocation buffers[Gfx::numFramesBuffered];
uint32 numBuffers; uint32 numBuffers;
void executeOwnershipBarrier(Gfx::QueueType newOwner); void executeOwnershipBarrier(Gfx::QueueType newOwner);
void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0; virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0;
virtual VkAccessFlags getSourceAccessMask() = 0; virtual VkAccessFlags getSourceAccessMask() = 0;
virtual VkAccessFlags getDestAccessMask() = 0; virtual VkAccessFlags getDestAccessMask() = 0;
}; };
DEFINE_REF(ShaderBuffer) DEFINE_REF(ShaderBuffer)
@@ -134,217 +116,217 @@ DECLARE_REF(StagingBuffer)
class UniformBuffer : public Gfx::UniformBuffer, public ShaderBuffer class UniformBuffer : public Gfx::UniformBuffer, public ShaderBuffer
{ {
public: public:
UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &resourceData); UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &resourceData);
virtual ~UniformBuffer(); virtual ~UniformBuffer();
virtual bool updateContents(const BulkResourceData &resourceData); virtual bool updateContents(const BulkResourceData &resourceData);
virtual void* lock(bool bWriteOnly = true) override; virtual void* lock(bool bWriteOnly = true) override;
virtual void unlock() override; virtual void unlock() override;
protected: protected:
// Inherited via Vulkan::Buffer // Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask(); virtual VkAccessFlags getSourceAccessMask();
virtual VkAccessFlags getDestAccessMask(); virtual VkAccessFlags getDestAccessMask();
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
private: private:
PStagingBuffer dedicatedStagingBuffer; PStagingBuffer dedicatedStagingBuffer;
}; };
DEFINE_REF(UniformBuffer) DEFINE_REF(UniformBuffer)
class StructuredBuffer : public Gfx::StructuredBuffer, public ShaderBuffer class StructuredBuffer : public Gfx::StructuredBuffer, public ShaderBuffer
{ {
public: public:
StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData); StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData);
virtual ~StructuredBuffer(); virtual ~StructuredBuffer();
virtual bool updateContents(const BulkResourceData &resourceData); virtual bool updateContents(const BulkResourceData &resourceData);
virtual void* lock(bool bWriteOnly = true) override; virtual void* lock(bool bWriteOnly = true) override;
virtual void unlock() override; virtual void unlock() override;
protected: protected:
// Inherited via Vulkan::Buffer // Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask(); virtual VkAccessFlags getSourceAccessMask();
virtual VkAccessFlags getDestAccessMask(); virtual VkAccessFlags getDestAccessMask();
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
private: private:
PStagingBuffer dedicatedStagingBuffer; PStagingBuffer dedicatedStagingBuffer;
}; };
DEFINE_REF(StructuredBuffer) DEFINE_REF(StructuredBuffer)
class VertexBuffer : public Gfx::VertexBuffer, public ShaderBuffer class VertexBuffer : public Gfx::VertexBuffer, public ShaderBuffer
{ {
public: public:
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData); VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData);
virtual ~VertexBuffer(); virtual ~VertexBuffer();
protected: protected:
// Inherited via Vulkan::Buffer // Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask(); virtual VkAccessFlags getSourceAccessMask();
virtual VkAccessFlags getDestAccessMask(); virtual VkAccessFlags getDestAccessMask();
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
}; };
DEFINE_REF(VertexBuffer) DEFINE_REF(VertexBuffer)
class IndexBuffer : public Gfx::IndexBuffer, public ShaderBuffer class IndexBuffer : public Gfx::IndexBuffer, public ShaderBuffer
{ {
public: public:
IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData); IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData);
virtual ~IndexBuffer(); virtual ~IndexBuffer();
protected: protected:
// Inherited via Vulkan::Buffer // Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask(); virtual VkAccessFlags getSourceAccessMask();
virtual VkAccessFlags getDestAccessMask(); virtual VkAccessFlags getDestAccessMask();
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner); virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
}; };
DEFINE_REF(IndexBuffer) DEFINE_REF(IndexBuffer)
class TextureHandle class TextureHandle
{ {
public: public:
TextureHandle(PGraphics graphics, VkImageViewType viewType, TextureHandle(PGraphics graphics, VkImageViewType viewType,
const TextureCreateInfo& createInfo, Gfx::QueueType& owner, VkImage existingImage = VK_NULL_HANDLE); const TextureCreateInfo& createInfo, Gfx::QueueType& owner, VkImage existingImage = VK_NULL_HANDLE);
virtual ~TextureHandle(); virtual ~TextureHandle();
inline VkImage getImage() const inline VkImage getImage() const
{ {
return image; return image;
} }
inline VkImageView getView() const inline VkImageView getView() const
{ {
return defaultView; return defaultView;
} }
inline Gfx::SeImageLayout getLayout() const inline Gfx::SeImageLayout getLayout() const
{ {
return layout; return layout;
} }
inline VkImageAspectFlags getAspect() const inline VkImageAspectFlags getAspect() const
{ {
return aspect; return aspect;
} }
inline VkImageUsageFlags getUsage() const inline VkImageUsageFlags getUsage() const
{ {
return usage; return usage;
} }
inline Gfx::SeFormat getFormat() const inline Gfx::SeFormat getFormat() const
{ {
return format; return format;
} }
inline Gfx::SeSampleCountFlags getNumSamples() const inline Gfx::SeSampleCountFlags getNumSamples() const
{ {
return samples; return samples;
} }
inline uint32 getMipLevels() const inline uint32 getMipLevels() const
{ {
return mipLevels; return mipLevels;
} }
inline bool isDepthStencil() const inline bool isDepthStencil() const
{ {
return aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); return aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
} }
void executeOwnershipBarrier(Gfx::QueueType newOwner); void executeOwnershipBarrier(Gfx::QueueType newOwner);
void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
void changeLayout(Gfx::SeImageLayout newLayout); void changeLayout(Gfx::SeImageLayout newLayout);
private: private:
//Updates via reference //Updates via reference
Gfx::QueueType& currentOwner; Gfx::QueueType& currentOwner;
PGraphics graphics; PGraphics graphics;
PSubAllocation allocation; PSubAllocation allocation;
uint32 sizeX; uint32 sizeX;
uint32 sizeY; uint32 sizeY;
uint32 sizeZ; uint32 sizeZ;
uint32 arrayCount; uint32 arrayCount;
uint32 mipLevels; uint32 mipLevels;
uint32 samples; uint32 samples;
Gfx::SeFormat format; Gfx::SeFormat format;
Gfx::SeImageUsageFlags usage; Gfx::SeImageUsageFlags usage;
VkImage image; VkImage image;
VkImageView defaultView; VkImageView defaultView;
VkImageAspectFlags aspect; VkImageAspectFlags aspect;
Gfx::SeImageLayout layout; Gfx::SeImageLayout layout;
friend class TextureBase; friend class TextureBase;
friend class Texture2D; friend class Texture2D;
friend class Graphics; friend class Graphics;
}; };
class TextureBase class TextureBase
{ {
public: public:
static TextureHandle* cast(Gfx::PTexture texture); static TextureHandle* cast(Gfx::PTexture texture);
protected: protected:
TextureHandle* textureHandle; TextureHandle* textureHandle;
friend class Graphics; friend class Graphics;
}; };
DECLARE_REF(TextureBase) DECLARE_REF(TextureBase)
class Texture2D : public Gfx::Texture2D, public TextureBase class Texture2D : public Gfx::Texture2D, public TextureBase
{ {
public: public:
Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE); Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
virtual ~Texture2D(); virtual ~Texture2D();
virtual uint32 getSizeX() const override virtual uint32 getSizeX() const override
{ {
return textureHandle->sizeX; return textureHandle->sizeX;
} }
virtual uint32 getSizeY() const override virtual uint32 getSizeY() const override
{ {
return textureHandle->sizeY; return textureHandle->sizeY;
} }
virtual uint32 getSizeZ() const override virtual uint32 getSizeZ() const override
{ {
return textureHandle->sizeZ; return textureHandle->sizeZ;
} }
virtual Gfx::SeFormat getFormat() const override virtual Gfx::SeFormat getFormat() const override
{ {
return textureHandle->format; return textureHandle->format;
} }
virtual Gfx::SeSampleCountFlags getNumSamples() const override virtual Gfx::SeSampleCountFlags getNumSamples() const override
{ {
return textureHandle->getNumSamples(); return textureHandle->getNumSamples();
} }
virtual uint32 getMipLevels() const override virtual uint32 getMipLevels() const override
{ {
return textureHandle->getMipLevels(); return textureHandle->getMipLevels();
} }
virtual void changeLayout(Gfx::SeImageLayout newLayout) override; virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
virtual void* getNativeHandle() override virtual void* getNativeHandle() override
{ {
return textureHandle; return textureHandle;
} }
inline VkImage getHandle() const inline VkImage getHandle() const
{ {
return textureHandle->image; return textureHandle->image;
} }
inline VkImageView getView() const inline VkImageView getView() const
{ {
return textureHandle->defaultView; return textureHandle->defaultView;
} }
inline bool isDepthStencil() const inline bool isDepthStencil() const
{ {
return textureHandle->isDepthStencil(); return textureHandle->isDepthStencil();
} }
protected: protected:
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner); virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
}; };
DEFINE_REF(Texture2D) DEFINE_REF(Texture2D)
@@ -352,74 +334,74 @@ DEFINE_REF(Texture2D)
class SamplerState : public Gfx::SamplerState class SamplerState : public Gfx::SamplerState
{ {
public: public:
VkSampler sampler; VkSampler sampler;
}; };
DEFINE_REF(SamplerState) DEFINE_REF(SamplerState)
class Window : public Gfx::Window class Window : public Gfx::Window
{ {
public: public:
Window(PGraphics graphics, const WindowCreateInfo &createInfo); Window(PGraphics graphics, const WindowCreateInfo &createInfo);
virtual ~Window(); virtual ~Window();
virtual void beginFrame() override; virtual void beginFrame() override;
virtual void endFrame() override; virtual void endFrame() override;
virtual Gfx::PTexture2D getBackBuffer() const override; virtual Gfx::PTexture2D getBackBuffer() const override;
virtual void onWindowCloseEvent() override; virtual void onWindowCloseEvent() override;
virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) override; virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) override;
virtual void setMouseMoveCallback(std::function<void(double, double)> callback) override; virtual void setMouseMoveCallback(std::function<void(double, double)> callback) override;
virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) override; virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) override;
virtual void setScrollCallback(std::function<void(double, double)> callback) override; virtual void setScrollCallback(std::function<void(double, double)> callback) override;
virtual void setFileCallback(std::function<void(int, const char**)> callback) override; virtual void setFileCallback(std::function<void(int, const char**)> callback) override;
virtual void setCloseCallback(std::function<void()> callback); virtual void setCloseCallback(std::function<void()> callback);
std::function<void(KeyCode, InputAction, KeyModifier)> keyCallback; std::function<void(KeyCode, InputAction, KeyModifier)> keyCallback;
std::function<void(double, double)> mouseMoveCallback; std::function<void(double, double)> mouseMoveCallback;
std::function<void(MouseButton, InputAction, KeyModifier)> mouseButtonCallback; std::function<void(MouseButton, InputAction, KeyModifier)> mouseButtonCallback;
std::function<void(double, double)> scrollCallback; std::function<void(double, double)> scrollCallback;
std::function<void(int, const char**)> fileCallback; std::function<void(int, const char**)> fileCallback;
std::function<void()> closeCallback; std::function<void()> closeCallback;
protected: protected:
void advanceBackBuffer(); void advanceBackBuffer();
void recreateSwapchain(const WindowCreateInfo &createInfo); void recreateSwapchain(const WindowCreateInfo &createInfo);
void present(); void present();
void destroySwapchain(); void destroySwapchain();
void createSwapchain(); void createSwapchain();
void chooseSurfaceFormat(const Array<VkSurfaceFormatKHR> &available, Gfx::SeFormat preferred); void chooseSurfaceFormat(const Array<VkSurfaceFormatKHR> &available, Gfx::SeFormat preferred);
void choosePresentMode(const Array<VkPresentModeKHR> &modes); void choosePresentMode(const Array<VkPresentModeKHR> &modes);
PTexture2D backBufferImages[Gfx::numFramesBuffered]; PTexture2D backBufferImages[Gfx::numFramesBuffered];
PSemaphore renderFinished[Gfx::numFramesBuffered]; PSemaphore renderFinished[Gfx::numFramesBuffered];
PSemaphore imageAcquired[Gfx::numFramesBuffered]; PSemaphore imageAcquired[Gfx::numFramesBuffered];
PSemaphore imageAcquiredSemaphore; PSemaphore imageAcquiredSemaphore;
PGraphics graphics; PGraphics graphics;
VkInstance instance; VkInstance instance;
VkSwapchainKHR swapchain; VkSwapchainKHR swapchain;
VkSampleCountFlags numSamples; VkSampleCountFlags numSamples;
VkFormat pixelFormat; VkFormat pixelFormat;
VkPresentModeKHR presentMode; VkPresentModeKHR presentMode;
VkSurfaceKHR surface; VkSurfaceKHR surface;
VkSurfaceFormatKHR surfaceFormat; VkSurfaceFormatKHR surfaceFormat;
void *windowHandle; void *windowHandle;
int32 currentImageIndex; int32 currentImageIndex;
int32 acquiredImageIndex; int32 acquiredImageIndex;
int32 preAcquiredImageIndex; int32 preAcquiredImageIndex;
int32 semaphoreIndex; int32 semaphoreIndex;
}; };
DEFINE_REF(Window) DEFINE_REF(Window)
class Viewport : public Gfx::Viewport class Viewport : public Gfx::Viewport
{ {
public: public:
Viewport(PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo); Viewport(PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo);
virtual ~Viewport(); virtual ~Viewport();
virtual void resize(uint32 newX, uint32 newY); virtual void resize(uint32 newX, uint32 newY);
virtual void move(uint32 newOffsetX, uint32 newOffsetY); virtual void move(uint32 newOffsetX, uint32 newOffsetY);
VkViewport getHandle() const { return handle; } VkViewport getHandle() const { return handle; }
private: private:
VkViewport handle; VkViewport handle;
PGraphics graphics; PGraphics graphics;
friend class Graphics; friend class Graphics;
}; };
DECLARE_REF(Viewport) DECLARE_REF(Viewport)
} // namespace Vulkan } // namespace Vulkan
@@ -29,6 +29,7 @@ PipelineCache::PipelineCache(PGraphics graphics, const std::string& cacheFilePat
stream.read((char*)cacheData.data(), fileSize); stream.read((char*)cacheData.data(), fileSize);
cacheCreateInfo.initialDataSize = fileSize; cacheCreateInfo.initialDataSize = fileSize;
cacheCreateInfo.pInitialData = cacheData.data(); cacheCreateInfo.pInitialData = cacheData.data();
std::cout << "Loaded " << fileSize << " bytes from pipeline cache" << std::endl;
} }
VK_CHECK(vkCreatePipelineCache(graphics->getDevice(), &cacheCreateInfo, nullptr, &cache)); VK_CHECK(vkCreatePipelineCache(graphics->getDevice(), &cacheCreateInfo, nullptr, &cache));
} }
@@ -44,6 +45,7 @@ PipelineCache::~PipelineCache()
stream.flush(); stream.flush();
stream.close(); stream.close();
vkDestroyPipelineCache(graphics->getDevice(), cache, nullptr); vkDestroyPipelineCache(graphics->getDevice(), cache, nullptr);
std::cout << "Written " << cacheSize << " bytes to cache" << std::endl;
} }
struct PipelineCreateHashStruct struct PipelineCreateHashStruct
@@ -321,6 +323,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
uint32 hash = crc.checksum(); uint32 hash = crc.checksum();
VkPipeline pipelineHandle; VkPipeline pipelineHandle;
std::unique_lock lock(createdPipelinesLock);
auto foundPipeline = createdPipelines.find(hash); auto foundPipeline = createdPipelines.find(hash);
if (foundPipeline != createdPipelines.end()) if (foundPipeline != createdPipelines.end())
{ {
@@ -16,6 +16,7 @@ private:
VkPipelineCache cache; VkPipelineCache cache;
PGraphics graphics; PGraphics graphics;
std::string cacheFile; std::string cacheFile;
std::mutex createdPipelinesLock;
Map<uint32, VkPipeline> createdPipelines; Map<uint32, VkPipeline> createdPipelines;
}; };
DEFINE_REF(PipelineCache) DEFINE_REF(PipelineCache)
+8 -3
View File
@@ -4,6 +4,7 @@
#include "VulkanGraphicsEnums.h" #include "VulkanGraphicsEnums.h"
#include "VulkanAllocator.h" #include "VulkanAllocator.h"
#include "VulkanCommandBuffer.h" #include "VulkanCommandBuffer.h"
#include "ThreadPool.h"
#include <math.h> #include <math.h>
using namespace Seele; using namespace Seele;
@@ -161,13 +162,17 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType,
TextureHandle::~TextureHandle() TextureHandle::~TextureHandle()
{ {
auto &deletionQueue = graphics->getDeletionQueue();
auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
VkDevice device = graphics->getDevice(); VkDevice device = graphics->getDevice();
VkImageView view = defaultView; VkImageView view = defaultView;
VkImage img = image; VkImage img = image;
deletionQueue.addPendingDelete(cmdBuffer, [device, view]() { vkDestroyImageView(device, view, nullptr); }); auto deletionLambda = [cmdBuffer, device, view, img]() -> Job
deletionQueue.addPendingDelete(cmdBuffer, [device, img]() { vkDestroyImage(device, img, nullptr); }); {
vkDestroyImageView(device, view, nullptr);
vkDestroyImage(device, img, nullptr);
co_return;
};
deletionLambda();
} }
TextureHandle* TextureBase::cast(Gfx::PTexture texture) TextureHandle* TextureBase::cast(Gfx::PTexture texture)
+1
View File
@@ -1,6 +1,7 @@
#include "MaterialAsset.h" #include "MaterialAsset.h"
#include "Window/WindowManager.h" #include "Window/WindowManager.h"
#include "Asset/AssetRegistry.h" #include "Asset/AssetRegistry.h"
#include "Asset/TextureAsset.h"
#include "BRDF.h" #include "BRDF.h"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <sstream> #include <sstream>
+5 -17
View File
@@ -38,13 +38,9 @@ public:
: handle(ptr) : handle(ptr)
, deleter(std::move(deleter)) , deleter(std::move(deleter))
, refCount(1) , refCount(1)
{
registeredObjects[ptr] = this;
}
inline RefObject(const RefObject &rhs)
: handle(rhs.handle), refCount(rhs.refCount)
{ {
} }
RefObject(const RefObject &rhs) = delete;
RefObject(RefObject &&rhs) RefObject(RefObject &&rhs)
: handle(std::move(rhs.handle)), refCount(std::move(rhs.refCount)) : handle(std::move(rhs.handle)), refCount(std::move(rhs.refCount))
{ {
@@ -56,18 +52,11 @@ public:
registeredObjects.erase(handle); registeredObjects.erase(handle);
} }
// #pragma warning( disable: 4150) // #pragma warning( disable: 4150)
//deleter(handle); deleter(handle);
handle = nullptr;
// #pragma warning( default: 4150) // #pragma warning( default: 4150)
} }
RefObject &operator=(const RefObject &rhs) RefObject &operator=(const RefObject &rhs) = delete;
{
if (*this != rhs)
{
handle = rhs.handle;
refCount = rhs.refCount;
}
return *this;
}
RefObject &operator=(RefObject &&rhs) RefObject &operator=(RefObject &&rhs)
{ {
if (*this != rhs) if (*this != rhs)
@@ -131,11 +120,10 @@ public:
if (registeredObj == registeredEnd) if (registeredObj == registeredEnd)
{ {
object = new RefObject<T, Deleter>(ptr, std::move(deleter)); object = new RefObject<T, Deleter>(ptr, std::move(deleter));
l.unlock(); registeredObjects[ptr] = object;
} }
else else
{ {
l.unlock();
object = (RefObject<T, Deleter> *)registeredObj->value; object = (RefObject<T, Deleter> *)registeredObj->value;
object->addRef(); object->addRef();
} }
+2 -2
View File
@@ -38,6 +38,7 @@ ThreadPool::ThreadPool(uint32 threadCount)
ThreadPool::~ThreadPool() ThreadPool::~ThreadPool()
{ {
running.store(false);
for(auto& thread : workers) for(auto& thread : workers)
{ {
thread.join(); thread.join();
@@ -74,7 +75,7 @@ void ThreadPool::notify(Event* event)
{ {
std::unique_lock lock(jobQueueLock); std::unique_lock lock(jobQueueLock);
std::unique_lock lock2(waitingLock); std::unique_lock lock2(waitingLock);
while(!waitingJobs.empty()) while(!waitingJobs[*event].empty())
{ {
//std::cout << "Waking up job " << job << std::endl; //std::cout << "Waking up job " << job << std::endl;
jobQueue.add(std::move(waitingJobs[*event].retrieve())); jobQueue.add(std::move(waitingJobs[*event].retrieve()));
@@ -90,7 +91,6 @@ void ThreadPool::notify(Event* event)
mainJobCV.notify_one(); mainJobCV.notify_one();
} }
} }
event->reset();
} }
void ThreadPool::threadLoop(const bool mainThread) void ThreadPool::threadLoop(const bool mainThread)
{ {
+4
View File
@@ -91,6 +91,10 @@ public:
{ {
return *this; return *this;
} }
operator bool()
{
return flag->load();
}
void raise(); void raise();
void reset(); void reset();
+1
View File
@@ -1,4 +1,5 @@
#include "Element.h" #include "Element.h"
#include "UI/System.h"
using namespace Seele; using namespace Seele;
using namespace Seele::UI; using namespace Seele::UI;
+1
View File
@@ -1,4 +1,5 @@
#include "System.h" #include "System.h"
#include "Elements/Panel.h"
using namespace Seele; using namespace Seele;
using namespace Seele::UI; using namespace Seele::UI;
+2
View File
@@ -1,4 +1,6 @@
#include "InspectorView.h" #include "InspectorView.h"
#include "Graphics/Graphics.h"
#include "Scene/Actor/Actor.h"
#include "Window.h" #include "Window.h"
using namespace Seele; using namespace Seele;
+2
View File
@@ -1,6 +1,8 @@
#include "SceneView.h" #include "SceneView.h"
#include "Scene/Scene.h" #include "Scene/Scene.h"
#include "Window.h" #include "Window.h"
#include "Graphics/Graphics.h"
#include "Asset/MeshAsset.h"
#include "Asset/AssetRegistry.h" #include "Asset/AssetRegistry.h"
#include "Scene/Actor/CameraActor.h" #include "Scene/Actor/CameraActor.h"
#include "Scene/Components/CameraComponent.h" #include "Scene/Components/CameraComponent.h"
+1
View File
@@ -30,6 +30,7 @@ MainJob Window::render()
for(auto& windowView : views) for(auto& windowView : views)
{ {
co_await windowView->updateFinished; co_await windowView->updateFinished;
windowView->updateFinished.reset();
{ {
std::unique_lock lock(windowView->workerMutex); std::unique_lock lock(windowView->workerMutex);
windowView->view->prepareRender(); windowView->view->prepareRender();