Skip to content

Commit 4371b0e

Browse files
committed
inspect runtime errors, update code (update raster setup, use CSwapchainFramebuffersAndDepth, add missing descriptor set updates & use device's utils for descriptor pool creation) - finally I see the cube on the screen
1 parent 92820fb commit 4371b0e

File tree

3 files changed

+162
-61
lines changed

3 files changed

+162
-61
lines changed

64_Gizmo/main.cpp

Lines changed: 158 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,88 @@ using namespace asset;
1919
using namespace ui;
2020
using namespace video;
2121

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+
22104
class CEventCallback : public ISimpleManagedSurface::ICallback
23105
{
24106
public:
@@ -94,7 +176,7 @@ class GizmoApp final : public examples::SimpleWindowedApplication
94176
}
95177

96178
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));
98180
}
99181

100182
if (m_surface)
@@ -118,32 +200,41 @@ class GizmoApp final : public examples::SimpleWindowedApplication
118200
if (!swapchainParams.deduceFormat(m_physicalDevice))
119201
return logFail("Could not choose a Surface Format for the Swapchain!");
120202

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
123206
{
124207
.srcSubpass = IGPURenderpass::SCreationParams::SSubpassDependency::External,
125208
.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
134222
{
135223
.srcSubpass = 0,
136224
.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
144235
};
145236

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);
147238
auto* renderpass = scResources->getRenderpass();
148239

149240
if (!renderpass)
@@ -173,21 +264,6 @@ class GizmoApp final : public examples::SimpleWindowedApplication
173264
m_winMgr->setWindowSize(m_window.get(), WIN_W, WIN_H);
174265
m_surface->recreateSwapchain();
175266

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-
191267
SPushConstantRange pushConstantRanges[] = {
192268
{
193269
.stageFlags = IShader::ESS_VERTEX,
@@ -207,11 +283,24 @@ class GizmoApp final : public examples::SimpleWindowedApplication
207283
};
208284

209285
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+
}
210293

211294
m_gpuDescriptorSet = m_descriptorPool->createDescriptorSet(descriptorSetLayout);
212295

296+
if (!m_gpuDescriptorSet)
297+
return logFail("Could not create Descriptor Set!");
298+
213299
auto pipelineLayout = m_device->createPipelineLayout(pushConstantRanges, nullptr, std::move(descriptorSetLayout));
214300

301+
if (!pipelineLayout)
302+
return logFail("Could not create Pipeline Layout!");
303+
215304
struct
216305
{
217306
core::smart_refctd_ptr<video::IGPUShader> vertex, fragment;
@@ -271,11 +360,6 @@ class GizmoApp final : public examples::SimpleWindowedApplication
271360
}
272361

273362
SRasterizationParams rasterizationParams{};
274-
{
275-
rasterizationParams.faceCullingMode = EFCM_NONE;
276-
rasterizationParams.depthWriteEnable = false;
277-
rasterizationParams.depthBoundsTestEnable = false;
278-
}
279363

280364
SPrimitiveAssemblyParams primitiveAssemblyParams{};
281365
{
@@ -299,10 +383,7 @@ class GizmoApp final : public examples::SimpleWindowedApplication
299383
};
300384

301385
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!");
306387
}
307388

308389
auto getRandomColor = []
@@ -327,20 +408,19 @@ class GizmoApp final : public examples::SimpleWindowedApplication
327408
VSInput{{-1.0f, 1.0f, 1.0f, 1.0f}, {getRandomColor(), getRandomColor(), getRandomColor(), 1.0f}} // vertex 7
328409
});
329410

330-
// indices of the cube
331411
_NBL_STATIC_INLINE_CONSTEXPR auto indices = std::to_array<uint16_t>(
332412
{
333-
// Front face
413+
// Front face (0, 1, 2, 3)
334414
0, 1, 2, 2, 3, 0,
335-
// Back face
415+
// Back face (4, 5, 6, 7)
336416
4, 5, 6, 6, 7, 4,
337-
// Left face
417+
// Left face (0, 3, 7, 4)
338418
0, 3, 7, 7, 4, 0,
339-
// Right face
419+
// Right face (1, 2, 6, 5)
340420
1, 5, 6, 6, 2, 1,
341-
// Top face
421+
// Top face (3, 2, 6, 7)
342422
3, 2, 6, 6, 7, 3,
343-
// Bottom face
423+
// Bottom face (0, 1, 5, 4)
344424
0, 1, 5, 5, 4, 0
345425
});
346426

