Skip to content

Commit eb35144

Browse files
command: Improve state management
Rather than have GetCommandBufferState() look at checkpoints, move this to a separate method called UpdateStateFromCheckpoints(). This is called at the last possible moment after we know there's been a crash. Otherwise the checkpoint values are somewhat unreliable. Rename command buffer and command states to match what it is printed in the dump file so that its easier to go back and forth.
1 parent a42a400 commit eb35144

4 files changed

Lines changed: 137 additions & 144 deletions

File tree

src/command.cpp

Lines changed: 103 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -113,24 +113,10 @@ void CommandBuffer::WriteCommandEndCheckpoint(uint32_t command_id) {
113113
}
114114
}
115115

116-
bool CommandBuffer::WasSubmittedToQueue() const { return buffer_state_ == CommandBufferState::kPending; }
117-
118-
bool CommandBuffer::StartedExecution() const {
119-
if (!checkpoint_) {
120-
return false;
121-
}
122-
return (checkpoint_->ReadTop() > begin_value_);
123-
}
124-
125-
bool CommandBuffer::CompletedExecution() const {
126-
if (!checkpoint_) {
127-
return false;
128-
}
129-
return (checkpoint_->ReadBottom() >= end_value_);
130-
}
116+
bool CommandBuffer::WasSubmittedToQueue() const { return buffer_state_ >= CommandBufferState::kSubmitted; }
131117

