|
|
@@ -3,51 +3,130 @@
|
|
|
#include "BsVulkanHardwareBuffer.h"
|
|
|
#include "BsVulkanRenderAPI.h"
|
|
|
#include "BsVulkanDevice.h"
|
|
|
+#include "BsVulkanUtility.h"
|
|
|
#include "BsException.h"
|
|
|
|
|
|
namespace BansheeEngine
|
|
|
{
|
|
|
- VulkanHardwareBuffer::VulkanHardwareBuffer(GpuBufferUsage usage, const VkMemoryRequirements& reqs, bool useSystemMem,
|
|
|
- GpuDeviceFlags deviceMask)
|
|
|
- : HardwareBuffer(usage, useSystemMem), mAllocations{}
|
|
|
+ VulkanBuffer::VulkanBuffer(VulkanResourceManager* owner, VkBuffer buffer, VkBufferView view, VkDeviceMemory memory)
|
|
|
+ :VulkanResource(owner, false, VulkanResourceType::Buffer), mBuffer(buffer), mView(view), mMemory(memory)
|
|
|
{
|
|
|
- VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPICore::instance());
|
|
|
|
|
|
- UINT32 deviceIdx = 0;
|
|
|
- if(deviceMask == GDF_DEFAULT)
|
|
|
- {
|
|
|
- const Vector<SPtr<VulkanDevice>>& devices = rapi._getPrimaryDevices();
|
|
|
- for (auto& device : devices)
|
|
|
- mAllocations[deviceIdx++].device = device;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- for(UINT32 i = 0; i < BS_MAX_DEVICES; i++)
|
|
|
- {
|
|
|
- if ((1 << i) & deviceMask)
|
|
|
- mAllocations[deviceIdx++].device = rapi._getDevice(i);
|
|
|
- }
|
|
|
- }
|
|
|
+ }
|
|
|
+
|
|
|
+ VulkanBuffer::~VulkanBuffer()
|
|
|
+ {
|
|
|
+ VulkanDevice& device = mOwner->getDevice();
|
|
|
|
|
|
- VkMemoryPropertyFlags flags = useSystemMem ?
|
|
|
+ if (mView != VK_NULL_HANDLE)
|
|
|
+ vkDestroyBufferView(device.getLogical(), mView, gVulkanAllocator);
|
|
|
+
|
|
|
+ vkDestroyBuffer(device.getLogical(), mBuffer, gVulkanAllocator);
|
|
|
+ device.freeMemory(mMemory);
|
|
|
+ }
|
|
|
+
|
|
|
+ VulkanHardwareBuffer::VulkanHardwareBuffer(BufferType type, GpuBufferFormat format, GpuBufferUsage usage,
|
|
|
+ UINT32 size, GpuDeviceFlags deviceMask)
|
|
|
+ : HardwareBuffer(usage), mBuffers()
|
|
|
+ {
|
|
|
+ bool staging = type == BT_STAGING;
|
|
|
+ bool needsView = false;
|
|
|
+
|
|
|
+ VkMemoryPropertyFlags flags = staging ?
|
|
|
(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) : // Note: Try using cached uncoherent memory
|
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
|
|
|
|
|
+ VkBufferUsageFlags usageFlags = 0;
|
|
|
+ switch(type)
|
|
|
+ {
|
|
|
+ case BT_VERTEX:
|
|
|
+ usageFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
|
|
+ break;
|
|
|
+ case BT_INDEX:
|
|
|
+ usageFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
|
|
+ break;
|
|
|
+ case BT_UNIFORM:
|
|
|
+ usageFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
|
|
+ break;
|
|
|
+ case BT_GENERIC:
|
|
|
+ usageFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
|
|
|
+ needsView = true;
|
|
|
+ break;
|
|
|
+ case BT_STORAGE:
|
|
|
+ usageFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
|
|
|
+ needsView = true;
|
|
|
+ break;
|
|
|
+ case BT_STAGING:
|
|
|
+ usageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPICore::instance());
|
|
|
+ VulkanDevice* devices[BS_MAX_DEVICES];
|
|
|
+ VulkanUtility::getDevices(rapi, deviceMask, devices);
|
|
|
+
|
|
|
+ // Allocate buffers per-device
|
|
|
for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
|
|
|
{
|
|
|
- if (mAllocations[i].device == nullptr)
|
|
|
+ if (devices[i] == nullptr)
|
|
|
break;
|
|
|
|
|
|
- mAllocations[i].memory = mAllocations[i].device->allocateMemory(reqs, flags);
|
|
|
+ VkBufferCreateInfo bufferCI;
|
|
|
+ bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
|
+ bufferCI.pNext = nullptr;
|
|
|
+ bufferCI.flags = 0;
|
|
|
+ bufferCI.size = size;
|
|
|
+ bufferCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
+ bufferCI.usage = usageFlags;
|
|
|
+ bufferCI.queueFamilyIndexCount = 0;
|
|
|
+ bufferCI.pQueueFamilyIndices = nullptr;
|
|
|
+
|
|
|
+ VkDevice device = devices[i]->getLogical();
|
|
|
+
|
|
|
+ VkBuffer buffer;
|
|
|
+ VkResult result = vkCreateBuffer(device, &bufferCI, gVulkanAllocator, &buffer);
|
|
|
+ assert(result == VK_SUCCESS);
|
|
|
+
|
|
|
+ VkMemoryRequirements memReqs;
|
|
|
+ vkGetBufferMemoryRequirements(device, buffer, &memReqs);
|
|
|
+
|
|
|
+ VkDeviceMemory memory = devices[i]->allocateMemory(memReqs, flags);
|
|
|
+ result = vkBindBufferMemory(device, buffer, memory, 0);
|
|
|
+ assert(result == VK_SUCCESS);
|
|
|
+
|
|
|
+ VkBufferView view;
|
|
|
+ if (needsView)
|
|
|
+ {
|
|
|
+ VkBufferViewCreateInfo bufferViewCI;
|
|
|
+ bufferViewCI.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
|
|
|
+ bufferViewCI.pNext = nullptr;
|
|
|
+ bufferViewCI.flags = 0;
|
|
|
+ bufferViewCI.buffer = buffer;
|
|
|
+ bufferViewCI.format = VulkanUtility::getBufferFormat(format);
|
|
|
+ bufferViewCI.offset = 0;
|
|
|
+ bufferViewCI.range = VK_WHOLE_SIZE;
|
|
|
+
|
|
|
+ result = vkCreateBufferView(device, &bufferViewCI, gVulkanAllocator, &view);
|
|
|
+ assert(result == VK_SUCCESS);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ view = VK_NULL_HANDLE;
|
|
|
+
|
|
|
+ mBuffers[i] = devices[i]->getResourceManager().create<VulkanBuffer>(buffer, view, memory);
|
|
|
}
|
|
|
|
|
|
- mSizeInBytes = (UINT32)reqs.size;
|
|
|
+ mSizeInBytes = size;
|
|
|
}
|
|
|
|
|
|
VulkanHardwareBuffer::~VulkanHardwareBuffer()
|
|
|
{
|
|
|
- for(auto& alloc : mAllocations)
|
|
|
- alloc.device->freeMemory(alloc.memory);
|
|
|
+ for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
|
|
|
+ {
|
|
|
+ if (mBuffers[i] == nullptr)
|
|
|
+ return;
|
|
|
+
|
|
|
+ mBuffers[i]->destroy();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void* VulkanHardwareBuffer::map(UINT32 offset, UINT32 length, GpuLockOptions options, UINT32 syncMask)
|