@@ -19,6 +19,88 @@ using namespace asset;
19
19
using namespace ui ;
20
20
using namespace video ;
21
21
22
+ class CSwapchainFramebuffersAndDepth final : public nbl::video::CDefaultSwapchainFramebuffers
23
+ {
24
+ using base_t = CDefaultSwapchainFramebuffers;
25
+
26
+ public:
27
+ template <typename ... Args>
28
+ inline CSwapchainFramebuffersAndDepth (ILogicalDevice* device, const asset::E_FORMAT _desiredDepthFormat, Args&&... args) : CDefaultSwapchainFramebuffers(device, std::forward<Args>(args)...)
29
+ {
30
+ const IPhysicalDevice::SImageFormatPromotionRequest req = {
31
+ .originalFormat = _desiredDepthFormat,
32
+ .usages = {IGPUImage::EUF_RENDER_ATTACHMENT_BIT}
33
+ };
34
+ m_depthFormat = m_device->getPhysicalDevice ()->promoteImageFormat (req, IGPUImage::TILING::OPTIMAL);
35
+
36
+ const static IGPURenderpass::SCreationParams::SDepthStencilAttachmentDescription depthAttachments[] = {
37
+ {{
38
+ {
39
+ .format = m_depthFormat,
40
+ .samples = IGPUImage::ESCF_1_BIT,
41
+ .mayAlias = false
42
+ },
43
+ /* .loadOp = */ {IGPURenderpass::LOAD_OP::CLEAR},
44
+ /* .storeOp = */ {IGPURenderpass::STORE_OP::STORE},
45
+ /* .initialLayout = */ {IGPUImage::LAYOUT::UNDEFINED}, // because we clear we don't care about contents
46
+ /* .finalLayout = */ {IGPUImage::LAYOUT::ATTACHMENT_OPTIMAL} // transition to presentation right away so we can skip a barrier
47
+ }},
48
+ IGPURenderpass::SCreationParams::DepthStencilAttachmentsEnd
49
+ };
50
+ m_params.depthStencilAttachments = depthAttachments;
51
+
52
+ static IGPURenderpass::SCreationParams::SSubpassDescription subpasses[] = {
53
+ m_params.subpasses [0 ],
54
+ IGPURenderpass::SCreationParams::SubpassesEnd
55
+ };
56
+ subpasses[0 ].depthStencilAttachment .render = { .attachmentIndex = 0 ,.layout = IGPUImage::LAYOUT::ATTACHMENT_OPTIMAL };
57
+ m_params.subpasses = subpasses;
58
+ }
59
+
60
+ protected:
61
+ inline bool onCreateSwapchain_impl (const uint8_t qFam) override
62
+ {
63
+ auto device = const_cast <ILogicalDevice*>(m_renderpass->getOriginDevice ());
64
+
65
+ const auto depthFormat = m_renderpass->getCreationParameters ().depthStencilAttachments [0 ].format ;
66
+ const auto & sharedParams = getSwapchain ()->getCreationParameters ().sharedParams ;
67
+ auto image = device->createImage ({ IImage::SCreationParams{
68
+ .type = IGPUImage::ET_2D,
69
+ .samples = IGPUImage::ESCF_1_BIT,
70
+ .format = depthFormat,
71
+ .extent = {sharedParams.width ,sharedParams.height ,1 },
72
+ .mipLevels = 1 ,
73
+ .arrayLayers = 1 ,
74
+ .depthUsage = IGPUImage::EUF_RENDER_ATTACHMENT_BIT
75
+ } });
76
+
77
+ device->allocate (image->getMemoryReqs (), image.get ());
78
+
79
+ m_depthBuffer = device->createImageView ({
80
+ .flags = IGPUImageView::ECF_NONE,
81
+ .subUsages = IGPUImage::EUF_RENDER_ATTACHMENT_BIT,
82
+ .image = std::move (image),
83
+ .viewType = IGPUImageView::ET_2D,
84
+ .format = depthFormat,
85
+ .subresourceRange = {IGPUImage::EAF_DEPTH_BIT,0 ,1 ,0 ,1 }
86
+ });
87
+
88
+ const auto retval = base_t::onCreateSwapchain_impl (qFam);
89
+ m_depthBuffer = nullptr ;
90
+ return retval;
91
+ }
92
+
93
+ inline smart_refctd_ptr<IGPUFramebuffer> createFramebuffer (IGPUFramebuffer::SCreationParams&& params) override
94
+ {
95
+ params.depthStencilAttachments = &m_depthBuffer.get ();
96
+ return m_device->createFramebuffer (std::move (params));
97
+ }
98
+
99
+ E_FORMAT m_depthFormat;
100
+ // only used to pass a parameter from `onCreateSwapchain_impl` to `createFramebuffer`
101
+ smart_refctd_ptr<IGPUImageView> m_depthBuffer;
102
+ };
103
+
22
104
class CEventCallback : public ISimpleManagedSurface ::ICallback
23
105
{
24
106
public:
@@ -94,7 +176,7 @@ class GizmoApp final : public examples::SimpleWindowedApplication
94
176
}
95
177
96
178
auto surface = CSurfaceVulkanWin32::create (smart_refctd_ptr (m_api), smart_refctd_ptr_static_cast<IWindowWin32>(m_window));
97
- const_cast <std::remove_const_t <decltype (m_surface)>&>(m_surface) = nbl::video::CSimpleResizeSurface<nbl::video::CDefaultSwapchainFramebuffers >::create (std::move (surface));
179
+ const_cast <std::remove_const_t <decltype (m_surface)>&>(m_surface) = nbl::video::CSimpleResizeSurface<CSwapchainFramebuffersAndDepth >::create (std::move (surface));
98
180
}
99
181
100
182
if (m_surface)
@@ -118,32 +200,41 @@ class GizmoApp final : public examples::SimpleWindowedApplication
118
200
if (!swapchainParams.deduceFormat (m_physicalDevice))
119
201
return logFail (" Could not choose a Surface Format for the Swapchain!" );
120
202
121
- const static IGPURenderpass::SCreationParams::SSubpassDependency dependencies[] =
122
- {
203
+ // Subsequent submits don't wait for each other, hence its important to have External Dependencies which prevent users of the depth attachment overlapping.
204
+ const static IGPURenderpass::SCreationParams::SSubpassDependency dependencies[] = {
205
+ // wipe-transition of Color to ATTACHMENT_OPTIMAL
123
206
{
124
207
.srcSubpass = IGPURenderpass::SCreationParams::SSubpassDependency::External,
125
208
.dstSubpass = 0 ,
126
- .memoryBarrier =
127
- {
128
- .srcStageMask = asset::PIPELINE_STAGE_FLAGS::COPY_BIT,
129
- .srcAccessMask = asset::ACCESS_FLAGS::TRANSFER_WRITE_BIT,
130
- .dstStageMask = asset::PIPELINE_STAGE_FLAGS::COLOR_ATTACHMENT_OUTPUT_BIT,
131
- .dstAccessMask = asset::ACCESS_FLAGS::COLOR_ATTACHMENT_WRITE_BIT
132
- }
133
- },
209
+ .memoryBarrier = {
210
+ // last place where the depth can get modified in previous frame
211
+ .srcStageMask = PIPELINE_STAGE_FLAGS::LATE_FRAGMENT_TESTS_BIT,
212
+ // only write ops, reads can't be made available
213
+ .srcAccessMask = ACCESS_FLAGS::DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
214
+ // destination needs to wait as early as possible
215
+ .dstStageMask = PIPELINE_STAGE_FLAGS::EARLY_FRAGMENT_TESTS_BIT,
216
+ // because of depth test needing a read and a write
217
+ .dstAccessMask = ACCESS_FLAGS::DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | ACCESS_FLAGS::DEPTH_STENCIL_ATTACHMENT_READ_BIT
218
+ }
219
+ // leave view offsets and flags default
220
+ },
221
+ // color from ATTACHMENT_OPTIMAL to PRESENT_SRC
134
222
{
135
223
.srcSubpass = 0 ,
136
224
.dstSubpass = IGPURenderpass::SCreationParams::SSubpassDependency::External,
137
- .memoryBarrier =
138
- {
139
- .srcStageMask = asset::PIPELINE_STAGE_FLAGS::COLOR_ATTACHMENT_OUTPUT_BIT,
140
- .srcAccessMask = asset::ACCESS_FLAGS::COLOR_ATTACHMENT_WRITE_BIT
141
- }
142
- },
143
- IGPURenderpass::SCreationParams::DependenciesEnd
225
+ .memoryBarrier = {
226
+ // last place where the depth can get modified
227
+ .srcStageMask = PIPELINE_STAGE_FLAGS::COLOR_ATTACHMENT_OUTPUT_BIT,
228
+ // only write ops, reads can't be made available
229
+ .srcAccessMask = ACCESS_FLAGS::COLOR_ATTACHMENT_WRITE_BIT
230
+ // spec says nothing is needed when presentation is the destination
231
+ }
232
+ // leave view offsets and flags default
233
+ },
234
+ IGPURenderpass::SCreationParams::DependenciesEnd
144
235
};
145
236
146
- auto scResources = std::make_unique<CDefaultSwapchainFramebuffers >(m_device.get (), swapchainParams.surfaceFormat .format , dependencies);
237
+ auto scResources = std::make_unique<CSwapchainFramebuffersAndDepth >(m_device.get (), EF_D16_UNORM , swapchainParams.surfaceFormat .format , dependencies);
147
238
auto * renderpass = scResources->getRenderpass ();
148
239
149
240
if (!renderpass)
@@ -173,21 +264,6 @@ class GizmoApp final : public examples::SimpleWindowedApplication
173
264
m_winMgr->setWindowSize (m_window.get (), WIN_W, WIN_H);
174
265
m_surface->recreateSwapchain ();
175
266
176
- {
177
- static constexpr int TotalSetCount = 1 ;
178
- IDescriptorPool::SCreateInfo createInfo = {};
179
- createInfo.maxDescriptorCount [static_cast <uint32_t >(asset::IDescriptor::E_TYPE::ET_COMBINED_IMAGE_SAMPLER)] = TotalSetCount;
180
- createInfo.maxSets = 1 ;
181
- createInfo.flags = IDescriptorPool::E_CREATE_FLAGS::ECF_NONE;
182
-
183
- m_descriptorPool = m_device->createDescriptorPool (std::move (createInfo));
184
- if (!m_descriptorPool)
185
- {
186
- m_logger->log (" Could not create Descriptor Pool!" , system::ILogger::ELL_ERROR);
187
- return false ;
188
- }
189
- }
190
-
191
267
SPushConstantRange pushConstantRanges[] = {
192
268
{
193
269
.stageFlags = IShader::ESS_VERTEX,
@@ -207,11 +283,24 @@ class GizmoApp final : public examples::SimpleWindowedApplication
207
283
};
208
284
209
285
auto descriptorSetLayout = m_device->createDescriptorSetLayout (bindings);
286
+ {
287
+ const video::IGPUDescriptorSetLayout* const layouts[] = { nullptr , descriptorSetLayout.get () };
288
+ const uint32_t setCounts[] = { 0u , 1u };
289
+ m_descriptorPool = m_device->createDescriptorPoolForDSLayouts (IDescriptorPool::E_CREATE_FLAGS::ECF_NONE, layouts, setCounts);
290
+ if (!m_descriptorPool)
291
+ return logFail (" Failed to Create Descriptor Pool" );
292
+ }
210
293
211
294
m_gpuDescriptorSet = m_descriptorPool->createDescriptorSet (descriptorSetLayout);
212
295
296
+ if (!m_gpuDescriptorSet)
297
+ return logFail (" Could not create Descriptor Set!" );
298
+
213
299
auto pipelineLayout = m_device->createPipelineLayout (pushConstantRanges, nullptr , std::move (descriptorSetLayout));
214
300
301
+ if (!pipelineLayout)
302
+ return logFail (" Could not create Pipeline Layout!" );
303
+
215
304
struct
216
305
{
217
306
core::smart_refctd_ptr<video::IGPUShader> vertex, fragment;
@@ -271,11 +360,6 @@ class GizmoApp final : public examples::SimpleWindowedApplication
271
360
}
272
361
273
362
SRasterizationParams rasterizationParams{};
274
- {
275
- rasterizationParams.faceCullingMode = EFCM_NONE;
276
- rasterizationParams.depthWriteEnable = false ;
277
- rasterizationParams.depthBoundsTestEnable = false ;
278
- }
279
363
280
364
SPrimitiveAssemblyParams primitiveAssemblyParams{};
281
365
{
@@ -299,10 +383,7 @@ class GizmoApp final : public examples::SimpleWindowedApplication
299
383
};
300
384
301
385
if (!m_device->createGraphicsPipelines (nullptr , params, &pipeline))
302
- {
303
- m_logger->log (" Could not create pipeline!" , system::ILogger::ELL_ERROR);
304
- assert (false );
305
- }
386
+ return logFail (" Could not create pipeline!" );
306
387
}
307
388
308
389
auto getRandomColor = []
@@ -327,20 +408,19 @@ class GizmoApp final : public examples::SimpleWindowedApplication
327
408
VSInput{{-1 .0f , 1 .0f , 1 .0f , 1 .0f }, {getRandomColor (), getRandomColor (), getRandomColor (), 1 .0f }} // vertex 7
328
409
});
329
410
330
- // indices of the cube
331
411
_NBL_STATIC_INLINE_CONSTEXPR auto indices = std::to_array<uint16_t >(
332
412
{
333
- // Front face
413
+ // Front face (0, 1, 2, 3)
334
414
0 , 1 , 2 , 2 , 3 , 0 ,
335
- // Back face
415
+ // Back face (4, 5, 6, 7)
336
416
4 , 5 , 6 , 6 , 7 , 4 ,
337
- // Left face
417
+ // Left face (0, 3, 7, 4)
338
418
0 , 3 , 7 , 7 , 4 , 0 ,
339
- // Right face
419
+ // Right face (1, 2, 6, 5)
340
420
1 , 5 , 6 , 6 , 2 , 1 ,
341
- // Top face
421
+ // Top face (3, 2, 6, 7)
342
422
3 , 2 , 6 , 6 , 7 , 3 ,
343
- // Bottom face
423
+ // Bottom face (0, 1, 5, 4)
344
424
0 , 1 , 5 , 5 , 4 , 0
345
425
});
346
426
@@ -359,22 +439,40 @@ class GizmoApp final : public examples::SimpleWindowedApplication
359
439
m_device->allocate (reqs, it.get ());
360
440
}
361
441
442
+ {
443
+ video::IGPUDescriptorSet::SWriteDescriptorSet write;
444
+ write.dstSet = m_gpuDescriptorSet.get ();
445
+ write.binding = 0 ;
446
+ write.arrayElement = 0u ;
447
+ write.count = 1u ;
448
+ video::IGPUDescriptorSet::SDescriptorInfo info;
449
+ {
450
+ info.desc = core::smart_refctd_ptr (m_ubo);
451
+ info.info .buffer .offset = 0ull ;
452
+ info.info .buffer .size = m_ubo->getSize ();
453
+ }
454
+ write.info = &info;
455
+ m_device->updateDescriptorSets (1u , &write, 0u , nullptr );
456
+ }
457
+
362
458
{
363
459
auto vBinding = m_vertexBuffer->getBoundMemory ();
364
460
auto iBinding = m_indexBuffer->getBoundMemory ();
365
461
366
462
{
367
463
if (!vBinding.memory ->map ({ 0ull , vBinding.memory ->getAllocationSize () }, IDeviceMemoryAllocation::EMCAF_READ))
368
- m_logger-> log (" Could not map device memory for vertex buffer data!" , system::ILogger::ELL_ERROR );
464
+ return logFail (" Could not map device memory for vertex buffer data!" );
369
465
370
- assert (vBinding.memory ->isCurrentlyMapped ());
466
+ if (!vBinding.memory ->isCurrentlyMapped ())
467
+ return logFail (" Vertex Buffer memory is not mapped!" );
371
468
}
372
469
373
470
{
374
471
if (!iBinding.memory ->map ({ 0ull , iBinding.memory ->getAllocationSize () }, IDeviceMemoryAllocation::EMCAF_READ))
375
- m_logger-> log (" Could not map device memory for index buffer data!" , system::ILogger::ELL_ERROR );
472
+ return logFail (" Could not map device memory for index buffer data!" );
376
473
377
- assert (iBinding.memory ->isCurrentlyMapped ());
474
+ if (!iBinding.memory ->isCurrentlyMapped ())
475
+ return logFail (" Index Buffer memory is not mapped!" );
378
476
}
379
477
380
478
auto * vPointer = static_cast <VSInput*>(vBinding.memory ->getMappedPointer ());
@@ -390,10 +488,10 @@ class GizmoApp final : public examples::SimpleWindowedApplication
390
488
391
489
// camera
392
490
{
393
- core::vectorSIMDf cameraPosition (-250 . 0f , 177 . 0f , 1 . 69f );
394
- core::vectorSIMDf cameraTarget (50 . 0f , 125 . 0f , - 3 . 0f );
491
+ core::vectorSIMDf cameraPosition (-5.81655884 , 2.58630896 , - 4.23974705 );
492
+ core::vectorSIMDf cameraTarget (- 0.349590302 , - 0.213266611 , 0.317821503 );
395
493
matrix4SIMD projectionMatrix = matrix4SIMD::buildProjectionMatrixPerspectiveFovLH (core::radians (60 .0f ), float (WIN_W) / WIN_H, 0.1 , 10000 );
396
- camera = Camera (cameraPosition, cameraTarget, projectionMatrix, 10 . f , 1 . f );
494
+ camera = Camera (cameraPosition, cameraTarget, projectionMatrix, 1 . 069f , 0 . 4f );
397
495
}
398
496
399
497
m_winMgr->show (m_window.get ());
@@ -495,12 +593,13 @@ class GizmoApp final : public examples::SimpleWindowedApplication
495
593
};
496
594
497
595
const IGPUCommandBuffer::SClearColorValue clearValue = { .float32 = {0 .f ,0 .f ,0 .f ,1 .f } };
596
+ const IGPUCommandBuffer::SClearDepthStencilValue depthValue = { .depth = 0 .f };
498
597
auto scRes = static_cast <CDefaultSwapchainFramebuffers*>(m_surface->getSwapchainResources ());
499
598
const IGPUCommandBuffer::SRenderpassBeginInfo info =
500
599
{
501
600
.framebuffer = scRes->getFramebuffer (m_currentImageAcquire.imageIndex ),
502
601
.colorClearValues = &clearValue,
503
- .depthStencilClearValues = nullptr ,
602
+ .depthStencilClearValues = &depthValue ,
504
603
.renderArea = currentRenderArea
505
604
};
506
605
@@ -578,7 +677,7 @@ class GizmoApp final : public examples::SimpleWindowedApplication
578
677
579
678
private:
580
679
smart_refctd_ptr<IWindow> m_window;
581
- smart_refctd_ptr<CSimpleResizeSurface<CDefaultSwapchainFramebuffers >> m_surface;
680
+ smart_refctd_ptr<CSimpleResizeSurface<CSwapchainFramebuffersAndDepth >> m_surface;
582
681
smart_refctd_ptr<IGPUGraphicsPipeline> m_pipeline;
583
682
smart_refctd_ptr<ISemaphore> m_semaphore;
584
683
smart_refctd_ptr<IGPUCommandPool> m_cmdPool;
0 commit comments