Lots of refactoring
This commit is contained in:
@@ -498,6 +498,8 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterialIns
|
||||
globalMeshes[meshIndex]->meshlets = std::move(meshlets);
|
||||
globalMeshes[meshIndex]->indices = std::move(indices);
|
||||
globalMeshes[meshIndex]->vertexCount = mesh->mNumVertices;
|
||||
globalMeshes[meshIndex]->blas =
|
||||
graphics->createBottomLevelAccelerationStructure(Gfx::BottomLevelASCreateInfo(globalMeshes[meshIndex]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<uint32> indices;
|
||||
Array<Meshlet> meshlets;
|
||||
Gfx::OBottomLevelAS blas;
|
||||
void save(ArchiveBuffer& buffer) const;
|
||||
void load(ArchiveBuffer& buffer);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<StaticMatData>& getStaticMeshes() const { return staticData; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<MaterialData>& getMaterialData() const { return materialData; }
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
#include "Buffer.h"
|
||||
#include "Command.h"
|
||||
#include "Enums.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
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<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)
|
||||
: 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<uint8>& 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<uint8>& 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; }
|
||||
@@ -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<OBufferAllocation> 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<uint8>& 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<uint8>& 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,
|
||||
|
||||
@@ -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<ShaderBuffer>()->getHandle(), offset, drawCount, stride);
|
||||
vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset, drawCount, stride);
|
||||
}
|
||||
|
||||
ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) {
|
||||
|
||||
@@ -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 <GLFW/glfw3.h>
|
||||
#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::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<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 =
|
||||
{
|
||||
{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");
|
||||
}
|
||||
|
||||
@@ -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<const char*> getRequiredExtensions();
|
||||
void initInstance(GraphicsInitializer initInfo);
|
||||
void setupDebugCallback();
|
||||
@@ -103,10 +96,9 @@ class Graphics : public Gfx::Graphics {
|
||||
Array<OCommandPool> pools;
|
||||
VkPhysicalDeviceProperties props;
|
||||
VkPhysicalDeviceFeatures2 features;
|
||||
VkPhysicalDeviceVulkan11Features features11;
|
||||
VkPhysicalDeviceVulkan12Features features12;
|
||||
VkPhysicalDeviceVulkan13Features features13;
|
||||
VkPhysicalDeviceRobustness2FeaturesEXT robustness;
|
||||
VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures;
|
||||
VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration;
|
||||
VkDebugUtilsMessengerEXT callback;
|
||||
Map<uint32, OFramebuffer> allocatedFramebuffers;
|
||||
VmaAllocator allocator;
|
||||
|
||||
@@ -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<Buffer>()->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<Buffer>()->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<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,
|
||||
.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<uint32_t>(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<uint32_t>(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<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() {}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include "Texture.h"
|
||||
#include "Command.h"
|
||||
#include "Enums.h"
|
||||
#include "Graphics/Enums.h"
|
||||
#include "Graphics/Initializer.h"
|
||||
#include <math.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
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<uint8>& buffer) {
|
||||
void TextureHandle::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& 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<uint8>& 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);
|
||||
}
|
||||
|
||||
@@ -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 <vulkan/vulkan_core.h>
|
||||
|
||||
|
||||
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<uint8>& 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<uint8>& 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<uint8>& 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<uint8>& 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<uint8>& buffer) override;
|
||||
|
||||
Reference in New Issue
Block a user