@@ -45,12 +45,11 @@ struct SIntendedSubmitInfo final : core::Uncopyable
4545 // Can get called repeatedly! The argument is the scratch semaphore (so it can poll itself to know when to finish work - prevent priority inversion)
4646 std::function<void (const ISemaphore::SWaitInfo&)> overflowCallback = {};
4747
48-
4948 //
5049 inline ISemaphore::SWaitInfo getFutureScratchSemaphore () const {return {scratchSemaphore.semaphore ,scratchSemaphore.value +1 };}
51-
50+
5251 // Returns the scratch to use if valid, nullptr otherwise
53- inline const IQueue::SSubmitInfo::SCommandBufferInfo* valid () const
52+ inline const IQueue::SSubmitInfo::SCommandBufferInfo* getCommandBufferForRecording () const
5453 {
5554 if (!queue || scratchCommandBuffers.empty () || !scratchSemaphore.semaphore )
5655 return nullptr ;
@@ -95,6 +94,23 @@ struct SIntendedSubmitInfo final : core::Uncopyable
9594 return scratch;
9695 }
9796
97+ // Returns the scratch to use if valid, nullptr otherwise
98+ inline const IQueue::SSubmitInfo::SCommandBufferInfo* valid () const
99+ {
100+ if (!queue || scratchCommandBuffers.empty () || !scratchSemaphore.semaphore )
101+ return nullptr ;
102+ // All commandbuffers must be compatible with the queue we're about to submit to
103+ auto cmdbufNotSubmittableToQueue = [this ](const IGPUCommandBuffer* cmdbuf)->bool
104+ {
105+ return !cmdbuf || cmdbuf->getPool ()->getQueueFamilyIndex ()!=queue->getFamilyIndex ();
106+ };
107+ // All commandbuffers before the scratch must be executable (ready to be submitted)
108+ for (const auto & info : prevCommandBuffers)
109+ if (cmdbufNotSubmittableToQueue (info.cmdbuf ) || info.cmdbuf ->getState ()!=IGPUCommandBuffer::STATE::EXECUTABLE)
110+ return nullptr ;
111+ return getCommandBufferForRecording ();
112+ }
113+
98114 // ! xxxx
99115 class CSubmitStorage final : core::Uncopyable
100116 {
@@ -144,10 +160,10 @@ struct SIntendedSubmitInfo final : core::Uncopyable
144160 // We assume you'll actually submit the return value before popping another one, hence we:
145161 // - increment the `scratchSemaphore.value`
146162 // - clear the `waitSemaphores` which we'll use in the future because they will already be awaited on this `queue`
147- inline CSubmitStorage popSubmit (IGPUCommandBuffer* scratch , const std::span<const IQueue::SSubmitInfo::SSemaphoreInfo> signalSemaphores)
163+ inline CSubmitStorage popSubmit (IGPUCommandBuffer* recordingCmdBuf , const std::span<const IQueue::SSubmitInfo::SSemaphoreInfo> signalSemaphores)
148164 {
149165 assert (scratch);
150- CSubmitStorage retval (*this ,scratch ,signalSemaphores);
166+ CSubmitStorage retval (*this ,recordingCmdBuf ,signalSemaphores);
151167
152168 // If you want to wait for the result of this popped submit, you need to wait for this new value
153169 scratchSemaphore.value ++;
@@ -159,26 +175,26 @@ struct SIntendedSubmitInfo final : core::Uncopyable
159175 return retval;
160176 }
161177
162- //
163- inline IQueue::RESULT overflowSubmit (const IQueue::SSubmitInfo::SCommandBufferInfo* &scratch )
178+ // recordingCmdBuf pointer may change so some other command buffer info in `scratchCommandBuffers` when applicable
179+ inline IQueue::RESULT overflowSubmit (const IQueue::SSubmitInfo::SCommandBufferInfo* &recordingCmdBuf )
164180 {
165181 const auto pLast = &scratchCommandBuffers.back ();
166- if (scratch <scratchCommandBuffers.data () || scratch >pLast)
182+ if (recordingCmdBuf <scratchCommandBuffers.data () || recordingCmdBuf >pLast)
167183 return IQueue::RESULT::OTHER_ERROR;
168184 // First, submit the already buffered up work
169- scratch ->cmdbuf ->end ();
185+ recordingCmdBuf ->cmdbuf ->end ();
170186
171187 // we only signal the scratch semaphore when overflowing
172- const auto submit = popSubmit (scratch ->cmdbuf ,{});
188+ const auto submit = popSubmit (recordingCmdBuf ->cmdbuf ,{});
173189 IQueue::RESULT res = queue->submit (submit);
174190 if (res!=IQueue::RESULT::SUCCESS)
175191 return res;
176192
177193 // Get the next scratch buffer
178- if (scratch !=pLast)
179- scratch ++;
194+ if (recordingCmdBuf !=pLast)
195+ recordingCmdBuf ++;
180196 else
181- scratch = scratchCommandBuffers.data ();
197+ recordingCmdBuf = scratchCommandBuffers.data ();
182198 // Now figure out if we need to block to reuse the next command buffer.
183199 const auto submitsInFlight = scratchCommandBuffers.size ()-1 ;
184200 // We assume nobody was messing around with the scratchSemaphore too much and every popped submit increments value by 1
@@ -197,16 +213,17 @@ struct SIntendedSubmitInfo final : core::Uncopyable
197213 }
198214 }
199215 // could have just called begin to reset but also need to reset with the release resources flag
200- scratch ->cmdbuf ->reset (IGPUCommandBuffer::RESET_FLAGS::RELEASE_RESOURCES_BIT);
201- scratch ->cmdbuf ->begin (IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT);
216+ recordingCmdBuf ->cmdbuf ->reset (IGPUCommandBuffer::RESET_FLAGS::RELEASE_RESOURCES_BIT);
217+ recordingCmdBuf ->cmdbuf ->begin (IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT);
202218
203219 return res;
204220 }
221+
205222 // useful overload if you forgot what was scratch
206223 inline IQueue::RESULT overflowSubmit ()
207224 {
208- auto scratch = valid ();
209- return overflowSubmit (scratch );
225+ auto recordingCmdBuf = valid ();
226+ return overflowSubmit (recordingCmdBuf );
210227 }
211228
212229 // Error Text to Log/Display if you try to use an invalid `SIntendedSubmitInfo`
0 commit comments