Files
Seele/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp
T

387 lines
12 KiB
C++
Raw Normal View History

#include "VulkanGraphicsResources.h"
2020-03-24 21:05:32 +01:00
#include "VulkanInitializer.h"
2020-04-12 15:47:19 +02:00
#include "VulkanGraphics.h"
#include "VulkanCommandBuffer.h"
#include "VulkanAllocator.h"
2020-03-24 21:05:32 +01:00
using namespace Seele;
using namespace Seele::Vulkan;
2020-04-12 15:47:19 +02:00
struct PendingBuffer
{
2020-04-12 15:47:19 +02:00
PStagingBuffer stagingBuffer;
Gfx::QueueType prevQueue;
bool bWriteOnly;
};
2020-09-19 14:36:50 +02:00
static Map<ShaderBuffer *, PendingBuffer> pendingBuffers;
2020-09-19 14:36:50 +02:00
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType)
2020-06-02 11:46:18 +02:00
: graphics(graphics), currentBuffer(0), size(size), currentOwner(queueType)
{
if (usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT ||
2020-04-12 15:47:19 +02:00
usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ||
usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)
{
numBuffers = 1;
}
else
{
numBuffers = Gfx::numFramesBuffered;
}
usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
VkBufferCreateInfo info =
init::BufferCreateInfo(
usage,
size);
2020-10-23 01:47:56 +02:00
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
uint32 queueFamilyIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(queueType);
info.pQueueFamilyIndices = &queueFamilyIndex;
info.queueFamilyIndexCount = 0;
2020-04-12 15:47:19 +02:00
VkBufferMemoryRequirementsInfo2 bufferReqInfo;
bufferReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
bufferReqInfo.pNext = nullptr;
VkMemoryDedicatedRequirements dedicatedRequirements;
dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
dedicatedRequirements.pNext = nullptr;
VkMemoryRequirements2 memRequirements;
memRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
memRequirements.pNext = &dedicatedRequirements;
for (uint32 i = 0; i < numBuffers; ++i)
{
vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer);
bufferReqInfo.buffer = buffers[i].buffer;
vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferReqInfo, &memRequirements);
buffers[i].allocation = graphics->getAllocator()->allocate(memRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buffers[i].buffer);
2020-04-12 15:47:19 +02:00
vkBindBufferMemory(graphics->getDevice(), buffers[i].buffer, buffers[i].allocation->getHandle(), buffers[i].allocation->getOffset());
}
}
2020-09-19 14:36:50 +02:00
ShaderBuffer::~ShaderBuffer()
{
2020-09-19 14:36:50 +02:00
auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
2020-05-05 01:51:13 +02:00
auto &deletionQueue = graphics->getDeletionQueue();
VkDevice device = graphics->getDevice();
VkBuffer buf[Gfx::numFramesBuffered];
2020-04-12 15:47:19 +02:00
for (uint32 i = 0; i < numBuffers; ++i)
{
2020-05-05 01:51:13 +02:00
buf[i] = buffers[i].buffer;
2020-09-19 14:36:50 +02:00
deletionQueue.addPendingDelete(cmdBuffer, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); });
2020-04-12 15:47:19 +02:00
buffers[i].allocation = nullptr;
}
2020-09-19 14:36:50 +02:00
graphics = nullptr;
}
2020-10-03 11:00:10 +02:00
VkDeviceSize ShaderBuffer::getOffset() const
{
return buffers[currentBuffer].allocation->getOffset();
}
2020-09-19 14:36:50 +02:00
void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
2020-04-12 15:47:19 +02:00
{
VkBufferMemoryBarrier barrier =
init::BufferMemoryBarrier();
2020-06-02 11:46:18 +02:00
PCommandBufferManager sourceManager = graphics->getQueueCommands(currentOwner);
2020-04-12 15:47:19 +02:00
PCommandBufferManager dstManager = nullptr;
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
2020-06-02 11:46:18 +02:00
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
2020-04-12 15:47:19 +02:00
barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner);
barrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner);
assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex);
if (currentOwner == Gfx::QueueType::TRANSFER || currentOwner == Gfx::QueueType::DEDICATED_TRANSFER)
{
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (currentOwner == Gfx::QueueType::COMPUTE)
{
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
}
else if (currentOwner == 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;
dstManager = graphics->getTransferCommands();
}
else if (newOwner == Gfx::QueueType::DEDICATED_TRANSFER)
{
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstManager = graphics->getDedicatedTransferCommands();
}
else if (newOwner == Gfx::QueueType::COMPUTE)
{
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
dstManager = graphics->getComputeCommands();
}
else if (newOwner == Gfx::QueueType::GRAPHICS)
{
barrier.dstAccessMask = getDestAccessMask();
dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
dstManager = graphics->getGraphicsCommands();
}
VkCommandBuffer srcCommand = sourceManager->getCommands()->getHandle();
VkCommandBuffer dstCommand = dstManager->getCommands()->getHandle();
VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered];
for (uint32_t i = 0; i < numBuffers; ++i)
{
dynamicBarriers[i] = barrier;
dynamicBarriers[i].buffer = buffers[i].buffer;
dynamicBarriers[i].offset = 0;
2020-06-08 01:44:47 +02:00
dynamicBarriers[i].size = size;
2020-04-12 15:47:19 +02:00
}
vkCmdPipelineBarrier(srcCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
vkCmdPipelineBarrier(dstCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
sourceManager->submitCommands();
2020-06-02 11:46:18 +02:00
currentOwner = newOwner;
2020-04-12 15:47:19 +02:00
}
2020-09-19 14:36:50 +02:00
void *ShaderBuffer::lock(bool bWriteOnly)
2020-04-12 15:47:19 +02:00
{
void *data = nullptr;
/*if (bVolatile)
{
if (lockMode == RLM_ReadOnly)
{
assert(0);
}
else
{
throw new std::logic_error("TODO implement volatile buffers");
//device->getRHIDevice()->getTemp
}
}*/
//assert(bStatic || bDynamic || bUAV);
PendingBuffer pending;
pending.bWriteOnly = bWriteOnly;
pending.prevQueue = currentOwner;
if (bWriteOnly)
{
//requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
2020-04-12 15:47:19 +02:00
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
data = stagingBuffer->getMappedPointer();
pending.stagingBuffer = stagingBuffer;
}
else
{
2020-06-02 11:46:18 +02:00
PCmdBuffer current = graphics->getQueueCommands(currentOwner)->getCommands();
graphics->getQueueCommands(currentOwner)->submitCommands();
graphics->getQueueCommands(currentOwner)->waitForCommands(current);
2020-04-12 15:47:19 +02:00
2020-06-02 11:46:18 +02:00
requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
VkCommandBuffer handle = graphics->getQueueCommands(currentOwner)->getCommands()->getHandle();
2020-04-12 15:47:19 +02:00
VkBufferMemoryBarrier barrier =
init::BufferMemoryBarrier();
barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
barrier.buffer = buffers[currentBuffer].buffer;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.offset = 0;
barrier.size = size;
vkCmdPipelineBarrier(handle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true);
VkBufferCopy regions;
regions.size = size;
regions.srcOffset = 0;
regions.dstOffset = 0;
vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, &regions);
2020-06-02 11:46:18 +02:00
graphics->getQueueCommands(currentOwner)->submitCommands();
vkQueueWaitIdle(graphics->getQueueCommands(currentOwner)->getQueue()->getHandle());
2020-04-12 15:47:19 +02:00
stagingBuffer->flushMappedMemory();
pending.stagingBuffer = stagingBuffer;
data = stagingBuffer->getMappedPointer();
}
pendingBuffers[this] = pending;
assert(data);
return data;
}
2020-09-19 14:36:50 +02:00
void ShaderBuffer::unlock()
2020-04-12 15:47:19 +02:00
{
auto found = pendingBuffers.find(this);
if (found != pendingBuffers.end())
{
PendingBuffer pending = found->value;
pending.stagingBuffer->flushMappedMemory();
pendingBuffers.erase(this);
if (pending.bWriteOnly)
{
PStagingBuffer stagingBuffer = pending.stagingBuffer;
2020-06-02 11:46:18 +02:00
PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
2020-04-12 15:47:19 +02:00
VkCommandBuffer cmdHandle = cmdBuffer->getHandle();
VkBufferCopy region;
std::memset(&region, 0, sizeof(VkBufferCopy));
region.size = size;
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
2020-10-31 00:04:23 +01:00
graphics->getQueueCommands(currentOwner)->submitCommands();
2020-04-12 15:47:19 +02:00
}
//requestOwnershipTransfer(pending.prevQueue);
2020-05-05 01:51:13 +02:00
graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer);
2020-04-12 15:47:19 +02:00
}
}
UniformBuffer::UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData)
2020-09-19 14:36:50 +02:00
: Vulkan::ShaderBuffer(graphics, resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, resourceData.owner)
2020-10-03 11:00:10 +02:00
, Gfx::UniformBuffer(graphics->getFamilyMapping(), resourceData)
2020-04-12 15:47:19 +02:00
{
if (resourceData.data != nullptr)
{
void *data = lock();
std::memcpy(data, resourceData.data, resourceData.size);
unlock();
}
}
UniformBuffer::~UniformBuffer()
{
}
2020-04-12 15:47:19 +02:00
2020-06-02 11:46:18 +02:00
void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{
Gfx::QueueOwnedResource::transferOwnership(newOwner);
2020-09-19 14:36:50 +02:00
Vulkan::ShaderBuffer::currentOwner = newOwner;
2020-06-02 11:46:18 +02:00
}
void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{
2020-09-19 14:36:50 +02:00
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
2020-06-02 11:46:18 +02:00
}
2020-04-12 15:47:19 +02:00
VkAccessFlags UniformBuffer::getSourceAccessMask()
{
return VK_ACCESS_MEMORY_WRITE_BIT;
}
VkAccessFlags UniformBuffer::getDestAccessMask()
{
return VK_ACCESS_UNIFORM_READ_BIT;
}
StructuredBuffer::StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData)
2020-09-19 14:36:50 +02:00
: Vulkan::ShaderBuffer(graphics, resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, resourceData.owner)
, Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.owner)
2020-04-12 15:47:19 +02:00
{
if (resourceData.data != nullptr)
{
void *data = lock();
std::memcpy(data, resourceData.data, resourceData.size);
unlock();
}
}
StructuredBuffer::~StructuredBuffer()
{
}
2020-06-02 11:46:18 +02:00
void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{
Gfx::QueueOwnedResource::transferOwnership(newOwner);
}
void StructuredBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{
2020-09-19 14:36:50 +02:00
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
2020-06-02 11:46:18 +02:00
}
2020-04-12 15:47:19 +02:00
VkAccessFlags StructuredBuffer::getSourceAccessMask()
{
return VK_ACCESS_MEMORY_WRITE_BIT;
}
VkAccessFlags StructuredBuffer::getDestAccessMask()
{
return VK_ACCESS_MEMORY_READ_BIT;
}
2020-05-05 01:51:13 +02:00
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData)
2020-09-19 14:36:50 +02:00
: Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner)
, Gfx::VertexBuffer(graphics->getFamilyMapping(), resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner)
2020-04-12 15:47:19 +02:00
{
2020-05-05 01:51:13 +02:00
if (resourceData.resourceData.data != nullptr)
2020-04-12 15:47:19 +02:00
{
void *data = lock();
2020-05-05 01:51:13 +02:00
std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size);
2020-04-12 15:47:19 +02:00
unlock();
}
}
VertexBuffer::~VertexBuffer()
{
}
2020-06-02 11:46:18 +02:00
void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{
Gfx::QueueOwnedResource::transferOwnership(newOwner);
}
void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{
2020-09-19 14:36:50 +02:00
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
2020-06-02 11:46:18 +02:00
}
2020-04-12 15:47:19 +02:00
VkAccessFlags VertexBuffer::getSourceAccessMask()
{
return VK_ACCESS_MEMORY_WRITE_BIT;
}
VkAccessFlags VertexBuffer::getDestAccessMask()
{
return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
}
2020-05-05 01:51:13 +02:00
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData)
2020-09-19 14:36:50 +02:00
: Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner)
, Gfx::IndexBuffer(graphics->getFamilyMapping(), resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner)
2020-04-12 15:47:19 +02:00
{
2020-05-05 01:51:13 +02:00
if (resourceData.resourceData.data != nullptr)
2020-04-12 15:47:19 +02:00
{
void *data = lock();
2020-05-05 01:51:13 +02:00
std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size);
2020-04-12 15:47:19 +02:00
unlock();
}
}
IndexBuffer::~IndexBuffer()
{
}
2020-06-02 11:46:18 +02:00
void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{
Gfx::QueueOwnedResource::transferOwnership(newOwner);
}
void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{
2020-09-19 14:36:50 +02:00
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
2020-06-02 11:46:18 +02:00
}
2020-04-12 15:47:19 +02:00
VkAccessFlags IndexBuffer::getSourceAccessMask()
{
return VK_ACCESS_MEMORY_WRITE_BIT;
}
VkAccessFlags IndexBuffer::getDestAccessMask()
{
return VK_ACCESS_INDEX_READ_BIT;
}