From 2f9ad73f789d4f83e459db1cfa2be0c330bc82c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Feb 2020 15:07:35 +0900 Subject: [PATCH] Implement buffer memory up to barriers Still lots to go (views, destruction, transfer...) and I'm uncertain about the location of the pipeline barrier function. --- include/QF/Vulkan/buffer.h | 47 ++++++++ include/QF/Vulkan/command.h | 10 ++ include/QF/Vulkan/funclist.h | 6 + libs/video/renderer/vulkan/Makefile.am | 1 + libs/video/renderer/vulkan/buffer.c | 161 +++++++++++++++++++++++++ libs/video/renderer/vulkan/command.c | 30 +++++ 6 files changed, 255 insertions(+) create mode 100644 include/QF/Vulkan/buffer.h create mode 100644 libs/video/renderer/vulkan/buffer.c diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h new file mode 100644 index 000000000..dfd8c2313 --- /dev/null +++ b/include/QF/Vulkan/buffer.h @@ -0,0 +1,47 @@ +#ifndef __QF_Vulkan_buffer_h +#define __QF_Vulkan_buffer_h + +typedef struct qfv_buffer_s { + struct qfv_device_s *device; + VkBuffer buffer; +} qfv_buffer_t; + +typedef struct qfv_memory_s { + struct qfv_device_s *device; + VkDeviceMemory object; +} qfv_memory_t; + +typedef struct qfv_buffertransition_s { + qfv_buffer_t *buffer; + VkAccessFlags srcAccess; + VkAccessFlags dstAccess; + uint32_t srcQueueFamily; + uint32_t dstQueueFamily; + VkDeviceSize offset; + VkDeviceSize size; +} qfv_buffertransition_t; + +typedef struct qfv_bufferbarrierset_s { + struct qfv_device_s *device; + uint32_t numBarriers; + VkBufferMemoryBarrier *barriers; +} qfv_bufferbarrierset_t; + +struct qfv_device_s; +qfv_buffer_t *QFV_CreateBuffer (struct qfv_device_s *device, + VkDeviceSize size, + VkBufferUsageFlags usage); + +qfv_memory_t *QFV_AllocMemory (qfv_buffer_t *buffer, + VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset); + +int QFV_BindBufferMemory (qfv_buffer_t *buffer, qfv_memory_t *memory, + VkDeviceSize offset); + +qfv_bufferbarrierset_t * +QFV_CreateBufferTransitionSet (qfv_buffertransition_t **transitions, + int numTransitions); + + +#endif//__QF_Vulkan_buffer_h diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 94165ce13..a19ff7bd3 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -79,5 +79,15 @@ int QFV_QueueSubmit (struct qfv_queue_s *queue, qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence); int QFV_QueueWaitIdle (struct qfv_queue_s *queue); +struct qfv_memorybarrierset_s *memBarriers; +struct qfv_bufferbarrierset_s *buffBarriers; +struct qfv_imagebarrierset_s *imgBarriers; +void QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + struct qfv_memorybarrierset_s *memBarriers, + struct qfv_bufferbarrierset_s *buffBarriers, + struct qfv_imagebarrierset_s *imgBarriers); #endif//__QF_Vulkan_command_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 5d649d5c2..5337bd472 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -107,6 +107,12 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFence) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeCommandBuffers) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyCommandPool) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkGetBufferMemoryRequirements) +DEVICE_LEVEL_VULKAN_FUNCTION (vkAllocateMemory) +DEVICE_LEVEL_VULKAN_FUNCTION (vkBindBufferMemory) + +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index f754853f2..cfe2acb0d 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -4,6 +4,7 @@ AM_CFLAGS= @PREFER_PIC@ AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES vulkan_src = \ + buffer.c \ command.c \ device.c \ instance.c \ diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c new file mode 100644 index 000000000..6a69b201d --- /dev/null +++ b/libs/video/renderer/vulkan/buffer.c @@ -0,0 +1,161 @@ +/* + buffer.c + + Vulkan buffer functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2020 Bill Currie + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +qfv_buffer_t * +QFV_CreateBuffer (qfv_device_t *device, VkDeviceSize size, + VkBufferUsageFlags usage) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + VkBufferCreateInfo createInfo = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 0, + 0, + size, usage, VK_SHARING_MODE_EXCLUSIVE, + 0, 0 + }; + qfv_buffer_t *buffer = malloc (sizeof (*buffer)); + dfunc->vkCreateBuffer (dev, &createInfo, 0, &buffer->buffer); + buffer->device = device; + return buffer; +} + +qfv_memory_t * +QFV_AllocMemory (qfv_buffer_t *buffer, VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset) +{ + qfv_device_t *device = buffer->device; + VkDevice dev = device->dev; + qfv_physdev_t *physdev = device->physDev; + VkPhysicalDeviceMemoryProperties *memprops = &physdev->memory_properties; + qfv_devfuncs_t *dfunc = device->funcs; + + VkMemoryRequirements requirements; + dfunc->vkGetBufferMemoryRequirements (dev, buffer->buffer, &requirements); + + size = max (size, offset + requirements.size); + VkDeviceMemory object = 0; + + for (uint32_t type = 0; type < memprops->memoryTypeCount; type++) { + if ((requirements.memoryTypeBits & (1 << type)) + && ((memprops->memoryTypes[type].propertyFlags & properties) + == properties)) { + VkMemoryAllocateInfo allocate_info = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 0, + size, type + }; + + VkResult res = dfunc->vkAllocateMemory (dev, &allocate_info, + 0, &object); + if (res == VK_SUCCESS) { + break; + } + } + } + + qfv_memory_t *memory = 0; + + if (object) { + memory = malloc (sizeof (*memory)); + memory->device = device; + memory->object = object; + } + return memory; +} + +int +QFV_BindBufferMemory (qfv_buffer_t *buffer, qfv_memory_t *memory, + VkDeviceSize offset) +{ + qfv_device_t *device = buffer->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + VkResult res = dfunc->vkBindBufferMemory (dev, buffer->buffer, + memory->object, offset); + return res == VK_SUCCESS; +} + +qfv_bufferbarrierset_t * +QFV_CreateBufferTransitionSet (qfv_buffertransition_t **transitions, + int numTransitions) +{ + qfv_device_t *device = transitions[0]->buffer->device; + qfv_bufferbarrierset_t *barrierset = malloc (sizeof (*barrierset) + + sizeof (VkBufferMemoryBarrier) * numTransitions); + + barrierset->device = device; + barrierset->numBarriers = numTransitions; + barrierset->barriers = (VkBufferMemoryBarrier *) (barrierset + 1); + + for (int i = 0; i < numTransitions; i++) { + VkBufferMemoryBarrier *barrier = &barrierset->barriers[i]; + barrier->sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier->pNext = 0; + barrier->srcAccessMask = transitions[i]->srcAccess; + barrier->dstAccessMask = transitions[i]->dstAccess; + barrier->srcQueueFamilyIndex = transitions[i]->srcQueueFamily; + barrier->dstQueueFamilyIndex = transitions[i]->dstQueueFamily; + barrier->buffer = transitions[i]->buffer->buffer; + barrier->offset = transitions[i]->offset; + barrier->size = transitions[i]->size; + } + return barrierset; +} diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index d3f3d4082..f30b1dfeb 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -49,6 +49,7 @@ #include "QF/va.h" #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/buffer.h"//FIXME should QFV_CmdPipelineBarrier be here? #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" @@ -387,3 +388,32 @@ QFV_QueueWaitIdle (qfv_queue_t *queue) qfv_devfuncs_t *dfunc = device->funcs; return dfunc->vkQueueWaitIdle (queue->queue) == VK_SUCCESS; } + +void +QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + struct qfv_memorybarrierset_s *memBarrierSet, + qfv_bufferbarrierset_t *buffBarrierSet, + struct qfv_imagebarrierset_s *imgBarrierSet) +{ + qfv_device_t *device = cmdBuffer->device; + qfv_devfuncs_t *dfunc = device->funcs; + uint32_t numMemBarriers = 0; + VkMemoryBarrier *memBarriers = 0; + uint32_t numBuffBarriers = 0; + VkBufferMemoryBarrier *buffBarriers = 0; + uint32_t numImgBarriers = 0; + VkImageMemoryBarrier *imgBarriers = 0; + + if (buffBarrierSet) { + numBuffBarriers = buffBarrierSet->numBarriers; + buffBarriers = buffBarrierSet->barriers; + } + dfunc->vkCmdPipelineBarrier (cmdBuffer->buffer, + srcStageMask, dstStageMask, dependencyFlags, + numMemBarriers, memBarriers, + numBuffBarriers, buffBarriers, + numImgBarriers, imgBarriers); +}