Skip to content

Commit 29500f0

Browse files
committed
Merge branch 'asset-conversion-v3' into intended_submit_info_changes
# Conflicts: # include/nbl/video/utilities/SIntendedSubmitInfo.h
2 parents 650b981 + c1d5f34 commit 29500f0

File tree

2 files changed

+63
-64
lines changed

2 files changed

+63
-64
lines changed

include/nbl/video/utilities/SIntendedSubmitInfo.h

Lines changed: 62 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,63 @@ namespace nbl::video
1717
//! The "current recording commandBuffer" is returned by `getCurrentRecordingCommandBufferInfo` or updated via the pointer ref in beginNextCommandBuffer or overflowSubmit)
1818
struct SIntendedSubmitInfo final : core::Uncopyable
1919
{
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+
2077
public:
2178
// This parameter is required but may be unused if there is no need (no overflow) to do submit
2279
IQueue* queue = nullptr;
@@ -49,69 +106,11 @@ struct SIntendedSubmitInfo final : core::Uncopyable
49106
//
50107
inline ISemaphore::SWaitInfo getFutureScratchSemaphore() const {return {scratchSemaphore.semaphore,scratchSemaphore.value+1};}
51108

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>();}
112111

113-
return getCurrentRecordingCommandBufferInfo();
114-
}
112+
//
113+
inline const auto* valid() const {return valid_impl<true>();}
115114

116115
//! xxxx
117116
class CSubmitStorage final : core::Uncopyable
@@ -164,7 +163,7 @@ struct SIntendedSubmitInfo final : core::Uncopyable
164163
// - clear the `waitSemaphores` which we'll use in the future because they will already be awaited on this `queue`
165164
inline CSubmitStorage popSubmit(IGPUCommandBuffer* recordingCmdBuf, const std::span<const IQueue::SSubmitInfo::SSemaphoreInfo> signalSemaphores)
166165
{
167-
assert(scratch);
166+
assert(recordingCmdBuf);
168167
CSubmitStorage retval(*this,recordingCmdBuf,signalSemaphores);
169168

170169
// If you want to wait for the result of this popped submit, you need to wait for this new value

0 commit comments

Comments
 (0)