diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index dc08fe6..fe376e7 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -498,6 +498,8 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Arraymeshlets = std::move(meshlets); globalMeshes[meshIndex]->indices = std::move(indices); globalMeshes[meshIndex]->vertexCount = mesh->mNumVertices; + globalMeshes[meshIndex]->blas = + graphics->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo(globalMeshes[meshIndex])); } } diff --git a/src/Engine/Graphics/Buffer.cpp b/src/Engine/Graphics/Buffer.cpp index 85b0a16..42aa084 100644 --- a/src/Engine/Graphics/Buffer.cpp +++ b/src/Engine/Graphics/Buffer.cpp @@ -1,24 +1,25 @@ #include "Buffer.h" +#include "Initializer.h" using namespace Seele; using namespace Seele::Gfx; -Buffer::Buffer(QueueFamilyMapping mapping, QueueType startQueue) : QueueOwnedResource(mapping, startQueue) {} +Buffer::Buffer(QueueFamilyMapping mapping) : QueueOwnedResource(mapping) {} Buffer::~Buffer() {} -VertexBuffer::VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType) - : Buffer(mapping, startQueueType), numVertices(numVertices), vertexSize(vertexSize) {} +VertexBuffer::VertexBuffer(QueueFamilyMapping mapping, const VertexBufferCreateInfo& createInfo) + : Buffer(mapping), numVertices(createInfo.numVertices), vertexSize(createInfo.vertexSize) {} VertexBuffer::~VertexBuffer() {} -IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType indexType, QueueType startQueueType) - : Buffer(mapping, startQueueType), indexType(indexType) { +IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, const IndexBufferCreateInfo& createInfo) + : Buffer(mapping), indexType(createInfo.indexType) { switch (indexType) { case SE_INDEX_TYPE_UINT16: - numIndices = size / sizeof(uint16); + numIndices = createInfo.sourceData.size / sizeof(uint16); break; case SE_INDEX_TYPE_UINT32: - numIndices = size / sizeof(uint32); + numIndices = createInfo.sourceData.size / sizeof(uint32); break; default: break; @@ -26,11 +27,11 @@ IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexTy } IndexBuffer::~IndexBuffer() {} -UniformBuffer::UniformBuffer(QueueFamilyMapping mapping, const DataSource& sourceData) : Buffer(mapping, sourceData.owner) {} +UniformBuffer::UniformBuffer(QueueFamilyMapping mapping, const UniformBufferCreateInfo&) : Buffer(mapping) {} UniformBuffer::~UniformBuffer() {} -ShaderBuffer::ShaderBuffer(QueueFamilyMapping mapping, uint32 numElements, const DataSource& sourceData) - : Buffer(mapping, sourceData.owner), numElements(numElements) {} +ShaderBuffer::ShaderBuffer(QueueFamilyMapping mapping, const ShaderBufferCreateInfo& createInfo) + : Buffer(mapping), numElements(createInfo.numElements) {} ShaderBuffer::~ShaderBuffer() {} diff --git a/src/Engine/Graphics/Buffer.h b/src/Engine/Graphics/Buffer.h index eae9395..e582728 100644 --- a/src/Engine/Graphics/Buffer.h +++ b/src/Engine/Graphics/Buffer.h @@ -2,22 +2,23 @@ #include "Initializer.h" #include "Resources.h" - namespace Seele { namespace Gfx { class Buffer : public QueueOwnedResource { public: - Buffer(QueueFamilyMapping mapping, QueueType startQueueType); + Buffer(QueueFamilyMapping mapping); virtual ~Buffer(); protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, + SePipelineStageFlags dstStage) = 0; }; class VertexBuffer : public Buffer { public: - VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType); + VertexBuffer(QueueFamilyMapping mapping, const VertexBufferCreateInfo& createInfo); virtual ~VertexBuffer(); constexpr uint32 getNumVertices() const { return numVertices; } // Size of one vertex in bytes @@ -38,7 +39,7 @@ DEFINE_REF(VertexBuffer) class IndexBuffer : public Buffer { public: - IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType index, QueueType startQueueType); + IndexBuffer(QueueFamilyMapping mapping, const IndexBufferCreateInfo& createInfo); virtual ~IndexBuffer(); constexpr uint64 getNumIndices() const { return numIndices; } constexpr Gfx::SeIndexType getIndexType() const { return indexType; } @@ -58,7 +59,7 @@ DEFINE_REF(IndexBuffer) DECLARE_REF(UniformBuffer) class UniformBuffer : public Buffer { public: - UniformBuffer(QueueFamilyMapping mapping, const DataSource& sourceData); + UniformBuffer(QueueFamilyMapping mapping, const UniformBufferCreateInfo& createInfo); virtual ~UniformBuffer(); virtual void rotateBuffer(uint64 size) = 0; @@ -73,7 +74,7 @@ class UniformBuffer : public Buffer { DEFINE_REF(UniformBuffer) class ShaderBuffer : public Buffer { public: - ShaderBuffer(QueueFamilyMapping mapping, uint32 numElements, const DataSource& bulkResourceData); + ShaderBuffer(QueueFamilyMapping mapping, const ShaderBufferCreateInfo& createInfo); virtual ~ShaderBuffer(); virtual void rotateBuffer(uint64 size, bool preserveContents = false) = 0; virtual void updateContents(const ShaderBufferCreateInfo& sourceData) = 0; diff --git a/src/Engine/Graphics/Mesh.h b/src/Engine/Graphics/Mesh.h index 6e47b7c..9366a5f 100644 --- a/src/Engine/Graphics/Mesh.h +++ b/src/Engine/Graphics/Mesh.h @@ -2,7 +2,7 @@ #include "Asset/MaterialInstanceAsset.h" #include "Graphics/Buffer.h" #include "VertexData.h" - +#include "Graphics/RayTracing.h" namespace Seele { class Mesh { @@ -18,6 +18,7 @@ class Mesh { PMaterialInstanceAsset referencedMaterial; Array indices; Array meshlets; + Gfx::OBottomLevelAS blas; void save(ArchiveBuffer& buffer) const; void load(ArchiveBuffer& buffer); diff --git a/src/Engine/Graphics/Resources.cpp b/src/Engine/Graphics/Resources.cpp index 3b57f9f..dbeb7fa 100644 --- a/src/Engine/Graphics/Resources.cpp +++ b/src/Engine/Graphics/Resources.cpp @@ -1,22 +1,15 @@ #include "Resources.h" -#include "Graphics.h" -#include "Material/Material.h" -#include "Resources.h" - using namespace Seele; using namespace Seele::Gfx; -QueueOwnedResource::QueueOwnedResource(QueueFamilyMapping mapping, QueueType startQueueType) - : currentOwner(startQueueType), mapping(mapping) {} +QueueOwnedResource::QueueOwnedResource(QueueFamilyMapping mapping) + : mapping(mapping) {} QueueOwnedResource::~QueueOwnedResource() {} void QueueOwnedResource::transferOwnership(QueueType newOwner) { - if (mapping.needsTransfer(currentOwner, newOwner)) { - executeOwnershipBarrier(newOwner); - } - currentOwner = newOwner; + executeOwnershipBarrier(newOwner); } void QueueOwnedResource::pipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, diff --git a/src/Engine/Graphics/Resources.h b/src/Engine/Graphics/Resources.h index 2b69dad..04e32de 100644 --- a/src/Engine/Graphics/Resources.h +++ b/src/Engine/Graphics/Resources.h @@ -48,7 +48,7 @@ struct QueueFamilyMapping { class QueueOwnedResource { public: - QueueOwnedResource(QueueFamilyMapping mapping, QueueType startQueueType); + QueueOwnedResource(QueueFamilyMapping mapping); virtual ~QueueOwnedResource(); // 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 executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; - Gfx::QueueType currentOwner; QueueFamilyMapping mapping; }; DEFINE_REF(QueueOwnedResource) diff --git a/src/Engine/Graphics/StaticMeshVertexData.h b/src/Engine/Graphics/StaticMeshVertexData.h index 97264df..6b01f6f 100644 --- a/src/Engine/Graphics/StaticMeshVertexData.h +++ b/src/Engine/Graphics/StaticMeshVertexData.h @@ -37,6 +37,7 @@ class StaticMeshVertexData : public VertexData { virtual Gfx::PDescriptorSet getVertexDataSet() override; virtual std::string getTypeName() const override { return "StaticMeshVertexData"; } virtual Gfx::PShaderBuffer getPositionBuffer() const override { return positions; } + virtual Vector* getPositionData() const override { return positionData.data(); } constexpr const Array& getStaticMeshes() const { return staticData; } private: diff --git a/src/Engine/Graphics/Texture.cpp b/src/Engine/Graphics/Texture.cpp index 179415a..80ba950 100644 --- a/src/Engine/Graphics/Texture.cpp +++ b/src/Engine/Graphics/Texture.cpp @@ -4,18 +4,18 @@ using namespace Seele; using namespace Seele::Gfx; -Texture::Texture(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) : QueueOwnedResource(mapping, startQueueType) {} +Texture::Texture(QueueFamilyMapping mapping) : QueueOwnedResource(mapping) {} Texture::~Texture() {} -Texture2D::Texture2D(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) : Texture(mapping, startQueueType) {} +Texture2D::Texture2D(QueueFamilyMapping mapping) : Texture(mapping) {} Texture2D::~Texture2D() {} -Texture3D::Texture3D(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) : Texture(mapping, startQueueType) {} +Texture3D::Texture3D(QueueFamilyMapping mapping) : Texture(mapping) {} Texture3D::~Texture3D() {} -TextureCube::TextureCube(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) : Texture(mapping, startQueueType) {} +TextureCube::TextureCube(QueueFamilyMapping mapping) : Texture(mapping) {} TextureCube::~TextureCube() {} diff --git a/src/Engine/Graphics/Texture.h b/src/Engine/Graphics/Texture.h index 6d22c0a..24b5304 100644 --- a/src/Engine/Graphics/Texture.h +++ b/src/Engine/Graphics/Texture.h @@ -5,7 +5,7 @@ namespace Seele { namespace Gfx { class Texture : public QueueOwnedResource { public: - Texture(QueueFamilyMapping mapping, QueueType startQueueType); + Texture(QueueFamilyMapping mapping); virtual ~Texture(); virtual SeFormat getFormat() const = 0; @@ -29,7 +29,7 @@ DEFINE_REF(Texture) class Texture2D : public Texture { public: - Texture2D(QueueFamilyMapping mapping, QueueType startQueueType); + Texture2D(QueueFamilyMapping mapping); virtual ~Texture2D(); virtual SeFormat getFormat() const = 0; @@ -52,7 +52,7 @@ DEFINE_REF(Texture2D) class Texture3D : public Texture { public: - Texture3D(QueueFamilyMapping mapping, QueueType startQueueType); + Texture3D(QueueFamilyMapping mapping); virtual ~Texture3D(); virtual SeFormat getFormat() const = 0; @@ -75,7 +75,7 @@ DEFINE_REF(Texture3D) class TextureCube : public Texture { public: - TextureCube(QueueFamilyMapping mapping, QueueType startQueueType); + TextureCube(QueueFamilyMapping mapping); virtual ~TextureCube(); virtual SeFormat getFormat() const = 0; diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index f6461ec..4768553 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -52,7 +52,9 @@ class VertexData { virtual Gfx::PDescriptorSet getVertexDataSet() = 0; virtual std::string getTypeName() 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::PDescriptorSet getInstanceDataSet() { return descriptorSet; } const Array& getMaterialData() const { return materialData; } diff --git a/src/Engine/Graphics/Vulkan/Buffer.cpp b/src/Engine/Graphics/Vulkan/Buffer.cpp index cd9fd8a..c17ceb8 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.cpp +++ b/src/Engine/Graphics/Vulkan/Buffer.cpp @@ -1,19 +1,12 @@ #include "Buffer.h" #include "Command.h" #include "Enums.h" +#include "Graphics/Enums.h" #include using namespace Seele; using namespace Seele::Vulkan; -BufferAllocation::BufferAllocation(PGraphics graphics) : CommandBoundResource(graphics) {} - -BufferAllocation::~BufferAllocation() { - if (buffer != VK_NULL_HANDLE) { - vmaDestroyBuffer(graphics->getAllocator(), buffer, allocation); - } -} - struct PendingBuffer { OBufferAllocation allocation; uint64 offset; @@ -21,71 +14,30 @@ struct PendingBuffer { bool writeOnly; }; -static Map pendingBuffers; +static Map pendingBuffers; -Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool dynamic, std::string name) - : graphics(graphics), currentBuffer(0), owner(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::executeOwnershipBarrier(Gfx::QueueType newOwner) { - if (getSize() == 0) - return; - Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); - VkBufferMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, +BufferAllocation::BufferAllocation(PGraphics graphics, VkBufferCreateInfo bufferInfo, VmaAllocationCreateInfo allocInfo, + Gfx::QueueType owner) + : CommandBoundResource(graphics), size(bufferInfo.size), owner(owner) { + VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &bufferInfo, &allocInfo, &buffer, &allocation, nullptr)); + vmaGetAllocationMemoryProperties(graphics->getAllocator(), allocation, &properties); + VkBufferDeviceAddressInfo addrInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_KHR, .pNext = nullptr, - .srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner), - .dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner), - .buffer = getHandle(), - .offset = 0, - .size = getSize(), + .buffer = buffer, }; - PCommandPool sourcePool = graphics->getQueueCommands(owner); - 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(); + deviceAddress = vkGetBufferDeviceAddress(graphics->getDevice(), &addrInfo); } -void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, - VkPipelineStageFlags dstStage) { - if (getSize() == 0) +BufferAllocation::~BufferAllocation() { + if (buffer != VK_NULL_HANDLE) { + vmaDestroyBuffer(graphics->getAllocator(), buffer, allocation); + } +} + +void BufferAllocation::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, + VkPipelineStageFlags dstStage) { + if (size == 0) return; PCommand commandBuffer = graphics->getQueueCommands(owner)->getCommands(); VkBufferMemoryBarrier barrier = { @@ -95,29 +47,49 @@ void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlag .dstAccessMask = dstAccess, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = getHandle(), + .buffer = buffer, .offset = 0, - .size = getSize(), + .size = size, }; 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) { - if (regionSize == 0) - return nullptr; +void* BufferAllocation::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) { void* data = nullptr; - PendingBuffer pending; - pending.allocation = new BufferAllocation(graphics); - pending.allocation->size = regionSize; pending.writeOnly = writeOnly; pending.prevQueue = owner; pending.offset = regionOffset; + transferOwnership(Gfx::QueueType::TRANSFER); if (writeOnly) { - if (buffers[currentBuffer]->properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - VK_CHECK(vmaMapMemory(graphics->getAllocator(), buffers[currentBuffer]->allocation, &data)); + if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + VK_CHECK(vmaMapMemory(graphics->getAllocator(), allocation, &data)); } else { VkBufferCreateInfo stagingInfo = { .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, .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, }; - VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &allocInfo, &pending.allocation->buffer, - &pending.allocation->allocation, nullptr)); + pending.allocation = new BufferAllocation(graphics, stagingInfo, allocInfo, Gfx::QueueType::TRANSFER); vmaMapMemory(graphics->getAllocator(), pending.allocation->allocation, &data); vmaSetAllocationName(graphics->getAllocator(), pending.allocation->allocation, "MappingStaging"); } @@ -141,18 +112,16 @@ void* Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) assert(false); } pendingBuffers[this] = std::move(pending); - - assert(data); return data; } -void Buffer::unmap() { +void BufferAllocation::unmap() { auto found = pendingBuffers.find(this); if (found != pendingBuffers.end()) { PendingBuffer& pending = found->value; if (pending.writeOnly) { - if (buffers[currentBuffer]->properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { - vmaUnmapMemory(graphics->getAllocator(), buffers[currentBuffer]->allocation); + if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + vmaUnmapMemory(graphics->getAllocator(), allocation); } else { vmaFlushAllocation(graphics->getAllocator(), pending.allocation->allocation, 0, VK_WHOLE_SIZE); vmaUnmapMemory(graphics->getAllocator(), pending.allocation->allocation); @@ -172,13 +141,13 @@ void Buffer::unmap() { .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer]->buffer, + .buffer = buffer, .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, &barrier, 0, nullptr); - vkCmdCopyBuffer(cmdHandle, pending.allocation->buffer, buffers[currentBuffer]->buffer, 1, ®ion); + vkCmdCopyBuffer(cmdHandle, pending.allocation->buffer, buffer, 1, ®ion); barrier = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .pNext = nullptr, @@ -186,34 +155,64 @@ void Buffer::unmap() { .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer]->buffer, + .buffer = buffer, .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, &barrier, 0, nullptr); graphics->getDestructionManager()->queueResourceForDestruction(std::move(pending.allocation)); } } + transferOwnership(pending.prevQueue); 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) { assert(dynamic); 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()) { continue; } if (buffers[i]->size < size) { vmaDestroyBuffer(graphics->getAllocator(), buffers[i]->buffer, buffers[i]->allocation); + uint32 family = graphics->getFamilyMapping().getQueueTypeFamilyIndex(initialOwner); VkBufferCreateInfo info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, + .flags = 0, .size = size, .usage = usage, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 1, + .pQueueFamilyIndices = &family, }; VmaAllocationCreateInfo allocInfo = { .flags = @@ -229,7 +228,7 @@ void Buffer::rotateBuffer(uint64 size, bool preserveContents) { .objectType = VK_OBJECT_TYPE_BUFFER, .objectHandle = (uint64)buffers[i]->buffer, .pObjectName = this->name.c_str()}; - graphics->vkSetDebugUtilsObjectNameEXT(&nameInfo); + vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo); } buffers[i]->size = size; } @@ -247,36 +246,32 @@ void Buffer::rotateBuffer(uint64 size, bool preserveContents) { } void Buffer::createBuffer(uint64 size) { + uint32 family = graphics->getFamilyMapping().getQueueTypeFamilyIndex(initialOwner); VkBufferCreateInfo info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, + .flags = 0, .size = size, .usage = usage, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 1, + .pQueueFamilyIndices = &family, }; VmaAllocationCreateInfo allocInfo = { .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, .usage = VMA_MEMORY_USAGE_AUTO, }; - buffers.add(new BufferAllocation(graphics)); + buffers.add(new BufferAllocation(graphics, info, allocInfo, initialOwner)); if (size > 0) { VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &info, &allocInfo, &buffers.back()->buffer, &buffers.back()->allocation, &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()) { VkDebugUtilsObjectNameInfoEXT nameInfo = {.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, .pNext = nullptr, .objectType = VK_OBJECT_TYPE_BUFFER, .objectHandle = (uint64)buffers.back()->buffer, .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) { return; } - PCommand command = graphics->getQueueCommands(owner)->getCommands(); + PCommand command = graphics->getQueueCommands(getAlloc()->owner)->getCommands(); VkBufferMemoryBarrier srcBarrier = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .pNext = nullptr, @@ -316,10 +311,17 @@ void Buffer::copyBuffer(uint64 src, uint64 dst) { &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) - : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData), - Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.dynamic, - createInfo.name) { + : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo), + Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, createInfo.sourceData.owner, + createInfo.dynamic, createInfo.name) { if (getSize() > 0 && createInfo.sourceData.data != nullptr) { void* data = map(); 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::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); } - -void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::executeOwnershipBarrier(newOwner); } +void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::transferOwnership(newOwner); } void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, 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; } - -VkAccessFlags UniformBuffer::getDestAccessMask() { return VK_ACCESS_UNIFORM_READ_BIT; } - -ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& sourceData) - : Gfx::ShaderBuffer(graphics->getFamilyMapping(), sourceData.numElements, sourceData.sourceData), - Vulkan::Buffer(graphics, sourceData.sourceData.size, +ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& createInfo) + : Gfx::ShaderBuffer(graphics->getFamilyMapping(), createInfo), + Vulkan::Buffer(graphics, createInfo.sourceData.size, 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 : 0), - currentOwner, sourceData.dynamic, sourceData.name) { - if (getSize() > 0 && sourceData.sourceData.data != nullptr) { + createInfo.sourceData.owner, createInfo.dynamic, createInfo.name) { + if (getSize() > 0 && createInfo.sourceData.data != nullptr) { void* data = map(); - std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); + std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size); unmap(); } } @@ -387,28 +383,24 @@ void* ShaderBuffer::mapRegion(uint64 offset, uint64 size, bool writeOnly) { retu void ShaderBuffer::unmap() { Vulkan::Buffer::unmap(); } 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::executeOwnershipBarrier(newOwner); } +void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::transferOwnership(newOwner); } void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, 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; } - -VkAccessFlags ShaderBuffer::getDestAccessMask() { return VK_ACCESS_MEMORY_READ_BIT; } - -VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo& sourceData) - : 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) { +VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo& createInfo) + : Gfx::VertexBuffer(graphics->getFamilyMapping(), createInfo), + Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, createInfo.sourceData.owner, false, + createInfo.name) { + if (createInfo.sourceData.data != nullptr) { void* data = map(); - std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); + std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size); unmap(); } } @@ -428,28 +420,22 @@ void VertexBuffer::download(Array& buffer) { unmap(); } -void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); } - -void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::executeOwnershipBarrier(newOwner); } +void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::transferOwnership(newOwner); } void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, 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; } - -VkAccessFlags VertexBuffer::getDestAccessMask() { return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; } - -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, +IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& createInfo) + : Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo), + Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, - currentOwner, false, sourceData.name) { - if (sourceData.sourceData.data != nullptr) { + createInfo.sourceData.owner, false, createInfo.name) { + if (createInfo.sourceData.data != nullptr) { void* data = map(); - std::memcpy(data, sourceData.sourceData.data, sourceData.sourceData.size); + std::memcpy(data, createInfo.sourceData.data, createInfo.sourceData.size); unmap(); } } @@ -463,15 +449,9 @@ void IndexBuffer::download(Array& buffer) { unmap(); } -void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); } - -void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::executeOwnershipBarrier(newOwner); } +void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Vulkan::Buffer::transferOwnership(newOwner); } void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, 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; } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/Buffer.h b/src/Engine/Graphics/Vulkan/Buffer.h index 60e889a..61e5867 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.h +++ b/src/Engine/Graphics/Vulkan/Buffer.h @@ -1,6 +1,7 @@ #pragma once #include "Graphics.h" #include "Graphics/Buffer.h" +#include "Graphics/Enums.h" #include "Resources.h" namespace Seele { @@ -9,19 +10,25 @@ DECLARE_REF(Command) DECLARE_REF(Fence) class BufferAllocation : public CommandBoundResource { public: - BufferAllocation(PGraphics graphics); + BufferAllocation(PGraphics graphics, VkBufferCreateInfo bufferInfo, VmaAllocationCreateInfo allocInfo, Gfx::QueueType owner); 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; VmaAllocation allocation = VmaAllocation(); VmaAllocationInfo info = VmaAllocationInfo(); VkMemoryPropertyFlags properties = 0; uint64 size = 0; VkDeviceAddress deviceAddress; + Gfx::QueueType owner; }; DEFINE_REF(BufferAllocation); class Buffer { 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(); VkBuffer getHandle() const { return buffers[currentBuffer]->buffer; } VkDeviceAddress getDeviceAddress() const { return buffers[currentBuffer]->deviceAddress; } @@ -34,7 +41,7 @@ class Buffer { protected: PGraphics graphics; uint32 currentBuffer; - Gfx::QueueType& owner; + Gfx::QueueType initialOwner; Array buffers; VkBufferUsageFlags usage; bool dynamic; @@ -43,14 +50,9 @@ class Buffer { void createBuffer(uint64 size); void copyBuffer(uint64 src, uint64 dest); - void executeOwnershipBarrier(Gfx::QueueType newOwner); - void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, + void transferOwnership(Gfx::QueueType newOwner); + void pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); - - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0; - - virtual VkAccessFlags getSourceAccessMask() = 0; - virtual VkAccessFlags getDestAccessMask() = 0; }; DEFINE_REF(Buffer) @@ -63,10 +65,6 @@ class VertexBuffer : public Gfx::VertexBuffer, public Buffer { virtual void download(Array& buffer) override; protected: - // Inherited via Vulkan::Buffer - virtual VkAccessFlags getSourceAccessMask() override; - virtual VkAccessFlags getDestAccessMask() override; - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; 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& buffer) override; protected: - // Inherited via Vulkan::Buffer - virtual VkAccessFlags getSourceAccessMask() override; - virtual VkAccessFlags getDestAccessMask() override; - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; 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; protected: - // Inherited via Vulkan::Buffer - virtual VkAccessFlags getSourceAccessMask() override; - virtual VkAccessFlags getDestAccessMask() override; - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; 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; protected: - // Inherited via Vulkan::Buffer - virtual VkAccessFlags getSourceAccessMask() override; - virtual VkAccessFlags getDestAccessMask() override; - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess, diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index cc7282e..0abab6b 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -302,12 +302,12 @@ void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 f } void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) { 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) { assert(threadId == std::this_thread::get_id()); - graphics->vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast()->getHandle(), offset, drawCount, stride); + vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast()->getHandle(), offset, drawCount, stride); } ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) { diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index df0bff8..0f4146b 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -9,10 +9,10 @@ #include "Graphics/Graphics.h" #include "Graphics/Initializer.h" #include "PipelineCache.h" +#include "Query.h" #include "RayTracing.h" #include "RenderPass.h" #include "Shader.h" -#include "Query.h" #include "Window.h" #include #include @@ -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::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() { @@ -95,9 +131,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) { getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer); } -void Graphics::endRenderPass() { - getGraphicsCommands()->getCommands()->endRenderPass(); -} +void Graphics::endRenderPass() { getGraphicsCommands()->getCommands()->endRenderPass(); } 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) { PTextureBase src = source.cast(); PTextureBase dst = destination.cast(); - 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 = { {0, 0, 0}, {(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 = { {0, 0, 0}, {(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(); vkCmdBlitImage(command->getHandle(), src->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst->getImage(), 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) { @@ -266,16 +312,6 @@ Gfx::OTopLevelAS Graphics::createTopLevelAccelerationStructure(const Gfx::TopLev 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) { switch (queueType) { case Gfx::QueueType::GRAPHICS: @@ -394,20 +430,9 @@ void Graphics::pickPhysicalDevice() { vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()); VkPhysicalDevice bestDevice = VK_NULL_HANDLE; 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) { uint32 currentRating = 0; vkGetPhysicalDeviceProperties(dev, &props); - vkGetPhysicalDeviceFeatures2(dev, &features); if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { std::cout << "found dedicated gpu " << props.deviceName << std::endl; currentRating += 100; @@ -424,9 +449,29 @@ void Graphics::pickPhysicalDevice() { physicalDevice = bestDevice; vkGetPhysicalDeviceProperties(physicalDevice, &props); - vkGetPhysicalDeviceFeatures2(physicalDevice, &features); - features.features.robustBufferAccess = 0; - features.features.inheritedQueries = true; + acceleration = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR, + .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) { uint32 count = 0; vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &count, nullptr); @@ -508,14 +553,8 @@ void Graphics::createDevice(GraphicsInitializer initializer) { *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()) { - features12.pNext = &enabledMeshShaderFeatures; initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME); } #ifdef __APPLE__ @@ -525,19 +564,17 @@ void Graphics::createDevice(GraphicsInitializer initializer) { initializer.deviceExtensions.add(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); VkDeviceCreateInfo deviceInfo = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = &features11, + .pNext = &features, .queueCreateInfoCount = (uint32)queueInfos.size(), .pQueueCreateInfos = queueInfos.data(), .enabledExtensionCount = (uint32)initializer.deviceExtensions.size(), .ppEnabledExtensionNames = initializer.deviceExtensions.data(), - .pEnabledFeatures = &features.features, + .pEnabledFeatures = nullptr, }; VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle)); // std::cout << "Vulkan handle: " << handle << std::endl; - cmdDrawMeshTasks = (PFN_vkCmdDrawMeshTasksEXT)vkGetDeviceProcAddr(handle, "vkCmdDrawMeshTasksEXT"); - graphicsQueue = 0; computeQueue = 0; transferQueue = 0; @@ -554,5 +591,14 @@ void Graphics::createDevice(GraphicsInitializer initializer) { queueMapping.graphicsFamily = queues[graphicsQueue]->getFamilyIndex(); queueMapping.computeFamily = queues[computeQueue]->getFamilyIndex(); queueMapping.transferFamily = queues[transferQueue]->getFamilyIndex(); + + cmdDrawMeshTasks = (PFN_vkCmdDrawMeshTasksEXT)vkGetDeviceProcAddr(handle, "vkCmdDrawMeshTasksEXT"); + cmdDrawMeshTasksIndirect = (PFN_vkCmdDrawMeshTasksIndirectEXT)vkGetDeviceProcAddr(handle, "vkCmdDrawMeshTasksIndirectEXT"); setDebugUtilsObjectName = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT"); + + createAccelerationStructure = (PFN_vkCreateAccelerationStructureKHR)vkGetDeviceProcAddr(handle, "vkCreateAccelerationStructureKHR"); + cmdBuildAccelerationStructures = + (PFN_vkCmdBuildAccelerationStructuresKHR)vkGetDeviceProcAddr(handle, "vkCmdBuildAccelerationStructuresKHR"); + getAccelerationStructureBuildSize = + (PFN_vkGetAccelerationStructureBuildSizesKHR)vkGetDeviceProcAddr(handle, "vkGetAccelerationStructureBuildSizesKHR"); } diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index 5e34bc6..f830b32 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -74,14 +74,7 @@ class Graphics : public Gfx::Graphics { virtual Gfx::OBottomLevelAS createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& 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: - PFN_vkCmdDrawMeshTasksEXT cmdDrawMeshTasks; - PFN_vkCmdDrawMeshTasksIndirectEXT cmdDrawMeshTasksIndirect; - PFN_vkSetDebugUtilsObjectNameEXT setDebugUtilsObjectName; Array getRequiredExtensions(); void initInstance(GraphicsInitializer initInfo); void setupDebugCallback(); @@ -103,10 +96,9 @@ class Graphics : public Gfx::Graphics { Array pools; VkPhysicalDeviceProperties props; VkPhysicalDeviceFeatures2 features; - VkPhysicalDeviceVulkan11Features features11; VkPhysicalDeviceVulkan12Features features12; - VkPhysicalDeviceVulkan13Features features13; - VkPhysicalDeviceRobustness2FeaturesEXT robustness; + VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures; + VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration; VkDebugUtilsMessengerEXT callback; Map allocatedFramebuffers; VmaAllocator allocator; diff --git a/src/Engine/Graphics/Vulkan/RayTracing.cpp b/src/Engine/Graphics/Vulkan/RayTracing.cpp index 0e3e017..422e923 100644 --- a/src/Engine/Graphics/Vulkan/RayTracing.cpp +++ b/src/Engine/Graphics/Vulkan/RayTracing.cpp @@ -1,6 +1,10 @@ #include "RayTracing.h" #include "Buffer.h" +#include "Command.h" +#include "Enums.h" #include "Graphics/Buffer.h" +#include "Graphics/Enums.h" +#include "Graphics/Graphics.h" #include "Graphics/Initializer.h" #include "Graphics/Mesh.h" #include "Graphics/VertexData.h" @@ -10,15 +14,37 @@ using namespace Seele::Vulkan; BottomLevelAS::BottomLevelAS(PGraphics graphics, const Gfx::BottomLevelASCreateInfo& createInfo) : graphics(graphics) { VertexData* vertexData = createInfo.mesh->vertexData; + MeshData meshData = vertexData->getMeshData(createInfo.mesh->id); Gfx::PShaderBuffer positionBuffer = vertexData->getPositionBuffer(); Gfx::PIndexBuffer indexBuffer = vertexData->getIndexBuffer(); - VkDeviceOrHostAddressConstKHR vertexDataDeviceAddress = { - .deviceAddress = positionBuffer.cast()->getDeviceAddress(), + VkTransformMatrixKHR matrix = { + 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 = { - .deviceAddress = indexBuffer.cast()->getDeviceAddress(), + VkBufferCreateInfo transformBufferInfo = { + .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()->getDeviceAddress() + vertexData->getMeshOffset(createInfo.mesh->id), + }; + VkDeviceOrHostAddressConstKHR indexDataAddress = { + .deviceAddress = indexBuffer.cast()->getDeviceAddress() + meshData.firstIndex, + }; + VkDeviceOrHostAddressConstKHR transformDataAddress = { + .deviceAddress = transformBuffer->deviceAddress, + }; + VkAccelerationStructureGeometryKHR geometry = { .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR, .pNext = nullptr, .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, .pNext = nullptr, .vertexFormat = VK_FORMAT_R32G32B32_SFLOAT, - .vertexData = vertexDataDeviceAddress, + .vertexData = vertexDataAddress, .vertexStride = sizeof(Vector), .maxVertex = static_cast(createInfo.mesh->vertexCount), .indexType = VK_INDEX_TYPE_UINT32, - .indexData = indexDataDeviceAddress, + .indexData = indexDataAddress, + .transformData = transformDataAddress, }}, .flags = VK_GEOMETRY_OPAQUE_BIT_KHR, }; - - VkAccelerationStructureBuildRangeInfoKHR buildRangeInfo = {.primitiveCount = static_cast(createInfo.mesh->indices.size()), - .primitiveOffset = 0, - .firstVertex = 0, - .transformOffset = 0}; - - VkAccelerationStructureBuildGeometryInfoKHR buildGeometry = { + VkAccelerationStructureBuildGeometryInfoKHR structureBuildGeometry = { .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, + .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, .pNext = nullptr, .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 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() {} diff --git a/src/Engine/Graphics/Vulkan/RayTracing.h b/src/Engine/Graphics/Vulkan/RayTracing.h index e0709ba..e8f82f2 100644 --- a/src/Engine/Graphics/Vulkan/RayTracing.h +++ b/src/Engine/Graphics/Vulkan/RayTracing.h @@ -15,6 +15,7 @@ class BottomLevelAS : public Gfx::BottomLevelAS { private: PGraphics graphics; VkAccelerationStructureKHR handle; + Gfx::OShaderBuffer buffer; }; DEFINE_REF(BottomLevelAS) class TopLevelAS : public Gfx::TopLevelAS { diff --git a/src/Engine/Graphics/Vulkan/Texture.cpp b/src/Engine/Graphics/Vulkan/Texture.cpp index be9bb77..6114c87 100644 --- a/src/Engine/Graphics/Vulkan/Texture.cpp +++ b/src/Engine/Graphics/Vulkan/Texture.cpp @@ -1,7 +1,10 @@ #include "Texture.h" #include "Command.h" #include "Enums.h" +#include "Graphics/Enums.h" +#include "Graphics/Initializer.h" #include +#include using namespace Seele; using namespace Seele::Vulkan; @@ -24,25 +27,12 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format) { } } -TextureHandle::TextureHandle(PGraphics graphics) : CommandBoundResource(graphics) {} - -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), +TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, VkImage existingImage) + : CommandBoundResource(graphics), image(existingImage), width(createInfo.width), height(createInfo.height), depth(createInfo.depth), arrayCount(createInfo.elements), layerCount(createInfo.layers), mipLevels(createInfo.mipLevels), samples(createInfo.samples), - format(createInfo.format), usage(createInfo.usage), handle(new TextureHandle(graphics)), - aspect(getAspectFromFormat(createInfo.format)), layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED) { - handle->image = existingImage; - handle->ownsImage = false; + format(createInfo.format), usage(createInfo.usage), layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED), + aspect(getAspectFromFormat(createInfo.format)), ownsImage(false) { if (existingImage == VK_NULL_HANDLE) { - handle->ownsImage = true; VkImageType type = VK_IMAGE_TYPE_MAX_ENUM; VkImageCreateFlags flags = 0; switch (viewType) { @@ -92,15 +82,14 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const Tex VmaAllocationCreateInfo allocInfo = { .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; if (sourceData.size > 0) { 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); void* data; - OBufferAllocation stagingAlloc = new BufferAllocation(graphics); VkBufferCreateInfo stagingInfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .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, .usage = VMA_MEMORY_USAGE_AUTO, }; - VK_CHECK( - vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingAlloc->buffer, &stagingAlloc->allocation, nullptr)); + OBufferAllocation stagingAlloc = new BufferAllocation(graphics, stagingInfo, alloc, Gfx::QueueType::TRANSFER); vmaMapMemory(graphics->getAllocator(), stagingAlloc->allocation, &data); vmaSetAllocationName(graphics->getAllocator(), stagingAlloc->allocation, "TextureStaging"); std::memcpy(data, sourceData.data, sourceData.size); vmaUnmapMemory(graphics->getAllocator(), stagingAlloc->allocation); - PCommandPool commandPool = graphics->getQueueCommands(currentOwner); + PCommandPool commandPool = graphics->getQueueCommands(owner); VkBufferImageCopy region = { .bufferOffset = 0, .bufferRowLength = 0, @@ -142,8 +130,8 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const Tex .imageExtent = {.width = width, .height = height, .depth = depth}, }; - vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(), stagingAlloc->buffer, handle->image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(), stagingAlloc->buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ®ion); commandPool->getCommands()->bindResource(PBufferAllocation(stagingAlloc)); generateMipmaps(); @@ -167,7 +155,7 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const Tex .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .pNext = nullptr, .flags = 0, - .image = handle->image, + .image = image, .viewType = viewType, .format = cast(format), .subresourceRange = @@ -178,17 +166,76 @@ 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, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { +void TextureHandle::changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { VkImageMemoryBarrier barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .pNext = nullptr, @@ -198,7 +245,7 @@ void TextureBase::changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAc .newLayout = cast(newLayout), .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = handle->image, + .image = image, .subresourceRange = { .aspectMask = aspect, @@ -208,21 +255,20 @@ void TextureBase::changeLayout(Gfx::SeImageLayout newLayout, VkAccessFlags srcAc .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); - commandPool->getCommands()->bindResource(PTextureHandle(handle)); + commandPool->getCommands()->bindResource(PTextureHandle(this)); commandPool->submitCommands(); layout = newLayout; } -void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) { +void TextureHandle::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) { uint64 imageSize = width * height * depth * Gfx::getFormatInfo(format).blockSize; auto prevLayout = layout; 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); 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 VkBufferCreateInfo stagingInfo = { .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, .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"); - PCommand cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); + PCommand cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); // Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format); VkBufferImageCopy region = { .bufferOffset = 0, @@ -260,7 +307,7 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra }, .imageExtent = {.width = width, .height = height, .depth = depth}, }; - vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), handle->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingAlloc->buffer, 1, ®ion); + vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingAlloc->buffer, 1, ®ion); cmdBuffer->bindResource(PBufferAllocation(stagingAlloc)); changeLayout(prevLayout, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_MEMORY_READ_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)); } -void TextureBase::generateMipmaps() { - PCommandPool commandPool = graphics->getQueueCommands(currentOwner); +void TextureHandle::generateMipmaps() { + PCommandPool commandPool = graphics->getQueueCommands(owner); VkImageMemoryBarrier barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, @@ -281,7 +328,7 @@ void TextureBase::generateMipmaps() { .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = handle->image, + .image = image, .subresourceRange = { .aspectMask = aspect, @@ -318,8 +365,9 @@ void TextureBase::generateMipmaps() { {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, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, aspect & VK_IMAGE_ASPECT_DEPTH_BIT ? VK_FILTER_NEAREST : VK_FILTER_LINEAR); + 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); if (mipWidth > 1) mipWidth /= 2; @@ -334,93 +382,29 @@ void TextureBase::generateMipmaps() { layout = Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; } -void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); - VkImageMemoryBarrier imageBarrier = { - .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(); - } +TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, VkImage existingImage) + : handle(new TextureHandle(graphics, viewType, createInfo, existingImage)), graphics(graphics), + initialOwner(createInfo.sourceData.owner) {} - VkCommandBuffer sourceCmd = sourcePool->getCommands()->getHandle(); - 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(); -} +TextureBase::~TextureBase() { graphics->getDestructionManager()->queueResourceForDestruction(std::move(handle)); } -void TextureBase::executePipelineBarrier(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 = 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::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, + VkPipelineStageFlags dstStage) { + handle->pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } +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& buffer) { + handle->download(mipLevel, arrayLayer, face, buffer); +} +void TextureBase::generateMipmaps() { handle->generateMipmaps(); } Texture2D::Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage) - : Gfx::Texture2D(graphics->getFamilyMapping(), createInfo.sourceData.owner), - TextureBase(graphics, createInfo.elements > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D, createInfo, - Gfx::Texture2D::currentOwner, existingImage) {} + : Gfx::Texture2D(graphics->getFamilyMapping()), + TextureBase(graphics, createInfo.elements > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D, createInfo, existingImage) {} Texture2D::~Texture2D() {} @@ -435,16 +419,15 @@ void Texture2D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array< 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, VkPipelineStageFlags dstStage) { - TextureBase::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); + TextureBase::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } Texture3D::Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage) - : Gfx::Texture3D(graphics->getFamilyMapping(), createInfo.sourceData.owner), - TextureBase(graphics, VK_IMAGE_VIEW_TYPE_3D, createInfo, Gfx::Texture3D::currentOwner, existingImage) {} + : Gfx::Texture3D(graphics->getFamilyMapping()), TextureBase(graphics, VK_IMAGE_VIEW_TYPE_3D, createInfo, existingImage) {} Texture3D::~Texture3D() {} @@ -459,17 +442,16 @@ void Texture3D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array< 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, VkPipelineStageFlags dstStage) { - TextureBase::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); + TextureBase::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } TextureCube::TextureCube(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage) - : Gfx::TextureCube(graphics->getFamilyMapping(), createInfo.sourceData.owner), - TextureBase(graphics, createInfo.elements > 1 ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE, createInfo, - Gfx::TextureCube::currentOwner, existingImage) {} + : Gfx::TextureCube(graphics->getFamilyMapping()), + TextureBase(graphics, createInfo.elements > 1 ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE, createInfo, existingImage) {} TextureCube::~TextureCube() {} @@ -484,9 +466,9 @@ void TextureCube::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra 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, VkPipelineStageFlags dstStage) { - TextureBase::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); + TextureBase::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } diff --git a/src/Engine/Graphics/Vulkan/Texture.h b/src/Engine/Graphics/Vulkan/Texture.h index b1afda9..7865c5f 100644 --- a/src/Engine/Graphics/Vulkan/Texture.h +++ b/src/Engine/Graphics/Vulkan/Texture.h @@ -1,53 +1,29 @@ #pragma once #include "Graphics.h" +#include "Graphics/Enums.h" +#include "Graphics/Initializer.h" #include "Graphics/Texture.h" #include "Resources.h" +#include namespace Seele { namespace Vulkan { class TextureHandle : public CommandBoundResource { public: - TextureHandle(PGraphics graphics); + TextureHandle(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, VkImage existingImage); virtual ~TextureHandle(); - VkImage image; - 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, + 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& buffer); void generateMipmaps(); - - protected: - OTextureHandle handle; - // Updates via reference - Gfx::QueueType& currentOwner; - PGraphics graphics; + VkImage image; + VkImageView imageView; + VmaAllocation allocation; + Gfx::QueueType owner; uint32 width; uint32 height; uint32 depth; @@ -57,8 +33,43 @@ class TextureBase { uint32 samples; Gfx::SeFormat format; Gfx::SeImageUsageFlags usage; - VkImageAspectFlags aspect; 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& buffer); + void generateMipmaps(); + protected: + OTextureHandle handle; + // Updates via reference + PGraphics graphics; + Gfx::QueueType initialOwner; friend class Graphics; }; DEFINE_REF(TextureBase) @@ -67,12 +78,12 @@ class Texture2D : public Gfx::Texture2D, public TextureBase { public: Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE); virtual ~Texture2D(); - virtual uint32 getWidth() const override { return width; } - virtual uint32 getHeight() const override { return height; } - virtual uint32 getDepth() const override { return depth; } - virtual Gfx::SeFormat getFormat() const override { return format; } - virtual Gfx::SeSampleCountFlags getNumSamples() const override { return samples; } - virtual uint32 getMipLevels() const override { return mipLevels; } + virtual uint32 getWidth() const override { return handle->width; } + virtual uint32 getHeight() const override { return handle->height; } + virtual uint32 getDepth() const override { return handle->depth; } + virtual Gfx::SeFormat getFormat() const override { return handle->format; } + virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; } + virtual uint32 getMipLevels() const override { return handle->mipLevels; } virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) override; @@ -90,12 +101,12 @@ class Texture3D : public Gfx::Texture3D, public TextureBase { public: Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE); virtual ~Texture3D(); - virtual uint32 getWidth() const override { return width; } - virtual uint32 getHeight() const override { return height; } - virtual uint32 getDepth() const override { return depth; } - virtual Gfx::SeFormat getFormat() const override { return format; } - virtual Gfx::SeSampleCountFlags getNumSamples() const override { return samples; } - virtual uint32 getMipLevels() const override { return mipLevels; } + virtual uint32 getWidth() const override { return handle->width; } + virtual uint32 getHeight() const override { return handle->height; } + virtual uint32 getDepth() const override { return handle->depth; } + virtual Gfx::SeFormat getFormat() const override { return handle->format; } + virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; } + virtual uint32 getMipLevels() const override { return handle->mipLevels; } virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) override; @@ -113,12 +124,12 @@ class TextureCube : public Gfx::TextureCube, public TextureBase { public: TextureCube(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE); virtual ~TextureCube(); - virtual uint32 getWidth() const override { return width; } - virtual uint32 getHeight() const override { return height; } - virtual uint32 getDepth() const override { return depth; } - virtual Gfx::SeFormat getFormat() const override { return format; } - virtual Gfx::SeSampleCountFlags getNumSamples() const override { return samples; } - virtual uint32 getMipLevels() const override { return mipLevels; } + virtual uint32 getWidth() const override { return handle->width; } + virtual uint32 getHeight() const override { return handle->height; } + virtual uint32 getDepth() const override { return handle->depth; } + virtual Gfx::SeFormat getFormat() const override { return handle->format; } + virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; } + virtual uint32 getMipLevels() const override { return handle->mipLevels; } virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) override;