LCOV - code coverage report
Current view: top level - xenolith/backend/vk - XLVkDeviceQueue.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 16 19 84.2 %
Date: 2024-05-12 00:16:13 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2021 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_XLVKDEVICEQUEUE_H_
      25             : #define XENOLITH_BACKEND_VK_XLVKDEVICEQUEUE_H_
      26             : 
      27             : #include "XLVkInstance.h"
      28             : #include "XLVkLoop.h"
      29             : #include "XLCoreDevice.h"
      30             : #include "XLCoreLoop.h"
      31             : #include "XLCoreFrameHandle.h"
      32             : 
      33             : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk {
      34             : 
      35             : class Device;
      36             : class DeviceQueue;
      37             : class CommandPool;
      38             : class Semaphore;
      39             : class Fence;
      40             : class Loop;
      41             : class Image;
      42             : class ImageView;
      43             : class Buffer;
      44             : class RenderPass;
      45             : class Framebuffer;
      46             : class GraphicPipeline;
      47             : class ComputePipeline;
      48             : class CommandBuffer;
      49             : class DeviceMemoryPool;
      50             : struct DescriptorSet;
      51             : 
      52             : using PipelineDescriptor = core::PipelineDescriptor;
      53             : 
      54             : struct DeviceQueueFamily {
      55             :         using FrameHandle = core::FrameHandle;
      56             : 
      57             :         struct Waiter {
      58             :                 Function<void(Loop &, const Rc<DeviceQueue> &)> acquireForLoop;
      59             :                 Function<void(Loop &)> releaseForLoop;
      60             :                 Function<void(FrameHandle &, const Rc<DeviceQueue> &)> acquireForFrame;
      61             :                 Function<void(FrameHandle &)> releaseForFrame;
      62             : 
      63             :                 Rc<FrameHandle> handle;
      64             :                 Rc<Loop> loop;
      65             :                 Rc<Ref> ref;
      66             : 
      67           1 :                 Waiter(Function<void(FrameHandle &, const Rc<DeviceQueue> &)> &&a, Function<void(FrameHandle &)> &&r,
      68             :                                 FrameHandle *h, Rc<Ref> &&ref)
      69           1 :                 : acquireForFrame(move(a)), releaseForFrame(move(r)), handle(h), ref(move(ref)) { }
      70             : 
      71           0 :                 Waiter(Function<void(Loop &, const Rc<DeviceQueue> &)> &&a, Function<void(Loop &)> &&r,
      72             :                                 Loop *h, Rc<Ref> &&ref)
      73           0 :                 : acquireForLoop(move(a)), releaseForLoop(move(r)), loop(h), ref(move(ref)) { }
      74             :         };
      75             : 
      76             :         uint32_t index;
      77             :         uint32_t count;
      78             :         QueueOperations preferred = QueueOperations::None;
      79             :         QueueOperations ops = QueueOperations::None;
      80             :         VkExtent3D transferGranularity;
      81             :         Vector<Rc<DeviceQueue>> queues;
      82             :         Vector<Rc<CommandPool>> pools;
      83             :         Vector<Waiter> waiters;
      84             : };
      85             : 
      86             : class DeviceQueue final : public Ref {
      87             : public:
      88             :         enum class IdleMode {
      89             :                 None,
      90             :                 Queue,
      91             :                 Device
      92             :         };
      93             : 
      94             :         using FrameSync = core::FrameSync;
      95             :         using FrameHandle = core::FrameHandle;
      96             : 
      97             :         virtual ~DeviceQueue();
      98             : 
      99             :         virtual bool init(Device &, VkQueue, uint32_t, QueueOperations);
     100             : 
     101             :         bool submit(const FrameSync &, Fence &, CommandPool &, SpanView<const CommandBuffer *>, IdleMode = IdleMode::None);
     102             :         bool submit(Fence &, const CommandBuffer *, IdleMode = IdleMode::None);
     103             :         bool submit(Fence &, SpanView<const CommandBuffer *>, IdleMode = IdleMode::None);
     104             : 
     105             :         void waitIdle();
     106             : 
     107             :         uint32_t getActiveFencesCount();
     108             :         void retainFence(const Fence &);
     109             :         void releaseFence(const Fence &);
     110             : 
     111      581639 :         uint32_t getIndex() const { return _index; }
     112             :         uint64_t getFrameIndex() const { return _frameIdx; }
     113        4640 :         VkQueue getQueue() const { return _queue; }
     114             :         QueueOperations getOps() const { return _ops; }
     115             :         VkResult getResult() const { return _result; }
     116             : 
     117             :         void setOwner(FrameHandle &);
     118             :         void reset();
     119             : 
     120             : protected:
     121             :         Device *_device = nullptr;
     122             :         uint32_t _index = 0;
     123             :         uint64_t _frameIdx = 0;
     124             :         QueueOperations _ops = QueueOperations::None;
     125             :         VkQueue _queue;
     126             :         std::atomic<uint32_t> _nfences;
     127             :         VkResult _result = VK_ERROR_UNKNOWN;
     128             : };
     129             : 
     130             : enum class BufferLevel {
     131             :         Primary = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
     132             :         Secondary = VK_COMMAND_BUFFER_LEVEL_SECONDARY,
     133             : };
     134             : 
     135             : struct QueueFamilyTransfer {
     136             :         uint32_t srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
     137             :         uint32_t dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
     138             : };
     139             : 
     140             : struct ImageMemoryBarrier {
     141         210 :         ImageMemoryBarrier() = default;
     142             : 
     143             :         ImageMemoryBarrier(Image *, VkAccessFlags src, VkAccessFlags dst,
     144             :                         VkImageLayout old, VkImageLayout _new);
     145             :         ImageMemoryBarrier(Image *, VkAccessFlags src, VkAccessFlags dst,
     146             :                         VkImageLayout old, VkImageLayout _new, VkImageSubresourceRange);
     147             :         ImageMemoryBarrier(Image *, VkAccessFlags src, VkAccessFlags dst,
     148             :                         VkImageLayout old, VkImageLayout _new, QueueFamilyTransfer);
     149             :         ImageMemoryBarrier(Image *, VkAccessFlags src, VkAccessFlags dst,
     150             :                         VkImageLayout old, VkImageLayout _new, QueueFamilyTransfer, VkImageSubresourceRange);
     151             :         ImageMemoryBarrier(const VkImageMemoryBarrier &);
     152             : 
     153          42 :         explicit operator bool() const {
     154          42 :                 return srcAccessMask != 0 || dstAccessMask != 0
     155           0 :                         || oldLayout != VK_IMAGE_LAYOUT_UNDEFINED || newLayout != VK_IMAGE_LAYOUT_UNDEFINED
     156          84 :                         || image != nullptr;
     157             :         }
     158             : 
     159             :         VkAccessFlags srcAccessMask = 0;
     160             :         VkAccessFlags dstAccessMask = 0;
     161             :         VkImageLayout oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
     162             :         VkImageLayout newLayout = VK_IMAGE_LAYOUT_UNDEFINED;
     163             :         QueueFamilyTransfer familyTransfer;
     164             :         Image *image = nullptr;
     165             :         VkImageSubresourceRange subresourceRange;
     166             : };
     167             : 
     168             : struct BufferMemoryBarrier {
     169      403077 :         BufferMemoryBarrier() = default;
     170             :         BufferMemoryBarrier(Buffer *, VkAccessFlags src, VkAccessFlags dst);
     171             :         BufferMemoryBarrier(Buffer *, VkAccessFlags src, VkAccessFlags dst,
     172             :                         QueueFamilyTransfer);
     173             :         BufferMemoryBarrier(Buffer *, VkAccessFlags src, VkAccessFlags dst,
     174             :                         QueueFamilyTransfer, VkDeviceSize, VkDeviceSize);
     175             :         BufferMemoryBarrier(const VkBufferMemoryBarrier &);
     176             : 
     177      403094 :         explicit operator bool() const {
     178      403094 :                 return srcAccessMask != 0 || dstAccessMask != 0 || buffer != nullptr;
     179             :         }
     180             : 
     181             :         VkAccessFlags srcAccessMask = 0;
     182             :         VkAccessFlags dstAccessMask = 0;
     183             :         QueueFamilyTransfer familyTransfer;
     184             :         Buffer *buffer = nullptr;
     185             :         VkDeviceSize offset = 0;
     186             :         VkDeviceSize size = VK_WHOLE_SIZE;
     187             : };
     188             : 
     189             : struct DescriptorInfo {
     190     1609762 :         DescriptorInfo(const PipelineDescriptor *desc, uint32_t index, bool external)
     191     1609762 :         : descriptor(desc), index(index), external(external) { }
     192             : 
     193             :         const PipelineDescriptor *descriptor;
     194             :         uint32_t index;
     195             :         bool external;
     196             : };
     197             : 
     198             : struct DescriptorImageInfo : public DescriptorInfo {
     199             :         ~DescriptorImageInfo();
     200             :         DescriptorImageInfo(const PipelineDescriptor *desc, uint32_t index, bool external);
     201             : 
     202             :         Rc<ImageView> imageView;
     203             :         VkSampler sampler = VK_NULL_HANDLE;
     204             :         VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
     205             : };
     206             : 
     207             : struct DescriptorBufferInfo : public DescriptorInfo {
     208             :         ~DescriptorBufferInfo();
     209             :         DescriptorBufferInfo(const PipelineDescriptor *desc, uint32_t index, bool external);
     210             : 
     211             :         Rc<Buffer> buffer;
     212             :         VkDeviceSize offset = 0;
     213             :         VkDeviceSize range = VK_WHOLE_SIZE;
     214             : };
     215             : 
     216             : struct DescriptorBufferViewInfo : public DescriptorInfo {
     217             :         ~DescriptorBufferViewInfo();
     218             :         DescriptorBufferViewInfo(const PipelineDescriptor *desc, uint32_t index, bool external);
     219             : 
     220             :         Rc<Buffer> buffer;
     221             :         VkBufferView target = VK_NULL_HANDLE;
     222             : };
     223             : 
     224             : class CommandBuffer : public core::CommandBuffer {
     225             : public:
     226             :         virtual ~CommandBuffer();
     227             : 
     228             :         bool init(const CommandPool *, const DeviceTable *, VkCommandBuffer);
     229             :         void invalidate();
     230             : 
     231             :         void cmdPipelineBarrier(VkPipelineStageFlags, VkPipelineStageFlags, VkDependencyFlags,
     232             :                         SpanView<ImageMemoryBarrier>);
     233             :         void cmdPipelineBarrier(VkPipelineStageFlags, VkPipelineStageFlags, VkDependencyFlags,
     234             :                         SpanView<BufferMemoryBarrier>);
     235             :         void cmdPipelineBarrier(VkPipelineStageFlags, VkPipelineStageFlags, VkDependencyFlags,
     236             :                         SpanView<BufferMemoryBarrier>, SpanView<ImageMemoryBarrier>);
     237             : 
     238             :         void cmdCopyBuffer(Buffer *src, Buffer *dst);
     239             :         void cmdCopyBuffer(Buffer *src, Buffer *dst, VkDeviceSize srcOffset, VkDeviceSize dstOffset, VkDeviceSize size);
     240             :         void cmdCopyBuffer(Buffer *src, Buffer *dst, SpanView<VkBufferCopy>);
     241             : 
     242             :         void cmdCopyImage(Image *src, VkImageLayout, Image *dst, VkImageLayout, VkFilter filter = VK_FILTER_LINEAR);
     243             :         void cmdCopyImage(Image *src, VkImageLayout, Image *dst, VkImageLayout, const VkImageCopy &copy);
     244             :         void cmdCopyImage(Image *src, VkImageLayout, Image *dst, VkImageLayout, SpanView<VkImageCopy>);
     245             : 
     246             :         void cmdCopyBufferToImage(Buffer *, Image *, VkImageLayout, VkDeviceSize offset);
     247             :         void cmdCopyBufferToImage(Buffer *, Image *, VkImageLayout, SpanView<VkBufferImageCopy>);
     248             : 
     249             :         void cmdCopyImageToBuffer(Image *, VkImageLayout, Buffer *buf, VkDeviceSize offset);
     250             :         void cmdCopyImageToBuffer(Image *, VkImageLayout, Buffer *buf, SpanView<VkBufferImageCopy>);
     251             : 
     252             :         void cmdClearColorImage(Image *, VkImageLayout, const Color4F &);
     253             : 
     254             :         void cmdBeginRenderPass(RenderPass *pass, Framebuffer *fb, VkSubpassContents subpass, bool alt = false);
     255             :         void cmdEndRenderPass();
     256             : 
     257             :         void cmdSetViewport(uint32_t firstViewport, SpanView<VkViewport> viewports);
     258             :         void cmdSetScissor(uint32_t firstScissor, SpanView<VkRect2D> scissors);
     259             : 
     260             :         void cmdBindPipeline(GraphicPipeline *);
     261             :         void cmdBindPipeline(ComputePipeline *);
     262             : 
     263             :         void cmdBindIndexBuffer(Buffer *, VkDeviceSize offset, VkIndexType indexType);
     264             : 
     265             :         void cmdBindDescriptorSets(RenderPass *, uint32_t layoutIndex, uint32_t firstSet = 0);
     266             :         void cmdBindDescriptorSets(RenderPass *, uint32_t layoutIndex, SpanView<VkDescriptorSet>, uint32_t firstSet = 0);
     267             : 
     268             :         void cmdBindGraphicDescriptorSets(VkPipelineLayout, SpanView<VkDescriptorSet>, uint32_t firstSet = 0);
     269             :         void cmdBindComputeDescriptorSets(VkPipelineLayout, SpanView<VkDescriptorSet>, uint32_t firstSet = 0);
     270             : 
     271             :         void cmdDraw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance);
     272             :         void cmdDrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex,
     273             :                         int32_t vertexOffset, uint32_t firstInstance);
     274             : 
     275             :         void cmdPushConstants(VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, BytesView);
     276             :         void cmdPushConstants(VkShaderStageFlags stageFlags, uint32_t offset, BytesView);
     277             : 
     278             :         void cmdFillBuffer(Buffer *, uint32_t data);
     279             :         void cmdFillBuffer(Buffer *, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data);
     280             : 
     281             :         // count in group blocks
     282             :         void cmdDispatch(uint32_t groupCountX, uint32_t groupCountY = 1, uint32_t groupCountZ = 1);
     283             : 
     284             :         // count in individual elements, not in blocks
     285             :         void cmdDispatchPipeline(ComputePipeline *, uint32_t countX, uint32_t countY = 1, uint32_t countZ = 1);
     286             : 
     287             :         uint32_t cmdNextSubpass();
     288             : 
     289      395916 :         VkCommandBuffer getBuffer() const { return _buffer; }
     290             : 
     291             :         uint32_t getCurrentSubpass() const { return _currentSubpass; }
     292             :         uint32_t getBoundLayoutIndex() const { return _boundLayoutIndex; }
     293             :         VkPipelineLayout getBoundLayout() const { return _boundLayout; }
     294             : 
     295             :         void writeImageTransfer(uint32_t sourceFamily, uint32_t targetFamily, const Rc<Buffer> &, const Rc<Image> &);
     296             : 
     297             :         virtual void bindBuffer(core::BufferObject *) override;
     298             : 
     299             : protected:
     300             :         VkPipelineLayout _boundLayout = VK_NULL_HANDLE;
     301             : 
     302             :         const CommandPool *_pool = nullptr;
     303             :         const DeviceTable *_table = nullptr;
     304             :         VkCommandBuffer _buffer = VK_NULL_HANDLE;
     305             : 
     306             :         Set<Rc<DescriptorSet>> _descriptorSets;
     307             :         Set<Rc<DeviceMemoryPool>> _memPool;
     308             : };
     309             : 
     310             : class CommandPool : public Ref {
     311             : public:
     312             :         static constexpr VkCommandBufferUsageFlagBits DefaultFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
     313             : 
     314             :         using Level = BufferLevel;
     315             : 
     316             :         virtual ~CommandPool();
     317             : 
     318             :         bool init(Device &dev, uint32_t familyIdx, QueueOperations c = QueueOperations::Graphics, bool transient = true);
     319             :         void invalidate(Device &dev);
     320             : 
     321        2428 :         QueueOperations getClass() const { return _class; }
     322      265498 :         uint32_t getFamilyIdx() const { return _familyIdx; }
     323             :         VkCommandPool getCommandPool() const { return _commandPool; }
     324             : 
     325             :         const CommandBuffer * recordBuffer(Device &dev, const Callback<bool(CommandBuffer &)> &,
     326             :                         VkCommandBufferUsageFlagBits = DefaultFlags, Level = Level::Primary);
     327             : 
     328             :         void freeDefaultBuffers(Device &dev, Vector<VkCommandBuffer> &);
     329             :         void reset(Device &dev, bool release = false);
     330             : 
     331             :         void autorelease(Rc<Ref> &&);
     332             : 
     333             : protected:
     334             :         uint32_t _familyIdx = 0;
     335             :         uint32_t _currentComplexity = 0;
     336             :         uint32_t _bestComplexity = 0;
     337             :         QueueOperations _class = QueueOperations::Graphics;
     338             :         VkCommandPool _commandPool = VK_NULL_HANDLE;
     339             :         Vector<Rc<Ref>> _autorelease;
     340             :         Vector<Rc<CommandBuffer>> _buffers;
     341             : };
     342             : 
     343             : }
     344             : 
     345             : #endif /* XENOLITH_BACKEND_VK_XLVKDEVICEQUEUE_H_ */

Generated by: LCOV version 1.14