Line data Source code
1 : /* Copyright (C) 2023 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef INCLUDED_RENDERER_BACKEND_VULKAN_RINGCOMMANDCONTEXT
19 : #define INCLUDED_RENDERER_BACKEND_VULKAN_RINGCOMMANDCONTEXT
20 :
21 : #include "renderer/backend/vulkan/SubmitScheduler.h"
22 :
23 : #include <glad/vulkan.h>
24 : #include <memory>
25 : #include <vector>
26 :
27 : namespace Renderer
28 : {
29 :
30 : namespace Backend
31 : {
32 :
33 : namespace Vulkan
34 : {
35 :
36 : class CBuffer;
37 : class CDevice;
38 :
39 : /**
40 : * A simple helper class to decouple command buffers rotation from frames
41 : * presenting. It might be useful when sometimes we need to submit more work
42 : * than we can usually have during a frame. For example if we need to upload
43 : * something, an upload buffer is full and we can't extend it at the moment.
44 : * Then the only way is to wait until uploading is done and submit more work.
45 : * @note not thread-safe, should be created and used from the same thread.
46 : */
47 : class CRingCommandContext
48 : {
49 : public:
50 : CRingCommandContext(
51 : CDevice* device, const size_t size, const uint32_t queueFamilyIndex,
52 : CSubmitScheduler& submitScheduler);
53 : ~CRingCommandContext();
54 :
55 : /**
56 : * @return the current available command buffer. If there is none waits until
57 : * it appeared.
58 : */
59 : VkCommandBuffer GetCommandBuffer();
60 :
61 : /**
62 : * Submits the current command buffer to the SubmitScheduler.
63 : */
64 : void Flush();
65 :
66 : /**
67 : * Schedules uploads until next render pass or flush.
68 : * @note doesn't save a command buffer returned by GetCommandBuffer during
69 : * scheduling uploads, because it might be changed.
70 : */
71 : void ScheduleUpload(
72 : CTexture* texture, const Format dataFormat,
73 : const void* data, const size_t dataSize,
74 : const uint32_t level, const uint32_t layer);
75 : void ScheduleUpload(
76 : CTexture* texture, const Format dataFormat,
77 : const void* data, const size_t dataSize,
78 : const uint32_t xOffset, const uint32_t yOffset,
79 : const uint32_t width, const uint32_t height,
80 : const uint32_t level, const uint32_t layer);
81 :
82 : void ScheduleUpload(
83 : CBuffer* buffer, const void* data, const uint32_t dataOffset,
84 : const uint32_t dataSize);
85 : using UploadBufferFunction = std::function<void(u8*)>;
86 : void ScheduleUpload(
87 : CBuffer* buffer,
88 : const uint32_t dataOffset, const uint32_t dataSize,
89 : const UploadBufferFunction& uploadFunction);
90 :
91 : private:
92 : void Begin();
93 : void End();
94 :
95 : void ScheduleUpload(
96 : CBuffer* buffer, const uint32_t dataOffset, const uint32_t dataSize,
97 : const uint32_t acquiredOffset);
98 :
99 : uint32_t AcquireFreeSpace(
100 : const uint32_t requiredSize, const uint32_t requiredAlignment);
101 : uint32_t GetFreeSpaceOffset(
102 : const uint32_t requiredSize, const uint32_t requiredAlignment) const;
103 :
104 : CDevice* m_Device = nullptr;
105 : CSubmitScheduler& m_SubmitScheduler;
106 :
107 : std::unique_ptr<CBuffer> m_StagingBuffer;
108 : uint32_t m_StagingBufferFirst = 0, m_StagingBufferCurrentFirst = 0, m_StagingBufferLast = 0;
109 : uint32_t m_OptimalBufferCopyOffsetAlignment = 1;
110 : uint32_t m_MaxStagingBufferCapacity = 0;
111 :
112 0 : struct RingItem
113 : {
114 : VkCommandPool commandPool = VK_NULL_HANDLE;
115 : VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
116 : CSubmitScheduler::SubmitHandle handle = CSubmitScheduler::INVALID_SUBMIT_HANDLE;
117 : bool isBegan = false;
118 : uint32_t stagingBufferFirst = 0, stagingBufferLast = 0;
119 : };
120 : std::vector<RingItem> m_Ring;
121 : size_t m_RingIndex = 0;
122 :
123 : void WaitUntilFree(RingItem& item);
124 : };
125 :
126 : } // namespace Vulkan
127 :
128 : } // namespace Backend
129 :
130 : } // namespace Renderer
131 :
132 : #endif // INCLUDED_RENDERER_BACKEND_VULKAN_RINGCOMMANDCONTEXT
|