@@ -359,22 +439,40 @@ class GizmoApp final : public examples::SimpleWindowedApplication
359439
m_device->allocate(reqs, it.get());
360440
}
361441

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+
362458
{
363459
auto vBinding = m_vertexBuffer->getBoundMemory();
364460
auto iBinding = m_indexBuffer->getBoundMemory();
365461

366462
{
367463
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!");
369465

370-
assert(vBinding.memory->isCurrentlyMapped());
466+
if(!vBinding.memory->isCurrentlyMapped())
467+
return logFail("Vertex Buffer memory is not mapped!");
371468
}
372469

373470
{
374471
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!");
376473

377-
assert(iBinding.memory->isCurrentlyMapped());
474+
if(!iBinding.memory->isCurrentlyMapped())
475+
return logFail("Index Buffer memory is not mapped!");
378476
}
379477

380478
auto* vPointer = static_cast<VSInput*>(vBinding.memory->getMappedPointer());
@@ -390,10 +488,10 @@ class GizmoApp final : public examples::SimpleWindowedApplication
390488

391489
// camera
392490
{
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);
395493
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);
397495
}
398496

399497
m_winMgr->show(m_window.get());
@@ -495,12 +593,13 @@ class GizmoApp final : public examples::SimpleWindowedApplication
495593
};
496594

497595
const IGPUCommandBuffer::SClearColorValue clearValue = { .float32 = {0.f,0.f,0.f,1.f} };
596+
const IGPUCommandBuffer::SClearDepthStencilValue depthValue = { .depth = 0.f };
498597
auto scRes = static_cast<CDefaultSwapchainFramebuffers*>(m_surface->getSwapchainResources());
499598
const IGPUCommandBuffer::SRenderpassBeginInfo info =
500599
{
501600
.framebuffer = scRes->getFramebuffer(m_currentImageAcquire.imageIndex),
502601
.colorClearValues = &clearValue,
503-
.depthStencilClearValues = nullptr,
602+
.depthStencilClearValues = &depthValue,
504603
.renderArea = currentRenderArea
505604
};
506605

@@ -578,7 +677,7 @@ class GizmoApp final : public examples::SimpleWindowedApplication
578677

579678
private:
580679
smart_refctd_ptr<IWindow> m_window;
581-
smart_refctd_ptr<CSimpleResizeSurface<CDefaultSwapchainFramebuffers>> m_surface;
680+
smart_refctd_ptr<CSimpleResizeSurface<CSwapchainFramebuffersAndDepth>> m_surface;
582681
smart_refctd_ptr<IGPUGraphicsPipeline> m_pipeline;
583682
smart_refctd_ptr<ISemaphore> m_semaphore;
584683
smart_refctd_ptr<IGPUCommandPool> m_cmdPool;

64_Gizmo/shaders/common.hlsl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@
1111
float4 color : COLOR0;
1212
};
1313

14-
struct SBasicViewParameters
14+
struct SBasicViewParameters //! matches CPU version size & alignment (160, 4)
1515
{
1616
float4x4 MVP;
1717
float3x4 MV;
1818
float3x3 normalMat;
19-
float3 padding;
2019
};
2120
#else
2221
#include "nbl/nblpack.h"
@@ -33,4 +32,6 @@
3332
struct PushConstants
3433
{
3534
bool withGizmo;
35+
36+
bool padding[3]; //! size of PushConstants must be multiple of 4
3637
};

64_Gizmo/shaders/vertex.hlsl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
[[vk::push_constant]] struct PushConstants pc;
44

5+
// set 1, binding 0
56
[[vk::binding(0, 1)]]
67
cbuffer CameraData
78
{

0 commit comments

Comments
 (0)