From 7416e3dddee59202ceaa46d19180c4efd4d89273 Mon Sep 17 00:00:00 2001 From: Squareys Date: Thu, 13 Oct 2016 21:44:57 +0200 Subject: [PATCH] More code... --- src/Magnum/Vk/Buffer.cpp | 2 +- src/Magnum/Vk/Buffer.h | 21 +++++++++++++++++ src/Magnum/Vk/DescriptorSet.h | 44 ++++++++++++++++++++++++++++++++++- src/Magnum/Vk/Device.h | 1 + src/Magnum/Vk/Image.cpp | 44 ++++++++++++++++++++++++++++++++--- src/Magnum/Vk/Image.h | 44 ++++++++++++++++++++++++++++------- src/Magnum/Vk/ImageView.h | 5 ++-- src/Magnum/Vk/RenderPass.h | 5 ++-- src/Magnum/Vk/Swapchain.cpp | 10 ++++---- src/Magnum/Vk/Texture.h | 35 ++++++++++++++++++++++++++-- 10 files changed, 186 insertions(+), 25 deletions(-) diff --git a/src/Magnum/Vk/Buffer.cpp b/src/Magnum/Vk/Buffer.cpp index ae7f7a8dd..5f060d792 100644 --- a/src/Magnum/Vk/Buffer.cpp +++ b/src/Magnum/Vk/Buffer.cpp @@ -1,4 +1,4 @@ -/* +/* This file is part of Magnum. Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 diff --git a/src/Magnum/Vk/Buffer.h b/src/Magnum/Vk/Buffer.h index 0d77b6f48..5e3e77da2 100644 --- a/src/Magnum/Vk/Buffer.h +++ b/src/Magnum/Vk/Buffer.h @@ -132,6 +132,13 @@ class MAGNUM_VK_EXPORT Buffer { }; } + auto cmdCopyTo(Image& dest, std::initializer_list regions) { + const VkBuffer source = _buffer; + return [source, &dest, ®ions](VkCommandBuffer cmdBuffer){ + vkCmdCopyBufferToImage(cmdBuffer, source, dest, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, UnsignedInt(regions.size()), std::vector(regions).data()); + }; + } + auto cmdFullCopyTo(Buffer& dest) { const VkBuffer source = _buffer; const UnsignedInt size = _size; @@ -141,6 +148,20 @@ class MAGNUM_VK_EXPORT Buffer { }; } + auto cmdFullCopyTo(Image& dest) { + const VkBuffer source = _buffer; + const UnsignedInt size = _size; + return [source, &dest, size](VkCommandBuffer cmdBuffer){ + VkBufferImageCopy copy; + copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy.imageSubresource.mipLevel = 0; + copy.imageSubresource.baseArrayLayer = 0; + copy.imageSubresource.layerCount = 1; + copy.imageExtent = VkExtent3D(dest.extent()); + vkCmdCopyBufferToImage(cmdBuffer, source, dest, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); + }; + } + VkDescriptorBufferInfo getDescriptor() { VkDescriptorBufferInfo descriptor; descriptor.buffer = _buffer; diff --git a/src/Magnum/Vk/DescriptorSet.h b/src/Magnum/Vk/DescriptorSet.h index 9a9187b08..182e23ad6 100644 --- a/src/Magnum/Vk/DescriptorSet.h +++ b/src/Magnum/Vk/DescriptorSet.h @@ -30,12 +30,16 @@ * @brief Class @ref Magnum::Vk::DescriptorSet */ +#include + #include #include "Magnum/Magnum.h" +#include "Magnum/Vk/Buffer.h" #include "Magnum/Vk/Device.h" #include "Magnum/Vk/visibility.h" #include "Magnum/Vk/ShaderStage.h" +#include "Magnum/Vk/Texture.h" #include "vulkan.h" @@ -124,7 +128,6 @@ class MAGNUM_VK_EXPORT DescriptorSetLayout { class MAGNUM_VK_EXPORT DescriptorSet { public: - DescriptorSet(Device& device, DescriptorPool& pool, VkDescriptorSet vkDescriptorSet): _device{device}, _pool{pool}, @@ -161,6 +164,45 @@ class MAGNUM_VK_EXPORT DescriptorSet { VkDescriptorSet _descriptorSet; }; +class MAGNUM_VK_EXPORT DescriptorSetUpdate { + public: + void run(Device& device) { + if(_writes.empty()) { + return; + } + // TODO: Error check? + vkUpdateDescriptorSets(device, UnsignedInt(_writes.size()), _writes.data(), 0, NULL); + } + + DescriptorSetUpdate& useDescriptorSet(DescriptorSet& ds) { + _descriptorSet = &ds; + return *this; + } + + DescriptorSetUpdate& bindUniformBuffer(Buffer& buffer, UnsignedInt dstBinding, UnsignedInt dstArrayElement=0) { + _buffers.push_back(buffer.getDescriptor()); + _writes.push_back(VkWriteDescriptorSet{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, *_descriptorSet, + dstBinding, dstArrayElement, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, nullptr, &_buffers.back(), nullptr}); + return *this; + } + + DescriptorSetUpdate& bindTexture(Vk::Texture& texture, UnsignedInt dstBinding, UnsignedInt dstArrayElement=0) { + _images.push_back(texture.getDescriptor()); + _writes.push_back(VkWriteDescriptorSet{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, *_descriptorSet, + dstBinding, dstArrayElement, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &_images.back(), nullptr, nullptr}); + return *this; + } + + private: + std::vector _images; + std::vector _buffers; + std::vector _bufferViews; + + std::vector _writes; + // TODO copies + DescriptorSet* _descriptorSet; +}; + }} #endif diff --git a/src/Magnum/Vk/Device.h b/src/Magnum/Vk/Device.h index a10fb606b..306599d7d 100644 --- a/src/Magnum/Vk/Device.h +++ b/src/Magnum/Vk/Device.h @@ -114,6 +114,7 @@ public: DeviceFeatures(const std::initializer_list& features) { VkBool32* enabled = reinterpret_cast(&_features); + std::memset(enabled, 0, sizeof(VkPhysicalDeviceFeatures)); for(DeviceFeature f : features) { enabled[UnsignedInt(f)] = VK_TRUE; } diff --git a/src/Magnum/Vk/Image.cpp b/src/Magnum/Vk/Image.cpp index 29ace52aa..343214d1f 100644 --- a/src/Magnum/Vk/Image.cpp +++ b/src/Magnum/Vk/Image.cpp @@ -1,4 +1,4 @@ -/* +/* This file is part of Magnum. Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 @@ -25,14 +25,52 @@ */ #include "Image.h" - +#include "Magnum/Vk/Buffer.h" +#include "Magnum/Vk/Command.h" +#include "Magnum/Vk/CommandBuffer.h" +#include "Magnum/Vk/CommandPool.h" +#include "Magnum/Vk/DeviceMemory.h" +#include "Magnum/Vk/Queue.h" namespace Magnum { namespace Vk { Image::~Image() { if(_flags >= ObjectFlag::DeleteOnDestruction) { - vkDestroyImage(_device, _image, nullptr); + vkDestroyImage(*_device, _image, nullptr); } } +std::unique_ptr Image::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}); + bindImageMemory(*memory); + + return std::unique_ptr{}; +} + +Image& Image::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, UnsignedInt(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() + << Vk::Cmd::imageMemoryk + << stagingBuffer.cmdFullCopyTo(*this) + << Vk::Cmd::end(); + queue.submit(*copyToDeviceCmds).waitIdle(); + + return *this; +} + }} diff --git a/src/Magnum/Vk/Image.h b/src/Magnum/Vk/Image.h index b897c0cc4..54f4bec8c 100644 --- a/src/Magnum/Vk/Image.h +++ b/src/Magnum/Vk/Image.h @@ -34,6 +34,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Math/Vector3.h" #include "Magnum/Vk/Device.h" +#include "Magnum/Vk/Format.h" #include "Magnum/Vk/DeviceMemory.h" #include "Magnum/Vk/Math.h" #include "Magnum/Vk/visibility.h" @@ -108,28 +109,29 @@ class MAGNUM_VK_EXPORT Image { public: Image(Device& device, VkImage vkImage): - _device{device}, + _device{&device}, _image{vkImage}, _flags{} {} - Image(Device& device, Vector3ui extent, VkFormat format, ImageUsageFlags usage): - _device{device}, _flags{ObjectFlag::DeleteOnDestruction} + Image(Device& device, const Vector3ui& extent, Vk::Format format, ImageUsageFlags usage): + _device{&device}, _flags{ObjectFlag::DeleteOnDestruction}, _extent(extent) { VkImageCreateInfo image = {}; image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; image.flags = 0; image.pNext = nullptr; image.imageType = VK_IMAGE_TYPE_2D; - image.format = format; + image.format = VkFormat(format); image.extent = VkExtent3D(extent); image.samples = VK_SAMPLE_COUNT_1_BIT; image.mipLevels = 1; image.arrayLayers = 1; image.tiling = VK_IMAGE_TILING_OPTIMAL; image.usage = UnsignedInt(usage); + image.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - VkResult err = vkCreateImage(_device, &image, nullptr, &_image); + VkResult err = vkCreateImage(*_device, &image, nullptr, &_image); MAGNUM_VK_ASSERT_ERROR(err); } @@ -158,29 +160,53 @@ class MAGNUM_VK_EXPORT Image { VkMemoryRequirements getMemoryRequirements() { VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(_device, _image, &memReqs); + vkGetImageMemoryRequirements(*_device, _image, &memReqs); return memReqs; } Image& bindImageMemory(DeviceMemory& memory, UnsignedLong memoryOffset=0) { - VkResult err = vkBindImageMemory(_device, _image, memory, memoryOffset); + VkResult err = vkBindImageMemory(*_device, _image, memory, memoryOffset); MAGNUM_VK_ASSERT_ERROR(err); return *this; } + /** + * @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. + */ + Image& 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); + + Vector3ui extent() const { + return _extent; + } + /** * @brief The device this image was created for. */ Device& device() { - return _device; + return *_device; } private: - Device& _device; + Device* _device; VkImage _image; ObjectFlags _flags; + Vector3ui _extent; }; struct ImageMemoryBarrier { diff --git a/src/Magnum/Vk/ImageView.h b/src/Magnum/Vk/ImageView.h index 50cf55ab5..a7a263180 100644 --- a/src/Magnum/Vk/ImageView.h +++ b/src/Magnum/Vk/ImageView.h @@ -33,6 +33,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Vk/visibility.h" #include "Magnum/Vk/Image.h" +#include "Magnum/Vk/Format.h" #include "vulkan.h" @@ -52,7 +53,7 @@ CORRADE_ENUMSET_OPERATORS(ImageAspects) class MAGNUM_VK_EXPORT ImageView { public: - ImageView(Device& device, Image& image, VkFormat format, + ImageView(Device& device, Image& image, Vk::Format format, VkImageViewType type, ImageAspects aspects, VkComponentMapping components = {}): _device{device} @@ -62,7 +63,7 @@ class MAGNUM_VK_EXPORT ImageView { createInfo.pNext = nullptr; createInfo.flags = 0; createInfo.viewType = type; - createInfo.format = format; + createInfo.format = VkFormat(format); createInfo.subresourceRange = { VkImageAspectFlags(aspects), 0, /* base mip level */ diff --git a/src/Magnum/Vk/RenderPass.h b/src/Magnum/Vk/RenderPass.h index d9e2257bf..8b0b1d454 100644 --- a/src/Magnum/Vk/RenderPass.h +++ b/src/Magnum/Vk/RenderPass.h @@ -33,6 +33,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Vk/Device.h" #include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Format.h" #include "vulkan.h" @@ -44,7 +45,7 @@ class MAGNUM_VK_EXPORT RenderPass { RenderPass(NoCreateT) noexcept: _device{nullptr} { } - RenderPass(Device& device, VkFormat depthFormat): _device{&device} { + RenderPass(Device& device, Vk::Format depthFormat): _device{&device} { VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT; VkAttachmentDescription attachments[2]; @@ -57,7 +58,7 @@ class MAGNUM_VK_EXPORT RenderPass { attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - attachments[1].format = depthFormat; + attachments[1].format = VkFormat(depthFormat); attachments[1].samples = sampleCount; attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; diff --git a/src/Magnum/Vk/Swapchain.cpp b/src/Magnum/Vk/Swapchain.cpp index 043c3b175..006d629c5 100644 --- a/src/Magnum/Vk/Swapchain.cpp +++ b/src/Magnum/Vk/Swapchain.cpp @@ -27,7 +27,7 @@ #include "Swapchain.h" #include "Magnum/Vk/Queue.h" - +#include "Magnum/Vk/Format.h" #include "Magnum/Vk/ImageView.h" namespace Magnum { namespace Vk { @@ -127,16 +127,16 @@ Swapchain::Swapchain(Device& device, CommandBuffer& cb, VkSurfaceKHR surface): MAGNUM_VK_ASSERT_ERROR(err); VkColorSpaceKHR colorSpace = surfaceFormats[0].colorSpace; - VkFormat colorFormat = VK_FORMAT_B8G8R8A8_UNORM; + Format colorFormat = Vk::Format(VK_FORMAT_R8G8B8A8_UNORM); if ((formatCount == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED)) { /* no preferred format */ - colorFormat = VK_FORMAT_B8G8R8A8_UNORM; + colorFormat = Vk::Format(VK_FORMAT_R8G8B8A8_UNORM); } else { // Always select the first available color format // If you need a specific format (e.g. SRGB) you'd need to // iterate over the list of available surface format and // check for it's presence - colorFormat = surfaceFormats[0].format; + colorFormat = Format(surfaceFormats[0].format); } // Get physical device surface properties and formats @@ -197,7 +197,7 @@ Swapchain::Swapchain(Device& device, CommandBuffer& cb, VkSurfaceKHR surface): swapchainCI.flags = 0; swapchainCI.surface = _surface; - swapchainCI.imageFormat = colorFormat; + swapchainCI.imageFormat = VkFormat(colorFormat); swapchainCI.imageColorSpace = colorSpace; swapchainCI.imageExtent = swapchainExtent; swapchainCI.minImageCount = desiredNumberOfSwapchainImages; diff --git a/src/Magnum/Vk/Texture.h b/src/Magnum/Vk/Texture.h index 216d72b2e..04f67251e 100644 --- a/src/Magnum/Vk/Texture.h +++ b/src/Magnum/Vk/Texture.h @@ -40,10 +40,20 @@ namespace Magnum { namespace Vk { +/** + @brief Texture + + A Sampler combined with an Image. +*/ class MAGNUM_VK_EXPORT Texture { public: - Texture(Device& device): _device{device} { + Texture(Device& device, std::unique_ptr&& imageView, ImageLayout layout, Int numMipLevels): + _device{device}, + _imageView{std::move(imageView)}, + _imageLayout{VkImageLayout(layout)}, + _mipLevels{numMipLevels} + { int mipLevels = 0; VkSamplerCreateInfo sampler{VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, nullptr, 0}; sampler.magFilter = VK_FILTER_LINEAR; @@ -85,12 +95,33 @@ class MAGNUM_VK_EXPORT Texture { /** @brief Move assignment is not allowed */ Texture& operator=(Texture&&) = delete; + ImageView& imageView() { + return *_imageView; + } + + operator VkSampler() const { + return _sampler; + } + + UnsignedInt mipLevels() const { + return _mipLevels; + } + + VkImageLayout imageLayout() const { + return _imageLayout; + } + + VkDescriptorImageInfo getDescriptor() const { + return VkDescriptorImageInfo{_sampler, *_imageView, _imageLayout}; + } + private: Device& _device; VkSampler _sampler; + std::unique_ptr _imageView; VkImageLayout _imageLayout; - UnsignedInt _mipLevels; + Int _mipLevels; }; }}