Lots of refactoring

This commit is contained in:
Dynamitos
2024-06-13 15:43:03 +02:00
parent df7fbef8bd
commit 42b4d43a6d
19 changed files with 566 additions and 482 deletions
+2
View File
@@ -498,6 +498,8 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialIns
globalMeshes[meshIndex]->meshlets = std::move(meshlets); globalMeshes[meshIndex]->meshlets = std::move(meshlets);
globalMeshes[meshIndex]->indices = std::move(indices); globalMeshes[meshIndex]->indices = std::move(indices);
globalMeshes[meshIndex]->vertexCount = mesh->mNumVertices; globalMeshes[meshIndex]->vertexCount = mesh->mNumVertices;
globalMeshes[meshIndex]->blas =
graphics->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo(globalMeshes[meshIndex]));
} }
} }
+11 -10
View File
@@ -1,24 +1,25 @@
#include "Buffer.h" #include "Buffer.h"
#include "Initializer.h"
using namespace Seele; using namespace Seele;
using namespace Seele::Gfx; using namespace Seele::Gfx;
Buffer::Buffer(QueueFamilyMapping mapping, QueueType startQueue) : QueueOwnedResource(mapping, startQueue) {} Buffer::Buffer(QueueFamilyMapping mapping) : QueueOwnedResource(mapping) {}
Buffer::~Buffer() {} Buffer::~Buffer() {}
VertexBuffer::VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType) VertexBuffer::VertexBuffer(QueueFamilyMapping mapping, const VertexBufferCreateInfo& createInfo)
: Buffer(mapping, startQueueType), numVertices(numVertices), vertexSize(vertexSize) {} : Buffer(mapping), numVertices(createInfo.numVertices), vertexSize(createInfo.vertexSize) {}
VertexBuffer::~VertexBuffer() {} VertexBuffer::~VertexBuffer() {}
IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType indexType, QueueType startQueueType) IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, const IndexBufferCreateInfo& createInfo)
: Buffer(mapping, startQueueType), indexType(indexType) { : Buffer(mapping), indexType(createInfo.indexType) {
switch (indexType) { switch (indexType) {
case SE_INDEX_TYPE_UINT16: case SE_INDEX_TYPE_UINT16:
numIndices = size / sizeof(uint16); numIndices = createInfo.sourceData.size / sizeof(uint16);
break; break;
case SE_INDEX_TYPE_UINT32: case SE_INDEX_TYPE_UINT32:
numIndices = size / sizeof(uint32); numIndices = createInfo.sourceData.size / sizeof(uint32);
break; break;
default: default:
break; break;
@@ -26,11 +27,11 @@ IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexTy
} }
IndexBuffer::~IndexBuffer() {} IndexBuffer::~IndexBuffer() {}
UniformBuffer::UniformBuffer(QueueFamilyMapping mapping, const DataSource& sourceData) : Buffer(mapping, sourceData.owner) {} UniformBuffer::UniformBuffer(QueueFamilyMapping mapping, const UniformBufferCreateInfo&) : Buffer(mapping) {}
UniformBuffer::~UniformBuffer() {} UniformBuffer::~UniformBuffer() {}
ShaderBuffer::ShaderBuffer(QueueFamilyMapping mapping, uint32 numElements, const DataSource& sourceData) ShaderBuffer::ShaderBuffer(QueueFamilyMapping mapping, const ShaderBufferCreateInfo& createInfo)
: Buffer(mapping, sourceData.owner), numElements(numElements) {} : Buffer(mapping), numElements(createInfo.numElements) {}
ShaderBuffer::~ShaderBuffer() {} ShaderBuffer::~ShaderBuffer() {}
+7 -6
View File
@@ -2,22 +2,23 @@
#include "Initializer.h" #include "Initializer.h"
#include "Resources.h" #include "Resources.h"
namespace Seele { namespace Seele {
namespace Gfx { namespace Gfx {
class Buffer : public QueueOwnedResource { class Buffer : public QueueOwnedResource {
public: public:
Buffer(QueueFamilyMapping mapping, QueueType startQueueType); Buffer(QueueFamilyMapping mapping);
virtual ~Buffer(); virtual ~Buffer();
protected: protected:
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(QueueType newOwner) = 0; virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
SePipelineStageFlags dstStage) = 0;
}; };
class VertexBuffer : public Buffer { class VertexBuffer : public Buffer {
public: public:
VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType); VertexBuffer(QueueFamilyMapping mapping, const VertexBufferCreateInfo& createInfo);
virtual ~VertexBuffer(); virtual ~VertexBuffer();
constexpr uint32 getNumVertices() const { return numVertices; } constexpr uint32 getNumVertices() const { return numVertices; }
// Size of one vertex in bytes // Size of one vertex in bytes
@@ -38,7 +39,7 @@ DEFINE_REF(VertexBuffer)
class IndexBuffer : public Buffer { class IndexBuffer : public Buffer {
public: public:
IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType index, QueueType startQueueType); IndexBuffer(QueueFamilyMapping mapping, const IndexBufferCreateInfo& createInfo);
virtual ~IndexBuffer(); virtual ~IndexBuffer();
constexpr uint64 getNumIndices() const { return numIndices; } constexpr uint64 getNumIndices() const { return numIndices; }
constexpr Gfx::SeIndexType getIndexType() const { return indexType; } constexpr Gfx::SeIndexType getIndexType() const { return indexType; }
@@ -58,7 +59,7 @@ DEFINE_REF(IndexBuffer)
DECLARE_REF(UniformBuffer) DECLARE_REF(UniformBuffer)
class UniformBuffer : public Buffer { class UniformBuffer : public Buffer {
public: public:
UniformBuffer(QueueFamilyMapping mapping, const DataSource& sourceData); UniformBuffer(QueueFamilyMapping mapping, const UniformBufferCreateInfo& createInfo);
virtual ~UniformBuffer(); virtual ~UniformBuffer();
virtual void rotateBuffer(uint64 size) = 0; virtual void rotateBuffer(uint64 size) = 0;
@@ -73,7 +74,7 @@ class UniformBuffer : public Buffer {
DEFINE_REF(UniformBuffer) DEFINE_REF(UniformBuffer)
class ShaderBuffer : public Buffer { class ShaderBuffer : public Buffer {
public: public:
ShaderBuffer(QueueFamilyMapping mapping, uint32 numElements, const DataSource& bulkResourceData); ShaderBuffer(QueueFamilyMapping mapping, const ShaderBufferCreateInfo& createInfo);
virtual ~ShaderBuffer(); virtual ~ShaderBuffer();
virtual void rotateBuffer(uint64 size, bool preserveContents = false) = 0; virtual void rotateBuffer(uint64 size, bool preserveContents = false) = 0;
virtual void updateContents(const ShaderBufferCreateInfo& sourceData) = 0; virtual void updateContents(const ShaderBufferCreateInfo& sourceData) = 0;
+2 -1
View File
@@ -2,7 +2,7 @@
#include "Asset/MaterialInstanceAsset.h" #include "Asset/MaterialInstanceAsset.h"
#include "Graphics/Buffer.h" #include "Graphics/Buffer.h"
#include "VertexData.h" #include "VertexData.h"
#include "Graphics/RayTracing.h"
namespace Seele { namespace Seele {
class Mesh { class Mesh {
@@ -18,6 +18,7 @@ class Mesh {
PMaterialInstanceAsset referencedMaterial; PMaterialInstanceAsset referencedMaterial;
Array<uint32> indices; Array<uint32> indices;
Array<Meshlet> meshlets; Array<Meshlet> meshlets;
Gfx::OBottomLevelAS blas;
void save(ArchiveBuffer& buffer) const; void save(ArchiveBuffer& buffer) const;
void load(ArchiveBuffer& buffer); void load(ArchiveBuffer& buffer);
+2 -9
View File
@@ -1,23 +1,16 @@
#include "Resources.h" #include "Resources.h"
#include "Graphics.h"
#include "Material/Material.h"
#include "Resources.h"
using namespace Seele; using namespace Seele;
using namespace Seele::Gfx; using namespace Seele::Gfx;
QueueOwnedResource::QueueOwnedResource(QueueFamilyMapping mapping, QueueType startQueueType) QueueOwnedResource::QueueOwnedResource(QueueFamilyMapping mapping)
: currentOwner(startQueueType), mapping(mapping) {} : mapping(mapping) {}
QueueOwnedResource::~QueueOwnedResource() {} QueueOwnedResource::~QueueOwnedResource() {}
void QueueOwnedResource::transferOwnership(QueueType newOwner) { void QueueOwnedResource::transferOwnership(QueueType newOwner) {
if (mapping.needsTransfer(currentOwner, newOwner)) {
executeOwnershipBarrier(newOwner); executeOwnershipBarrier(newOwner);
} }
currentOwner = newOwner;
}
void QueueOwnedResource::pipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, void QueueOwnedResource::pipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
SePipelineStageFlags dstStage) { SePipelineStageFlags dstStage) {
+1 -2
View File
@@ -48,7 +48,7 @@ struct QueueFamilyMapping {
class QueueOwnedResource { class QueueOwnedResource {
public: public:
QueueOwnedResource(QueueFamilyMapping mapping, QueueType startQueueType); QueueOwnedResource(QueueFamilyMapping mapping);
virtual ~QueueOwnedResource(); virtual ~QueueOwnedResource();
// Preliminary checks to see if the barrier should be executed at all // Preliminary checks to see if the barrier should be executed at all
@@ -59,7 +59,6 @@ class QueueOwnedResource {
virtual void executeOwnershipBarrier(QueueType newOwner) = 0; virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess,
SePipelineStageFlags dstStage) = 0; SePipelineStageFlags dstStage) = 0;
Gfx::QueueType currentOwner;
QueueFamilyMapping mapping; QueueFamilyMapping mapping;
}; };
DEFINE_REF(QueueOwnedResource) DEFINE_REF(QueueOwnedResource)
@@ -37,6 +37,7 @@ class StaticMeshVertexData : public VertexData {
virtual Gfx::PDescriptorSet getVertexDataSet() override; virtual Gfx::PDescriptorSet getVertexDataSet() override;
virtual std::string getTypeName() const override { return "StaticMeshVertexData"; } virtual std::string getTypeName() const override { return "StaticMeshVertexData"; }
virtual Gfx::PShaderBuffer getPositionBuffer() const override { return positions; } virtual Gfx::PShaderBuffer getPositionBuffer() const override { return positions; }
virtual Vector* getPositionData() const override { return positionData.data(); }
constexpr const Array<StaticMatData>& getStaticMeshes() const { return staticData; } constexpr const Array<StaticMatData>& getStaticMeshes() const { return staticData; }
private: private:
+4 -4
View File
@@ -4,18 +4,18 @@
using namespace Seele; using namespace Seele;
using namespace Seele::Gfx; using namespace Seele::Gfx;
Texture::Texture(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) : QueueOwnedResource(mapping, startQueueType) {} Texture::Texture(QueueFamilyMapping mapping) : QueueOwnedResource(mapping) {}
Texture::~Texture() {} Texture::~Texture() {}
Texture2D::Texture2D(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) : Texture(mapping, startQueueType) {} Texture2D::Texture2D(QueueFamilyMapping mapping) : Texture(mapping) {}
Texture2D::~Texture2D() {} Texture2D::~Texture2D() {}
Texture3D::Texture3D(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) : Texture(mapping, startQueueType) {} Texture3D::Texture3D(QueueFamilyMapping mapping) : Texture(mapping) {}
Texture3D::~Texture3D() {} Texture3D::~Texture3D() {}
TextureCube::TextureCube(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) : Texture(mapping, startQueueType) {} TextureCube::TextureCube(QueueFamilyMapping mapping) : Texture(mapping) {}
TextureCube::~TextureCube() {} TextureCube::~TextureCube() {}
+4 -4
View File
@@ -5,7 +5,7 @@ namespace Seele {
namespace Gfx { namespace Gfx {
class Texture : public QueueOwnedResource { class Texture : public QueueOwnedResource {
public: public:
Texture(QueueFamilyMapping mapping, QueueType startQueueType); Texture(QueueFamilyMapping mapping);
virtual ~Texture(); virtual ~Texture();
virtual SeFormat getFormat() const = 0; virtual SeFormat getFormat() const = 0;
@@ -29,7 +29,7 @@ DEFINE_REF(Texture)
class Texture2D : public Texture { class Texture2D : public Texture {
public: public:
Texture2D(QueueFamilyMapping mapping, QueueType startQueueType); Texture2D(QueueFamilyMapping mapping);
virtual ~Texture2D(); virtual ~Texture2D();
virtual SeFormat getFormat() const = 0; virtual SeFormat getFormat() const = 0;
@@ -52,7 +52,7 @@ DEFINE_REF(Texture2D)
class Texture3D : public Texture { class Texture3D : public Texture {
public: public:
Texture3D(QueueFamilyMapping mapping, QueueType startQueueType); Texture3D(QueueFamilyMapping mapping);
virtual ~Texture3D(); virtual ~Texture3D();
virtual SeFormat getFormat() const = 0; virtual SeFormat getFormat() const = 0;
@@ -75,7 +75,7 @@ DEFINE_REF(Texture3D)
class TextureCube : public Texture { class TextureCube : public Texture {
public: public:
TextureCube(QueueFamilyMapping mapping, QueueType startQueueType); TextureCube(QueueFamilyMapping mapping);
virtual ~TextureCube(); virtual ~TextureCube();
virtual SeFormat getFormat() const = 0; virtual SeFormat getFormat() const = 0;
+3 -1
View File
@@ -52,7 +52,9 @@ class VertexData {
virtual Gfx::PDescriptorSet getVertexDataSet() = 0; virtual Gfx::PDescriptorSet getVertexDataSet() = 0;
virtual std::string getTypeName() const = 0; virtual std::string getTypeName() const = 0;
virtual Gfx::PShaderBuffer getPositionBuffer() const = 0; virtual Gfx::PShaderBuffer getPositionBuffer() const = 0;
Gfx::PIndexBuffer getIndexBuffer() { return indexBuffer; } virtual Vector* getPositionData() const = 0;
Gfx::PIndexBuffer getIndexBuffer() const { return indexBuffer; }
uint32* getIndexData() const { return indices.data(); }
Gfx::PDescriptorLayout getInstanceDataLayout() { return instanceDataLayout; } Gfx::PDescriptorLayout getInstanceDataLayout() { return instanceDataLayout; }
Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; } Gfx::PDescriptorSet getInstanceDataSet() { return descriptorSet; }
const Array<MaterialData>& getMaterialData() const { return materialData; } const Array<MaterialData>& getMaterialData() const { return materialData; }
+137 -157
View File
@@ -1,19 +1,12 @@
#include "Buffer.h" #include "Buffer.h"
#include "Command.h" #include "Command.h"
#include "Enums.h" #include "Enums.h"
#include "Graphics/Enums.h"
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
using namespace Seele; using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
BufferAllocation::BufferAllocation(PGraphics graphics) : CommandBoundResource(graphics) {}
BufferAllocation::~BufferAllocation() {
if (buffer != VK_NULL_HANDLE) {
vmaDestroyBuffer(graphics->getAllocator(), buffer, allocation);
}
}
struct PendingBuffer { struct PendingBuffer {
OBufferAllocation allocation; OBufferAllocation allocation;
uint64 offset; uint64 offset;
@@ -21,71 +14,30 @@ struct PendingBuffer {
bool writeOnly; bool writeOnly;
}; };
static Map<Vulkan::Buffer*, PendingBuffer> pendingBuffers; static Map<BufferAllocation*, PendingBuffer> pendingBuffers;
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool dynamic, std::string name) BufferAllocation::BufferAllocation(PGraphics graphics, VkBufferCreateInfo bufferInfo, VmaAllocationCreateInfo allocInfo,
: graphics(graphics), currentBuffer(0), owner(queueType), Gfx::QueueType owner)
usage(usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT), dynamic(dynamic), name(name) { : CommandBoundResource(graphics), size(bufferInfo.size), owner(owner) {
createBuffer(size); VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &bufferInfo, &allocInfo, &buffer, &allocation, nullptr));
} vmaGetAllocationMemoryProperties(graphics->getAllocator(), allocation, &properties);
VkBufferDeviceAddressInfo addrInfo = {
Buffer::~Buffer() { .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR,
for (uint32 i = 0; i < buffers.size(); ++i) {
graphics->getDestructionManager()->queueResourceForDestruction(std::move(buffers[i]));
}
}
void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner) {
if (getSize() == 0)
return;
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
VkBufferMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr, .pNext = nullptr,
.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner), .buffer = buffer,
.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner),
.buffer = getHandle(),
.offset = 0,
.size = getSize(),
}; };
PCommandPool sourcePool = graphics->getQueueCommands(owner); deviceAddress = vkGetBufferDeviceAddress(graphics->getDevice(), &addrInfo);
PCommandPool dstPool = nullptr;
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex);
if (owner == Gfx::QueueType::TRANSFER) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (owner == Gfx::QueueType::COMPUTE) {
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
} else if (owner == Gfx::QueueType::GRAPHICS) {
barrier.srcAccessMask = getSourceAccessMask();
srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
}
if (newOwner == Gfx::QueueType::TRANSFER) {
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstPool = graphics->getTransferCommands();
} else if (newOwner == Gfx::QueueType::COMPUTE) {
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
dstPool = graphics->getComputeCommands();
} else if (newOwner == Gfx::QueueType::GRAPHICS) {
barrier.dstAccessMask = getDestAccessMask();
dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
dstPool = graphics->getGraphicsCommands();
}
VkCommandBuffer srcCommand = sourcePool->getCommands()->getHandle();
VkCommandBuffer dstCommand = dstPool->getCommands()->getHandle();
vkCmdPipelineBarrier(srcCommand, srcStage, srcStage, 0, 0, nullptr, 1, &barrier, 0, nullptr);
vkCmdPipelineBarrier(dstCommand, dstStage, dstStage, 0, 0, nullptr, 1, &barrier, 0, nullptr);
sourcePool->submitCommands();
} }
void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, BufferAllocation::~BufferAllocation() {
if (buffer != VK_NULL_HANDLE) {
vmaDestroyBuffer(graphics->getAllocator(), buffer, allocation);
}
}
void BufferAllocation::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
if (getSize() == 0) if (size == 0)
return; return;
PCommand commandBuffer = graphics->getQueueCommands(owner)->getCommands(); PCommand commandBuffer = graphics->getQueueCommands(owner)->getCommands();
VkBufferMemoryBarrier barrier = { VkBufferMemoryBarrier barrier = {
@@ -95,29 +47,49 @@ void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlag
.dstAccessMask = dstAccess, .dstAccessMask = dstAccess,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = getHandle(), .buffer = buffer,
.offset = 0, .offset = 0,
.size = getSize(), .size = size,
}; };
vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, 1, &barrier, 0, nullptr); vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, 1, &barrier, 0, nullptr);
} }
void* Buffer::map(bool writeOnly) { return mapRegion(0, getSize(), writeOnly); } void BufferAllocation::transferOwnership(Gfx::QueueType newOwner) {
if (size == 0)
return;
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
VkBufferMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner),
.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner),
.buffer = buffer,
.offset = 0,
.size = size,
};
PCommandPool sourcePool = graphics->getQueueCommands(owner);
PCommandPool dstPool = graphics->getQueueCommands(newOwner);
assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex);
vkCmdPipelineBarrier(sourcePool->getCommands()->getHandle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
0, nullptr, 1, &barrier, 0, nullptr);
vkCmdPipelineBarrier(dstPool->getCommands()->getHandle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0,
nullptr, 1, &barrier, 0, nullptr);
sourcePool->submitCommands();
owner = newOwner;
}
void* Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) { void* BufferAllocation::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) {
if (regionSize == 0)
return nullptr;
void* data = nullptr; void* data = nullptr;
PendingBuffer pending; PendingBuffer pending;
pending.allocation = new BufferAllocation(graphics);
pending.allocation->size = regionSize;
pending.writeOnly = writeOnly; pending.writeOnly = writeOnly;
pending.prevQueue = owner; pending.prevQueue = owner;
pending.offset = regionOffset; pending.offset = regionOffset;
transferOwnership(Gfx::QueueType::TRANSFER);
if (writeOnly) { if (writeOnly) {
if (buffers[currentBuffer]->properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
VK_CHECK(vmaMapMemory(graphics->getAllocator(), buffers[currentBuffer]->allocation, &data)); VK_CHECK(vmaMapMemory(graphics->getAllocator(), allocation, &data));
} else { } else {
VkBufferCreateInfo stagingInfo = { VkBufferCreateInfo stagingInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
@@ -132,8 +104,7 @@ void* Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly)
.usage = VMA_MEMORY_USAGE_AUTO, .usage = VMA_MEMORY_USAGE_AUTO,
.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
}; };
VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &allocInfo, &pending.allocation->buffer, pending.allocation = new BufferAllocation(graphics, stagingInfo, allocInfo, Gfx::QueueType::TRANSFER);
&pending.allocation->allocation, nullptr));
vmaMapMemory(graphics->getAllocator(), pending.allocation->allocation, &data); vmaMapMemory(graphics->getAllocator(), pending.allocation->allocation, &data);
vmaSetAllocationName(graphics->getAllocator(), pending.allocation->allocation, "MappingStaging"); vmaSetAllocationName(graphics->getAllocator(), pending.allocation->allocation, "MappingStaging");
} }
@@ -141,18 +112,16 @@ void* Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly)
assert(false); assert(false);
} }
pendingBuffers[this] = std::move(pending); pendingBuffers[this] = std::move(pending);
assert(data);
return data; return data;
} }
void Buffer::unmap() { void BufferAllocation::unmap() {
auto found = pendingBuffers.find(this); auto found = pendingBuffers.find(this);
if (found != pendingBuffers.end()) { if (found != pendingBuffers.end()) {
PendingBuffer& pending = found->value; PendingBuffer& pending = found->value;
if (pending.writeOnly) { if (pending.writeOnly) {
if (buffers[currentBuffer]->properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
vmaUnmapMemory(graphics->getAllocator(), buffers[currentBuffer]->allocation); vmaUnmapMemory(graphics->getAllocator(), allocation);
} else { } else {
vmaFlushAllocation(graphics->getAllocator(), pending.allocation->allocation, 0, VK_WHOLE_SIZE); vmaFlushAllocation(graphics->getAllocator(), pending.allocation->allocation, 0, VK_WHOLE_SIZE);
vmaUnmapMemory(graphics->getAllocator(), pending.allocation->allocation); vmaUnmapMemory(graphics->getAllocator(), pending.allocation->allocation);
@@ -172,13 +141,13 @@ void Buffer::unmap() {
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer]->buffer, .buffer = buffer,
.offset = 0, .offset = 0,
.size = buffers[currentBuffer]->size, .size = size,
}; };
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1,
&barrier, 0, nullptr); &barrier, 0, nullptr);
vkCmdCopyBuffer(cmdHandle, pending.allocation->buffer, buffers[currentBuffer]->buffer, 1, &region); vkCmdCopyBuffer(cmdHandle, pending.allocation->buffer, buffer, 1, &region);
barrier = { barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr, .pNext = nullptr,
@@ -186,34 +155,64 @@ void Buffer::unmap() {
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer]->buffer, .buffer = buffer,
.offset = 0, .offset = 0,
.size = buffers[currentBuffer]->size, .size = size,
}; };
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1,
&barrier, 0, nullptr); &barrier, 0, nullptr);
graphics->getDestructionManager()->queueResourceForDestruction(std::move(pending.allocation)); graphics->getDestructionManager()->queueResourceForDestruction(std::move(pending.allocation));
} }
} }
transferOwnership(pending.prevQueue);
pendingBuffers.erase(this); pendingBuffers.erase(this);
} }
} }
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType queueType, bool dynamic, std::string name)
: graphics(graphics), currentBuffer(0), initialOwner(queueType),
usage(usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT),
dynamic(dynamic), name(name) {
createBuffer(size);
}
Buffer::~Buffer() {
for (uint32 i = 0; i < buffers.size(); ++i) {
graphics->getDestructionManager()->queueResourceForDestruction(std::move(buffers[i]));
}
}
void* Buffer::map(bool writeOnly) { return mapRegion(0, getSize(), writeOnly); }
void* Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) {
if (regionSize == 0)
return nullptr;
void* data = getAlloc()->mapRegion(regionOffset, regionSize, writeOnly);
assert(data);
return data;
}
void Buffer::unmap() { getAlloc()->unmap(); }
void Buffer::rotateBuffer(uint64 size, bool preserveContents) { void Buffer::rotateBuffer(uint64 size, bool preserveContents) {
assert(dynamic); assert(dynamic);
size = std::max(getSize(), size); size = std::max(getSize(), size);
for (size_t i = 0; i < buffers.size(); ++i) { for (uint32 i = 0; i < buffers.size(); ++i) {
if (buffers[i]->isCurrentlyBound()) { if (buffers[i]->isCurrentlyBound()) {
continue; continue;
} }
if (buffers[i]->size < size) { if (buffers[i]->size < size) {
vmaDestroyBuffer(graphics->getAllocator(), buffers[i]->buffer, buffers[i]->allocation); vmaDestroyBuffer(graphics->getAllocator(), buffers[i]->buffer, buffers[i]->allocation);
uint32 family = graphics->getFamilyMapping().getQueueTypeFamilyIndex(initialOwner);
VkBufferCreateInfo info = { VkBufferCreateInfo info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0,
.size = size, .size = size,
.usage = usage, .usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 1,
.pQueueFamilyIndices = &family,
}; };
VmaAllocationCreateInfo allocInfo = { VmaAllocationCreateInfo allocInfo = {
.flags = .flags =
@@ -229,7 +228,7 @@ void Buffer::rotateBuffer(uint64 size, bool preserveContents) {
.objectType = VK_OBJECT_TYPE_BUFFER, .objectType = VK_OBJECT_TYPE_BUFFER,
.objectHandle = (uint64)buffers[i]->buffer, .objectHandle = (uint64)buffers[i]->buffer,
.pObjectName = this->name.c_str()}; .pObjectName = this->name.c_str()};
graphics->vkSetDebugUtilsObjectNameEXT(&nameInfo); vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo);
} }
buffers[i]->size = size; buffers[i]->size = size;
} }
@@ -247,36 +246,32 @@ void Buffer::rotateBuffer(uint64 size, bool preserveContents) {
} }
void Buffer::createBuffer(uint64 size) { void Buffer::createBuffer(uint64 size) {
uint32 family = graphics->getFamilyMapping().getQueueTypeFamilyIndex(initialOwner);
VkBufferCreateInfo info = { VkBufferCreateInfo info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0,
.size = size, .size = size,
.usage = usage, .usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 1,
.pQueueFamilyIndices = &family,
}; };
VmaAllocationCreateInfo allocInfo = { VmaAllocationCreateInfo allocInfo = {
.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
.usage = VMA_MEMORY_USAGE_AUTO, .usage = VMA_MEMORY_USAGE_AUTO,
}; };
buffers.add(new BufferAllocation(graphics)); buffers.add(new BufferAllocation(graphics, info, allocInfo, initialOwner));
if (size > 0) { if (size > 0) {
VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &info, &allocInfo, &buffers.back()->buffer, &buffers.back()->allocation, VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &info, &allocInfo, &buffers.back()->buffer, &buffers.back()->allocation,
&buffers.back()->info)); &buffers.back()->info));
buffers.back()->size = size;
vmaGetAllocationMemoryProperties(graphics->getAllocator(), buffers.back()->allocation, &buffers.back()->properties);
VkBufferDeviceAddressInfo addrInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR,
.pNext = nullptr,
.buffer = buffers.back()->buffer,
};
buffers.back()->deviceAddress = vkGetBufferDeviceAddress(graphics->getDevice(), &addrInfo);
if (!name.empty()) { if (!name.empty()) {
VkDebugUtilsObjectNameInfoEXT nameInfo = {.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, VkDebugUtilsObjectNameInfoEXT nameInfo = {.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
.pNext = nullptr, .pNext = nullptr,
.objectType = VK_OBJECT_TYPE_BUFFER, .objectType = VK_OBJECT_TYPE_BUFFER,
.objectHandle = (uint64)buffers.back()->buffer, .objectHandle = (uint64)buffers.back()->buffer,
.pObjectName = this->name.c_str()}; .pObjectName = this->name.c_str()};
graphics->vkSetDebugUtilsObjectNameEXT(&nameInfo); vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo);
} }
} }
} }
@@ -285,7 +280,7 @@ void Buffer::copyBuffer(uint64 src, uint64 dst) {
if (src == dst) { if (src == dst) {
return; return;
} }
PCommand command = graphics->getQueueCommands(owner)->getCommands(); PCommand command = graphics->getQueueCommands(getAlloc()->owner)->getCommands();
VkBufferMemoryBarrier srcBarrier = { VkBufferMemoryBarrier srcBarrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr, .pNext = nullptr,
@@ -316,10 +311,17 @@ void Buffer::copyBuffer(uint64 src, uint64 dst) {
&dstBarrier, 0, nullptr); &dstBarrier, 0, nullptr);
} }
void Buffer::transferOwnership(Gfx::QueueType newOwner) { getAlloc()->transferOwnership(newOwner); }
void Buffer::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) {
getAlloc()->pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
}
UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo& createInfo) UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo& createInfo)
: Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData), : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo),
Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.dynamic, Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, createInfo.sourceData.owner,
createInfo.name) { createInfo.dynamic, createInfo.name) {
if (getSize() > 0 && createInfo.sourceData.data != nullptr) { if (getSize() > 0 && createInfo.sourceData.data != nullptr) {
void* data = map(); void* data = map();
std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size); std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size);
@@ -337,30 +339,24 @@ void UniformBuffer::updateContents(const DataSource& sourceData) {
void UniformBuffer::rotateBuffer(uint64 size) { Vulkan::Buffer::rotateBuffer(size); } void UniformBuffer::rotateBuffer(uint64 size) { Vulkan::Buffer::rotateBuffer(size); }
void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); } void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::transferOwnership(newOwner); }
void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::executeOwnershipBarrier(newOwner); }
void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); Vulkan::Buffer::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
} }
VkAccessFlags UniformBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; } ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& createInfo)
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), createInfo),
VkAccessFlags UniformBuffer::getDestAccessMask() { return VK_ACCESS_UNIFORM_READ_BIT; } Vulkan::Buffer(graphics, createInfo.sourceData.size,
ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& sourceData)
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), sourceData.numElements, sourceData.sourceData),
Vulkan::Buffer(graphics, sourceData.sourceData.size,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
(sourceData.vertexBuffer ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | (createInfo.vertexBuffer ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
: 0), : 0),
currentOwner, sourceData.dynamic, sourceData.name) { createInfo.sourceData.owner, createInfo.dynamic, createInfo.name) {
if (getSize() > 0 && sourceData.sourceData.data != nullptr) { if (getSize() > 0 && createInfo.sourceData.data != nullptr) {
void* data = map(); void* data = map();
std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size);
unmap(); unmap();
} }
} }
@@ -387,28 +383,24 @@ void* ShaderBuffer::mapRegion(uint64 offset, uint64 size, bool writeOnly) { retu
void ShaderBuffer::unmap() { Vulkan::Buffer::unmap(); } void ShaderBuffer::unmap() { Vulkan::Buffer::unmap(); }
void ShaderBuffer::clear() { void ShaderBuffer::clear() {
vkCmdFillBuffer(graphics->getQueueCommands(owner)->getCommands()->getHandle(), Vulkan::Buffer::getHandle(), 0, VK_WHOLE_SIZE, 0); vkCmdFillBuffer(graphics->getQueueCommands(getAlloc()->owner)->getCommands()->getHandle(), Vulkan::Buffer::getHandle(), 0,
VK_WHOLE_SIZE, 0);
} }
void ShaderBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); } void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::transferOwnership(newOwner); }
void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::executeOwnershipBarrier(newOwner); }
void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); Vulkan::Buffer::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
} }
VkAccessFlags ShaderBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; } VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo& createInfo)
: Gfx::VertexBuffer(graphics->getFamilyMapping(), createInfo),
VkAccessFlags ShaderBuffer::getDestAccessMask() { return VK_ACCESS_MEMORY_READ_BIT; } Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, createInfo.sourceData.owner, false,
createInfo.name) {
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo& sourceData) if (createInfo.sourceData.data != nullptr) {
: Gfx::VertexBuffer(graphics->getFamilyMapping(), sourceData.numVertices, sourceData.vertexSize, sourceData.sourceData.owner),
Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner, false, sourceData.name) {
if (sourceData.sourceData.data != nullptr) {
void* data = map(); void* data = map();
std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size);
unmap(); unmap();
} }
} }
@@ -428,28 +420,22 @@ void VertexBuffer::download(Array<uint8>& buffer) {
unmap(); unmap();
} }
void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); } void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::transferOwnership(newOwner); }
void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::executeOwnershipBarrier(newOwner); }
void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); Vulkan::Buffer::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
} }
VkAccessFlags VertexBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; } IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& createInfo)
: Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo),
VkAccessFlags VertexBuffer::getDestAccessMask() { return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; } Vulkan::Buffer(graphics, createInfo.sourceData.size,
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& sourceData)
: Gfx::IndexBuffer(graphics->getFamilyMapping(), sourceData.sourceData.size, sourceData.indexType, sourceData.sourceData.owner),
Vulkan::Buffer(graphics, sourceData.sourceData.size,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
currentOwner, false, sourceData.name) { createInfo.sourceData.owner, false, createInfo.name) {
if (sourceData.sourceData.data != nullptr) { if (createInfo.sourceData.data != nullptr) {
void* data = map(); void* data = map();
std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size);
unmap(); unmap();
} }
} }
@@ -463,15 +449,9 @@ void IndexBuffer::download(Array<uint8>& buffer) {
unmap(); unmap();
} }
void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); } void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::transferOwnership(newOwner); }
void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::executeOwnershipBarrier(newOwner); }
void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); Vulkan::Buffer::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
} }
VkAccessFlags IndexBuffer::getSourceAccessMask() { return VK_ACCESS_MEMORY_WRITE_BIT; }
VkAccessFlags IndexBuffer::getDestAccessMask() { return VK_ACCESS_INDEX_READ_BIT; }
+12 -26
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Graphics.h" #include "Graphics.h"
#include "Graphics/Buffer.h" #include "Graphics/Buffer.h"
#include "Graphics/Enums.h"
#include "Resources.h" #include "Resources.h"
namespace Seele { namespace Seele {
@@ -9,19 +10,25 @@ DECLARE_REF(Command)
DECLARE_REF(Fence) DECLARE_REF(Fence)
class BufferAllocation : public CommandBoundResource { class BufferAllocation : public CommandBoundResource {
public: public:
BufferAllocation(PGraphics graphics); BufferAllocation(PGraphics graphics, VkBufferCreateInfo bufferInfo, VmaAllocationCreateInfo allocInfo, Gfx::QueueType owner);
virtual ~BufferAllocation(); virtual ~BufferAllocation();
void pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage);
void transferOwnership(Gfx::QueueType newOwner);
void* mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly = true);
void unmap();
VkBuffer buffer = VK_NULL_HANDLE; VkBuffer buffer = VK_NULL_HANDLE;
VmaAllocation allocation = VmaAllocation(); VmaAllocation allocation = VmaAllocation();
VmaAllocationInfo info = VmaAllocationInfo(); VmaAllocationInfo info = VmaAllocationInfo();
VkMemoryPropertyFlags properties = 0; VkMemoryPropertyFlags properties = 0;
uint64 size = 0; uint64 size = 0;
VkDeviceAddress deviceAddress; VkDeviceAddress deviceAddress;
Gfx::QueueType owner;
}; };
DEFINE_REF(BufferAllocation); DEFINE_REF(BufferAllocation);
class Buffer { class Buffer {
public: public:
Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool dynamic, std::string name); Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType initialOwner, bool dynamic, std::string name);
virtual ~Buffer(); virtual ~Buffer();
VkBuffer getHandle() const { return buffers[currentBuffer]->buffer; } VkBuffer getHandle() const { return buffers[currentBuffer]->buffer; }
VkDeviceAddress getDeviceAddress() const { return buffers[currentBuffer]->deviceAddress; } VkDeviceAddress getDeviceAddress() const { return buffers[currentBuffer]->deviceAddress; }
@@ -34,7 +41,7 @@ class Buffer {
protected: protected:
PGraphics graphics; PGraphics graphics;
uint32 currentBuffer; uint32 currentBuffer;
Gfx::QueueType& owner; Gfx::QueueType initialOwner;
Array<OBufferAllocation> buffers; Array<OBufferAllocation> buffers;
VkBufferUsageFlags usage; VkBufferUsageFlags usage;
bool dynamic; bool dynamic;
@@ -43,14 +50,9 @@ class Buffer {
void createBuffer(uint64 size); void createBuffer(uint64 size);
void copyBuffer(uint64 src, uint64 dest); void copyBuffer(uint64 src, uint64 dest);
void executeOwnershipBarrier(Gfx::QueueType newOwner); void transferOwnership(Gfx::QueueType newOwner);
void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage); VkPipelineStageFlags dstStage);
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0;
virtual VkAccessFlags getSourceAccessMask() = 0;
virtual VkAccessFlags getDestAccessMask() = 0;
}; };
DEFINE_REF(Buffer) DEFINE_REF(Buffer)
@@ -63,10 +65,6 @@ class VertexBuffer : public Gfx::VertexBuffer, public Buffer {
virtual void download(Array<uint8>& buffer) override; virtual void download(Array<uint8>& buffer) override;
protected: protected:
// Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask() override;
virtual VkAccessFlags getDestAccessMask() override;
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override;
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override;
virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess, virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
@@ -82,10 +80,6 @@ class IndexBuffer : public Gfx::IndexBuffer, public Buffer {
virtual void download(Array<uint8>& buffer) override; virtual void download(Array<uint8>& buffer) override;
protected: protected:
// Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask() override;
virtual VkAccessFlags getDestAccessMask() override;
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override;
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override;
virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess, virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
@@ -100,10 +94,6 @@ class UniformBuffer : public Gfx::UniformBuffer, public Buffer {
virtual void rotateBuffer(uint64 size) override; virtual void rotateBuffer(uint64 size) override;
protected: protected:
// Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask() override;
virtual VkAccessFlags getDestAccessMask() override;
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override;
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override;
virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess, virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
@@ -125,10 +115,6 @@ class ShaderBuffer : public Gfx::ShaderBuffer, public Buffer {
virtual void clear() override; virtual void clear() override;
protected: protected:
// Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask() override;
virtual VkAccessFlags getDestAccessMask() override;
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override;
// Inherited via QueueOwnedResource // Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override;
virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess, virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
+2 -2
View File
@@ -302,12 +302,12 @@ void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 f
} }
void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) { void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) {
assert(threadId == std::this_thread::get_id()); assert(threadId == std::this_thread::get_id());
graphics->vkCmdDrawMeshTasksEXT(handle, groupX, groupY, groupZ); vkCmdDrawMeshTasksEXT(handle, groupX, groupY, groupZ);
} }
void RenderCommand::drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) { void RenderCommand::drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) {
assert(threadId == std::this_thread::get_id()); assert(threadId == std::this_thread::get_id());
graphics->vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset, drawCount, stride); vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset, drawCount, stride);
} }
ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) { ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) {
+88 -42
View File
@@ -9,10 +9,10 @@
#include "Graphics/Graphics.h" #include "Graphics/Graphics.h"
#include "Graphics/Initializer.h" #include "Graphics/Initializer.h"
#include "PipelineCache.h" #include "PipelineCache.h"
#include "Query.h"
#include "RayTracing.h" #include "RayTracing.h"
#include "RenderPass.h" #include "RenderPass.h"
#include "Shader.h" #include "Shader.h"
#include "Query.h"
#include "Window.h" #include "Window.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <cstring> #include <cstring>
@@ -28,6 +28,42 @@ thread_local PCommandPool Seele::Vulkan::Graphics::graphicsCommands = nullptr;
thread_local PCommandPool Seele::Vulkan::Graphics::computeCommands = nullptr; thread_local PCommandPool Seele::Vulkan::Graphics::computeCommands = nullptr;
thread_local PCommandPool Seele::Vulkan::Graphics::transferCommands = nullptr; thread_local PCommandPool Seele::Vulkan::Graphics::transferCommands = nullptr;
PFN_vkCmdDrawMeshTasksEXT cmdDrawMeshTasks;
PFN_vkCmdDrawMeshTasksIndirectEXT cmdDrawMeshTasksIndirect;
PFN_vkSetDebugUtilsObjectNameEXT setDebugUtilsObjectName;
PFN_vkCreateAccelerationStructureKHR createAccelerationStructure;
PFN_vkCmdBuildAccelerationStructuresKHR cmdBuildAccelerationStructures;
PFN_vkGetAccelerationStructureBuildSizesKHR getAccelerationStructureBuildSize;
void vkCmdDrawMeshTasksEXT(VkCommandBuffer command, uint32 groupX, uint32 groupY, uint32 groupZ) {
cmdDrawMeshTasks(command, groupX, groupY, groupZ);
}
void vkCmdDrawMeshTasksIndirectEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount,
uint32_t stride) {
cmdDrawMeshTasksIndirect(commandBuffer, buffer, offset, drawCount, stride);
}
VkResult vkSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo) {
return setDebugUtilsObjectName(device, pNameInfo);
}
VkResult vkCreateAccelerationStructureKHR(VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure) {
return createAccelerationStructure(device, pCreateInfo, pAllocator, pAccelerationStructure);
}
void vkCmdBuildAccelerationStructuresKHR(VkCommandBuffer commandBuffer, uint32_t infoCount,
const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos) {
cmdBuildAccelerationStructures(commandBuffer, infoCount, pInfos, ppBuildRangeInfos);
}
void vkGetAccelerationStructureBuildSizesKHR(VkDevice device, VkAccelerationStructureBuildTypeKHR buildType,
const VkAccelerationStructureBuildGeometryInfoKHR* pBuildInfo,
const uint32_t* pMaxPrimitiveCounts, VkAccelerationStructureBuildSizesInfoKHR* pSizeInfo) {
getAccelerationStructureBuildSize(device, buildType, pBuildInfo, pMaxPrimitiveCounts, pSizeInfo);
}
Graphics::Graphics() : instance(VK_NULL_HANDLE), handle(VK_NULL_HANDLE), physicalDevice(VK_NULL_HANDLE), callback(VK_NULL_HANDLE) {} Graphics::Graphics() : instance(VK_NULL_HANDLE), handle(VK_NULL_HANDLE), physicalDevice(VK_NULL_HANDLE), callback(VK_NULL_HANDLE) {}
Graphics::~Graphics() { Graphics::~Graphics() {
@@ -95,9 +131,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) {
getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer); getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer);
} }
void Graphics::endRenderPass() { void Graphics::endRenderPass() { getGraphicsCommands()->getCommands()->endRenderPass(); }
getGraphicsCommands()->getCommands()->endRenderPass();
}
void Graphics::waitDeviceIdle() { vkDeviceWaitIdle(handle); } void Graphics::waitDeviceIdle() { vkDeviceWaitIdle(handle); }
@@ -241,13 +275,25 @@ void Graphics::resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) {
void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) { void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) {
PTextureBase src = source.cast<TextureBase>(); PTextureBase src = source.cast<TextureBase>();
PTextureBase dst = destination.cast<TextureBase>(); PTextureBase dst = destination.cast<TextureBase>();
VkImageBlit blit = {.srcSubresource = {.aspectMask = src->getAspect(), .mipLevel = 0, .baseArrayLayer = 0, .layerCount = 1}, VkImageBlit blit = {.srcSubresource =
{
.aspectMask = src->getAspect(),
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
},
.srcOffsets = .srcOffsets =
{ {
{0, 0, 0}, {0, 0, 0},
{(int32)src->getWidth(), (int32)src->getHeight(), (int32)src->getDepth()}, {(int32)src->getWidth(), (int32)src->getHeight(), (int32)src->getDepth()},
}, },
.dstSubresource = {.aspectMask = dst->aspect, .mipLevel = 0, .baseArrayLayer = 0, .layerCount = 1}, .dstSubresource =
{
.aspectMask = dst->getAspect(),
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = 1,
},
.dstOffsets = { .dstOffsets = {
{0, 0, 0}, {0, 0, 0},
{(int32)dst->getWidth(), (int32)dst->getHeight(), (int32)dst->getDepth()}, {(int32)dst->getWidth(), (int32)dst->getHeight(), (int32)dst->getDepth()},
@@ -255,7 +301,7 @@ void Graphics::copyTexture(Gfx::PTexture source, Gfx::PTexture destination) {
PCommand command = getGraphicsCommands()->getCommands(); PCommand command = getGraphicsCommands()->getCommands();
vkCmdBlitImage(command->getHandle(), src->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst->getImage(), vkCmdBlitImage(command->getHandle(), src->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst->getImage(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
src->aspect & VK_IMAGE_ASPECT_DEPTH_BIT ? VK_FILTER_NEAREST : VK_FILTER_LINEAR); src->getAspect() & VK_IMAGE_ASPECT_DEPTH_BIT ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
} }
Gfx::OBottomLevelAS Graphics::createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) { Gfx::OBottomLevelAS Graphics::createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) {
@@ -266,16 +312,6 @@ Gfx::OTopLevelAS Graphics::createTopLevelAccelerationStructure(const Gfx::TopLev
return new TopLevelAS(this, createInfo); return new TopLevelAS(this, createInfo);
} }
void Graphics::vkCmdDrawMeshTasksEXT(VkCommandBuffer cmd, uint32 groupX, uint32 groupY, uint32 groupZ) {
cmdDrawMeshTasks(cmd, groupX, groupY, groupZ);
}
void Graphics::vkCmdDrawMeshTasksIndirectEXT(VkCommandBuffer cmd, VkBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) {
cmdDrawMeshTasksIndirect(cmd, buffer, offset, drawCount, stride);
}
void Graphics::vkSetDebugUtilsObjectNameEXT(VkDebugUtilsObjectNameInfoEXT* info) { VK_CHECK(setDebugUtilsObjectName(handle, info)); }
PCommandPool Graphics::getQueueCommands(Gfx::QueueType queueType) { PCommandPool Graphics::getQueueCommands(Gfx::QueueType queueType) {
switch (queueType) { switch (queueType) {
case Gfx::QueueType::GRAPHICS: case Gfx::QueueType::GRAPHICS:
@@ -394,20 +430,9 @@ void Graphics::pickPhysicalDevice() {
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;
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
features.pNext = &robustness;
robustness.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
robustness.pNext = &features11;
features11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
features11.pNext = &features12;
features12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
features12.pNext = &features13;
features13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
features13.pNext = nullptr;
for (auto dev : physicalDevices) { for (auto dev : physicalDevices) {
uint32 currentRating = 0; uint32 currentRating = 0;
vkGetPhysicalDeviceProperties(dev, &props); vkGetPhysicalDeviceProperties(dev, &props);
vkGetPhysicalDeviceFeatures2(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;
@@ -424,9 +449,29 @@ void Graphics::pickPhysicalDevice() {
physicalDevice = bestDevice; physicalDevice = bestDevice;
vkGetPhysicalDeviceProperties(physicalDevice, &props); vkGetPhysicalDeviceProperties(physicalDevice, &props);
vkGetPhysicalDeviceFeatures2(physicalDevice, &features); acceleration = {
features.features.robustBufferAccess = 0; .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR,
features.features.inheritedQueries = true; .pNext = nullptr,
.accelerationStructure = true,
};
meshShaderFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT,
.pNext = &acceleration,
.taskShader = true,
.meshShader = true,
.meshShaderQueries = true,
};
features12 = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
.pNext = &meshShaderFeatures,
.bufferDeviceAddress = true,
};
features = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
.pNext = &features12,
.features = {
.occlusionQueryPrecise = true,
.inheritedQueries = true,
}};
if (Gfx::useMeshShading) { if (Gfx::useMeshShading) {
uint32 count = 0; uint32 count = 0;
vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &count, nullptr); vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &count, nullptr);
@@ -508,14 +553,8 @@ void Graphics::createDevice(GraphicsInitializer initializer) {
*currentPriority++ = 1.0f; *currentPriority++ = 1.0f;
} }
} }
VkPhysicalDeviceMeshShaderFeaturesEXT enabledMeshShaderFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT,
.pNext = nullptr,
.taskShader = VK_TRUE,
.meshShader = VK_TRUE,
};
if (supportMeshShading()) { if (supportMeshShading()) {
features12.pNext = &enabledMeshShaderFeatures;
initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME); initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
} }
#ifdef __APPLE__ #ifdef __APPLE__
@@ -525,19 +564,17 @@ void Graphics::createDevice(GraphicsInitializer initializer) {
initializer.deviceExtensions.add(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); initializer.deviceExtensions.add(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
VkDeviceCreateInfo deviceInfo = { VkDeviceCreateInfo deviceInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &features11, .pNext = &features,
.queueCreateInfoCount = (uint32)queueInfos.size(), .queueCreateInfoCount = (uint32)queueInfos.size(),
.pQueueCreateInfos = queueInfos.data(), .pQueueCreateInfos = queueInfos.data(),
.enabledExtensionCount = (uint32)initializer.deviceExtensions.size(), .enabledExtensionCount = (uint32)initializer.deviceExtensions.size(),
.ppEnabledExtensionNames = initializer.deviceExtensions.data(), .ppEnabledExtensionNames = initializer.deviceExtensions.data(),
.pEnabledFeatures = &features.features, .pEnabledFeatures = nullptr,
}; };
VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle)); VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle));
// std::cout << "Vulkan handle: " << handle << std::endl; // std::cout << "Vulkan handle: " << handle << std::endl;
cmdDrawMeshTasks = (PFN_vkCmdDrawMeshTasksEXT)vkGetDeviceProcAddr(handle, "vkCmdDrawMeshTasksEXT");
graphicsQueue = 0; graphicsQueue = 0;
computeQueue = 0; computeQueue = 0;
transferQueue = 0; transferQueue = 0;
@@ -554,5 +591,14 @@ void Graphics::createDevice(GraphicsInitializer initializer) {
queueMapping.graphicsFamily = queues[graphicsQueue]->getFamilyIndex(); queueMapping.graphicsFamily = queues[graphicsQueue]->getFamilyIndex();
queueMapping.computeFamily = queues[computeQueue]->getFamilyIndex(); queueMapping.computeFamily = queues[computeQueue]->getFamilyIndex();
queueMapping.transferFamily = queues[transferQueue]->getFamilyIndex(); queueMapping.transferFamily = queues[transferQueue]->getFamilyIndex();
cmdDrawMeshTasks = (PFN_vkCmdDrawMeshTasksEXT)vkGetDeviceProcAddr(handle, "vkCmdDrawMeshTasksEXT");
cmdDrawMeshTasksIndirect = (PFN_vkCmdDrawMeshTasksIndirectEXT)vkGetDeviceProcAddr(handle, "vkCmdDrawMeshTasksIndirectEXT");
setDebugUtilsObjectName = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT"); setDebugUtilsObjectName = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT");
createAccelerationStructure = (PFN_vkCreateAccelerationStructureKHR)vkGetDeviceProcAddr(handle, "vkCreateAccelerationStructureKHR");
cmdBuildAccelerationStructures =
(PFN_vkCmdBuildAccelerationStructuresKHR)vkGetDeviceProcAddr(handle, "vkCmdBuildAccelerationStructuresKHR");
getAccelerationStructureBuildSize =
(PFN_vkGetAccelerationStructureBuildSizesKHR)vkGetDeviceProcAddr(handle, "vkGetAccelerationStructureBuildSizesKHR");
} }
+2 -10
View File
@@ -74,14 +74,7 @@ class Graphics : public Gfx::Graphics {
virtual Gfx::OBottomLevelAS createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) override; virtual Gfx::OBottomLevelAS createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) override;
virtual Gfx::OTopLevelAS createTopLevelAccelerationStructure(const Gfx::TopLevelASCreateInfo& createInfo) override; virtual Gfx::OTopLevelAS createTopLevelAccelerationStructure(const Gfx::TopLevelASCreateInfo& createInfo) override;
void vkCmdDrawMeshTasksEXT(VkCommandBuffer handle, uint32 groupX, uint32 groupY, uint32 groupZ);
void vkCmdDrawMeshTasksIndirectEXT(VkCommandBuffer handle, VkBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride);
void vkSetDebugUtilsObjectNameEXT(VkDebugUtilsObjectNameInfoEXT* info);
protected: protected:
PFN_vkCmdDrawMeshTasksEXT cmdDrawMeshTasks;
PFN_vkCmdDrawMeshTasksIndirectEXT cmdDrawMeshTasksIndirect;
PFN_vkSetDebugUtilsObjectNameEXT setDebugUtilsObjectName;
Array<const char*> getRequiredExtensions(); Array<const char*> getRequiredExtensions();
void initInstance(GraphicsInitializer initInfo); void initInstance(GraphicsInitializer initInfo);
void setupDebugCallback(); void setupDebugCallback();
@@ -103,10 +96,9 @@ class Graphics : public Gfx::Graphics {
Array<OCommandPool> pools; Array<OCommandPool> pools;
VkPhysicalDeviceProperties props; VkPhysicalDeviceProperties props;
VkPhysicalDeviceFeatures2 features; VkPhysicalDeviceFeatures2 features;
VkPhysicalDeviceVulkan11Features features11;
VkPhysicalDeviceVulkan12Features features12; VkPhysicalDeviceVulkan12Features features12;
VkPhysicalDeviceVulkan13Features features13; VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures;
VkPhysicalDeviceRobustness2FeaturesEXT robustness; VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration;
VkDebugUtilsMessengerEXT callback; VkDebugUtilsMessengerEXT callback;
Map<uint32, OFramebuffer> allocatedFramebuffers; Map<uint32, OFramebuffer> allocatedFramebuffers;
VmaAllocator allocator; VmaAllocator allocator;
+101 -15
View File
@@ -1,6 +1,10 @@
#include "RayTracing.h" #include "RayTracing.h"
#include "Buffer.h" #include "Buffer.h"
#include "Command.h"
#include "Enums.h"
#include "Graphics/Buffer.h" #include "Graphics/Buffer.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h" #include "Graphics/Initializer.h"
#include "Graphics/Mesh.h" #include "Graphics/Mesh.h"
#include "Graphics/VertexData.h" #include "Graphics/VertexData.h"
@@ -10,15 +14,37 @@ using namespace Seele::Vulkan;
BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateInfo& createInfo) : graphics(graphics) { BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateInfo& createInfo) : graphics(graphics) {
VertexData* vertexData = createInfo.mesh->vertexData; VertexData* vertexData = createInfo.mesh->vertexData;
MeshData meshData = vertexData->getMeshData(createInfo.mesh->id);
Gfx::PShaderBuffer positionBuffer = vertexData->getPositionBuffer(); Gfx::PShaderBuffer positionBuffer = vertexData->getPositionBuffer();
Gfx::PIndexBuffer indexBuffer = vertexData->getIndexBuffer(); Gfx::PIndexBuffer indexBuffer = vertexData->getIndexBuffer();
VkDeviceOrHostAddressConstKHR vertexDataDeviceAddress = { VkTransformMatrixKHR matrix = {
.deviceAddress = positionBuffer.cast<Buffer>()->getDeviceAddress(), createInfo.mesh->transform[0][0], createInfo.mesh->transform[1][0], createInfo.mesh->transform[2][0],
createInfo.mesh->transform[3][0], createInfo.mesh->transform[0][1], createInfo.mesh->transform[1][1],
createInfo.mesh->transform[2][1], createInfo.mesh->transform[3][1], createInfo.mesh->transform[0][2],
createInfo.mesh->transform[1][2], createInfo.mesh->transform[2][2], createInfo.mesh->transform[3][2],
}; };
VkDeviceOrHostAddressConstKHR indexDataDeviceAddress = { VkBufferCreateInfo transformBufferInfo = {
.deviceAddress = indexBuffer.cast<Buffer>()->getDeviceAddress(), .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = sizeof(VkTransformMatrixKHR),
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
}; };
VkAccelerationStructureGeometryKHR accelerationStructureGeometry = { VmaAllocationCreateInfo transformAllocInfo = {
.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
.usage = VMA_MEMORY_USAGE_AUTO,
};
OBufferAllocation transformBuffer = new BufferAllocation(graphics, transformBufferInfo, transformAllocInfo, Gfx::QueueType::GRAPHICS);
VkDeviceOrHostAddressConstKHR vertexDataAddress = {
.deviceAddress = positionBuffer.cast<ShaderBuffer>()->getDeviceAddress() + vertexData->getMeshOffset(createInfo.mesh->id),
};
VkDeviceOrHostAddressConstKHR indexDataAddress = {
.deviceAddress = indexBuffer.cast<ShaderBuffer>()->getDeviceAddress() + meshData.firstIndex,
};
VkDeviceOrHostAddressConstKHR transformDataAddress = {
.deviceAddress = transformBuffer->deviceAddress,
};
VkAccelerationStructureGeometryKHR geometry = {
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR,
.pNext = nullptr, .pNext = nullptr,
.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR, .geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR,
@@ -27,32 +53,92 @@ BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateI
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR, .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR,
.pNext = nullptr, .pNext = nullptr,
.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT, .vertexFormat = VK_FORMAT_R32G32B32_SFLOAT,
.vertexData = vertexDataDeviceAddress, .vertexData = vertexDataAddress,
.vertexStride = sizeof(Vector), .vertexStride = sizeof(Vector),
.maxVertex = static_cast<uint32_t>(createInfo.mesh->vertexCount), .maxVertex = static_cast<uint32_t>(createInfo.mesh->vertexCount),
.indexType = VK_INDEX_TYPE_UINT32, .indexType = VK_INDEX_TYPE_UINT32,
.indexData = indexDataDeviceAddress, .indexData = indexDataAddress,
.transformData = transformDataAddress,
}}, }},
.flags = VK_GEOMETRY_OPAQUE_BIT_KHR, .flags = VK_GEOMETRY_OPAQUE_BIT_KHR,
}; };
VkAccelerationStructureBuildGeometryInfoKHR structureBuildGeometry = {
VkAccelerationStructureBuildRangeInfoKHR buildRangeInfo = {.primitiveCount = static_cast<uint32_t>(createInfo.mesh->indices.size()),
.primitiveOffset = 0,
.firstVertex = 0,
.transformOffset = 0};
VkAccelerationStructureBuildGeometryInfoKHR buildGeometry = {
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR, .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,
.pNext = nullptr, .pNext = nullptr,
.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR, .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR,
.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR, .flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR,
.geometryCount = 1,
.pGeometries = &geometry,
}; };
VkAccelerationStructureCreateInfoKHR info = { const uint32 primitiveCount = 1;
VkAccelerationStructureBuildSizesInfoKHR buildSizesInfo = {
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR,
.pNext = nullptr,
};
vkGetAccelerationStructureBuildSizesKHR(graphics->getDevice(), VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR, &structureBuildGeometry,
&primitiveCount, &buildSizesInfo);
VkBufferCreateInfo tempBufferInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = buildSizesInfo.accelerationStructureSize,
.usage = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
};
VmaAllocationCreateInfo tempBufferAllocInfo = {
.usage = VMA_MEMORY_USAGE_AUTO,
};
OBufferAllocation tempAlloc = new BufferAllocation(graphics, tempBufferInfo, tempBufferAllocInfo, Gfx::QueueType::GRAPHICS);
VkAccelerationStructureCreateInfoKHR tempInfo = {
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR, .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR,
.pNext = nullptr, .pNext = nullptr,
.createFlags = 0, .createFlags = 0,
.buffer = tempAlloc->buffer,
.offset = 0,
.size = buildSizesInfo.accelerationStructureSize,
.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR,
}; };
VkAccelerationStructureKHR tempAS;
VK_CHECK(vkCreateAccelerationStructureKHR(graphics->getDevice(), &tempInfo, nullptr, &tempAS));
VkBufferCreateInfo scratchInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = buildSizesInfo.buildScratchSize,
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
};
VmaAllocationCreateInfo scratchAllocInfo = {
.usage = VMA_MEMORY_USAGE_AUTO,
};
OBufferAllocation scratchAlloc = new BufferAllocation(graphics, scratchInfo, scratchAllocInfo, Gfx::QueueType::GRAPHICS);
VkAccelerationStructureBuildGeometryInfoKHR buildGeometry = {.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,
.pNext = nullptr,
.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR,
.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR,
.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR,
.dstAccelerationStructure = tempAS,
.geometryCount = 1,
.pGeometries = &geometry,
.scratchData = {.deviceAddress = scratchAlloc->deviceAddress}};
VkAccelerationStructureBuildRangeInfoKHR buildRangeInfo = {
.primitiveCount = meshData.numIndices / 3, .primitiveOffset = 0, .firstVertex = 0, .transformOffset = 0};
Array<VkAccelerationStructureBuildRangeInfoKHR*> ranges = {&buildRangeInfo};
PCommand cmd = graphics->getGraphicsCommands()->getCommands();
vkCmdBuildAccelerationStructuresKHR(cmd->getHandle(), 1, &buildGeometry, ranges.data());
cmd->bindResource(PBufferAllocation(transformBuffer));
cmd->bindResource(PBufferAllocation(tempAlloc));
cmd->bindResource(PBufferAllocation(scratchAlloc));
graphics->getDestructionManager()->queueResourceForDestruction(std::move(transformBuffer));
graphics->getDestructionManager()->queueResourceForDestruction(std::move(tempAlloc));
graphics->getDestructionManager()->queueResourceForDestruction(std::move(scratchAlloc));
} }
BottomLevelAS::~BottomLevelAS() {} BottomLevelAS::~BottomLevelAS() {}
+1
View File
@@ -15,6 +15,7 @@ class BottomLevelAS : public Gfx::BottomLevelAS {
private: private:
PGraphics graphics; PGraphics graphics;
VkAccelerationStructureKHR handle; VkAccelerationStructureKHR handle;
Gfx::OShaderBuffer buffer;
}; };
DEFINE_REF(BottomLevelAS) DEFINE_REF(BottomLevelAS)
class TopLevelAS : public Gfx::TopLevelAS { class TopLevelAS : public Gfx::TopLevelAS {
+118 -136
View File
@@ -1,7 +1,10 @@
#include "Texture.h" #include "Texture.h"
#include "Command.h" #include "Command.h"
#include "Enums.h" #include "Enums.h"
#include "Graphics/Enums.h"
#include "Graphics/Initializer.h"
#include <math.h> #include <math.h>
#include <vulkan/vulkan_core.h>
using namespace Seele; using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
@@ -24,25 +27,12 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format) {
} }
} }
TextureHandle::TextureHandle(PGraphics graphics) : CommandBoundResource(graphics) {} TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, VkImage existingImage)
: CommandBoundResource(graphics), image(existingImage), width(createInfo.width), height(createInfo.height), depth(createInfo.depth),
TextureHandle::~TextureHandle() {
vkDestroyImageView(graphics->getDevice(), imageView, nullptr);
if (ownsImage) {
vmaDestroyImage(graphics->getAllocator(), image, allocation);
}
}
TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, Gfx::QueueType& owner,
VkImage existingImage)
: currentOwner(owner), graphics(graphics), width(createInfo.width), height(createInfo.height), depth(createInfo.depth),
arrayCount(createInfo.elements), layerCount(createInfo.layers), mipLevels(createInfo.mipLevels), samples(createInfo.samples), arrayCount(createInfo.elements), layerCount(createInfo.layers), mipLevels(createInfo.mipLevels), samples(createInfo.samples),
format(createInfo.format), usage(createInfo.usage), handle(new TextureHandle(graphics)), format(createInfo.format), usage(createInfo.usage), layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED),
aspect(getAspectFromFormat(createInfo.format)), layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED) { aspect(getAspectFromFormat(createInfo.format)), ownsImage(false) {
handle->image = existingImage;
handle->ownsImage = false;
if (existingImage == VK_NULL_HANDLE) { if (existingImage == VK_NULL_HANDLE) {
handle->ownsImage = true;
VkImageType type = VK_IMAGE_TYPE_MAX_ENUM; VkImageType type = VK_IMAGE_TYPE_MAX_ENUM;
VkImageCreateFlags flags = 0; VkImageCreateFlags flags = 0;
switch (viewType) { switch (viewType) {
@@ -92,15 +82,14 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const Tex
VmaAllocationCreateInfo allocInfo = { VmaAllocationCreateInfo allocInfo = {
.usage = VMA_MEMORY_USAGE_AUTO, .usage = VMA_MEMORY_USAGE_AUTO,
}; };
VK_CHECK(vmaCreateImage(graphics->getAllocator(), &info, &allocInfo, &handle->image, &handle->allocation, nullptr)); VK_CHECK(vmaCreateImage(graphics->getAllocator(), &info, &allocInfo, &image, &allocation, nullptr));
ownsImage = true;
} }
const DataSource& sourceData = createInfo.sourceData; const DataSource& sourceData = createInfo.sourceData;
if (sourceData.size > 0) { if (sourceData.size > 0) {
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_NONE, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_NONE, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
void* data; void* data;
OBufferAllocation stagingAlloc = new BufferAllocation(graphics);
VkBufferCreateInfo stagingInfo = { VkBufferCreateInfo stagingInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@@ -113,15 +102,14 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const Tex
.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT, .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
.usage = VMA_MEMORY_USAGE_AUTO, .usage = VMA_MEMORY_USAGE_AUTO,
}; };
VK_CHECK( OBufferAllocation stagingAlloc = new BufferAllocation(graphics, stagingInfo, alloc, Gfx::QueueType::TRANSFER);
vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingAlloc->buffer, &stagingAlloc->allocation, nullptr));
vmaMapMemory(graphics->getAllocator(), stagingAlloc->allocation, &data); vmaMapMemory(graphics->getAllocator(), stagingAlloc->allocation, &data);
vmaSetAllocationName(graphics->getAllocator(), stagingAlloc->allocation, "TextureStaging"); vmaSetAllocationName(graphics->getAllocator(), stagingAlloc->allocation, "TextureStaging");
std::memcpy(data, sourceData.data, sourceData.size); std::memcpy(data, sourceData.data, sourceData.size);
vmaUnmapMemory(graphics->getAllocator(), stagingAlloc->allocation); vmaUnmapMemory(graphics->getAllocator(), stagingAlloc->allocation);
PCommandPool commandPool = graphics->getQueueCommands(currentOwner); PCommandPool commandPool = graphics->getQueueCommands(owner);
VkBufferImageCopy region = { VkBufferImageCopy region = {
.bufferOffset = 0, .bufferOffset = 0,
.bufferRowLength = 0, .bufferRowLength = 0,
@@ -142,8 +130,8 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const Tex
.imageExtent = {.width = width, .height = height, .depth = depth}, .imageExtent = {.width = width, .height = height, .depth = depth},
}; };
vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(), stagingAlloc->buffer, handle->image, vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(), stagingAlloc->buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); 1, &region);
commandPool->getCommands()->bindResource(PBufferAllocation(stagingAlloc)); commandPool->getCommands()->bindResource(PBufferAllocation(stagingAlloc));
generateMipmaps(); generateMipmaps();
@@ -167,7 +155,7 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const Tex
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.image = handle->image, .image = image,
.viewType = viewType, .viewType = viewType,
.format = cast(format), .format = cast(format),
.subresourceRange = .subresourceRange =
@@ -178,16 +166,75 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const Tex
}, },
}; };
VK_CHECK(vkCreateImageView(graphics->getDevice(), &viewInfo, nullptr, &handle->imageView)); VK_CHECK(vkCreateImageView(graphics->getDevice(), &viewInfo, nullptr, &imageView));
} }
TextureBase::~TextureBase() { graphics->getDestructionManager()->queueResourceForDestruction(std::move(handle)); } TextureHandle::~TextureHandle() {
vkDestroyImageView(graphics->getDevice(), imageView, nullptr);
if (ownsImage) {
vmaDestroyImage(graphics->getAllocator(), image, allocation);
}
}
VkImage TextureBase::getImage() const { return handle->image; } void TextureHandle::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) {
VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = srcAccess,
.dstAccessMask = dstAccess,
.oldLayout = cast(layout),
.newLayout = cast(layout),
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange =
{
.aspectMask = aspect,
.baseMipLevel = 0,
.levelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
PCommand command = graphics->getQueueCommands(owner)->getCommands();
vkCmdPipelineBarrier(command->getHandle(), srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
command->bindResource(PTextureHandle(this));
}
VkImageView TextureBase::getView() const { return handle->imageView; } void TextureHandle::transferOwnership(Gfx::QueueType newOwner) {
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
.oldLayout = cast(layout),
.newLayout = cast(layout),
.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner),
.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner),
.image = image,
.subresourceRange =
{
.aspectMask = aspect,
.baseMipLevel = 0,
.levelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = arrayCount,
},
};
PCommandPool sourcePool = graphics->getQueueCommands(owner);
PCommandPool dstPool = graphics->getQueueCommands(newOwner);
assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex);
vkCmdPipelineBarrier(sourcePool->getCommands()->getHandle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
0, nullptr, 0, nullptr, 1, &barrier);
vkCmdPipelineBarrier(dstPool->getCommands()->getHandle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0,
nullptr, 0, nullptr, 1, &barrier);
sourcePool->submitCommands();
owner = newOwner;
}
void TextureBase::changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, void TextureHandle::changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) {
VkImageMemoryBarrier barrier = { VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@@ -198,7 +245,7 @@ void TextureBase::changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAc
.newLayout = cast(newLayout), .newLayout = cast(newLayout),
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = handle->image, .image = image,
.subresourceRange = .subresourceRange =
{ {
.aspectMask = aspect, .aspectMask = aspect,
@@ -208,21 +255,20 @@ void TextureBase::changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAc
.layerCount = layerCount, .layerCount = layerCount,
}, },
}; };
PCommandPool commandPool = graphics->getQueueCommands(currentOwner); PCommandPool commandPool = graphics->getQueueCommands(owner);
vkCmdPipelineBarrier(commandPool->getCommands()->getHandle(), srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); vkCmdPipelineBarrier(commandPool->getCommands()->getHandle(), srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
commandPool->getCommands()->bindResource(PTextureHandle(handle)); commandPool->getCommands()->bindResource(PTextureHandle(this));
commandPool->submitCommands(); commandPool->submitCommands();
layout = newLayout; layout = newLayout;
} }
void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) { void TextureHandle::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) {
uint64 imageSize = width * height * depth * Gfx::getFormatInfo(format).blockSize; uint64 imageSize = width * height * depth * Gfx::getFormatInfo(format).blockSize;
auto prevLayout = layout; auto prevLayout = layout;
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
void* data; void* data;
OBufferAllocation stagingAlloc = new BufferAllocation(graphics);
// always create a staging buffer since we do buffer -> image copy and the image may be in any tiling format // always create a staging buffer since we do buffer -> image copy and the image may be in any tiling format
VkBufferCreateInfo stagingInfo = { VkBufferCreateInfo stagingInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
@@ -236,10 +282,11 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra
.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,
.usage = VMA_MEMORY_USAGE_AUTO, .usage = VMA_MEMORY_USAGE_AUTO,
}; };
VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingAlloc->buffer, &stagingAlloc->allocation, nullptr)); OBufferAllocation stagingAlloc = new BufferAllocation(graphics, stagingInfo, alloc, owner);
vmaSetAllocationName(graphics->getAllocator(), stagingAlloc->allocation, "DownloadBuffer"); vmaSetAllocationName(graphics->getAllocator(), stagingAlloc->allocation, "DownloadBuffer");
PCommand cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); PCommand cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
// Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format); // Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format);
VkBufferImageCopy region = { VkBufferImageCopy region = {
.bufferOffset = 0, .bufferOffset = 0,
@@ -260,7 +307,7 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra
}, },
.imageExtent = {.width = width, .height = height, .depth = depth}, .imageExtent = {.width = width, .height = height, .depth = depth},
}; };
vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), handle->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingAlloc->buffer, 1, &region); vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingAlloc->buffer, 1, &region);
cmdBuffer->bindResource(PBufferAllocation(stagingAlloc)); cmdBuffer->bindResource(PBufferAllocation(stagingAlloc));
changeLayout(prevLayout, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_MEMORY_READ_BIT, changeLayout(prevLayout, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_MEMORY_READ_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
@@ -271,8 +318,8 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra
graphics->getDestructionManager()->queueResourceForDestruction(std::move(stagingAlloc)); graphics->getDestructionManager()->queueResourceForDestruction(std::move(stagingAlloc));
} }
void TextureBase::generateMipmaps() { void TextureHandle::generateMipmaps() {
PCommandPool commandPool = graphics->getQueueCommands(currentOwner); PCommandPool commandPool = graphics->getQueueCommands(owner);
VkImageMemoryBarrier barrier = { VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
@@ -281,7 +328,7 @@ void TextureBase::generateMipmaps() {
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = handle->image, .image = image,
.subresourceRange = .subresourceRange =
{ {
.aspectMask = aspect, .aspectMask = aspect,
@@ -318,8 +365,9 @@ void TextureBase::generateMipmaps() {
{mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1}, {mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1},
}, },
}; };
vkCmdBlitImage(commandPool->getCommands()->getHandle(), handle->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, handle->image, vkCmdBlitImage(commandPool->getCommands()->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, aspect & VK_IMAGE_ASPECT_DEPTH_BIT ? VK_FILTER_NEAREST : VK_FILTER_LINEAR); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
aspect & VK_IMAGE_ASPECT_DEPTH_BIT ? VK_FILTER_NEAREST : VK_FILTER_LINEAR);
if (mipWidth > 1) if (mipWidth > 1)
mipWidth /= 2; mipWidth /= 2;
@@ -334,93 +382,29 @@ void TextureBase::generateMipmaps() {
layout = Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; layout = Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
} }
void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, VkImage existingImage)
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); : handle(new TextureHandle(graphics, viewType, createInfo, existingImage)), graphics(graphics),
VkImageMemoryBarrier imageBarrier = { initialOwner(createInfo.sourceData.owner) {}
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.oldLayout = cast(layout),
.newLayout = cast(layout),
.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner),
.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner),
.image = handle->image,
.subresourceRange =
{
.aspectMask = aspect,
.baseMipLevel = 0,
.levelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = arrayCount,
},
};
PCommandPool sourcePool = graphics->getQueueCommands(currentOwner);
PCommandPool dstPool = nullptr;
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
if (currentOwner == Gfx::QueueType::TRANSFER) {
imageBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (currentOwner == Gfx::QueueType::COMPUTE) {
imageBarrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
} else if (currentOwner == Gfx::QueueType::GRAPHICS) {
imageBarrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
}
if (newOwner == Gfx::QueueType::TRANSFER) {
imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstPool = graphics->getTransferCommands();
} else if (newOwner == Gfx::QueueType::COMPUTE) {
imageBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
dstPool = graphics->getComputeCommands();
} else if (newOwner == Gfx::QueueType::GRAPHICS) {
imageBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
dstPool = graphics->getGraphicsCommands();
}
VkCommandBuffer sourceCmd = sourcePool->getCommands()->getHandle(); TextureBase::~TextureBase() { graphics->getDestructionManager()->queueResourceForDestruction(std::move(handle)); }
VkCommandBuffer destCmd = dstPool->getCommands()->getHandle();
sourcePool->getCommands()->bindResource(PTextureHandle(handle));
dstPool->getCommands()->bindResource(PTextureHandle(handle));
vkCmdPipelineBarrier(sourceCmd, srcStage, srcStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
vkCmdPipelineBarrier(destCmd, dstStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
currentOwner = newOwner;
sourcePool->submitCommands();
}
void TextureBase::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void TextureBase::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
VkImageMemoryBarrier barrier = { handle->pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = srcAccess,
.dstAccessMask = dstAccess,
.oldLayout = cast(layout),
.newLayout = cast(layout),
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = handle->image,
.subresourceRange =
{
.aspectMask = aspect,
.baseMipLevel = 0,
.levelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
},
};
PCommand command = graphics->getQueueCommands(currentOwner)->getCommands();
vkCmdPipelineBarrier(command->getHandle(), srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
command->bindResource(PTextureHandle(handle));
} }
void TextureBase::transferOwnership(Gfx::QueueType newOwner) { handle->transferOwnership(newOwner); }
void TextureBase::changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) {
handle->changeLayout(newLayout, srcAccess, srcStage, dstAccess, dstStage);
}
void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) {
handle->download(mipLevel, arrayLayer, face, buffer);
}
void TextureBase::generateMipmaps() { handle->generateMipmaps(); }
Texture2D::Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage) Texture2D::Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage)
: Gfx::Texture2D(graphics->getFamilyMapping(), createInfo.sourceData.owner), : Gfx::Texture2D(graphics->getFamilyMapping()),
TextureBase(graphics, createInfo.elements > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D, createInfo, TextureBase(graphics, createInfo.elements > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D, createInfo, existingImage) {}
Gfx::Texture2D::currentOwner, existingImage) {}
Texture2D::~Texture2D() {} Texture2D::~Texture2D() {}
@@ -435,16 +419,15 @@ void Texture2D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<
void Texture2D::generateMipmaps() { TextureBase::generateMipmaps(); } void Texture2D::generateMipmaps() { TextureBase::generateMipmaps(); }
void Texture2D::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::executeOwnershipBarrier(newOwner); } void Texture2D::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::transferOwnership(newOwner); }
void Texture2D::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void Texture2D::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
TextureBase::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); TextureBase::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
} }
Texture3D::Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage) Texture3D::Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage)
: Gfx::Texture3D(graphics->getFamilyMapping(), createInfo.sourceData.owner), : Gfx::Texture3D(graphics->getFamilyMapping()), TextureBase(graphics, VK_IMAGE_VIEW_TYPE_3D, createInfo, existingImage) {}
TextureBase(graphics, VK_IMAGE_VIEW_TYPE_3D, createInfo, Gfx::Texture3D::currentOwner, existingImage) {}
Texture3D::~Texture3D() {} Texture3D::~Texture3D() {}
@@ -459,17 +442,16 @@ void Texture3D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<
void Texture3D::generateMipmaps() { TextureBase::generateMipmaps(); } void Texture3D::generateMipmaps() { TextureBase::generateMipmaps(); }
void Texture3D::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::executeOwnershipBarrier(newOwner); } void Texture3D::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::transferOwnership(newOwner); }
void Texture3D::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void Texture3D::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
TextureBase::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); TextureBase::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
} }
TextureCube::TextureCube(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage) TextureCube::TextureCube(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage)
: Gfx::TextureCube(graphics->getFamilyMapping(), createInfo.sourceData.owner), : Gfx::TextureCube(graphics->getFamilyMapping()),
TextureBase(graphics, createInfo.elements > 1 ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE, createInfo, TextureBase(graphics, createInfo.elements > 1 ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE, createInfo, existingImage) {}
Gfx::TextureCube::currentOwner, existingImage) {}
TextureCube::~TextureCube() {} TextureCube::~TextureCube() {}
@@ -484,9 +466,9 @@ void TextureCube::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra
void TextureCube::generateMipmaps() { TextureBase::generateMipmaps(); } void TextureCube::generateMipmaps() { TextureBase::generateMipmaps(); }
void TextureCube::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::executeOwnershipBarrier(newOwner); } void TextureCube::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::transferOwnership(newOwner); }
void TextureCube::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void TextureCube::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage) { VkPipelineStageFlags dstStage) {
TextureBase::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); TextureBase::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
} }
+64 -53
View File
@@ -1,53 +1,29 @@
#pragma once #pragma once
#include "Graphics.h" #include "Graphics.h"
#include "Graphics/Enums.h"
#include "Graphics/Initializer.h"
#include "Graphics/Texture.h" #include "Graphics/Texture.h"
#include "Resources.h" #include "Resources.h"
#include <vulkan/vulkan_core.h>
namespace Seele { namespace Seele {
namespace Vulkan { namespace Vulkan {
class TextureHandle : public CommandBoundResource { class TextureHandle : public CommandBoundResource {
public: public:
TextureHandle(PGraphics graphics); TextureHandle(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, VkImage existingImage);
virtual ~TextureHandle(); virtual ~TextureHandle();
VkImage image; void pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkImageView imageView;
VmaAllocation allocation;
uint8 ownsImage;
};
DECLARE_REF(TextureHandle)
class TextureBase {
public:
TextureBase(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, Gfx::QueueType& owner,
VkImage existingImage = VK_NULL_HANDLE);
virtual ~TextureBase();
uint32 getWidth() const { return width; }
uint32 getHeight() const { return height; }
uint32 getDepth() const { return depth; }
PTextureHandle getHandle() const { return handle; }
VkImage getImage() const;
VkImageView getView() const;
constexpr Gfx::SeImageLayout getLayout() const { return layout; }
void setLayout(Gfx::SeImageLayout val) { layout = val; }
constexpr VkImageAspectFlags getAspect() const { return aspect; }
constexpr VkImageUsageFlags getUsage() const { return usage; }
constexpr Gfx::SeFormat getFormat() const { return format; }
constexpr Gfx::SeSampleCountFlags getNumSamples() const { return samples; }
constexpr uint32 getMipLevels() const { return mipLevels; }
constexpr bool isDepthStencil() const { return aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); }
void executeOwnershipBarrier(Gfx::QueueType newOwner);
void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage); VkPipelineStageFlags dstStage);
void transferOwnership(Gfx::QueueType newOwner);
void changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, void changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage); VkPipelineStageFlags dstStage);
void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer); void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer);
void generateMipmaps(); void generateMipmaps();
VkImage image;
protected: VkImageView imageView;
OTextureHandle handle; VmaAllocation allocation;
// Updates via reference Gfx::QueueType owner;
Gfx::QueueType& currentOwner;
PGraphics graphics;
uint32 width; uint32 width;
uint32 height; uint32 height;
uint32 depth; uint32 depth;
@@ -57,8 +33,43 @@ class TextureBase {
uint32 samples; uint32 samples;
Gfx::SeFormat format; Gfx::SeFormat format;
Gfx::SeImageUsageFlags usage; Gfx::SeImageUsageFlags usage;
VkImageAspectFlags aspect;
Gfx::SeImageLayout layout; Gfx::SeImageLayout layout;
VkImageAspectFlags aspect;
uint8 ownsImage;
};
DECLARE_REF(TextureHandle)
class TextureBase {
public:
TextureBase(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo,
VkImage existingImage = VK_NULL_HANDLE);
virtual ~TextureBase();
uint32 getWidth() const { return handle->width; }
uint32 getHeight() const { return handle->height; }
uint32 getDepth() const { return handle->depth; }
PTextureHandle getHandle() const { return handle; }
VkImage getImage() const { return handle->image; };
VkImageView getView() const { return handle->imageView; };
constexpr Gfx::SeImageLayout getLayout() const { return handle->layout; }
void setLayout(Gfx::SeImageLayout val) { handle->layout = val; }
constexpr VkImageAspectFlags getAspect() const { return handle->aspect; }
constexpr VkImageUsageFlags getUsage() const { return handle->usage; }
constexpr Gfx::SeFormat getFormat() const { return handle->format; }
constexpr Gfx::SeSampleCountFlags getNumSamples() const { return handle->samples; }
constexpr uint32 getMipLevels() const { return handle->mipLevels; }
constexpr bool isDepthStencil() const { return handle->aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); }
void pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage);
void transferOwnership(Gfx::QueueType newOwner);
void changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess,
VkPipelineStageFlags dstStage);
void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer);
void generateMipmaps();
protected:
OTextureHandle handle;
// Updates via reference
PGraphics graphics;
Gfx::QueueType initialOwner;
friend class Graphics; friend class Graphics;
}; };
DEFINE_REF(TextureBase) DEFINE_REF(TextureBase)
@@ -67,12 +78,12 @@ 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 getWidth() const override { return width; } virtual uint32 getWidth() const override { return handle->width; }
virtual uint32 getHeight() const override { return height; } virtual uint32 getHeight() const override { return handle->height; }
virtual uint32 getDepth() const override { return depth; } virtual uint32 getDepth() const override { return handle->depth; }
virtual Gfx::SeFormat getFormat() const override { return format; } virtual Gfx::SeFormat getFormat() const override { return handle->format; }
virtual Gfx::SeSampleCountFlags getNumSamples() const override { return samples; } virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; }
virtual uint32 getMipLevels() const override { return mipLevels; } virtual uint32 getMipLevels() const override { return handle->mipLevels; }
virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override; virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
@@ -90,12 +101,12 @@ class Texture3D : public Gfx::Texture3D, public TextureBase {
public: public:
Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE); Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
virtual ~Texture3D(); virtual ~Texture3D();
virtual uint32 getWidth() const override { return width; } virtual uint32 getWidth() const override { return handle->width; }
virtual uint32 getHeight() const override { return height; } virtual uint32 getHeight() const override { return handle->height; }
virtual uint32 getDepth() const override { return depth; } virtual uint32 getDepth() const override { return handle->depth; }
virtual Gfx::SeFormat getFormat() const override { return format; } virtual Gfx::SeFormat getFormat() const override { return handle->format; }
virtual Gfx::SeSampleCountFlags getNumSamples() const override { return samples; } virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; }
virtual uint32 getMipLevels() const override { return mipLevels; } virtual uint32 getMipLevels() const override { return handle->mipLevels; }
virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override; virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
@@ -113,12 +124,12 @@ class TextureCube : public Gfx::TextureCube, public TextureBase {
public: public:
TextureCube(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE); TextureCube(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
virtual ~TextureCube(); virtual ~TextureCube();
virtual uint32 getWidth() const override { return width; } virtual uint32 getWidth() const override { return handle->width; }
virtual uint32 getHeight() const override { return height; } virtual uint32 getHeight() const override { return handle->height; }
virtual uint32 getDepth() const override { return depth; } virtual uint32 getDepth() const override { return handle->depth; }
virtual Gfx::SeFormat getFormat() const override { return format; } virtual Gfx::SeFormat getFormat() const override { return handle->format; }
virtual Gfx::SeSampleCountFlags getNumSamples() const override { return samples; } virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; }
virtual uint32 getMipLevels() const override { return mipLevels; } virtual uint32 getMipLevels() const override { return handle->mipLevels; }
virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override; virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;