looks like command buffers need to be externally synchronized
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#include "MeshBatch.h"
|
||||||
|
#include "GraphicsResources.h"
|
||||||
|
#include "VertexShaderInput.h"
|
||||||
|
#include "Material/MaterialAsset.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
MeshBatchElement::MeshBatchElement()
|
||||||
|
: uniformBuffer(nullptr)
|
||||||
|
, indexBuffer(nullptr)
|
||||||
|
, firstIndex(0)
|
||||||
|
, numPrimitives(0)
|
||||||
|
, numInstances(1)
|
||||||
|
, baseVertexIndex(0)
|
||||||
|
, minVertexIndex(0)
|
||||||
|
, maxVertexIndex(0)
|
||||||
|
, indirectArgsBuffer(nullptr)
|
||||||
|
{}
|
||||||
|
MeshBatch::MeshBatch()
|
||||||
|
: useReverseCulling(false)
|
||||||
|
, isBackfaceCullingDisabled(false)
|
||||||
|
, isCastingShadow(true)
|
||||||
|
, useWireframe(false)
|
||||||
|
, topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||||||
|
, vertexInput(nullptr)
|
||||||
|
, material(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#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,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;
|
||||||
|
|||||||
@@ -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()));
|
||||||
}
|
}
|
||||||
@@ -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));
|
||||||
|
|||||||
@@ -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(©, 0, sizeof(VkImageCopy));
|
std::memset(©, 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, ©);
|
1, ©);
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,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>
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ public:
|
|||||||
{
|
{
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
operator bool()
|
||||||
|
{
|
||||||
|
return flag->load();
|
||||||
|
}
|
||||||
|
|
||||||
void raise();
|
void raise();
|
||||||
void reset();
|
void reset();
|
||||||
|
|||||||
@@ -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,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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user