@@ -17,6 +17,63 @@ namespace nbl::video
17
17
// ! The "current recording commandBuffer" is returned by `getCurrentRecordingCommandBufferInfo` or updated via the pointer ref in beginNextCommandBuffer or overflowSubmit)
18
18
struct SIntendedSubmitInfo final : core::Uncopyable
19
19
{
20
+ // All commandbuffers must be compatible with the queue we're about to submit to
21
+ bool cmdbufNotSubmittableToQueue (const IGPUCommandBuffer* cmdbuf) const
22
+ {
23
+ return !cmdbuf || cmdbuf->getPool ()->getQueueFamilyIndex ()!=queue->getFamilyIndex ();
24
+ }
25
+
26
+ // Returns the scratch to use if valid, nullptr otherwise
27
+ template <bool AllChecks>
28
+ inline const IQueue::SSubmitInfo::SCommandBufferInfo* valid_impl () const
29
+ {
30
+ if (!queue || scratchCommandBuffers.empty () || !scratchSemaphore.semaphore )
31
+ return nullptr ;
32
+ // the found scratch
33
+ const IQueue::SSubmitInfo::SCommandBufferInfo* scratch = nullptr ;
34
+ // skip expensive stuff
35
+ std::conditional_t <AllChecks,core::unordered_set<const IGPUCommandBuffer*>,const void *> uniqueCmdBufs;
36
+ if constexpr (AllChecks)
37
+ {
38
+ // All commandbuffers before the scratch must be executable (ready to be submitted)
39
+ for (const auto & info : prevCommandBuffers)
40
+ if (cmdbufNotSubmittableToQueue (info.cmdbuf ) || info.cmdbuf ->getState ()!=IGPUCommandBuffer::STATE::EXECUTABLE)
41
+ return nullptr ;
42
+ //
43
+ uniqueCmdBufs.reserve (scratchCommandBuffers.size ());
44
+ }
45
+ for (auto & info : scratchCommandBuffers)
46
+ {
47
+ if constexpr (AllChecks)
48
+ {
49
+ // Must be resettable so we can end, submit, wait, reset and continue recording commands into it as-if nothing happened
50
+ if (cmdbufNotSubmittableToQueue (info.cmdbuf ) || !info.cmdbuf ->isResettable ())
51
+ return nullptr ;
52
+ uniqueCmdBufs.insert (info.cmdbuf );
53
+ }
54
+ // not our scratch
55
+ if (info.cmdbuf ->getState ()!=IGPUCommandBuffer::STATE::RECORDING)
56
+ continue ;
57
+ // there can only be one scratch!
58
+ if (scratch)
59
+ return nullptr ;
60
+ scratch = &info;
61
+ }
62
+ // a commandbuffer repeats itself
63
+ if constexpr (AllChecks)
64
+ if (uniqueCmdBufs.size ()!=scratchCommandBuffers.size ())
65
+ return nullptr ;
66
+ // there is no scratch cmdbuf at all!
67
+ if (!scratch)
68
+ return nullptr ;
69
+ // It makes no sense to reuse the same commands for a second submission.
70
+ // Moreover its dangerous because the utilities record their own internal commands which might use subresources for which
71
+ // frees have already been latched on the scratch semaphore you must signal anyway.
72
+ if (!scratch->cmdbuf ->getRecordingFlags ().hasFlags (IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT))
73
+ return nullptr ;
74
+ return scratch;
75
+ }
76
+
20
77
public:
21
78
// This parameter is required but may be unused if there is no need (no overflow) to do submit
22
79
IQueue* queue = nullptr ;
@@ -49,69 +106,11 @@ struct SIntendedSubmitInfo final : core::Uncopyable
49
106
//
50
107
inline ISemaphore::SWaitInfo getFutureScratchSemaphore () const {return {scratchSemaphore.semaphore ,scratchSemaphore.value +1 };}
51
108
52
- // Returns the command buffer to use for recording if valid, nullptr otherwise
53
- inline const IQueue::SSubmitInfo::SCommandBufferInfo* getCurrentRecordingCommandBufferInfo () const
54
- {
55
- if (scratchCommandBuffers.empty ())
56
- return nullptr ;
57
-
58
- // All commandbuffers must be compatible with the queue we're about to submit to
59
- auto cmdbufNotSubmittableToQueue = [this ](const IGPUCommandBuffer* cmdbuf)->bool
60
- {
61
- return !cmdbuf || cmdbuf->getPool ()->getQueueFamilyIndex ()!=queue->getFamilyIndex ();
62
- };
63
-
64
- // finding command buffer toRecord
65
- const IQueue::SSubmitInfo::SCommandBufferInfo* toRecord = nullptr ;
66
- core::unordered_set<const IGPUCommandBuffer*> uniqueCmdBufs;
67
- uniqueCmdBufs.reserve (scratchCommandBuffers.size ());
68
- for (auto & info : scratchCommandBuffers)
69
- {
70
- // Must be resettable so we can end, submit, wait, reset and continue recording commands into it as-if nothing happened
71
- if (cmdbufNotSubmittableToQueue (info.cmdbuf ) || !info.cmdbuf ->isResettable ())
72
- return nullptr ;
73
- uniqueCmdBufs.insert (info.cmdbuf );
74
- // not our toRecord
75
- if (info.cmdbuf ->getState ()!=IGPUCommandBuffer::STATE::RECORDING)
76
- continue ;
77
- // there can only be one toRecord!
78
- if (toRecord)
79
- return nullptr ;
80
- toRecord = &info;
81
- }
82
- // a commandbuffer repeats itself
83
- if (uniqueCmdBufs.size ()!=scratchCommandBuffers.size ())
84
- return nullptr ;
85
- // there is no toRecord cmdbuf at all!
86
- if (!toRecord)
87
- return nullptr ;
88
- // It makes no sense to reuse the same commands for a second submission.
89
- // Moreover its dangerous because the utilities record their own internal commands which might use subresources for which
90
- // frees have already been latched on the scratch semaphore you must signal anyway.
91
- if (!toRecord->cmdbuf ->getRecordingFlags ().hasFlags (IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT))
92
- return nullptr ;
93
- return toRecord;
94
- }
95
-
96
- // Returns the command buffer to use for recording if valid, nullptr otherwise
97
- inline const IQueue::SSubmitInfo::SCommandBufferInfo* valid () const
98
- {
99
- if (!queue || !scratchSemaphore.semaphore )
100
- return nullptr ;
101
-
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
-
108
- // All prevCommandBuffers must be executable (ready to be submitted)
109
- for (const auto & info : prevCommandBuffers)
110
- if (cmdbufNotSubmittableToQueue (info.cmdbuf ) || info.cmdbuf ->getState ()!=IGPUCommandBuffer::STATE::EXECUTABLE)
111
- return nullptr ;
109
+ //
110
+ inline const auto * getCommandBufferForRecording () const {return valid_impl<false >();}
112
111
113
- return getCurrentRecordingCommandBufferInfo ();
114
- }
112
+ //
113
+ inline const auto * valid () const { return valid_impl< true >(); }
115
114
116
115
// ! xxxx
117
116
class CSubmitStorage final : core::Uncopyable
@@ -164,7 +163,7 @@ struct SIntendedSubmitInfo final : core::Uncopyable
164
163
// - clear the `waitSemaphores` which we'll use in the future because they will already be awaited on this `queue`
165
164
inline CSubmitStorage popSubmit (IGPUCommandBuffer* recordingCmdBuf, const std::span<const IQueue::SSubmitInfo::SSemaphoreInfo> signalSemaphores)
166
165
{
167
- assert (scratch );
166
+ assert (recordingCmdBuf );
168
167
CSubmitStorage retval (*this ,recordingCmdBuf,signalSemaphores);
169
168
170
169
// If you want to wait for the result of this popped submit, you need to wait for this new value
0 commit comments