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_CORE_XLCOREQUEUE_H_
25 : #define XENOLITH_CORE_XLCOREQUEUE_H_
26 :
27 : #include "XLCoreQueueData.h"
28 : #include "XLCoreInfo.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::xenolith::core {
31 :
32 : /* RenderQueue/RenderGraph implementation notes:
33 : *
34 : * - RenderQueue
35 : * - Attachment - global/per-queue data
36 : * - AttachmentDescriptor - per-pass attachment data
37 : * - AttachmentRef - per-subpass attachment data
38 : * - AttachmentHandle - per-frame attachment data
39 : * - RenderPass
40 : * - AttachmentDescriptor - pass attachments
41 : * - RenderSubpass
42 : * - AttachmentRef - subpass attachments
43 : * - RenderSubpassDependency - dependency between subpasses
44 : * - RenderPassHandle - per-frame pass data
45 : */
46 :
47 : class Queue : public NamedRef {
48 : public:
49 : using FrameRequest = core::FrameRequest;
50 : using FrameQueue = core::FrameQueue;
51 : using AttachmentHandle = core::AttachmentHandle;
52 : using FrameHandle = core::FrameHandle;
53 : using AttachmentData = core::AttachmentData;
54 : using AttachmentBuilder = core::AttachmentBuilder;
55 :
56 : class Builder;
57 :
58 : Queue();
59 : virtual ~Queue();
60 :
61 : virtual bool init(Builder &&);
62 :
63 : bool isCompiled() const;
64 :
65 : // mark queue as compiled for device with specific finalization
66 : void setCompiled(Device &, Function<void()> &&);
67 :
68 : bool isCompatible(const ImageInfo &) const;
69 :
70 : virtual StringView getName() const override;
71 :
72 : FrameRenderPassState getDefaultSyncPassState() const;
73 :
74 : const HashTable<ProgramData *> &getPrograms() const;
75 : const HashTable<QueuePassData *> &getPasses() const;
76 : const HashTable<GraphicPipelineData *> &getGraphicPipelines() const;
77 : const HashTable<ComputePipelineData *> &getComputePipelines() const;
78 : const HashTable<AttachmentData *> &getAttachments() const;
79 : const HashTable<Rc<Resource>> &getLinkedResources() const;
80 : Rc<Resource> getInternalResource() const;
81 :
82 : const memory::vector<AttachmentData *> &getInputAttachments() const;
83 : const memory::vector<AttachmentData *> &getOutputAttachments() const;
84 :
85 : template <typename T>
86 : auto getInputAttachment() const -> const T *;
87 :
88 : template <typename T>
89 : auto getOutputAttachment() const -> const T *;
90 :
91 : const Attachment *getInputAttachment(std::type_index name) const;
92 : const Attachment *getOutputAttachment(std::type_index name) const;
93 :
94 : const QueuePassData *getPass(StringView) const;
95 : const ProgramData *getProgram(StringView) const;
96 : const GraphicPipelineData *getGraphicPipeline(StringView) const;
97 : const ComputePipelineData *getComputePipeline(StringView) const;
98 : const AttachmentData *getAttachment(StringView) const;
99 :
100 : Vector<AttachmentData *> getOutput() const;
101 : Vector<AttachmentData *> getOutput(AttachmentType) const;
102 : AttachmentData *getPresentImageOutput() const;
103 : AttachmentData *getTransferImageOutput() const;
104 :
105 : // get next frame order dumber for this queue
106 : uint64_t incrementOrder();
107 :
108 : // Prepare queue to be used on target device
109 : bool prepare(Device &);
110 :
111 : void beginFrame(FrameRequest &);
112 : void endFrame(FrameRequest &);
113 :
114 : void attachFrame(FrameHandle *);
115 : void detachFrame(FrameHandle *);
116 :
117 : protected:
118 : QueueData *_data = nullptr;
119 : };
120 :
121 : class AttachmentBuilder final {
122 : public:
123 : void setType(AttachmentType type);
124 :
125 258 : void defineAsInput(AttachmentOps ops = AttachmentOps::WritesColor | AttachmentOps::WritesStencil);
126 206 : void defineAsOutput(AttachmentOps ops = AttachmentOps::ReadColor | AttachmentOps::ReadStencil,
127 : FrameRenderPassState pass = FrameRenderPassState::Submitted);
128 : void defineAsOutput(FrameRenderPassState pass);
129 :
130 624 : const AttachmentData *getAttachmentData() const { return _data; }
131 :
132 : protected:
133 : friend class Queue::Builder;
134 :
135 : AttachmentBuilder(AttachmentData *);
136 :
137 : AttachmentData *_data = nullptr;
138 : };
139 :
140 : class AttachmentPassBuilder final {
141 : public:
142 : void setAttachmentOps(AttachmentOps);
143 : void setInitialLayout(AttachmentLayout);
144 : void setFinalLayout(AttachmentLayout);
145 :
146 : void setLoadOp(AttachmentLoadOp);
147 : void setStoreOp(AttachmentStoreOp);
148 : void setStencilLoadOp(AttachmentLoadOp);
149 : void setStencilStoreOp(AttachmentStoreOp);
150 :
151 : void setColorMode(const ColorMode &);
152 : void setDependency(const AttachmentDependencyInfo &);
153 :
154 : protected:
155 : friend class QueuePassBuilder;
156 :
157 : AttachmentPassBuilder(AttachmentPassData *);
158 :
159 : AttachmentPassData *_data = nullptr;
160 : };
161 :
162 : class DescriptorSetBuilder final {
163 : public:
164 : // add single descriptor
165 : // compiler CAN inspect shaders to modify descriptors count, if descriptor is actually an array
166 : // if descriptor array size defined by spec constant - use addDescriptorArray instead
167 : bool addDescriptor(const AttachmentPassData *, DescriptorType = DescriptorType::Unknown, AttachmentLayout = AttachmentLayout::Ignored);
168 :
169 : // add descriptor array with predefined descriptors count
170 : // compiler can not modify size of this array
171 : bool addDescriptorArray(const AttachmentPassData *, uint32_t count, DescriptorType = DescriptorType::Unknown, AttachmentLayout = AttachmentLayout::Ignored);
172 :
173 : protected:
174 : friend class PipelineLayoutBuilder;
175 :
176 : DescriptorSetBuilder(DescriptorSetData *);
177 :
178 : DescriptorSetData *_data = nullptr;
179 : };
180 :
181 : class PipelineLayoutBuilder final {
182 : public:
183 : bool addSet(const Callback<void(DescriptorSetBuilder &)> &);
184 : void setUsesTextureSet(bool);
185 :
186 : protected:
187 : friend class QueuePassBuilder;
188 :
189 : PipelineLayoutBuilder(PipelineLayoutData *);
190 :
191 : PipelineLayoutData *_data = nullptr;
192 : };
193 :
194 : class SubpassBuilder final {
195 : public:
196 : bool addColor(const AttachmentPassData *, AttachmentDependencyInfo, AttachmentLayout = AttachmentLayout::Ignored,
197 : AttachmentOps = AttachmentOps::Undefined, BlendInfo = BlendInfo());
198 : bool addColor(const AttachmentPassData *, AttachmentDependencyInfo, BlendInfo);
199 : bool addInput(const AttachmentPassData *, AttachmentDependencyInfo, AttachmentLayout = AttachmentLayout::Ignored,
200 : AttachmentOps = AttachmentOps::Undefined);
201 :
202 : bool addResolve(const AttachmentPassData *color, const AttachmentPassData *resolve,
203 : AttachmentDependencyInfo colorDep, AttachmentDependencyInfo resolveDep);
204 :
205 : bool setDepthStencil(const AttachmentPassData *, AttachmentDependencyInfo, AttachmentLayout = AttachmentLayout::Ignored,
206 : AttachmentOps = AttachmentOps::Undefined);
207 :
208 : template <typename ... Args>
209 60 : const GraphicPipelineData * addGraphicPipeline(StringView key, const PipelineLayoutData *layout, Args && ...args) {
210 60 : if (auto p = emplacePipeline(key, layout)) {
211 60 : if (setPipelineOptions(*p, std::forward<Args>(args)...)) {
212 50 : finalizePipeline(p);
213 50 : return p;
214 : }
215 10 : erasePipeline(p);
216 : }
217 10 : return nullptr;
218 : }
219 :
220 : const ComputePipelineData *addComputePipeline(StringView key, const PipelineLayoutData *layout, SpecializationInfo &&);
221 :
222 : void setPrepareCallback(memory::function<void(const SubpassData &, FrameQueue &)> &&);
223 : void setCommandsCallback(memory::function<void(const SubpassData &, FrameQueue &, CommandBuffer &)> &&);
224 :
225 : protected:
226 : friend class QueuePassBuilder;
227 :
228 : GraphicPipelineData *emplacePipeline(StringView key, const PipelineLayoutData *);
229 : void finalizePipeline(GraphicPipelineData *);
230 : void erasePipeline(GraphicPipelineData *);
231 :
232 : bool setPipelineOption(GraphicPipelineData &f, DynamicState);
233 : bool setPipelineOption(GraphicPipelineData &f, const Vector<SpecializationInfo> &);
234 : bool setPipelineOption(GraphicPipelineData &f, const PipelineMaterialInfo &);
235 :
236 : template <typename T>
237 50 : bool setPipelineOptions(GraphicPipelineData &f, T && t) {
238 50 : return setPipelineOption(f, std::forward<T>(t));
239 : }
240 :
241 : template <typename T, typename ... Args>
242 70 : bool setPipelineOptions(GraphicPipelineData &f, T && t, Args && ... args) {
243 70 : if (!setPipelineOption(f, std::forward<T>(t))) {
244 10 : return false;
245 : }
246 60 : return setPipelineOptions(f, std::forward<Args>(args)...);
247 : }
248 :
249 : SubpassBuilder(SubpassData *);
250 :
251 : SubpassData *_data;
252 : };
253 :
254 : class QueuePassBuilder final {
255 : public:
256 : const PipelineLayoutData * addDescriptorLayout(const Callback<void(PipelineLayoutBuilder &)> &);
257 :
258 : const SubpassData * addSubpass(const Callback<void(SubpassBuilder &)> &);
259 :
260 : bool addSubpassDependency(const SubpassData *src, PipelineStage srcStage, AccessType srcAccess,
261 : const SubpassData *dst, PipelineStage dstStage, AccessType dstAccess, bool byRegion = true);
262 :
263 : const AttachmentPassData *addAttachment(const AttachmentData *);
264 : const AttachmentPassData *addAttachment(const AttachmentData *, const AttachmentDependencyInfo &);
265 : const AttachmentPassData *addAttachment(const AttachmentData *, const Callback<void(AttachmentPassBuilder &)> &);
266 :
267 : StringView getName() const;
268 :
269 : void addSubmittedCallback(memory::function<void(const QueuePassData &, FrameQueue &, bool success)> &&);
270 : void addCompleteCallback(memory::function<void(const QueuePassData &, FrameQueue &, bool success)> &&);
271 :
272 : protected:
273 : friend class Queue::Builder;
274 : friend class QueuePass;
275 :
276 320 : QueuePassData *getData() const { return _data; }
277 :
278 : QueuePassBuilder(QueuePassData *);
279 :
280 : QueuePassData *_data = nullptr;
281 : };
282 :
283 : class Queue::Builder final {
284 : public:
285 : Builder(StringView);
286 : ~Builder();
287 :
288 : void setDefaultSyncPassState(FrameRenderPassState);
289 :
290 : const AttachmentData *addAttachemnt(StringView name, const Callback<Rc<Attachment>(AttachmentBuilder &)> &);
291 :
292 : const QueuePassData * addPass(StringView name, PassType, RenderOrdering, const Callback<Rc<QueuePass>(QueuePassBuilder &)> &);
293 :
294 : // add program, copy all data
295 : const ProgramData * addProgram(StringView key, SpanView<uint32_t>, const ProgramInfo * = nullptr);
296 :
297 : // add program, take shader data by ref, data should exists for all resource lifetime
298 : const ProgramData * addProgramByRef(StringView key, SpanView<uint32_t>, const ProgramInfo * = nullptr);
299 :
300 : // add program, data will be acquired with callback when needed
301 : const ProgramData * addProgram(StringView key, const memory::function<void(const ProgramData::DataCallback &)> &,
302 : const ProgramInfo * = nullptr);
303 :
304 : // external resources, that should be compiled when added
305 : void addLinkedResource(const Rc<Resource> &);
306 :
307 : void setBeginCallback(Function<void(FrameRequest &)> &&);
308 : void setEndCallback(Function<void(FrameRequest &)> &&);
309 :
310 : void setAttachCallback(Function<void(const FrameHandle *)> &&);
311 : void setDetachCallback(Function<void(const FrameHandle *)> &&);
312 :
313 : const BufferData * addBufferByRef(StringView key, BufferInfo &&, BytesView data,
314 : Rc<DataAtlas> &&atlas = Rc<DataAtlas>(), AccessType = AccessType::ShaderRead);
315 : const BufferData * addBuffer(StringView key, BufferInfo &&, FilePath data,
316 : Rc<DataAtlas> &&atlas = Rc<DataAtlas>(), AccessType = AccessType::ShaderRead);
317 : const BufferData * addBuffer(StringView key, BufferInfo &&, BytesView data,
318 : Rc<DataAtlas> &&atlas = Rc<DataAtlas>(), AccessType = AccessType::ShaderRead);
319 : const BufferData * addBuffer(StringView key, BufferInfo &&,
320 : const memory::function<void(uint8_t *, uint64_t, const BufferData::DataCallback &)> &cb,
321 : Rc<DataAtlas> &&atlas = Rc<DataAtlas>(), AccessType = AccessType::ShaderRead);
322 :
323 : const ImageData * addImageByRef(StringView key, ImageInfo &&, BytesView data,
324 : AttachmentLayout = AttachmentLayout::ShaderReadOnlyOptimal, AccessType = AccessType::ShaderRead);
325 : const ImageData * addImage(StringView key, ImageInfo &&img, FilePath data,
326 : AttachmentLayout = AttachmentLayout::ShaderReadOnlyOptimal, AccessType = AccessType::ShaderRead);
327 : const ImageData * addImage(StringView key, ImageInfo &&img, BytesView data,
328 : AttachmentLayout = AttachmentLayout::ShaderReadOnlyOptimal, AccessType = AccessType::ShaderRead);
329 : const ImageData * addImage(StringView key, ImageInfo &&img,
330 : const memory::function<void(uint8_t *, uint64_t, const ImageData::DataCallback &)> &cb,
331 : AttachmentLayout = AttachmentLayout::ShaderReadOnlyOptimal, AccessType = AccessType::ShaderRead);
332 :
333 : protected:
334 : friend class Queue;
335 :
336 : QueueData *_data = nullptr;
337 : Resource::Builder _internalResource;
338 : };
339 :
340 :
341 : template <typename T>
342 10 : inline auto Queue::getInputAttachment() const -> const T * {
343 10 : if (auto c = getInputAttachment(std::type_index(typeid(T)))) {
344 0 : return static_cast<const T *>(c);
345 : }
346 :
347 10 : return nullptr;
348 : }
349 :
350 : template <typename T>
351 10 : inline auto Queue::getOutputAttachment() const -> const T * {
352 10 : if (auto c = getOutputAttachment(std::type_index(typeid(T)))) {
353 0 : return static_cast<const T *>(c);
354 : }
355 :
356 10 : return nullptr;
357 : }
358 :
359 : }
360 :
361 : #endif /* XENOLITH_GL_RENDERQUEUE_XLRENDERQUEUEQUEUE_H_ */
|