88#include " nbl/asset/interchange/IAssetLoader.h"
99#include " nbl/ext/FullScreenTriangle/FullScreenTriangle.h"
1010
11-
1211using namespace nbl ;
1312using namespace core ;
1413using namespace hlsl ;
@@ -95,6 +94,9 @@ class AutoexposureApp final : public examples::SimpleWindowedApplication, public
9594
9695 }
9796
97+ // Create semaphore
98+ m_semaphore = m_device->createSemaphore (m_submitIx);
99+
98100 // create the descriptor set and with enough room for one image sampler
99101 {
100102 const uint32_t setCount = 1 ;
@@ -107,6 +109,7 @@ class AutoexposureApp final : public examples::SimpleWindowedApplication, public
107109 return logFail (" Could not create Descriptor Set!" );
108110 }
109111
112+ auto ds = m_descriptorSets[0 ].get ();
110113 auto queue = getGraphicsQueue ();
111114
112115 // Gather swapchain resources
@@ -256,7 +259,7 @@ class AutoexposureApp final : public examples::SimpleWindowedApplication, public
256259 const auto cpuImgView = ICPUImageView::create (std::move (viewParams));
257260 const auto & cpuImgParams = cpuImgView->getCreationParameters ();
258261
259- // create matching size image
262+ // create matching size image upto dimensions
260263 IGPUImage::SCreationParams imageParams = {};
261264 imageParams = cpuImgParams.image ->getCreationParameters ();
262265 imageParams.usage |= IGPUImage::EUF_TRANSFER_DST_BIT | IGPUImage::EUF_SAMPLED_BIT | IGPUImage::E_USAGE_FLAGS::EUF_TRANSFER_SRC_BIT;
@@ -304,7 +307,6 @@ class AutoexposureApp final : public examples::SimpleWindowedApplication, public
304307
305308 // upload image and write to descriptor set
306309 queue->startCapture ();
307- auto ds = m_descriptorSets[0 ].get ();
308310
309311 cmdbuf->begin (IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT);
310312 // change the layout of the image
@@ -331,11 +333,28 @@ class AutoexposureApp final : public examples::SimpleWindowedApplication, public
331333 );
332334 IGPUImageView::SCreationParams gpuImgViewParams = {
333335 .image = m_gpuImg,
334- .viewType = IGPUImageView::ET_2D_ARRAY ,
336+ .viewType = IGPUImageView::ET_2D ,
335337 .format = m_gpuImg->getCreationParameters ().format
336338 };
337339
338340 m_gpuImgView = m_device->createImageView (std::move (gpuImgViewParams));
341+
342+ IGPUDescriptorSet::SDescriptorInfo info = {};
343+ info.info .image .imageLayout = IImage::LAYOUT::READ_ONLY_OPTIMAL;
344+ info.desc = m_gpuImgView;
345+
346+ IGPUDescriptorSet::SWriteDescriptorSet writeDescriptors[] = {
347+ {
348+ .dstSet = ds,
349+ .binding = 0 ,
350+ .arrayElement = 0 ,
351+ .count = 1 ,
352+ .info = &info
353+ }
354+ };
355+
356+ m_device->updateDescriptorSets (1 , writeDescriptors, 0 , nullptr );
357+
339358 queue->endCapture ();
340359 }
341360
@@ -345,6 +364,119 @@ class AutoexposureApp final : public examples::SimpleWindowedApplication, public
345364 // We do a very simple thing, display an image and wait `DisplayImageMs` to show it
346365 inline void workLoopBody () override
347366 {
367+ // Acquire
368+ auto acquire = m_surface->acquireNextImage ();
369+ if (!acquire)
370+ return ;
371+
372+ auto queue = getGraphicsQueue ();
373+ auto cmdbuf = m_cmdBufs[0 ].get ();
374+ auto ds = m_descriptorSets[0 ].get ();
375+
376+ // there's no previous operation to wait for
377+ const SMemoryBarrier toTransferBarrier = {
378+ .dstStageMask = PIPELINE_STAGE_FLAGS::COPY_BIT,
379+ .dstAccessMask = ACCESS_FLAGS::TRANSFER_WRITE_BIT
380+ };
381+ const auto gpuImgCreationParams = m_gpuImg->getCreationParameters ();
382+ const auto gpuImgViewCreationParams = m_gpuImgView->getCreationParameters ();
383+
384+ queue->startCapture ();
385+ // Render to the Image
386+ {
387+ cmdbuf->begin (IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT);
388+
389+ // need a pipeline barrier to transition layout
390+ const IGPUCommandBuffer::SImageMemoryBarrier<IGPUCommandBuffer::SOwnershipTransferBarrier> imgBarriers[] = { {
391+ .barrier = {
392+ .dep = toTransferBarrier.nextBarrier (PIPELINE_STAGE_FLAGS::FRAGMENT_SHADER_BIT,ACCESS_FLAGS::SAMPLED_READ_BIT)
393+ },
394+ .image = m_gpuImg.get (),
395+ .subresourceRange = gpuImgViewCreationParams.subresourceRange ,
396+ .oldLayout = IGPUImage::LAYOUT::TRANSFER_DST_OPTIMAL,
397+ .newLayout = IGPUImage::LAYOUT::READ_ONLY_OPTIMAL
398+ } };
399+ cmdbuf->pipelineBarrier (E_DEPENDENCY_FLAGS::EDF_NONE, { .imgBarriers = imgBarriers });
400+
401+ const VkRect2D currentRenderArea =
402+ {
403+ .offset = {0 ,0 },
404+ .extent = {gpuImgCreationParams.extent .width , gpuImgCreationParams.extent .height }
405+ };
406+ // set viewport
407+ {
408+ const asset::SViewport viewport =
409+ {
410+ .width = float (gpuImgCreationParams.extent .width ),
411+ .height = float (gpuImgCreationParams.extent .height )
412+ };
413+ cmdbuf->setViewport ({ &viewport,1 });
414+ }
415+ cmdbuf->setScissor ({ ¤tRenderArea,1 });
416+
417+ // begin the renderpass
418+ {
419+ const IGPUCommandBuffer::SClearColorValue clearValue = { .float32 = {1 .f ,0 .f ,1 .f ,1 .f } };
420+ auto scRes = static_cast <CDefaultSwapchainFramebuffers*>(m_surface->getSwapchainResources ());
421+ const IGPUCommandBuffer::SRenderpassBeginInfo info = {
422+ .framebuffer = scRes->getFramebuffer (acquire.imageIndex ),
423+ .colorClearValues = &clearValue,
424+ .depthStencilClearValues = nullptr ,
425+ .renderArea = currentRenderArea
426+ };
427+ cmdbuf->beginRenderPass (info, IGPUCommandBuffer::SUBPASS_CONTENTS::INLINE);
428+ }
429+ cmdbuf->bindGraphicsPipeline (m_pipeline.get ());
430+ cmdbuf->bindDescriptorSets (nbl::asset::EPBP_GRAPHICS, m_pipeline->getLayout (), 3 , 1 , &ds);
431+ ext::FullScreenTriangle::recordDrawCall (cmdbuf);
432+ cmdbuf->endRenderPass ();
433+
434+ cmdbuf->end ();
435+ }
436+
437+ // submit
438+ const IQueue::SSubmitInfo::SSemaphoreInfo rendered[1 ] = { {
439+ .semaphore = m_semaphore.get (),
440+ .value = ++m_submitIx,
441+ // just as we've outputted all pixels, signal
442+ .stageMask = PIPELINE_STAGE_FLAGS::COLOR_ATTACHMENT_OUTPUT_BIT
443+ } };
444+ {
445+ {
446+ const IQueue::SSubmitInfo::SCommandBufferInfo commandBuffers[1 ] = { {
447+ .cmdbuf = cmdbuf
448+ } };
449+ // we don't need to wait for the transfer semaphore, because we submit everything to the same queue
450+ const IQueue::SSubmitInfo::SSemaphoreInfo acquired[1 ] = { {
451+ .semaphore = acquire.semaphore ,
452+ .value = acquire.acquireCount ,
453+ .stageMask = PIPELINE_STAGE_FLAGS::NONE
454+ } };
455+ const IQueue::SSubmitInfo infos[1 ] = { {
456+ .waitSemaphores = acquired,
457+ .commandBuffers = commandBuffers,
458+ .signalSemaphores = rendered
459+ } };
460+ // we won't signal the sema if no success
461+ if (queue->submit (infos) != IQueue::RESULT::SUCCESS)
462+ m_submitIx--;
463+ }
464+ }
465+
466+ // Present
467+ m_surface->present (acquire.imageIndex , rendered);
468+ getGraphicsQueue ()->endCapture ();
469+
470+ {
471+ const ISemaphore::SWaitInfo cmdbufDonePending[] = {
472+ {
473+ .semaphore = m_semaphore.get (),
474+ .value = m_submitIx
475+ }
476+ };
477+ if (m_device->blockForSemaphores (cmdbufDonePending) != ISemaphore::WAIT_RESULT::SUCCESS)
478+ return ;
479+ }
348480 }
349481
350482 inline bool keepRunning () override
@@ -374,6 +506,8 @@ class AutoexposureApp final : public examples::SimpleWindowedApplication, public
374506 smart_refctd_ptr<IGPUCommandPool> m_cmdPool;
375507 std::array<smart_refctd_ptr<IGPUCommandBuffer>, ISwapchain::MaxImages> m_cmdBufs;
376508 smart_refctd_ptr<IGPUGraphicsPipeline> m_pipeline;
509+ smart_refctd_ptr<ISemaphore> m_semaphore;
510+ uint64_t m_submitIx = 0 ;
377511
378512 // window
379513 smart_refctd_ptr<IWindow> m_window;
0 commit comments