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 : #include "XLVkDevice.h"
25 : #include "XLVkRenderPass.h"
26 : #include "XLVkQueuePass.h"
27 : #include "XLVkAttachment.h"
28 : #include "XLVkTextureSet.h"
29 : #include "XLCoreAttachment.h"
30 : #include "XLCoreFrameQueue.h"
31 : #include <forward_list>
32 :
33 : namespace STAPPLER_VERSIONIZED stappler::xenolith::vk {
34 :
35 1113 : DescriptorBinding::~DescriptorBinding() {
36 1113 : data.clear();
37 1113 : }
38 :
39 441 : DescriptorBinding::DescriptorBinding(VkDescriptorType type, uint32_t count) : type(type) {
40 441 : data.resize(count, DescriptorData{core::ObjectHandle::zero(), nullptr});
41 441 : }
42 :
43 1581483 : Rc<Ref> DescriptorBinding::write(uint32_t idx, DescriptorBufferInfo &&info) {
44 1581483 : auto ret = move(data[idx].data);
45 1581483 : data[idx] = DescriptorData{core::ObjectHandle(info.buffer->getBuffer()), move(info.buffer)};
46 1581483 : return ret;
47 0 : }
48 :
49 28455 : Rc<Ref> DescriptorBinding::write(uint32_t idx, DescriptorImageInfo &&info) {
50 28455 : auto ret = move(data[idx].data);
51 28469 : data[idx] = DescriptorData{core::ObjectHandle(info.imageView->getImageView()), move(info.imageView)};
52 28450 : return ret;
53 0 : }
54 :
55 0 : Rc<Ref> DescriptorBinding::write(uint32_t idx, DescriptorBufferViewInfo &&info) {
56 0 : auto ret = move(data[idx].data);
57 0 : data[idx] = DescriptorData{core::ObjectHandle(info.buffer->getBuffer()), move(info.buffer)};
58 0 : return ret;
59 0 : }
60 :
61 117 : bool Framebuffer::init(Device &dev, RenderPass *renderPass, SpanView<Rc<core::ImageView>> imageViews) {
62 117 : Vector<VkImageView> views; views.reserve(imageViews.size());
63 117 : _viewIds.reserve(imageViews.size());
64 117 : _imageViews.reserve(imageViews.size());
65 117 : _renderPass = renderPass;
66 :
67 117 : auto extent = imageViews.front()->getFramebufferExtent();
68 :
69 468 : for (auto &it : imageViews) {
70 351 : views.emplace_back(((ImageView *)it.get())->getImageView());
71 351 : _viewIds.emplace_back(it->getIndex());
72 351 : _imageViews.emplace_back(it);
73 :
74 351 : if (extent != it->getFramebufferExtent()) {
75 0 : log::error("Framebuffer", "Invalid extent for framebuffer image: ", it->getFramebufferExtent());
76 0 : return false;
77 : }
78 : }
79 :
80 117 : VkFramebufferCreateInfo framebufferInfo { };
81 117 : framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
82 117 : framebufferInfo.renderPass = renderPass->getRenderPass();
83 117 : framebufferInfo.attachmentCount = views.size();
84 117 : framebufferInfo.pAttachments = views.data();
85 117 : framebufferInfo.width = extent.width;
86 117 : framebufferInfo.height = extent.height;
87 117 : framebufferInfo.layers = extent.depth;
88 :
89 117 : if (dev.getTable()->vkCreateFramebuffer(dev.getDevice(), &framebufferInfo, nullptr, &_framebuffer) == VK_SUCCESS) {
90 117 : _extent = Extent2(extent.width, extent.height);
91 117 : _layerCount = extent.depth;
92 117 : return core::Framebuffer::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle ptr, void *) {
93 117 : auto d = ((Device *)dev);
94 117 : d->getTable()->vkDestroyFramebuffer(d->getDevice(), (VkFramebuffer)ptr.get(), nullptr);
95 234 : }, core::ObjectType::Framebuffer, ObjectHandle(_framebuffer));
96 : }
97 0 : return false;
98 117 : }
99 :
100 357 : bool RenderPass::Data::cleanup(Device &dev) {
101 357 : if (renderPass) {
102 21 : dev.getTable()->vkDestroyRenderPass(dev.getDevice(), renderPass, nullptr);
103 21 : renderPass = VK_NULL_HANDLE;
104 : }
105 :
106 357 : if (renderPassAlternative) {
107 21 : dev.getTable()->vkDestroyRenderPass(dev.getDevice(), renderPassAlternative, nullptr);
108 21 : renderPassAlternative = VK_NULL_HANDLE;
109 : }
110 :
111 609 : for (auto &it : layouts) {
112 504 : for (VkDescriptorSetLayout &set : it.layouts) {
113 252 : dev.getTable()->vkDestroyDescriptorSetLayout(dev.getDevice(), set, nullptr);
114 : }
115 :
116 252 : if (it.layout) {
117 252 : dev.getTable()->vkDestroyPipelineLayout(dev.getDevice(), it.layout, nullptr);
118 : }
119 :
120 252 : if (it.descriptorPool) {
121 252 : dev.getTable()->vkDestroyDescriptorPool(dev.getDevice(), it.descriptorPool, nullptr);
122 : }
123 : }
124 :
125 357 : layouts.clear();
126 :
127 357 : return false;
128 : }
129 :
130 357 : bool RenderPass::init(Device &dev, QueuePassData &data) {
131 357 : _type = data.pass->getType();
132 357 : _name = data.key.str<Interface>();
133 357 : switch (_type) {
134 21 : case core::PassType::Graphics:
135 21 : return initGraphicsPass(dev, data);
136 : break;
137 168 : case core::PassType::Compute:
138 168 : return initComputePass(dev, data);
139 : break;
140 168 : case core::PassType::Transfer:
141 168 : return initTransferPass(dev, data);
142 : break;
143 0 : case core::PassType::Generic:
144 0 : return initGenericPass(dev, data);
145 : break;
146 : }
147 :
148 0 : return false;
149 : }
150 :
151 9718 : VkRenderPass RenderPass::getRenderPass(bool alt) const {
152 9718 : if (alt && _data->renderPassAlternative) {
153 21 : return _data->renderPassAlternative;
154 : }
155 9697 : return _data->renderPass;
156 : }
157 :
158 488784 : bool RenderPass::writeDescriptors(const QueuePassHandle &handle, uint32_t layoutIndex, bool async) const {
159 488784 : auto dev = (Device *)_object.device;
160 488784 : auto table = dev->getTable();
161 488598 : auto data = handle.getData();
162 :
163 488552 : std::forward_list<Vector<VkDescriptorImageInfo>> images;
164 488281 : std::forward_list<Vector<VkDescriptorBufferInfo>> buffers;
165 488132 : std::forward_list<Vector<VkBufferView>> views;
166 :
167 487839 : Vector<VkWriteDescriptorSet> writes;
168 :
169 321832 : auto writeDescriptor = [&] (DescriptorSet *set, const PipelineDescriptor &desc, uint32_t currentDescriptor, bool external) {
170 321832 : auto a = handle.getAttachmentHandle(desc.attachment->attachment);
171 321523 : if (!a) {
172 0 : return false;
173 : }
174 :
175 321523 : Vector<VkDescriptorImageInfo> *localImages = nullptr;
176 321523 : Vector<VkDescriptorBufferInfo> *localBuffers = nullptr;
177 321523 : Vector<VkBufferView> *localViews = nullptr;
178 :
179 : VkWriteDescriptorSet writeData;
180 321523 : writeData.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
181 321523 : writeData.pNext = nullptr;
182 321523 : writeData.dstSet = set->set;
183 321523 : writeData.dstBinding = currentDescriptor;
184 321523 : writeData.dstArrayElement = 0;
185 321523 : writeData.descriptorCount = 0;
186 321523 : writeData.descriptorType = VkDescriptorType(desc.type);
187 321523 : writeData.pImageInfo = VK_NULL_HANDLE;
188 321523 : writeData.pBufferInfo = VK_NULL_HANDLE;
189 321523 : writeData.pTexelBufferView = VK_NULL_HANDLE;
190 :
191 321523 : auto c = a->getDescriptorArraySize(handle, desc, external);
192 2032877 : for (uint32_t i = 0; i < c; ++ i) {
193 1711295 : if (a->isDescriptorDirty(handle, desc, i, external)) {
194 1609695 : switch (desc.type) {
195 28530 : case DescriptorType::Sampler:
196 : case DescriptorType::CombinedImageSampler:
197 : case DescriptorType::SampledImage:
198 : case DescriptorType::StorageImage:
199 : case DescriptorType::InputAttachment:
200 28530 : if (!localImages) {
201 28528 : localImages = &images.emplace_front(Vector<VkDescriptorImageInfo>());
202 : }
203 28470 : if (localImages) {
204 28469 : auto h = (ImageAttachmentHandle *)a;
205 :
206 28469 : DescriptorImageInfo info(&desc, i, external);
207 28470 : if (!h->writeDescriptor(handle, info)) {
208 0 : return false;
209 : } else {
210 28487 : localImages->emplace_back(VkDescriptorImageInfo{info.sampler, info.imageView->getImageView(), info.layout});
211 28455 : if (auto ref = set->bindings[currentDescriptor].write(i, move(info))) {
212 28367 : handle.autorelease(ref);
213 28568 : }
214 : }
215 28569 : }
216 28565 : break;
217 0 : case DescriptorType::StorageTexelBuffer:
218 : case DescriptorType::UniformTexelBuffer:
219 0 : if (!localViews) {
220 0 : localViews = &views.emplace_front(Vector<VkBufferView>());
221 : }
222 0 : if (localViews) {
223 0 : auto h = (TexelAttachmentHandle *)a;
224 :
225 0 : DescriptorBufferViewInfo info(&desc, i, external);
226 0 : if (h->writeDescriptor(handle, info)) {
227 0 : localViews->emplace_back(info.target);
228 0 : if (auto ref = set->bindings[currentDescriptor].write(i, move(info))) {
229 0 : handle.autorelease(ref);
230 0 : }
231 : } else {
232 0 : return false;
233 : }
234 0 : }
235 0 : break;
236 1581483 : case DescriptorType::UniformBuffer:
237 : case DescriptorType::StorageBuffer:
238 : case DescriptorType::UniformBufferDynamic:
239 : case DescriptorType::StorageBufferDynamic:
240 1581483 : if (!localBuffers) {
241 263486 : localBuffers = &buffers.emplace_front(Vector<VkDescriptorBufferInfo>());
242 : }
243 1581483 : if (localBuffers) {
244 1581483 : auto h = (BufferAttachmentHandle *)a;
245 :
246 1581483 : DescriptorBufferInfo info(&desc, i, external);
247 1581483 : if (!h->writeDescriptor(handle, info)) {
248 0 : return false;
249 : } else {
250 1581483 : localBuffers->emplace_back(VkDescriptorBufferInfo{info.buffer->getBuffer(), info.offset, info.range});
251 1581483 : if (auto ref = set->bindings[currentDescriptor].write(i, move(info))) {
252 1579824 : handle.autorelease(ref);
253 1581483 : }
254 : }
255 1581483 : }
256 1581483 : break;
257 0 : case DescriptorType::Unknown:
258 : case DescriptorType::Attachment:
259 0 : break;
260 : }
261 1609730 : ++ writeData.descriptorCount;
262 : } else {
263 101619 : if (writeData.descriptorCount > 0) {
264 0 : if (localImages) {
265 0 : writeData.pImageInfo = localImages->data();
266 : }
267 0 : if (localBuffers) {
268 0 : writeData.pBufferInfo = localBuffers->data();
269 : }
270 0 : if (localViews) {
271 0 : writeData.pTexelBufferView = localViews->data();
272 : }
273 :
274 0 : writes.emplace_back(move(writeData));
275 :
276 0 : writeData.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
277 0 : writeData.pNext = nullptr;
278 0 : writeData.dstSet = set->set;
279 0 : writeData.dstBinding = currentDescriptor;
280 0 : writeData.descriptorCount = 0;
281 0 : writeData.descriptorType = VkDescriptorType(desc.type);
282 0 : writeData.pImageInfo = VK_NULL_HANDLE;
283 0 : writeData.pBufferInfo = VK_NULL_HANDLE;
284 0 : writeData.pTexelBufferView = VK_NULL_HANDLE;
285 :
286 0 : localImages = nullptr;
287 0 : localBuffers = nullptr;
288 0 : localViews = nullptr;
289 : }
290 :
291 101619 : writeData.dstArrayElement = i + 1;
292 : }
293 : }
294 :
295 321582 : if (writeData.descriptorCount > 0) {
296 292047 : if (localImages) {
297 28566 : writeData.pImageInfo = localImages->data();
298 : }
299 292047 : if (localBuffers) {
300 263486 : writeData.pBufferInfo = localBuffers->data();
301 : }
302 292047 : if (localViews) {
303 0 : writeData.pTexelBufferView = localViews->data();
304 : }
305 :
306 292047 : writes.emplace_back(move(writeData));
307 : }
308 321879 : return true;
309 487513 : };
310 :
311 487513 : uint32_t currentSet = 0;
312 977124 : for (auto &descriptorSetData : data->pipelineLayouts[layoutIndex]->sets) {
313 486903 : auto set = _data->layouts[layoutIndex].sets[currentSet];
314 488108 : uint32_t currentDescriptor = 0;
315 1131954 : for (auto &it : descriptorSetData->descriptors) {
316 638553 : if (it->updateAfterBind != async) {
317 321963 : ++ currentDescriptor;
318 321963 : continue;
319 : }
320 316590 : if (!writeDescriptor(set, *it, currentDescriptor, false)) {
321 0 : return false;
322 : }
323 321883 : ++ currentDescriptor;
324 : }
325 489132 : ++ currentSet;
326 489132 : }
327 :
328 488085 : if (writes.empty()) {
329 236338 : return true;
330 : }
331 :
332 252544 : table->vkUpdateDescriptorSets(dev->getDevice(), writes.size(), writes.data(), 0, nullptr);
333 255372 : return true;
334 491724 : }
335 :
336 170251 : void RenderPass::perform(const QueuePassHandle &handle, CommandBuffer &buf, const Callback<void()> &cb, bool writeBarriers) {
337 170251 : bool useAlternative = false;
338 179747 : for (auto &it : _variableAttachments) {
339 9517 : if (auto aHandle = handle.getAttachmentHandle(it->attachment)) {
340 9517 : if (aHandle->getQueueData()->image && !aHandle->getQueueData()->image->isSwapchainImage()) {
341 21 : useAlternative = true;
342 21 : break;
343 : }
344 : }
345 : }
346 :
347 170253 : Vector<QueuePassHandle::ImageInputOutputBarrier> imageBarriersData;
348 170253 : Vector<QueuePassHandle::BufferInputOutputBarrier> bufferBarriersData;
349 :
350 170252 : Vector<vk::ImageMemoryBarrier> imageBarriers;
351 170252 : Vector<vk::BufferMemoryBarrier> bufferBarriers;
352 :
353 170251 : core::PipelineStage fromStage = core::PipelineStage::None;
354 170251 : core::PipelineStage toStage = core::PipelineStage::None;
355 :
356 170251 : if (writeBarriers) {
357 50417 : bool hasPendings = false;
358 :
359 201617 : for (auto &it : handle.getQueueData()->attachments) {
360 151194 : switch (it.first->attachment->type) {
361 21 : case core::AttachmentType::Image:
362 21 : if (auto h = dynamic_cast<ImageAttachmentHandle *>(it.second->handle.get())) {
363 21 : if (auto img = static_cast<Image *>(it.second->image->getImage().get())) {
364 21 : auto b = handle.getImageInputOutputBarrier(static_cast<Device *>(_object.device), img, *h);
365 21 : if (auto pending = img->getPendingBarrier()) {
366 0 : b.input = *pending;
367 0 : img->dropPendingBarrier();
368 0 : hasPendings = true;
369 : }
370 21 : if (b.input || b.output) {
371 21 : imageBarriersData.emplace_back(move(b));
372 : }
373 : }
374 : }
375 21 : break;
376 151173 : case core::AttachmentType::Buffer:
377 151173 : if (auto h = dynamic_cast<BufferAttachmentHandle *>(it.second->handle.get())) {
378 352739 : for (auto &it : h->getBuffers()) {
379 201556 : auto b = handle.getBufferInputOutputBarrier(static_cast<Device *>(_object.device), it.buffer, *h, it.offset, it.size);
380 201553 : if (auto pending = it.buffer->getPendingBarrier()) {
381 0 : b.input = *pending;
382 0 : it.buffer->dropPendingBarrier();
383 0 : hasPendings = true;
384 : }
385 201554 : if (b.input || b.output) {
386 0 : bufferBarriersData.emplace_back(move(b));
387 : }
388 : }
389 : }
390 151179 : break;
391 0 : default:
392 0 : break;
393 : }
394 : }
395 :
396 50403 : for (auto &it : imageBarriersData) {
397 21 : if (it.input) {
398 21 : fromStage |= it.inputFrom;
399 21 : toStage |= it.inputTo;
400 21 : imageBarriers.emplace_back(move(it.input));
401 : }
402 : }
403 50416 : for (auto &it : bufferBarriersData) {
404 0 : if (it.input) {
405 0 : fromStage |= it.inputFrom;
406 0 : toStage |= it.inputTo;
407 0 : bufferBarriers.emplace_back(move(it.input));
408 : }
409 : }
410 :
411 50416 : if (hasPendings) {
412 0 : if (fromStage == core::PipelineStage::None) {
413 0 : fromStage = core::PipelineStage::AllCommands;
414 : }
415 0 : if (toStage == core::PipelineStage::None) {
416 0 : toStage = core::PipelineStage::AllCommands;
417 : }
418 : }
419 :
420 100811 : if ((!imageBarriersData.empty() || !bufferBarriersData.empty())
421 100810 : && (fromStage != core::PipelineStage::None) && (toStage != core::PipelineStage::None)) {
422 21 : buf.cmdPipelineBarrier(VkPipelineStageFlags(fromStage), VkPipelineStageFlags(toStage), 0, bufferBarriers, imageBarriers);
423 : }
424 : }
425 :
426 170249 : if (_data->renderPass) {
427 9517 : buf.cmdBeginRenderPass(this, (Framebuffer *)handle.getFramebuffer().get(), VK_SUBPASS_CONTENTS_INLINE, useAlternative);
428 :
429 9517 : cb();
430 :
431 9517 : buf.cmdEndRenderPass();
432 : } else {
433 160732 : cb();
434 : }
435 :
436 170255 : if (writeBarriers) {
437 50421 : fromStage = core::PipelineStage::None;
438 50421 : toStage = core::PipelineStage::None;
439 :
440 50421 : imageBarriersData.clear();
441 50421 : bufferBarriersData.clear();
442 :
443 50421 : for (auto &it : imageBarriersData) {
444 0 : if (it.output) {
445 0 : fromStage |= it.outputFrom;
446 0 : toStage |= it.outputTo;
447 0 : imageBarriers.emplace_back(move(it.output));
448 : }
449 : }
450 50421 : for (auto &it : bufferBarriersData) {
451 0 : if (it.output) {
452 0 : fromStage |= it.outputFrom;
453 0 : toStage |= it.outputTo;
454 0 : bufferBarriers.emplace_back(move(it.output));
455 : }
456 : }
457 :
458 50421 : if (!imageBarriersData.empty() || !bufferBarriersData.empty()) {
459 0 : buf.cmdPipelineBarrier(VkPipelineStageFlags(fromStage), VkPipelineStageFlags(toStage), 0, bufferBarriers, imageBarriers);
460 : }
461 : }
462 170255 : }
463 :
464 21 : bool RenderPass::initGraphicsPass(Device &dev, QueuePassData &data) {
465 21 : bool hasAlternative = false;
466 21 : Data pass;
467 :
468 21 : size_t attachmentReferences = 0;
469 189 : for (auto &desc : data.attachments) {
470 168 : if (desc->attachment->type != core::AttachmentType::Image || desc->subpasses.empty()) {
471 105 : continue;
472 : }
473 :
474 : VkAttachmentDescription attachment;
475 : VkAttachmentDescription attachmentAlternative;
476 :
477 63 : bool mayAlias = false;
478 168 : for (auto &u : desc->subpasses) {
479 105 : if (u->usage == core::AttachmentUsage::InputOutput || u->usage == core::AttachmentUsage::InputDepthStencil) {
480 0 : mayAlias = true;
481 : }
482 : }
483 :
484 63 : auto imageAttachment = (core::ImageAttachment *)desc->attachment->attachment.get();
485 63 : auto &info = imageAttachment->getImageInfo();
486 :
487 63 : attachmentAlternative.flags = attachment.flags = (mayAlias ? VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT : 0);
488 63 : attachmentAlternative.format = attachment.format = VkFormat(info.format);
489 63 : attachmentAlternative.samples = attachment.samples = VkSampleCountFlagBits(info.samples);
490 63 : attachmentAlternative.loadOp = attachment.loadOp = VkAttachmentLoadOp(desc->loadOp);
491 63 : attachmentAlternative.storeOp = attachment.storeOp = VkAttachmentStoreOp(desc->storeOp);
492 63 : attachmentAlternative.stencilLoadOp = attachment.stencilLoadOp = VkAttachmentLoadOp(desc->stencilLoadOp);
493 63 : attachmentAlternative.stencilStoreOp = attachment.stencilStoreOp = VkAttachmentStoreOp(desc->stencilStoreOp);
494 63 : attachmentAlternative.initialLayout = attachment.initialLayout = VkImageLayout(desc->initialLayout);
495 63 : attachmentAlternative.finalLayout = attachment.finalLayout = VkImageLayout(desc->finalLayout);
496 :
497 63 : if (desc->finalLayout == core::AttachmentLayout::PresentSrc) {
498 21 : hasAlternative = true;
499 21 : attachmentAlternative.finalLayout = VkImageLayout(core::AttachmentLayout::TransferSrcOptimal);
500 21 : _variableAttachments.emplace(desc);
501 : }
502 :
503 63 : desc->index = _attachmentDescriptions.size();
504 :
505 63 : _attachmentDescriptions.emplace_back(attachment);
506 63 : _attachmentDescriptionsAlternative.emplace_back(attachmentAlternative);
507 :
508 63 : auto fmt = core::getImagePixelFormat(imageAttachment->getImageInfo().format);
509 63 : switch (fmt) {
510 21 : case core::PixelFormat::D:
511 21 : if (desc->loadOp == core::AttachmentLoadOp::Clear) {
512 21 : auto c = ((core::ImageAttachment *)desc->attachment->attachment.get())->getClearColor();
513 : VkClearValue clearValue;
514 21 : clearValue.depthStencil.depth = c.r;
515 21 : _clearValues.emplace_back(clearValue);
516 : } else {
517 : VkClearValue clearValue;
518 0 : clearValue.depthStencil.depth = 0.0f;
519 0 : _clearValues.emplace_back(clearValue);
520 : }
521 21 : break;
522 0 : case core::PixelFormat::DS:
523 0 : if (desc->stencilLoadOp == core::AttachmentLoadOp::Clear
524 0 : || desc->loadOp == core::AttachmentLoadOp::Clear) {
525 0 : auto c = imageAttachment->getClearColor();
526 : VkClearValue clearValue;
527 0 : clearValue.depthStencil.depth = c.r;
528 0 : clearValue.depthStencil.stencil = 0;
529 0 : _clearValues.emplace_back(clearValue);
530 0 : } else {
531 : VkClearValue clearValue;
532 0 : clearValue.depthStencil.depth = 0.0f;
533 0 : clearValue.depthStencil.stencil = 0;
534 0 : _clearValues.emplace_back(clearValue);
535 : }
536 0 : break;
537 0 : case core::PixelFormat::S:
538 0 : if (desc->stencilLoadOp == core::AttachmentLoadOp::Clear) {
539 : VkClearValue clearValue;
540 0 : clearValue.depthStencil.stencil = 0;
541 0 : _clearValues.emplace_back(clearValue);
542 : } else {
543 : VkClearValue clearValue;
544 0 : clearValue.depthStencil.stencil = 0;
545 0 : _clearValues.emplace_back(clearValue);
546 : }
547 0 : break;
548 42 : default:
549 42 : if (desc->loadOp == core::AttachmentLoadOp::Clear) {
550 42 : auto c = imageAttachment->getClearColor();
551 : VkClearValue clearValue;
552 42 : clearValue.color = VkClearColorValue{{c.r, c.g, c.b, c.a}};
553 42 : _clearValues.emplace_back(clearValue);
554 : } else {
555 : VkClearValue clearValue;
556 0 : clearValue.color = VkClearColorValue{{0.0f, 0.0f, 0.0f, 1.0f}};
557 0 : _clearValues.emplace_back(clearValue);
558 : }
559 42 : break;
560 : }
561 :
562 63 : attachmentReferences += desc->subpasses.size();
563 :
564 63 : if (data.subpasses.size() >= 3 && desc->subpasses.size() < data.subpasses.size()) {
565 0 : uint32_t initialSubpass = desc->subpasses.front()->subpass->index;
566 0 : uint32_t finalSubpass = desc->subpasses.back()->subpass->index;
567 :
568 0 : for (size_t i = initialSubpass + 1; i < finalSubpass; ++ i) {
569 0 : bool found = false;
570 0 : for (auto &u : desc->subpasses) {
571 0 : if (u->subpass->index == i) {
572 0 : found = true;
573 : }
574 : }
575 0 : if (!found) {
576 0 : data.subpasses[i]->preserve.emplace_back(desc->index);
577 : }
578 : }
579 : }
580 : }
581 :
582 21 : _attachmentReferences.reserve(attachmentReferences);
583 :
584 63 : for (auto &it : data.subpasses) {
585 42 : VkSubpassDescription subpass{};
586 42 : subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
587 :
588 42 : if (!it->inputImages.empty()) {
589 21 : auto off = _attachmentReferences.size();
590 :
591 42 : for (auto &iit : it->inputImages) {
592 21 : VkAttachmentReference attachmentRef{};
593 21 : if (!iit) {
594 0 : attachmentRef.attachment = VK_ATTACHMENT_UNUSED;
595 0 : attachmentRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
596 : } else {
597 21 : attachmentRef.attachment = iit->pass->index;
598 21 : attachmentRef.layout = VkImageLayout(iit->layout);
599 : }
600 21 : _attachmentReferences.emplace_back(attachmentRef);
601 : }
602 :
603 21 : subpass.inputAttachmentCount = it->inputImages.size();
604 21 : subpass.pInputAttachments = _attachmentReferences.data() + off;
605 : }
606 :
607 42 : if (!it->outputImages.empty()) {
608 42 : auto off = _attachmentReferences.size();
609 :
610 105 : for (auto &iit : it->outputImages) {
611 63 : VkAttachmentReference attachmentRef{};
612 63 : if (!iit) {
613 0 : attachmentRef.attachment = VK_ATTACHMENT_UNUSED;
614 0 : attachmentRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
615 : } else {
616 63 : attachmentRef.attachment = iit->pass->index;
617 63 : attachmentRef.layout = VkImageLayout(iit->layout);
618 : }
619 63 : _attachmentReferences.emplace_back(attachmentRef);
620 : }
621 :
622 42 : subpass.colorAttachmentCount = it->outputImages.size();
623 42 : subpass.pColorAttachments = _attachmentReferences.data() + off;
624 : }
625 :
626 42 : if (!it->resolveImages.empty()) {
627 0 : auto resolveImages = it->resolveImages;
628 0 : if (resolveImages.size() < it->outputImages.size()) {
629 0 : resolveImages.resize(it->outputImages.size(), nullptr);
630 : }
631 :
632 0 : auto off = _attachmentReferences.size();
633 :
634 0 : for (auto &iit : resolveImages) {
635 0 : VkAttachmentReference attachmentRef{};
636 0 : if (!iit) {
637 0 : attachmentRef.attachment = VK_ATTACHMENT_UNUSED;
638 0 : attachmentRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
639 : } else {
640 0 : attachmentRef.attachment = iit->pass->index;
641 0 : attachmentRef.layout = VkImageLayout(iit->layout);
642 : }
643 0 : _attachmentReferences.emplace_back(attachmentRef);
644 : }
645 :
646 0 : subpass.pResolveAttachments = _attachmentReferences.data() + off;
647 0 : }
648 :
649 42 : if (it->depthStencil) {
650 21 : VkAttachmentReference attachmentRef{};
651 21 : attachmentRef.attachment = it->depthStencil->pass->index;
652 21 : attachmentRef.layout = VkImageLayout(it->depthStencil->layout);
653 21 : _attachmentReferences.emplace_back(attachmentRef);
654 21 : subpass.pDepthStencilAttachment = &_attachmentReferences.back();
655 : }
656 :
657 42 : if (!it->preserve.empty()) {
658 0 : subpass.preserveAttachmentCount = it->preserve.size();
659 0 : subpass.pPreserveAttachments = it->preserve.data();
660 : }
661 :
662 42 : _subpasses.emplace_back(subpass);
663 : }
664 :
665 21 : _subpassDependencies.reserve(data.dependencies.size());
666 :
667 : // TODO: deal with internal dependencies through AttachmentDependencyInfo
668 :
669 63 : for (auto &it : data.dependencies) {
670 42 : VkSubpassDependency dependency{};
671 42 : dependency.srcSubpass = (it.srcSubpass == core::SubpassDependency::External) ? VK_SUBPASS_EXTERNAL : it.srcSubpass;
672 42 : dependency.dstSubpass = (it.dstSubpass == core::SubpassDependency::External) ? VK_SUBPASS_EXTERNAL : it.dstSubpass;
673 42 : dependency.srcStageMask = VkPipelineStageFlags(it.srcStage);
674 42 : dependency.srcAccessMask = VkAccessFlags(it.srcAccess);
675 42 : dependency.dstStageMask = VkPipelineStageFlags(it.dstStage);
676 42 : dependency.dstAccessMask = VkAccessFlags(it.dstAccess);
677 42 : dependency.dependencyFlags = 0;
678 42 : if (it.byRegion) {
679 42 : dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
680 : }
681 :
682 42 : _subpassDependencies.emplace_back(dependency);
683 : }
684 :
685 21 : VkRenderPassCreateInfo renderPassInfo{};
686 21 : renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
687 21 : renderPassInfo.attachmentCount = _attachmentDescriptions.size();
688 21 : renderPassInfo.pAttachments = _attachmentDescriptions.data();
689 21 : renderPassInfo.subpassCount = _subpasses.size();
690 21 : renderPassInfo.pSubpasses = _subpasses.data();
691 21 : renderPassInfo.dependencyCount = _subpassDependencies.size();
692 21 : renderPassInfo.pDependencies = _subpassDependencies.data();
693 :
694 21 : if (dev.getTable()->vkCreateRenderPass(dev.getDevice(), &renderPassInfo, nullptr, &pass.renderPass) != VK_SUCCESS) {
695 0 : return pass.cleanup(dev);
696 : }
697 :
698 21 : if (hasAlternative) {
699 21 : renderPassInfo.attachmentCount = _attachmentDescriptionsAlternative.size();
700 21 : renderPassInfo.pAttachments = _attachmentDescriptionsAlternative.data();
701 :
702 21 : if (dev.getTable()->vkCreateRenderPass(dev.getDevice(), &renderPassInfo, nullptr, &pass.renderPassAlternative) != VK_SUCCESS) {
703 0 : return pass.cleanup(dev);
704 : }
705 : }
706 :
707 21 : if (initDescriptors(dev, data, pass)) {
708 21 : auto l = new Data(move(pass));
709 21 : _data = l;
710 21 : return core::RenderPass::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle, void *ptr) {
711 21 : auto d = ((Device *)dev);
712 21 : auto l = (Data *)ptr;
713 21 : l->cleanup(*d);
714 21 : delete l;
715 42 : }, core::ObjectType::RenderPass, ObjectHandle(_data->renderPass), l);
716 : }
717 :
718 0 : return pass.cleanup(dev);
719 21 : }
720 :
721 168 : bool RenderPass::initComputePass(Device &dev, QueuePassData &data) {
722 168 : Data pass;
723 168 : if (initDescriptors(dev, data, pass)) {
724 168 : auto l = new Data(move(pass));
725 168 : _data = l;
726 168 : return core::RenderPass::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle, void *ptr) {
727 168 : auto d = ((Device *)dev);
728 168 : auto l = (Data *)ptr;
729 168 : l->cleanup(*d);
730 168 : delete l;
731 336 : }, core::ObjectType::RenderPass, ObjectHandle(_data->renderPass), l);
732 : }
733 :
734 0 : return pass.cleanup(dev);
735 168 : }
736 :
737 168 : bool RenderPass::initTransferPass(Device &dev, QueuePassData &) {
738 : // init nothing - no descriptors or render pass implementation needed
739 168 : auto l = new Data();
740 168 : _data = l;
741 168 : return core::RenderPass::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle, void *ptr) {
742 168 : auto d = ((Device *)dev);
743 168 : auto l = (Data *)ptr;
744 168 : l->cleanup(*d);
745 168 : delete l;
746 336 : }, core::ObjectType::RenderPass, ObjectHandle(_data->renderPass), l);
747 : }
748 :
749 0 : bool RenderPass::initGenericPass(Device &dev, QueuePassData &) {
750 : // init nothing - no descriptors or render pass implementation needed
751 0 : auto l = new Data();
752 0 : _data = l;
753 0 : return core::RenderPass::init(dev, [] (core::Device *dev, core::ObjectType, ObjectHandle, void *ptr) {
754 0 : auto d = ((Device *)dev);
755 0 : auto l = (Data *)ptr;
756 0 : l->cleanup(*d);
757 0 : delete l;
758 0 : }, core::ObjectType::RenderPass, ObjectHandle(_data->renderPass), l);
759 : }
760 :
761 189 : bool RenderPass::initDescriptors(Device &dev, const QueuePassData &data, Data &pass) {
762 0 : auto cleanupLayouts = [&] {
763 0 : for (auto &it : pass.layouts) {
764 0 : for (VkDescriptorSetLayout &set : it.layouts) {
765 0 : dev.getTable()->vkDestroyDescriptorSetLayout(dev.getDevice(), set, nullptr);
766 : }
767 :
768 0 : if (it.layout) {
769 0 : dev.getTable()->vkDestroyPipelineLayout(dev.getDevice(), it.layout, nullptr);
770 : }
771 :
772 0 : if (it.descriptorPool) {
773 0 : dev.getTable()->vkDestroyDescriptorPool(dev.getDevice(), it.descriptorPool, nullptr);
774 : }
775 : }
776 0 : pass.layouts.clear();
777 0 : };
778 :
779 441 : for (auto &it : data.pipelineLayouts) {
780 252 : LayoutData &layoutData = pass.layouts.emplace_back();
781 252 : if (!initDescriptors(dev, *it, pass, layoutData)) {
782 0 : cleanupLayouts();
783 0 : return false;
784 : }
785 : }
786 :
787 189 : return true;
788 : }
789 :
790 252 : bool RenderPass::initDescriptors(Device &dev, const core::PipelineLayoutData &data, Data &, LayoutData &layoutData) {
791 252 : Vector<VkDescriptorPoolSize> sizes;
792 :
793 1701 : auto incrementSize = [&sizes] (VkDescriptorType type, uint32_t count) {
794 441 : auto lb = std::lower_bound(sizes.begin(), sizes.end(), type, [] (const VkDescriptorPoolSize &l, VkDescriptorType r) {
795 273 : return l.type < r;
796 : });
797 441 : if (lb == sizes.end()) {
798 294 : sizes.emplace_back(VkDescriptorPoolSize({type, count}));
799 147 : } else if (lb->type == type) {
800 63 : lb->descriptorCount += count;
801 : } else {
802 84 : sizes.emplace(lb, VkDescriptorPoolSize({type, count}));
803 : }
804 441 : };
805 :
806 252 : bool updateAfterBind = false;
807 :
808 252 : uint32_t maxSets = 0;
809 504 : for (auto &setData : data.sets) {
810 252 : ++ maxSets;
811 :
812 252 : auto descriptorSet = Rc<DescriptorSet>::alloc();
813 :
814 252 : bool hasFlags = false;
815 252 : Vector<VkDescriptorBindingFlags> flags;
816 252 : VkDescriptorSetLayout setLayout = VK_NULL_HANDLE;
817 252 : Vector<VkDescriptorSetLayoutBinding> bindings; bindings.reserve(setData->descriptors.size());
818 252 : size_t bindingIdx = 0;
819 693 : for (auto &binding : setData->descriptors) {
820 441 : if (binding->updateAfterBind) {
821 420 : flags.emplace_back(VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT);
822 420 : hasFlags = true;
823 420 : updateAfterBind = true;
824 : } else {
825 21 : flags.emplace_back(0);
826 : }
827 :
828 441 : binding->index = bindingIdx;
829 :
830 : VkDescriptorSetLayoutBinding b;
831 441 : b.binding = bindingIdx;
832 441 : b.descriptorCount = binding->count;
833 441 : b.descriptorType = VkDescriptorType(binding->type);
834 441 : b.stageFlags = VkShaderStageFlags(binding->stages);
835 441 : if (binding->type == DescriptorType::Sampler) {
836 : // do nothing
837 0 : log::warn("vk::RenderPass", "gl::DescriptorType::Sampler is not supported for descriptors");
838 : } else {
839 441 : incrementSize(VkDescriptorType(binding->type), binding->count);
840 441 : b.pImmutableSamplers = nullptr;
841 : }
842 441 : bindings.emplace_back(b);
843 441 : descriptorSet->bindings.emplace_back(DescriptorBinding(VkDescriptorType(binding->type), binding->count));
844 441 : ++ bindingIdx;
845 : }
846 252 : VkDescriptorSetLayoutCreateInfo layoutInfo { };
847 252 : layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
848 252 : layoutInfo.pNext = nullptr;
849 252 : layoutInfo.bindingCount = bindings.size();
850 252 : layoutInfo.pBindings = bindings.data();
851 252 : layoutInfo.flags = 0;
852 :
853 252 : if (hasFlags) {
854 252 : layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
855 :
856 : VkDescriptorSetLayoutBindingFlagsCreateInfoEXT bindingFlags;
857 252 : bindingFlags.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
858 252 : bindingFlags.pNext = nullptr;
859 252 : bindingFlags.bindingCount = flags.size();
860 252 : bindingFlags.pBindingFlags = flags.data();
861 252 : layoutInfo.pNext = &bindingFlags;
862 :
863 252 : if (dev.getTable()->vkCreateDescriptorSetLayout(dev.getDevice(), &layoutInfo, nullptr, &setLayout) == VK_SUCCESS) {
864 252 : layoutData.sets.emplace_back(move(descriptorSet));
865 252 : layoutData.layouts.emplace_back(setLayout);
866 : } else {
867 0 : return false;
868 : }
869 : } else {
870 0 : if (dev.getTable()->vkCreateDescriptorSetLayout(dev.getDevice(), &layoutInfo, nullptr, &setLayout) == VK_SUCCESS) {
871 0 : layoutData.sets.emplace_back(move(descriptorSet));
872 0 : layoutData.layouts.emplace_back(setLayout);
873 : } else {
874 0 : return false;
875 : }
876 : }
877 252 : }
878 :
879 252 : VkDescriptorPoolCreateInfo poolInfo{};
880 252 : poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
881 252 : poolInfo.pNext = nullptr;
882 252 : if (updateAfterBind) {
883 252 : poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
884 : } else {
885 0 : poolInfo.flags = 0;
886 : }
887 252 : poolInfo.poolSizeCount = sizes.size();
888 252 : poolInfo.pPoolSizes = sizes.data();
889 252 : poolInfo.maxSets = maxSets;
890 :
891 252 : if (dev.getTable()->vkCreateDescriptorPool(dev.getDevice(), &poolInfo, nullptr, &layoutData.descriptorPool) != VK_SUCCESS) {
892 0 : return false;
893 : }
894 :
895 252 : VkDescriptorSetAllocateInfo allocInfo{};
896 252 : allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
897 252 : allocInfo.pNext = nullptr;
898 252 : allocInfo.descriptorPool = layoutData.descriptorPool;
899 252 : allocInfo.descriptorSetCount = static_cast<uint32_t>(layoutData.layouts.size());
900 252 : allocInfo.pSetLayouts = layoutData.layouts.data();
901 :
902 252 : Vector<VkDescriptorSet> sets; sets.resize(layoutData.layouts.size());
903 :
904 252 : if (dev.getTable()->vkAllocateDescriptorSets(dev.getDevice(), &allocInfo, sets.data()) != VK_SUCCESS) {
905 0 : layoutData.sets.clear();
906 0 : return false;
907 : }
908 :
909 504 : for (size_t i = 0; i < sets.size(); ++ i) {
910 252 : layoutData.sets[i]->set = sets[i];
911 : }
912 :
913 252 : Vector<VkPushConstantRange> ranges;
914 :
915 1281 : auto addRange = [&] (VkShaderStageFlags flags, uint32_t offset, uint32_t size) {
916 1428 : for (auto &it : ranges) {
917 1197 : if (it.stageFlags == flags) {
918 1050 : if (offset < it.offset) {
919 0 : it.size += (it.offset - offset);
920 0 : it.offset = offset;
921 : }
922 1050 : if (size > it.size) {
923 147 : it.size = size;
924 : }
925 1050 : return;
926 : }
927 : }
928 :
929 231 : ranges.emplace_back(VkPushConstantRange{flags, offset, size});
930 252 : };
931 :
932 336 : for (auto &pipeline : data.graphicPipelines) {
933 252 : for (auto &shader : pipeline->shaders) {
934 378 : for (auto &constantBlock : shader.data->constants) {
935 210 : addRange(VkShaderStageFlags(shader.data->stage), constantBlock.offset, constantBlock.size);
936 : }
937 : }
938 : }
939 :
940 1764 : for (auto &pipeline : data.computePipelines) {
941 2583 : for (auto &constantBlock : pipeline->shader.data->constants) {
942 1071 : addRange(VkShaderStageFlags(pipeline->shader.data->stage), constantBlock.offset, constantBlock.size);
943 : }
944 : }
945 :
946 252 : auto textureSetLayout = dev.getTextureSetLayout();
947 252 : Vector<VkDescriptorSetLayout> layouts(layoutData.layouts);
948 252 : if (data.usesTextureSet) {
949 21 : layouts.emplace_back(textureSetLayout->getLayout());
950 : }
951 :
952 : VkPipelineLayoutCreateInfo pipelineLayoutInfo;
953 252 : pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
954 252 : pipelineLayoutInfo.pNext = nullptr;
955 252 : pipelineLayoutInfo.flags = 0;
956 252 : pipelineLayoutInfo.setLayoutCount = layouts.size();
957 252 : pipelineLayoutInfo.pSetLayouts = layouts.data();
958 252 : pipelineLayoutInfo.pushConstantRangeCount = ranges.size();
959 252 : pipelineLayoutInfo.pPushConstantRanges = ranges.data();
960 :
961 252 : if (dev.getTable()->vkCreatePipelineLayout(dev.getDevice(), &pipelineLayoutInfo, nullptr, &layoutData.layout) == VK_SUCCESS) {
962 252 : return true;
963 : }
964 :
965 0 : return false;
966 252 : }
967 :
968 : }
|