Line data Source code
1 : /** 2 : Copyright (c) 2021-2022 Roman Katuntsev <sbkarr@stappler.org> 3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev> 4 : 5 : Permission is hereby granted, free of charge, to any person obtaining a copy 6 : of this software and associated documentation files (the "Software"), to deal 7 : in the Software without restriction, including without limitation the rights 8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 : copies of the Software, and to permit persons to whom the Software is 10 : furnished to do so, subject to the following conditions: 11 : 12 : The above copyright notice and this permission notice shall be included in 13 : all copies or substantial portions of the Software. 14 : 15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 : THE SOFTWARE. 22 : **/ 23 : 24 : #ifndef XENOLITH_BACKEND_VK_XLVKTRANSFERQUEUE_H_ 25 : #define XENOLITH_BACKEND_VK_XLVKTRANSFERQUEUE_H_ 26 : 27 : #include "XLVkQueuePass.h" 28 : #include "XLVkAllocator.h" 29 : #include "XLVkAttachment.h" 30 : #include "XLCoreResource.h" 31 : 32 : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk { 33 : 34 : class DeviceQueue; 35 : class CommandPool; 36 : class TransferAttachment; 37 : 38 : class TransferResource final : public core::AttachmentInputData { 39 : public: 40 : struct BufferAllocInfo { 41 : core::BufferData *data = nullptr; 42 : VkBufferCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr }; 43 : MemoryRequirements req; 44 : VkBuffer buffer = VK_NULL_HANDLE; 45 : VkDeviceSize offset = 0; 46 : VkDeviceSize stagingOffset = 0; 47 : VkDeviceMemory dedicated = VK_NULL_HANDLE; 48 : uint32_t dedicatedMemType = 0; 49 : std::optional<VkBufferMemoryBarrier> barrier; 50 : bool useStaging = false; 51 : 52 63 : BufferAllocInfo() = default; 53 : BufferAllocInfo(core::BufferData *); 54 : }; 55 : 56 : struct ImageAllocInfo { 57 : core::ImageData *data = nullptr; 58 : VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, nullptr }; 59 : MemoryRequirements req; 60 : VkImage image = VK_NULL_HANDLE; 61 : VkDeviceSize offset = 0; 62 : VkDeviceSize stagingOffset = 0; 63 : VkDeviceMemory dedicated = VK_NULL_HANDLE; 64 : uint32_t dedicatedMemType = 0; 65 : std::optional<VkImageMemoryBarrier> barrier; 66 : bool useStaging = false; 67 : 68 : ImageAllocInfo() = default; 69 : ImageAllocInfo(core::ImageData *); 70 : }; 71 : 72 : struct StagingCopy { 73 : VkDeviceSize sourceOffet; 74 : VkDeviceSize sourceSize; 75 : ImageAllocInfo *targetImage = nullptr; 76 : BufferAllocInfo *targetBuffer = nullptr; 77 : }; 78 : 79 : struct StagingBuffer : public Ref { 80 63 : virtual ~StagingBuffer() { } 81 : 82 : uint32_t memoryTypeIndex = maxOf<uint32_t>(); 83 : BufferAllocInfo buffer; 84 : Vector<StagingCopy> copyData; 85 : }; 86 : 87 : virtual ~TransferResource(); 88 : void invalidate(Device &dev); 89 : 90 : bool init(const Rc<Allocator> &alloc, const Rc<core::Resource> &, Function<void(bool)> &&cb = nullptr); 91 : bool init(const Rc<Allocator> &alloc, Rc<core::Resource> &&, Function<void(bool)> &&cb = nullptr); 92 : 93 : bool initialize(AllocationUsage = AllocationUsage::DeviceLocal); 94 : bool compile(); 95 : 96 : bool prepareCommands(uint32_t idx, VkCommandBuffer buf, 97 : Vector<VkImageMemoryBarrier> &outputImageBarriers, Vector<VkBufferMemoryBarrier> &outputBufferBarriers); 98 : bool transfer(const Rc<DeviceQueue> &, const Rc<CommandPool> &, const Rc<Fence> &); 99 : 100 : bool isValid() const { return _alloc != nullptr; } 101 : bool isStagingRequired() const { return !_stagingBuffer.copyData.empty(); } 102 : 103 : protected: 104 : bool allocate(); 105 : bool upload(); 106 : 107 : bool allocateDedicated(const Rc<Allocator> &alloc, BufferAllocInfo &); 108 : bool allocateDedicated(const Rc<Allocator> &alloc, ImageAllocInfo &); 109 : 110 : size_t writeData(uint8_t *, BufferAllocInfo &); 111 : size_t writeData(uint8_t *, ImageAllocInfo &); 112 : 113 : // calculate offsets, size and transfer if no staging needed 114 : size_t preTransferData(); 115 : 116 : bool createStagingBuffer(StagingBuffer &buffer, size_t) const; 117 : bool writeStaging(StagingBuffer &); 118 : void dropStaging(StagingBuffer &) const; 119 : 120 : Allocator::MemType * _memType = nullptr; 121 : VkDeviceSize _requiredMemory = 0; 122 : Rc<Allocator> _alloc; 123 : Rc<core::Resource> _resource; 124 : VkDeviceMemory _memory = VK_NULL_HANDLE; 125 : Vector<BufferAllocInfo> _buffers; 126 : Vector<ImageAllocInfo> _images; 127 : VkDeviceSize _nonCoherentAtomSize = 1; 128 : StagingBuffer _stagingBuffer; 129 : Function<void(bool)> _callback; 130 : 131 : bool _initialized = false; 132 : AllocationUsage _targetUsage = AllocationUsage::DeviceLocal; 133 : }; 134 : 135 : class TransferQueue : public core::Queue { 136 : public: 137 : virtual ~TransferQueue(); 138 : 139 : bool init(); 140 : 141 : Rc<FrameRequest> makeRequest(Rc<TransferResource> &&); 142 : 143 : protected: 144 : using core::Queue::init; 145 : 146 : const AttachmentData *_attachment = nullptr; 147 : }; 148 : 149 : } 150 : 151 : #endif /* XENOLITH_BACKEND_VK_XLVKTRANSFERQUEUE_H_ */