From ac3db521bae354e15ab7ffd24e5c968eea5336fb Mon Sep 17 00:00:00 2001 From: Squareys Date: Fri, 26 Aug 2016 10:49:55 +0200 Subject: [PATCH] Vk: Add NoCreate constructors, remove .vk*() methods, avoid some vectors Signed-off-by: Squareys --- src/Magnum/Vk/Buffer.cpp | 42 ++++++++++++++++++++++++++++++++- src/Magnum/Vk/Buffer.h | 40 ++++++++++++++++++++++++++----- src/Magnum/Vk/Command.h | 10 ++++---- src/Magnum/Vk/CommandBuffer.cpp | 4 +++- src/Magnum/Vk/CommandBuffer.h | 16 ++++++++++--- src/Magnum/Vk/Device.cpp | 5 ++-- src/Magnum/Vk/Device.h | 3 ++- src/Magnum/Vk/DeviceMemory.cpp | 4 ++++ src/Magnum/Vk/DeviceMemory.h | 6 ++--- src/Magnum/Vk/PhysicalDevice.h | 6 +++++ src/Magnum/Vk/Queue.cpp | 18 +++++++------- src/Magnum/Vk/Queue.h | 15 +++++++++++- src/Magnum/Vk/Semaphore.h | 5 ++-- src/Magnum/Vk/Shader.cpp | 4 +++- src/Magnum/Vk/Shader.h | 17 +++++++++---- src/Magnum/Vk/Swapchain.cpp | 2 +- src/Magnum/Vk/Swapchain.h | 2 +- 17 files changed, 158 insertions(+), 41 deletions(-) diff --git a/src/Magnum/Vk/Buffer.cpp b/src/Magnum/Vk/Buffer.cpp index 2c32a65a0..4aed61f9e 100644 --- a/src/Magnum/Vk/Buffer.cpp +++ b/src/Magnum/Vk/Buffer.cpp @@ -24,13 +24,53 @@ DEALINGS IN THE SOFTWARE. */ +#include + #include "Buffer.h" +#include "Magnum/Vk/Command.h" +#include "Magnum/Vk/CommandPool.h" +#include "Magnum/Vk/Queue.h" + namespace Magnum { namespace Vk { Buffer::~Buffer() { - vkDestroyBuffer(_device, _buffer, nullptr); + if(_device != nullptr) { + vkDestroyBuffer(*_device, _buffer, nullptr); + } +} + +Buffer& Buffer::update(Queue& queue, CommandPool& pool, const void* sourceData, UnsignedLong size, UnsignedLong destOffset) { + // TODO: Do not use staging if the memory bound to this buffer is host visible. + + /* command buffer needs to be destroyed before memory */ + std::unique_ptr copyToDeviceCmds = pool.allocateCommandBuffer(Vk::CommandBuffer::Level::Primary); + + /* plane vertices */ + Buffer stagingBuffer{*_device, size, Vk::BufferUsage::TransferSrc}; + std::unique_ptr stagingMemory = stagingBuffer.allocateDeviceMemory(Vk::MemoryProperty::HostVisible); + + Containers::ArrayView data = stagingMemory->map(destOffset, size); + std::memcpy(data, sourceData, stagingBuffer.size()); + stagingMemory->unmap(); + + *copyToDeviceCmds << Vk::Cmd::begin() + << stagingBuffer.cmdFullCopyTo(*this) + << Vk::Cmd::end(); + queue.submit(*copyToDeviceCmds).waitIdle(); + + return *this; +} + +std::unique_ptr Buffer::allocateDeviceMemory(Vk::MemoryProperty memProperty) { + VkMemoryRequirements memReqs = getMemoryRequirements(); + UnsignedInt memoryTypeIndex = _device->physicalDevice().getMemoryType(memReqs.memoryTypeBits, memProperty); + + std::unique_ptr memory(new Vk::DeviceMemory{*_device, memReqs.size, memoryTypeIndex}); + bindBufferMemory(*memory); + + return memory; } }} diff --git a/src/Magnum/Vk/Buffer.h b/src/Magnum/Vk/Buffer.h index 9b9dbf285..e7478138e 100644 --- a/src/Magnum/Vk/Buffer.h +++ b/src/Magnum/Vk/Buffer.h @@ -62,7 +62,7 @@ class MAGNUM_VK_EXPORT Buffer { public: Buffer(Device& device, UnsignedInt size, BufferUsageFlags usage): - _device{device}, + _device{&device}, _size{size} { VkBufferCreateInfo bufferInfo = {}; @@ -71,10 +71,13 @@ class MAGNUM_VK_EXPORT Buffer { bufferInfo.size = size; bufferInfo.usage = VkBufferUsageFlags(usage); - VkResult err = vkCreateBuffer(_device, &bufferInfo, nullptr, &_buffer); + VkResult err = vkCreateBuffer(*_device, &bufferInfo, nullptr, &_buffer); MAGNUM_VK_ASSERT_ERROR(err); } + Buffer(NoCreateT): _device{nullptr} { + } + /** @brief Copying is not allowed */ Buffer(const Buffer&) = delete; @@ -92,7 +95,13 @@ class MAGNUM_VK_EXPORT Buffer { Buffer& operator=(const Buffer&) = delete; /** @brief Move assignment is not allowed */ - Buffer& operator=(Buffer&&) = delete; + Buffer& operator=(Buffer&& other) { + std::swap(_device, other._device); + std::swap(_buffer, other._buffer); + std::swap(_size, other._size); + + return *this; + } operator VkBuffer() const { return _buffer; @@ -100,7 +109,7 @@ class MAGNUM_VK_EXPORT Buffer { VkMemoryRequirements getMemoryRequirements() const { VkMemoryRequirements memReqs; - vkGetBufferMemoryRequirements(_device, _buffer, &memReqs); + vkGetBufferMemoryRequirements(*_device, _buffer, &memReqs); return memReqs; } @@ -110,7 +119,7 @@ class MAGNUM_VK_EXPORT Buffer { } Buffer& bindBufferMemory(const DeviceMemory& deviceMemory, UnsignedLong offset=0) { - VkResult err = vkBindBufferMemory(_device, _buffer, deviceMemory, offset); + VkResult err = vkBindBufferMemory(*_device, _buffer, deviceMemory, offset); MAGNUM_VK_ASSERT_ERROR(err); return *this; @@ -141,8 +150,27 @@ class MAGNUM_VK_EXPORT Buffer { return descriptor; } + /** + * @brief Update contents of device memory. + * @return Reference to self (for method chaining) + * + * Will involve mapping and unmapping memory and possibly creating intermediate + * staging buffers if the memory is not visible by the host. + * + * At the end of the method, the queue will be waited for so that temporary buffers + * can be cleaned up. + */ + Buffer& update(Queue& queue, CommandPool& pool, const void* sourceData, UnsignedLong size, UnsignedLong destOffset=0); + + /** + * @brief Allocate memory matching requirements of this buffer and bind it + * @param memProperty property for the allocated memory + * @return the allocated and bound memory + */ + std::unique_ptr allocateDeviceMemory(Vk::MemoryProperty memProperty); + private: - Device& _device; + Device* _device; VkBuffer _buffer; UnsignedInt _size; }; diff --git a/src/Magnum/Vk/Command.h b/src/Magnum/Vk/Command.h index c953fc071..25988f9fd 100644 --- a/src/Magnum/Vk/Command.h +++ b/src/Magnum/Vk/Command.h @@ -53,19 +53,19 @@ CommandBuffer& operator << (CommandBuffer& cmdBuffer, const Lambda& lambda) { namespace Cmd { -auto begin() { +inline auto begin() { return [](CommandBuffer& cmdBuffer){ cmdBuffer.begin(); }; } -auto end() { +inline auto end() { return [](CommandBuffer& cmdBuffer){ cmdBuffer.end(); }; } -auto setScissor(UnsignedInt firstScissor, const std::initializer_list& ranges) { +inline auto setScissor(UnsignedInt firstScissor, const std::initializer_list& ranges) { return [firstScissor, &ranges](VkCommandBuffer cmdBuffer){ Corrade::Containers::Array vkRects(ranges.size()); @@ -78,13 +78,13 @@ auto setScissor(UnsignedInt firstScissor, const std::initializer_list& }; } -auto setViewport(UnsignedInt firstViewport, const std::vector& viewports) { +inline auto setViewport(UnsignedInt firstViewport, const std::vector& viewports) { return [firstViewport, &viewports](VkCommandBuffer cmdBuffer){ vkCmdSetViewport(cmdBuffer, firstViewport, viewports.size(), viewports.data()); }; } -auto pipelineBarrier(PipelineStageFlags srcStageMask, +inline auto pipelineBarrier(PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, const std::vector& memoryBarriers, const std::vector& bufferMemoryBarriers, diff --git a/src/Magnum/Vk/CommandBuffer.cpp b/src/Magnum/Vk/CommandBuffer.cpp index 9b94fc88d..884e4e616 100644 --- a/src/Magnum/Vk/CommandBuffer.cpp +++ b/src/Magnum/Vk/CommandBuffer.cpp @@ -32,7 +32,9 @@ namespace Magnum { namespace Vk { CommandBuffer::~CommandBuffer() { - _pool.freeCommandBuffer(this); + if(_cmdBuffer != VK_NULL_HANDLE) { + _pool->freeCommandBuffer(this); + } } }} diff --git a/src/Magnum/Vk/CommandBuffer.h b/src/Magnum/Vk/CommandBuffer.h index 2c6a1a722..ba16b6a61 100644 --- a/src/Magnum/Vk/CommandBuffer.h +++ b/src/Magnum/Vk/CommandBuffer.h @@ -76,7 +76,13 @@ class MAGNUM_VK_EXPORT CommandBuffer { */ CommandBuffer(VkCommandBuffer buffer, CommandPool& commandPool): _cmdBuffer{buffer}, - _pool{commandPool} + _pool{&commandPool} + { + } + + CommandBuffer(NoCreateT): + _cmdBuffer{VK_NULL_HANDLE}, + _pool{nullptr} { } @@ -97,7 +103,11 @@ class MAGNUM_VK_EXPORT CommandBuffer { CommandBuffer& operator=(const CommandBuffer&) = delete; /** @brief Move assignment is not allowed */ - CommandBuffer& operator=(CommandBuffer&&) = delete; + CommandBuffer& operator=(CommandBuffer&& other) { + std::swap(_cmdBuffer, other._cmdBuffer); + std::swap(_pool, other._pool); + return *this; + } operator VkCommandBuffer() const { return _cmdBuffer; @@ -162,7 +172,7 @@ class MAGNUM_VK_EXPORT CommandBuffer { private: VkCommandBuffer _cmdBuffer; - CommandPool& _pool; + CommandPool* _pool; }; }} diff --git a/src/Magnum/Vk/Device.cpp b/src/Magnum/Vk/Device.cpp index 726d89b17..da1d70710 100644 --- a/src/Magnum/Vk/Device.cpp +++ b/src/Magnum/Vk/Device.cpp @@ -33,7 +33,8 @@ namespace Magnum { namespace Vk { Device::Device(PhysicalDevice& physicalDevice, const std::vector& requestedQueues, - const std::vector& extensions, const std::vector& validationLayers): + const std::vector& extensions, const std::vector& validationLayers, + const VkPhysicalDeviceFeatures& features): _physicalDevice(physicalDevice) { VkDeviceCreateInfo deviceCreateInfo = { @@ -43,7 +44,7 @@ Device::Device(PhysicalDevice& physicalDevice, const std::vector& requestedQueues, const std::vector& extensions, - const std::vector& validationLayers); + const std::vector& validationLayers, + const VkPhysicalDeviceFeatures& features); /** * @brief Destructor diff --git a/src/Magnum/Vk/DeviceMemory.cpp b/src/Magnum/Vk/DeviceMemory.cpp index 9fcc47dc3..8a4417411 100644 --- a/src/Magnum/Vk/DeviceMemory.cpp +++ b/src/Magnum/Vk/DeviceMemory.cpp @@ -26,6 +26,10 @@ #include "DeviceMemory.h" +#include "Magnum/Vk/Buffer.h" +#include "Magnum/Vk/CommandBuffer.h" +#include "Magnum/Vk/CommandPool.h" + namespace Magnum { namespace Vk { diff --git a/src/Magnum/Vk/DeviceMemory.h b/src/Magnum/Vk/DeviceMemory.h index b6ffd85ef..dc5654ccf 100644 --- a/src/Magnum/Vk/DeviceMemory.h +++ b/src/Magnum/Vk/DeviceMemory.h @@ -80,17 +80,17 @@ class MAGNUM_VK_EXPORT DeviceMemory { return _deviceMemory; } - Containers::Array map() { + Containers::ArrayView map() { return map(0, _memAlloc.allocationSize); } - Containers::Array map(UnsignedInt offset, UnsignedInt size) { + Containers::ArrayView map(UnsignedInt offset, UnsignedInt size) { // TODO: Memory map flags (== 0) void* data; VkResult err = vkMapMemory(_device, _deviceMemory, offset, size, 0, &data); MAGNUM_VK_ASSERT_ERROR(err); - return Containers::Array(static_cast(data), size); + return Containers::ArrayView(static_cast(data), size); } DeviceMemory& unmap() { diff --git a/src/Magnum/Vk/PhysicalDevice.h b/src/Magnum/Vk/PhysicalDevice.h index a1907a8eb..4132e1fe6 100644 --- a/src/Magnum/Vk/PhysicalDevice.h +++ b/src/Magnum/Vk/PhysicalDevice.h @@ -129,6 +129,12 @@ class MAGNUM_VK_EXPORT PhysicalDevice { */ UnsignedInt getMemoryType(UnsignedInt supportedTypeBits, MemoryProperties properties); + VkPhysicalDeviceFeatures getFeatures() const { + VkPhysicalDeviceFeatures features; + vkGetPhysicalDeviceFeatures(_physicalDevice, &features); + return features; + } + private: VkPhysicalDevice _physicalDevice; VkPhysicalDeviceMemoryProperties _deviceMemoryProperties; diff --git a/src/Magnum/Vk/Queue.cpp b/src/Magnum/Vk/Queue.cpp index ac5e34d36..677f79fa4 100644 --- a/src/Magnum/Vk/Queue.cpp +++ b/src/Magnum/Vk/Queue.cpp @@ -47,8 +47,8 @@ Queue& Queue::submit(const CommandBuffer& cmdBuffer) { } Queue& Queue::submit(const CommandBuffer& cmdBuffer, - std::vector> waitSemaphores, - std::vector> signalSemaphores) { + Containers::ArrayView> waitSemaphores, + Containers::ArrayView> signalSemaphores) { const VkCommandBuffer cb = cmdBuffer; VkPipelineStageFlags pipelineDstStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; // TODO: Expose @@ -58,16 +58,18 @@ Queue& Queue::submit(const CommandBuffer& cmdBuffer, submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &cb; - std::vector waitSems; - waitSems.reserve(waitSemaphores.size()); + Containers::Array waitSems(Containers::NoInit, waitSemaphores.size()); + int i = 0; for(Semaphore& sem : waitSemaphores) { - waitSems.push_back(sem.vkSemaphore()); + waitSems[i] = sem; + ++i; } - std::vector sigSems; - sigSems.reserve(waitSemaphores.size()); + Containers::Array sigSems(Containers::NoInit, signalSemaphores.size()); + i = 0; for(Semaphore& sem : signalSemaphores) { - sigSems.push_back(sem.vkSemaphore()); + sigSems[i] = sem; + ++i; } submitInfo.waitSemaphoreCount = waitSemaphores.size(); submitInfo.pWaitSemaphores = waitSems.data(); diff --git a/src/Magnum/Vk/Queue.h b/src/Magnum/Vk/Queue.h index fbefafe85..569cae108 100644 --- a/src/Magnum/Vk/Queue.h +++ b/src/Magnum/Vk/Queue.h @@ -77,8 +77,21 @@ class MAGNUM_VK_EXPORT Queue { return *this; } + typedef std::reference_wrapper SemaphoreRef; + Queue& submit(const CommandBuffer& cmdBuffer); - Queue& submit(const CommandBuffer& cmdBuffer, std::vector> waitSemaphores, std::vector> signalSemaphores); + Queue& submit(const CommandBuffer& cmdBuffer, + const std::initializer_list waitSemaphores, + const std::initializer_list signalSemaphores) { + submit(cmdBuffer, + Containers::ArrayView(waitSemaphores.begin(), waitSemaphores.size()), + Containers::ArrayView(signalSemaphores.begin(), signalSemaphores.size())); + return *this; + } + + Queue& submit(const CommandBuffer& cmdBuffer, + Containers::ArrayView waitSemaphores, + Containers::ArrayView signalSemaphores); /** * @brief The device this queue was created for. diff --git a/src/Magnum/Vk/Semaphore.h b/src/Magnum/Vk/Semaphore.h index e8c5f2914..f08560d3d 100644 --- a/src/Magnum/Vk/Semaphore.h +++ b/src/Magnum/Vk/Semaphore.h @@ -75,12 +75,11 @@ class MAGNUM_VK_EXPORT Semaphore { } /** @brief Move constructor */ - Semaphore(Semaphore&& sem): _semaphore{sem.vkSemaphore()}, _device{sem._device} { + Semaphore(Semaphore&& sem): _semaphore{sem}, _device{sem._device} { sem._semaphore = VK_NULL_HANDLE; } - /** @brief Get the underlying VkSemaphore handle */ - VkSemaphore& vkSemaphore() { + operator VkSemaphore() const { return _semaphore; } diff --git a/src/Magnum/Vk/Shader.cpp b/src/Magnum/Vk/Shader.cpp index 51599fcef..fc38a8f4a 100644 --- a/src/Magnum/Vk/Shader.cpp +++ b/src/Magnum/Vk/Shader.cpp @@ -30,7 +30,9 @@ namespace Magnum { namespace Vk { Shader::~Shader() { - vkDestroyShaderModule(_device, _shaderModule, nullptr); + if(_device != nullptr) { + vkDestroyShaderModule(*_device, _shaderModule, nullptr); + } } }} diff --git a/src/Magnum/Vk/Shader.h b/src/Magnum/Vk/Shader.h index 1b2e72708..977210e04 100644 --- a/src/Magnum/Vk/Shader.h +++ b/src/Magnum/Vk/Shader.h @@ -43,7 +43,8 @@ namespace Magnum { namespace Vk { class MAGNUM_VK_EXPORT Shader { public: - Shader(Device& device, const Containers::Array& shaderCode): _device{device} { + Shader(Device& device, const Containers::Array& shaderCode): + _device{&device} { VkShaderModuleCreateInfo moduleCreateInfo; moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; moduleCreateInfo.pNext = nullptr; @@ -51,10 +52,13 @@ class MAGNUM_VK_EXPORT Shader { moduleCreateInfo.pCode = reinterpret_cast(shaderCode.data()); moduleCreateInfo.flags = 0; - const VkResult err = vkCreateShaderModule(device.vkDevice(), &moduleCreateInfo, nullptr, &_shaderModule); + const VkResult err = vkCreateShaderModule(*_device, &moduleCreateInfo, nullptr, &_shaderModule); MAGNUM_VK_ASSERT_ERROR(err); } + Shader(NoCreateT): _device{nullptr} { + } + /** @brief Copying is not allowed */ Shader(const Shader&) = delete; @@ -72,15 +76,20 @@ class MAGNUM_VK_EXPORT Shader { Shader& operator=(const Shader&) = delete; /** @brief Move assignment is not allowed */ - Shader& operator=(Shader&&) = delete; + Shader& operator=(Shader&& other) { + std::swap(_device, other._device); + std::swap(_shaderModule, other._shaderModule); + + return *this; + } VkShaderModule vkShaderModule() { return _shaderModule; } private: + Device* _device; VkShaderModule _shaderModule; - Device& _device; }; }} diff --git a/src/Magnum/Vk/Swapchain.cpp b/src/Magnum/Vk/Swapchain.cpp index adf212f37..c5ad0b74a 100644 --- a/src/Magnum/Vk/Swapchain.cpp +++ b/src/Magnum/Vk/Swapchain.cpp @@ -298,7 +298,7 @@ Swapchain& Swapchain::queuePresent(VkQueue queue, UnsignedInt currentBuffer) { } Swapchain& Swapchain::queuePresent(Queue& queue, UnsignedInt currentBuffer, Semaphore& waitSemaphore) { - VkSemaphore sem = waitSemaphore.vkSemaphore(); + VkSemaphore sem = waitSemaphore; VkPresentInfoKHR presentInfo = {}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.pNext = nullptr; diff --git a/src/Magnum/Vk/Swapchain.h b/src/Magnum/Vk/Swapchain.h index 7c563a6b9..312cff1eb 100644 --- a/src/Magnum/Vk/Swapchain.h +++ b/src/Magnum/Vk/Swapchain.h @@ -76,7 +76,7 @@ class MAGNUM_VK_EXPORT Swapchain { Swapchain& acquireNextImage(Semaphore& presentCompleteSemaphore) { VkResult err = vkAcquireNextImageKHR(_device.vkDevice(), _swapchain, UINT64_MAX, - presentCompleteSemaphore.vkSemaphore(), + presentCompleteSemaphore, VkFence(nullptr), &_currentIndex); MAGNUM_VK_ASSERT_ERROR(err);