132118
void CommandBuffer::Reset() {
133-
buffer_state_ = CommandBufferState::kInitialReset;
119+
buffer_state_ = CommandBufferState::kReset;
134120

135121
// Reset marker state.
136122
if (checkpoint_) {
@@ -150,7 +136,7 @@ void CommandBuffer::Reset() {
150136
}
151137

152138
void CommandBuffer::QueueSubmit(VkQueue queue, uint64_t queue_seq, VkFence fence) {
153-
buffer_state_ = CommandBufferState::kPending;
139+
buffer_state_ = CommandBufferState::kSubmitted;
154140
submitted_queue_ = queue;
155141
submitted_queue_seq_ = queue_seq;
156142
submitted_fence_ = fence;
@@ -168,7 +154,7 @@ VkResult CommandBuffer::PreBeginCommandBuffer(VkCommandBuffer commandBuffer,
168154
VkResult CommandBuffer::PostBeginCommandBuffer(VkCommandBuffer commandBuffer,
169155
const VkCommandBufferBeginInfo* pBeginInfo, VkResult result) {
170156
// Begin recording commands.
171-
buffer_state_ = CommandBufferState::kRecording;
157+
buffer_state_ = CommandBufferState::kBeginCalled;
172158

173159
if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
174160
cb_simultaneous_use_ = true;
@@ -196,7 +182,7 @@ VkResult CommandBuffer::PreEndCommandBuffer(VkCommandBuffer commandBuffer) {
196182
}
197183

198184
VkResult CommandBuffer::PostEndCommandBuffer(VkCommandBuffer commandBuffer, VkResult result) {
199-
buffer_state_ = CommandBufferState::kExecutable;
185+
buffer_state_ = CommandBufferState::kEndCalled;
200186

201187
return result;
202188
}
@@ -237,110 +223,125 @@ uint32_t CommandBuffer::GetLastCompleteCommand() const {
237223
return marker - begin_value_;
238224
}
239225

240-
CommandBufferState CommandBuffer::GetCommandBufferState() const {
241-
if (!checkpoint_ || (IsPrimaryCommandBuffer() && !WasSubmittedToQueue())) {
242-
return buffer_state_;
226+
void CommandBuffer::UpdateStateFromCheckpoints() {
227+
assert(WasSubmittedToQueue());
228+
if (!HasCheckpoints()) {
229+
return;
230+
}
231+
// If the queue timeline semaphore has already signaled, don't
232+
// look at the checkpoints
233+
if (buffer_state_ == CommandBufferState::kCompleted) {
234+
return;
243235
}
236+
auto top = checkpoint_->ReadTop();
237+
auto bottom = checkpoint_->ReadBottom();
238+
auto prev_state = buffer_state_;
239+
244240
// If the command buffer is submitted and markers can be used, determine the
245241
// execution state of the command buffer.
246-
if (!StartedExecution()) {
247-
return CommandBufferState::kSubmittedExecutionNotStarted;
248-
}
249-
if (!CompletedExecution()) {
250-
return CommandBufferState::kSubmittedExecutionIncomplete;
242+
if (top < begin_value_) {
243+
buffer_state_ = CommandBufferState::kNotStarted;
244+
} else if (bottom < end_value_) {
245+
buffer_state_ = CommandBufferState::kIncomplete;
246+
} else {
247+
buffer_state_ = CommandBufferState::kMaybeComplete;
251248
}
252-
return CommandBufferState::kSubmittedExecutionCompleted;
249+
250+
device_.Log().Verbose("%s seq: %lld top: %d bottom: %d prev_state: %s state: %s",
251+
device_.GetObjectName((uint64_t)vk_command_buffer_).c_str(), submitted_queue_seq_, top,
252+
bottom, PrintCommandBufferState(prev_state), PrintCommandBufferState(buffer_state_));
253253
}
254254

255-
CommandBufferState CommandBuffer::GetSecondaryCommandBufferState(
256-
CommandState vkcmd_execute_commands_command_state) const {
257-
assert(vkcmd_execute_commands_command_state != CommandState::kInvalidState);
258-
if (vkcmd_execute_commands_command_state == CommandState::kCommandNotSubmitted) {
259-
return CommandBufferState::kNotSubmitted;
260-
}
261-
if (vkcmd_execute_commands_command_state == CommandState::kCommandNotStarted) {
262-
return CommandBufferState::kSubmittedExecutionNotStarted;
263-
}
264-
if (vkcmd_execute_commands_command_state == CommandState::kCommandCompleted) {
265-
return CommandBufferState::kSubmittedExecutionCompleted;
255+
void CommandBuffer::UpdateSecondaryState(CommandState exec_cmds_state) {
256+
if (exec_cmds_state == CommandState::kNotSubmitted ||
257+
exec_cmds_state == CommandState::kInvalidState) {
258+
return;
266259
}
267-
return GetCommandBufferState();
260+
buffer_state_ = CommandBufferState::kSubmitted;
261+
UpdateStateFromCheckpoints();
262+
}
263+
264+
CommandBufferState CommandBuffer::GetCommandBufferState() const {
265+
return buffer_state_;
268266
}
269267

270-
std::string CommandBuffer::PrintCommandBufferState(CommandBufferState cb_state) const {
268+
const char* CommandBuffer::PrintCommandBufferState(CommandBufferState cb_state) const {
271269
switch (cb_state) {
272-
case CommandBufferState::kInitial:
270+
case CommandBufferState::kCreated:
273271
return "CREATED";
274-
case CommandBufferState::kRecording:
272+
case CommandBufferState::kBeginCalled:
275273
return "BEGIN_CALLED";
276-
case CommandBufferState::kExecutable:
274+
case CommandBufferState::kEndCalled:
277275
return "END_CALLED";
278-
case CommandBufferState::kPending:
276+
case CommandBufferState::kSubmitted:
279277
return "SUBMITTED";
280278
case CommandBufferState::kInvalid:
281279
return "INVALID";
282-
case CommandBufferState::kInitialReset:
280+
case CommandBufferState::kReset:
283281
return "RESET";
284-
case CommandBufferState::kSubmittedExecutionNotStarted:
282+
case CommandBufferState::kNotStarted:
285283
return "NOT_STARTED";
286-
case CommandBufferState::kSubmittedExecutionIncomplete:
284+
case CommandBufferState::kIncomplete:
287285
return "INCOMPLETE";
288-
case CommandBufferState::kSubmittedExecutionCompleted:
286+
case CommandBufferState::kMaybeComplete:
289287
return "MAYBE_COMPLETE";
290-
case CommandBufferState::kQueueCompleted:
288+
case CommandBufferState::kCompleted:
291289
return "COMPLETED";
292-
case CommandBufferState::kNotSubmitted:
293-
return "NOT_SUBMITTED";
294-
default:
295-
assert(true);
296-
return "UNKNOWN";
297290
}
291+
assert(false);
292+
return "UNKNOWN";
298293
}
299294

300-
CommandState CommandBuffer::GetCommandState(CommandBufferState cb_state, const Command& command) const {
301-
if (IsPrimaryCommandBuffer() && !WasSubmittedToQueue()) {
302-
return CommandState::kCommandNotSubmitted;
303-
}
304-
if (!checkpoint_) {
305-
return CommandState::kCommandPending;
306-
}
307-
if (!IsPrimaryCommandBuffer()) {
308-
if (cb_state == CommandBufferState::kNotSubmitted) {
309-
return CommandState::kCommandNotSubmitted;
310-
}
311-
if (cb_state == CommandBufferState::kSubmittedExecutionNotStarted) {
312-
return CommandState::kCommandNotStarted;
313-
}
314-
if (cb_state == CommandBufferState::kSubmittedExecutionCompleted) {
315-
return CommandState::kCommandCompleted;
316-
}
317-
assert(cb_state == CommandBufferState::kSubmittedExecutionIncomplete);
318-
}
319-
if (command.id > GetLastStartedCommand()) {
320-
return CommandState::kCommandNotStarted;
321-
}
322-
if (command.id <= GetLastCompleteCommand()) {
323-
return CommandState::kCommandCompleted;
295+
static CommandState GetCommandState(CommandBufferState cb_state, const Command& command, uint32_t last_started,
296+
uint32_t last_completed) {
297+
switch (cb_state) {
298+
case CommandBufferState::kCreated:
299+
case CommandBufferState::kBeginCalled:
300+
case CommandBufferState::kEndCalled:
301+
case CommandBufferState::kReset:
302+
return CommandState::kNotSubmitted;
303+
304+
case CommandBufferState::kSubmitted:
305+
return CommandState::kSubmitted;
306+
307+
case CommandBufferState::kNotStarted:
308+
return CommandState::kNotStarted;
309+
310+
case CommandBufferState::kIncomplete:
311+
case CommandBufferState::kMaybeComplete:
312+
if (command.id > last_started) {
313+
return CommandState::kNotStarted;
314+
} else if (command.id <= last_completed) {
315+
return CommandState::kCompleted;
316+
}
317+
return CommandState::kIncomplete;
318+
319+
case CommandBufferState::kCompleted:
320+
return CommandState::kCompleted;
321+
322+
case CommandBufferState::kInvalid:
323+
return CommandState::kInvalidState;
324324
}
325-
return CommandState::kCommandIncomplete;
325+
return CommandState::kInvalidState;
326326
}
327327

328-
std::string CommandBuffer::PrintCommandState(CommandState cm_state) const {
328+
const char* CommandBuffer::PrintCommandState(CommandState cm_state) const {
329329
switch (cm_state) {
330-
case CommandState::kCommandNotSubmitted:
330+
case CommandState::kNotSubmitted:
331331
return "NOT_SUBMITTED";
332-
case CommandState::kCommandPending:
332+
case CommandState::kSubmitted:
333333
return "SUBMITTED";
334-
case CommandState::kCommandNotStarted:
334+
case CommandState::kNotStarted:
335335
return "NOT_STARTED";
336-
case CommandState::kCommandIncomplete:
336+
case CommandState::kIncomplete:
337337
return "INCOMPLETE";
338-
case CommandState::kCommandCompleted:
338+
case CommandState::kCompleted:
339339
return "COMPLETED";
340-
default:
341-
assert(true);
342-
return "UNKNOWN";
340+
case CommandState::kInvalidState:
341+
return "INVALID";
343342
}
343+
assert(false);
344+
return "UNKNOWN";
344345
}
345346

346347
bool CommandBuffer::DumpCommand(const Command& command, YAML::Emitter& os) {
@@ -360,7 +361,8 @@ bool CommandBuffer::DumpCmdExecuteCommands(const Command& command, CommandState
360361
for (uint32_t i = 0; i < args->commandBufferCount; i++) {
361362
auto secondary_command_buffer = crash_diagnostic_layer::GetCommandBuffer(args->pCommandBuffers[i]);
362363
if (secondary_command_buffer) {
363-
secondary_command_buffer->DumpContents(os, settings, submitted_queue_seq_, command_state);
364+
secondary_command_buffer->UpdateSecondaryState(command_state);
365+
secondary_command_buffer->DumpContents(os, settings, submitted_queue_seq_);
364366
}
365367
}
366368
}
@@ -494,18 +496,13 @@ void CommandBuffer::DumpContents(YAML::Emitter& os, const Settings& settings, ui
494496
if (vk_command_buffer_ == VK_NULL_HANDLE) {
495497
return;
496498
}
497-
CommandBufferState cb_state;
498-
if (IsPrimaryCommandBuffer()) {
499-
cb_state = GetCommandBufferState();
500-
} else {
501-
cb_state = GetSecondaryCommandBufferState(vkcmd_execute_commands_command_state);
502-
}
499+
CommandBufferState cb_state = GetCommandBufferState();
503500
auto dump_cbs = settings.dump_command_buffers;
504501
switch (cb_state) {
505-
case CommandBufferState::kSubmittedExecutionIncomplete:
506-
case CommandBufferState::kSubmittedExecutionCompleted:
502+
case CommandBufferState::kIncomplete:
503+
case CommandBufferState::kMaybeComplete:
507504
break;
508-
case CommandBufferState::kSubmittedExecutionNotStarted:
505+
case CommandBufferState::kNotStarted:
509506
if (dump_cbs == DumpCommands::kRunning) {
510507
return;
511508
}
@@ -523,7 +520,7 @@ void CommandBuffer::DumpContents(YAML::Emitter& os, const Settings& settings, ui
523520

524521
os << YAML::Key << "handle" << YAML::Value << device_.GetObjectInfo((uint64_t)vk_command_buffer_);
525522
os << YAML::Key << "commandPool" << YAML::Value << device_.GetObjectInfo((uint64_t)vk_command_pool_);
526-
if (buffer_state_ == CommandBufferState::kPending) {
523+
if (WasSubmittedToQueue()) {
527524
os << YAML::Key << "queue" << device_.GetObjectInfo((uint64_t)submitted_queue_);
528525
os << YAML::Key << "fence" << device_.GetObjectInfo((uint64_t)submitted_fence_);
529526
}
@@ -556,9 +553,10 @@ void CommandBuffer::DumpContents(YAML::Emitter& os, const Settings& settings, ui
556553
// If the markers indicated we are complete but the queue semaphore thinks
557554
// we aren't completed, dump everything. We don't know which command in the
558555
// command buffer is the problem.
559-
if (cb_state == CommandBufferState::kSubmittedExecutionCompleted) {
560-
last_completed = 1;
556+
if (cb_state == CommandBufferState::kMaybeComplete) {
557+
last_completed = 0;
561558
}
559+
562560
os << YAML::Key << "lastStartedCommand" << YAML::Value << last_started;
563561
os << YAML::Key << "lastCompletedCommand" << YAML::Value << last_completed;
564562

@@ -569,7 +567,7 @@ void CommandBuffer::DumpContents(YAML::Emitter& os, const Settings& settings, ui
569567
os << YAML::Key << "Commands" << YAML::Value << YAML::BeginSeq;
570568
for (const auto& command : tracker_.GetCommands()) {
571569
auto command_name = Command::GetCommandName(command);
572-
auto command_state = GetCommandState(cb_state, command);
570+
auto command_state = GetCommandState(cb_state, command, last_started, last_completed);
573571

574572
if (dump_cmds == DumpCommands::kRunning) {
575573
if (command.id < last_completed || command.id > last_started) {
@@ -608,13 +606,13 @@ void CommandBuffer::DumpContents(YAML::Emitter& os, const Settings& settings, ui
608606
}
609607
os << YAML::EndMap;
610608
state.Print(command, os, device_.GetObjectInfoDB());
611-
if (command_state == CommandState::kCommandIncomplete) {
609+
if (command_state == CommandState::kIncomplete) {
612610
HandleIncompleteCommand(command, state);
613611
}
614612

615613
// To make this message more visible, we put it in a special
616614
// Command entry.
617-
if (cb_state == CommandBufferState::kSubmittedExecutionIncomplete) {
615+
if (cb_state == CommandBufferState::kIncomplete) {
618616
if (command.id == GetLastCompleteCommand()) {
619617
os << YAML::Key << "message" << YAML::Value << "'>>>>>>>>>>>>>> LAST COMPLETE COMMAND <<<<<<<<<<<<<<'";
620618
} else if (command.id == GetLastStartedCommand()) {

0 commit comments

Comments
 (0)