@@ -4,29 +4,43 @@ using namespace nbl;
4
4
using namespace video ;
5
5
6
6
7
- bool ISimpleManagedSurface::immediateBlit (const image_barrier_t & contents, IQueue* blitQueue )
7
+ bool ISimpleManagedSurface::immediateBlit (const image_barrier_t & contents, const IQueue::SSubmitInfo::SSemaphoreInfo& waitBeforeBlit, CThreadSafeQueueAdapter* blitAndPresentQueue )
8
8
{
9
- if (!contents.image || !m_queue)
9
+ auto & swapchainResources = getSwapchainResources ();
10
+ if (!contents.image || swapchainResources.getStatus ()!=ISwapchainResources::STATUS::USABLE)
10
11
return false ;
11
12
12
- auto device = const_cast <ILogicalDevice*>(m_queue->getOriginDevice ());
13
- const auto qFamProps = device->getPhysicalDevice ()->getQueueFamilyProperties ();
14
- if (!blitQueue)
13
+ auto * swapchain = swapchainResources.getSwapchain ();
14
+ assert (swapchain); // because status is usable
15
+ auto device = const_cast <ILogicalDevice*>(swapchain->getOriginDevice ());
16
+
17
+ // check queue provided
15
18
{
16
- // default to using the presentation queue if it can blit
17
- if (qFamProps[m_queue->getFamilyIndex ()].queueFlags .hasFlags (IQueue::FAMILY_FLAGS::GRAPHICS_BIT))
18
- blitQueue = m_queue;
19
- else // just pick first compatible
20
- for (uint8_t qFam=0 ; qFam<ILogicalDevice::MaxQueueFamilies; qFam++)
21
- if (device->getQueueCount (qFam) && qFamProps[qFam].queueFlags .hasFlags (IQueue::FAMILY_FLAGS::GRAPHICS_BIT))
19
+ const auto qFamProps = device->getPhysicalDevice ()->getQueueFamilyProperties ();
20
+ auto compatibleQueue = [&](const uint8_t qFam)->bool
22
21
{
23
- blitQueue = device->getThreadSafeQueue (qFam,0 );
24
- break ;
22
+ return qFamProps[qFam].queueFlags .hasFlags (IQueue::FAMILY_FLAGS::GRAPHICS_BIT) && m_surface->isSupportedForPhysicalDevice (device->getPhysicalDevice (),qFam);
23
+ };
24
+ // pick if default wanted
25
+ if (!blitAndPresentQueue)
26
+ {
27
+ for (uint8_t qFam=0 ; qFam<ILogicalDevice::MaxQueueFamilies; qFam++)
28
+ {
29
+ const auto qCount = device->getQueueCount (qFam);
30
+ if (qCount && qFamProps[qFam].queueFlags .hasFlags (IQueue::FAMILY_FLAGS::GRAPHICS_BIT))
31
+ {
32
+ // pick a different queue than we'd pick for a regular present
33
+ blitAndPresentQueue = device->getThreadSafeQueue (qFam,0 );
34
+ if (blitAndPresentQueue==m_queue)
35
+ blitAndPresentQueue = device->getThreadSafeQueue (qFam,qCount-1 );
36
+ break ;
37
+ }
38
+ }
25
39
}
26
- }
27
40
28
- if (!blitQueue || qFamProps[blitQueue->getFamilyIndex ()].queueFlags .hasFlags (IQueue::FAMILY_FLAGS::GRAPHICS_BIT))
29
- return false ;
41
+ if (!blitAndPresentQueue || compatibleQueue (blitAndPresentQueue->getFamilyIndex ()))
42
+ return false ;
43
+ }
30
44
31
45
// create a different semaphore so we don't increase the acquire counter in `this`
32
46
auto semaphore = device->createSemaphore (0 );
@@ -36,26 +50,42 @@ bool ISimpleManagedSurface::immediateBlit(const image_barrier_t& contents, IQueu
36
50
// transient commandbuffer and pool to perform the blit
37
51
core::smart_refctd_ptr<IGPUCommandBuffer> cmdbuf;
38
52
{
39
- auto pool = device->createCommandPool (blitQueue ->getFamilyIndex (),IGPUCommandPool::CREATE_FLAGS::TRANSIENT_BIT);
53
+ auto pool = device->createCommandPool (blitAndPresentQueue ->getFamilyIndex (),IGPUCommandPool::CREATE_FLAGS::TRANSIENT_BIT);
40
54
if (!pool || !pool->createCommandBuffers (IGPUCommandPool::BUFFER_LEVEL::PRIMARY,{&cmdbuf,1 }) || !cmdbuf)
41
55
return false ;
56
+
57
+ if (!cmdbuf->begin (IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT))
58
+ return false ;
42
59
}
43
60
44
- const IQueue::SSubmitInfo::SSemaphoreInfo acquired[1 ] = {
45
- {
46
- .semaphore =semaphore.get (),
47
- .value =1
48
- }
61
+ const IQueue::SSubmitInfo::SSemaphoreInfo acquired = {
62
+ .semaphore =semaphore.get (),
63
+ .value =1
49
64
};
50
65
// acquire
51
- ;
52
-
53
- // now record the blit commands
54
- auto acquiredImage = getSwapchainResources ().getImage (0xffu );
66
+ uint32_t imageIndex;
67
+ switch (swapchain->acquireNextImage ({.queue =blitAndPresentQueue,.signalSemaphores ={&acquired,1 }},&imageIndex))
55
68
{
56
- if (!cmdbuf->begin (IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT))
69
+ case ISwapchain::ACQUIRE_IMAGE_RESULT::SUBOPTIMAL: [[fallthrough]];
70
+ case ISwapchain::ACQUIRE_IMAGE_RESULT::SUCCESS:
71
+ break ;
72
+ case ISwapchain::ACQUIRE_IMAGE_RESULT::TIMEOUT: [[fallthrough]];
73
+ case ISwapchain::ACQUIRE_IMAGE_RESULT::NOT_READY: // don't throw our swapchain away just because of a timeout XD
74
+ assert (false ); // shouldn't happen though cause we use uint64_t::max() as the timeout
75
+ return false ;
76
+ case ISwapchain::ACQUIRE_IMAGE_RESULT::OUT_OF_DATE:
77
+ swapchainResources.invalidate ();
78
+ return false ;
79
+ default :
80
+ swapchainResources.becomeIrrecoverable ();
57
81
return false ;
82
+ }
83
+ // once image is acquired, WE HAVE TO present it
84
+ bool retval = true ;
58
85
86
+ // now record the blit commands
87
+ auto acquiredImage = swapchainResources.getImage (imageIndex);
88
+ {
59
89
const auto blitSrcLayout = IGPUImage::LAYOUT::TRANSFER_SRC_OPTIMAL;
60
90
const auto blitDstLayout = IGPUImage::LAYOUT::TRANSFER_DST_OPTIMAL;
61
91
IGPUCommandBuffer::SPipelineBarrierDependencyInfo depInfo = {};
@@ -100,8 +130,7 @@ bool ISimpleManagedSurface::immediateBlit(const image_barrier_t& contents, IQueu
100
130
}
101
131
};
102
132
depInfo.imgBarriers = preBarriers;
103
- if (!cmdbuf->pipelineBarrier (asset::EDF_NONE,depInfo))
104
- return false ;
133
+ retval &= cmdbuf->pipelineBarrier (asset::EDF_NONE,depInfo);
105
134
106
135
// TODO: Implement scaling modes other than plain STRETCH, and allow for using subrectangles of the initial contents
107
136
{
@@ -117,8 +146,7 @@ bool ISimpleManagedSurface::immediateBlit(const image_barrier_t& contents, IQueu
117
146
.dstBaseLayer = 0 ,
118
147
.srcMipLevel = 0 // TODO
119
148
}};
120
- if (!cmdbuf->blitImage (contents.image ,blitSrcLayout,acquiredImage,blitDstLayout,regions,IGPUSampler::ETF_LINEAR))
121
- return false ;
149
+ retval &= cmdbuf->blitImage (contents.image ,blitSrcLayout,acquiredImage,blitDstLayout,regions,IGPUSampler::ETF_LINEAR);
122
150
}
123
151
124
152
// barrier after
@@ -148,14 +176,54 @@ bool ISimpleManagedSurface::immediateBlit(const image_barrier_t& contents, IQueu
148
176
}
149
177
};
150
178
depInfo.imgBarriers = postBarriers;
151
- if (!cmdbuf->pipelineBarrier (asset::EDF_NONE,depInfo))
152
- return false ;
179
+ retval &= cmdbuf->pipelineBarrier (asset::EDF_NONE,depInfo);
180
+
181
+ retval &= cmdbuf->end ();
153
182
}
154
183
184
+ const IQueue::SSubmitInfo::SSemaphoreInfo blitted[1 ] = {
185
+ {
186
+ .semaphore = semaphore.get (),
187
+ .value = 2 ,
188
+ .stageMask = asset::PIPELINE_STAGE_FLAGS::BLIT_BIT
189
+ }
190
+ };
155
191
// submit
192
+ {
193
+ const IQueue::SSubmitInfo::SSemaphoreInfo wait[2 ] = {acquired,waitBeforeBlit};
194
+ const IQueue::SSubmitInfo::SCommandBufferInfo cmdbufs[1 ] = {{.cmdbuf =cmdbuf.get ()}};
195
+ IQueue::SSubmitInfo infos[1 ] = {
196
+ {
197
+ .waitSemaphores = wait,
198
+ .commandBuffers = cmdbufs,
199
+ .signalSemaphores = blitted
200
+ }
201
+ };
202
+ retval &= blitAndPresentQueue->submit (infos)==IQueue::RESULT::SUCCESS;
203
+ }
156
204
157
- // present
158
- ;
159
-
160
- return true ;
205
+ // present
206
+ switch (swapchainResources.swapchain ->present ({.queue =blitAndPresentQueue,.imgIndex =imageIndex,.waitSemaphores =blitted},std::move (cmdbuf)))
207
+ {
208
+ case ISwapchain::PRESENT_RESULT::SUBOPTIMAL: [[fallthrough]];
209
+ case ISwapchain::PRESENT_RESULT::SUCCESS:
210
+ // all resources can be dropped, the swapchain will hold onto them
211
+ return retval;
212
+ case ISwapchain::PRESENT_RESULT::OUT_OF_DATE:
213
+ swapchainResources.invalidate ();
214
+ break ;
215
+ default :
216
+ swapchainResources.becomeIrrecoverable ();
217
+ break ;
218
+ }
219
+ // swapchain won't hold onto anything, so just block till resources not used anymore
220
+ if (retval) // only if queue has submitted you have anything to wait on
221
+ {
222
+ ISemaphore::SWaitInfo infos[1 ] = {{
223
+ .semaphore = blitted[0 ].semaphore ,
224
+ .value = blitted[0 ].value
225
+ }};
226
+ device->blockForSemaphores (infos);
227
+ }
228
+ return false ;
161
229
}
0 commit comments