Skip to content

Commit

Permalink
gpuav: Update debug label regions management
Browse files Browse the repository at this point in the history
Took some of what Artem did for syncval
Add debug label regions for GPU-AV instrumentation based validation
Still need to add support for secondary command buffers, not so easy
  • Loading branch information
arno-lunarg committed Nov 28, 2024
1 parent b61aa3f commit 19102ba
Show file tree
Hide file tree
Showing 19 changed files with 670 additions and 176 deletions.
4 changes: 2 additions & 2 deletions layers/gpu/cmd_validation/gpuav_copy_buffer_to_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,8 @@ void InsertCopyBufferToImageValidation(Validator &gpuav, const Location &loc, Co
DispatchCmdDispatch(cb_state.VkHandle(), group_count_x, 1, 1);

CommandBuffer::ErrorLoggerFunc error_logger = [loc, src_buffer = copy_buffer_to_img_info->srcBuffer](
Validator &gpuav, const uint32_t *error_record,
const LogObjectList &objlist) {
Validator &gpuav, const CommandBuffer &, const uint32_t *error_record,
const LogObjectList &objlist, const std::vector<std::string> &) {
bool skip = false;

using namespace glsl;
Expand Down
3 changes: 2 additions & 1 deletion layers/gpu/cmd_validation/gpuav_dispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ void InsertIndirectDispatchValidation(Validator &gpuav, const Location &loc, Com
DispatchCmdDispatch(cb_state.VkHandle(), 1, 1, 1);

CommandBuffer::ErrorLoggerFunc error_logger =
[loc](Validator &gpuav, const uint32_t *error_record, const LogObjectList &objlist) {
[loc](Validator &gpuav, const CommandBuffer &, const uint32_t *error_record, const LogObjectList &objlist,
const std::vector<std::string> &) {
bool skip = false;
using namespace glsl;

Expand Down
5 changes: 3 additions & 2 deletions layers/gpu/cmd_validation/gpuav_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,9 @@ void InsertIndirectDrawValidation(Validator &gpuav, const Location &loc, Command
DispatchCmdDraw(cb_state.VkHandle(), 3, 1, 0, 0); // TODO: this 3 assumes triangles I think, probably could be 1?

CommandBuffer::ErrorLoggerFunc error_logger = [loc, indirect_buffer, indirect_offset, stride, indirect_buffer_size,
emit_task_error](Validator &gpuav, const uint32_t *error_record,
const LogObjectList &objlist) {
emit_task_error](Validator &gpuav, const CommandBuffer &,
const uint32_t *error_record, const LogObjectList &objlist,
const std::vector<std::string> &) {
bool skip = false;

using namespace glsl;
Expand Down
4 changes: 2 additions & 2 deletions layers/gpu/cmd_validation/gpuav_trace_rays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ void InsertIndirectTraceRaysValidation(Validator &gpuav, const Location &loc, Co
VkStridedDeviceAddressRegionKHR empty_sbt{};
DispatchCmdTraceRaysKHR(cb_state.VkHandle(), &ray_gen_sbt, &empty_sbt, &empty_sbt, &empty_sbt, 1, 1, 1);

CommandBuffer::ErrorLoggerFunc error_logger = [loc](Validator &gpuav, const uint32_t *error_record,
const LogObjectList &objlist) {
CommandBuffer::ErrorLoggerFunc error_logger = [loc](Validator &gpuav, const CommandBuffer &, const uint32_t *error_record,
const LogObjectList &objlist, const std::vector<std::string> &) {
bool skip = false;

using namespace glsl;
Expand Down
2 changes: 1 addition & 1 deletion layers/gpu/debug_printf/debug_printf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ void AnalyzeAndGenerateMessage(Validator &gpuav, VkCommandBuffer command_buffer,
const bool use_stdout = gpuav.gpuav_settings.debug_printf_to_stdout;
if (gpuav.gpuav_settings.debug_printf_verbose) {
std::string debug_info_message = gpuav.GenerateDebugInfoMessage(
command_buffer, std::nullopt, instructions, debug_record->stage_id, debug_record->stage_info_0,
command_buffer, std::string{}, instructions, debug_record->stage_id, debug_record->stage_info_0,
debug_record->stage_info_1, debug_record->stage_info_2, debug_record->instruction_position, instrumented_shader,
debug_record->shader_id, buffer_info.pipeline_bind_point, buffer_info.action_command_index);
if (use_stdout) {
Expand Down
77 changes: 37 additions & 40 deletions layers/gpu/instrumentation/gpuav_instrumentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,44 +411,26 @@ void PreCallSetupShaderInstrumentationResources(Validator &gpuav, CommandBuffer
const bool uses_robustness = (gpuav.enabled_features.robustBufferAccess || gpuav.enabled_features.robustBufferAccess2 ||
(last_bound.pipeline_state && last_bound.pipeline_state->uses_pipeline_robustness));

std::optional<vvl::LabelCommand> deepest_opened_label_region = std::nullopt;
{
int32_t ended_label_regions_count = 0;
if (auto deepest_opened_label_region_rit =
std::find_if(cb_state.GetLabelCommands().rbegin(), cb_state.GetLabelCommands().rend(),
[&ended_label_regions_count](const vvl::LabelCommand &label_cmd) {
if (label_cmd.begin) {
if (ended_label_regions_count == 0) {
return true;
} else {
--ended_label_regions_count;
return false;
}
} else {
++ended_label_regions_count;
return false;
}
});
deepest_opened_label_region_rit != cb_state.GetLabelCommands().rend()) {
deepest_opened_label_region = *deepest_opened_label_region_rit;
}
}

CommandBuffer::ErrorLoggerFunc error_logger =
[loc, descriptor_binding_index, descriptor_binding_list = &cb_state.descriptor_command_bindings,
cb_state_handle = cb_state.VkHandle(), bind_point, deepest_opened_label_region, operation_index, uses_shader_object,
uses_robustness](Validator &gpuav, const uint32_t *error_record, const LogObjectList &objlist) {
bool skip = false;

const DescriptorCommandBinding *descriptor_command_binding =
descriptor_binding_index != vvl::kU32Max ? &(*descriptor_binding_list)[descriptor_binding_index] : nullptr;
skip |=
LogInstrumentationError(gpuav, cb_state_handle, objlist, deepest_opened_label_region, operation_index, error_record,
const uint32_t last_label_command_i =
!cb_state.GetLabelCommands().empty() ? uint32_t(cb_state.GetLabelCommands().size() - 1) : vvl::kU32Max;

CommandBuffer::ErrorLoggerFunc error_logger = [loc, descriptor_binding_index,
descriptor_binding_list = &cb_state.descriptor_command_bindings, bind_point,
last_label_command_i, operation_index, uses_shader_object,
uses_robustness](Validator &gpuav, const CommandBuffer &cb_state,
const uint32_t *error_record, const LogObjectList &objlist,
const std::vector<std::string> &initial_label_stack) {
bool skip = false;

const DescriptorCommandBinding *descriptor_command_binding =
descriptor_binding_index != vvl::kU32Max ? &(*descriptor_binding_list)[descriptor_binding_index] : nullptr;
skip |= LogInstrumentationError(gpuav, cb_state, objlist, initial_label_stack, last_label_command_i, operation_index,
error_record,
descriptor_command_binding ? descriptor_command_binding->bound_descriptor_sets
: std::vector<std::shared_ptr<DescriptorSet>>(),
bind_point, uses_shader_object, uses_robustness, loc);
return skip;
};
return skip;
};

cb_state.per_command_error_loggers.emplace_back(error_logger);
}
Expand Down Expand Up @@ -736,9 +718,10 @@ bool LogMessageInstRayQuery(const uint32_t *error_record, std::string &out_error
// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
//
bool LogInstrumentationError(Validator &gpuav, VkCommandBuffer cmd_buffer, const LogObjectList &objlist,
const std::optional<vvl::LabelCommand> &label_cmd, uint32_t operation_index,
const uint32_t *error_record, const std::vector<std::shared_ptr<DescriptorSet>> &descriptor_sets,
bool LogInstrumentationError(Validator &gpuav, const CommandBuffer &cb_state, const LogObjectList &objlist,
const std::vector<std::string> &initial_label_stack, uint32_t label_command_i,
uint32_t operation_index, const uint32_t *error_record,
const std::vector<std::shared_ptr<DescriptorSet>> &descriptor_sets,
VkPipelineBindPoint pipeline_bind_point, bool uses_shader_object, bool uses_robustness,
const Location &loc) {
// The second word in the debug output buffer is the number of words that would have
Expand Down Expand Up @@ -789,9 +772,23 @@ bool LogInstrumentationError(Validator &gpuav, VkCommandBuffer cmd_buffer, const
if (instrumented_shader && !instrumented_shader->instrumented_spirv.empty()) {
::spirv::GenerateInstructions(instrumented_shader->instrumented_spirv, instructions);
}

std::string debug_region_name;
if (label_command_i != vvl::kU32Max) {
debug_region_name = cb_state.GetDebugRegionName(cb_state.GetLabelCommands(), label_command_i, initial_label_stack);
} else {
// label_command_i == vvl::kU32Max => when the instrumented command was recorded,
// no debug label region was yet opened in the corresponding command buffer,
// but still a region might have been started in another previously submitted
// command buffer. So just compute region name from initial_label_stack.
for (const std::string &label_name : initial_label_stack) {
if (!debug_region_name.empty()) {
debug_region_name += "::";
}
debug_region_name += label_name;
}
}
std::string debug_info_message = gpuav.GenerateDebugInfoMessage(
cmd_buffer, label_cmd, instructions, error_record[gpuav::glsl::kHeaderStageIdOffset],
cb_state.VkHandle(), debug_region_name, instructions, error_record[gpuav::glsl::kHeaderStageIdOffset],
error_record[gpuav::glsl::kHeaderStageInfoOffset_0], error_record[gpuav::glsl::kHeaderStageInfoOffset_1],
error_record[gpuav::glsl::kHeaderStageInfoOffset_2], error_record[gpuav::glsl::kHeaderInstructionIdOffset],
instrumented_shader, shader_id, pipeline_bind_point, operation_index);
Expand Down
9 changes: 5 additions & 4 deletions layers/gpu/instrumentation/gpuav_instrumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ struct LabelCommand;

namespace gpuav {

struct DescriptorCommandBountSet;
class DescriptorSet;
class Validator;
class CommandBuffer;
class Queue;

void UpdateInstrumentationDescSet(Validator& gpuav, CommandBuffer& cb_state, VkDescriptorSet instrumentation_desc_set,
const Location& loc);
Expand All @@ -47,9 +47,10 @@ void PostCallSetupShaderInstrumentationResources(Validator& gpuav, CommandBuffer
const Location& loc);

// Return true iff an error has been found
bool LogInstrumentationError(Validator& gpuav, VkCommandBuffer cmd_buffer, const LogObjectList& objlist,
const std::optional<vvl::LabelCommand>& label_cmd, uint32_t operation_index,
const uint32_t* error_record, const std::vector<std::shared_ptr<DescriptorSet>>& descriptor_sets,
bool LogInstrumentationError(Validator& gpuav, const CommandBuffer& cb_state, const LogObjectList& objlist,
const std::vector<std::string>& initial_label_stack, uint32_t label_command_i,
uint32_t operation_index, const uint32_t* error_record,
const std::vector<std::shared_ptr<DescriptorSet>>& descriptor_sets,
VkPipelineBindPoint pipeline_bind_point, bool uses_shader_object, bool uses_robustness,
const Location& loc);

Expand Down
16 changes: 9 additions & 7 deletions layers/gpu/instrumentation/gpuav_shader_instrumentor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1450,11 +1450,13 @@ static std::string FindShaderSource(std::ostringstream &ss, const std::vector<In
}

// Where we build up the error message with all the useful debug information about where the error occured
std::string GpuShaderInstrumentor::GenerateDebugInfoMessage(
VkCommandBuffer commandBuffer, const std::optional<vvl::LabelCommand> &label_cmd, const std::vector<Instruction> &instructions,
uint32_t stage_id, uint32_t stage_info_0, uint32_t stage_info_1, uint32_t stage_info_2, uint32_t instruction_position,
const InstrumentedShader *instrumented_shader, uint32_t shader_id, VkPipelineBindPoint pipeline_bind_point,
uint32_t operation_index) const {
std::string GpuShaderInstrumentor::GenerateDebugInfoMessage(VkCommandBuffer commandBuffer, const std::string &debug_region_name,
const std::vector<Instruction> &instructions, uint32_t stage_id,
uint32_t stage_info_0, uint32_t stage_info_1, uint32_t stage_info_2,
uint32_t instruction_position,
const InstrumentedShader *instrumented_shader, uint32_t shader_id,
VkPipelineBindPoint pipeline_bind_point,
uint32_t operation_index) const {
std::ostringstream ss;
if (instructions.empty() || !instrumented_shader) {
ss << "[Internal Error] - Can't get instructions from shader_map\n";
Expand All @@ -1474,8 +1476,8 @@ std::string GpuShaderInstrumentor::GenerateDebugInfoMessage(
std::unique_lock<std::mutex> lock(debug_report->debug_output_mutex);
ss << "Command buffer " << LookupDebugUtilsNameNoLock(debug_report, HandleToUint64(commandBuffer)) << "("
<< HandleToUint64(commandBuffer) << ")";
if (label_cmd.has_value()) {
ss << " - [ Debug label region: " << label_cmd->label_name << " ]";
if (!debug_region_name.empty()) {
ss << " - [ Debug label region: " << debug_region_name << " ]";
}

ss << '\n';
Expand Down
2 changes: 1 addition & 1 deletion layers/gpu/instrumentation/gpuav_shader_instrumentor.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ class GpuShaderInstrumentor : public ValidationStateTracker {

bool IsSelectiveInstrumentationEnabled(const void *pNext);

std::string GenerateDebugInfoMessage(VkCommandBuffer commandBuffer, const std::optional<vvl::LabelCommand> &label_cmd,
std::string GenerateDebugInfoMessage(VkCommandBuffer commandBuffer, const std::string &debug_region_name,
const std::vector<Instruction> &instructions, uint32_t stage_id, uint32_t stage_info_0,
uint32_t stage_info_1, uint32_t stage_info_2, uint32_t instruction_position,
const InstrumentedShader *instrumented_shader, uint32_t shader_id,
Expand Down
30 changes: 15 additions & 15 deletions layers/gpu/resources/gpuav_state_trackers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ bool CommandBuffer::PreProcess(const Location &loc) {
bool CommandBuffer::NeedsPostProcess() { return !error_output_buffer_.IsDestroyed(); }

// For the given command buffer, map its debug data buffers and read their contents for analysis.
void CommandBuffer::PostProcess(VkQueue queue, const Location &loc) {
void CommandBuffer::PostProcess(VkQueue queue, const std::vector<std::string> &initial_label_stack, const Location &loc) {
auto gpuav = static_cast<Validator *>(&dev_data);

// For the given command buffer, map its debug data buffers and read their contents for analysis.
Expand Down Expand Up @@ -493,7 +493,7 @@ void CommandBuffer::PostProcess(VkQueue queue, const Location &loc) {
assert(error_logger_i < per_command_error_loggers.size());
auto &error_logger = per_command_error_loggers[error_logger_i];
const LogObjectList objlist(queue, VkHandle());
skip |= error_logger(*gpuav, error_record_ptr, objlist);
skip |= error_logger(*gpuav, *this, error_record_ptr, objlist, initial_label_stack);

// Next record
error_record_ptr += record_size;
Expand Down Expand Up @@ -622,8 +622,8 @@ void Queue::SubmitBarrier(const Location &loc, uint64_t seq) {
vvl::PreSubmitResult Queue::PreSubmit(std::vector<vvl::QueueSubmission> &&submissions) {
for (const auto &submission : submissions) {
auto loc = submission.loc.Get();
for (auto &cb : submission.cbs) {
auto gpu_cb = std::static_pointer_cast<CommandBuffer>(cb);
for (auto &cb_submission : submission.cb_submissions) {
auto gpu_cb = std::static_pointer_cast<CommandBuffer>(cb_submission.cb);
auto guard = gpu_cb->ReadLock();
gpu_cb->PreProcess(loc);
for (auto *secondary_cb : gpu_cb->linkedCommandBuffers) {
Expand Down Expand Up @@ -652,34 +652,34 @@ void Queue::Retire(vvl::QueueSubmission &submission) {
// that signals barrier_sem_. The following timeline wait must not be called.
return;
}
retiring_.emplace_back(submission.cbs);
retiring_.emplace_back(submission.cb_submissions);
if (submission.end_batch) {
VkSemaphoreWaitInfo wait_info = vku::InitStructHelper();
wait_info.semaphoreCount = 1;
wait_info.pSemaphores = &barrier_sem_;
wait_info.pValues = &submission.seq;

if (timeline_khr_) {
DispatchWaitSemaphoresKHR(state_.device, &wait_info, 1000000000);
DispatchWaitSemaphoresKHR(state_.device, &wait_info, 1'000'000'000);
} else {
DispatchWaitSemaphores(state_.device, &wait_info, 1000000000);
DispatchWaitSemaphores(state_.device, &wait_info, 1'000'000'000);
}

for (auto &cbs : retiring_) {
for (auto &cb : cbs) {
auto gpu_cb = std::static_pointer_cast<CommandBuffer>(cb);
for (std::vector<vvl::CommandBufferSubmission> &cb_submissions : retiring_) {
for (vvl::CommandBufferSubmission &cb_submission : cb_submissions) {
auto gpu_cb = std::static_pointer_cast<CommandBuffer>(cb_submission.cb);
auto guard = gpu_cb->WriteLock();
auto loc = submission.loc.Get();
gpu_cb->PostProcess(VkHandle(), loc);
for (auto *secondary_cb : gpu_cb->linkedCommandBuffers) {
auto *secondary_gpu_cb = static_cast<CommandBuffer *>(secondary_cb);
gpu_cb->PostProcess(VkHandle(), cb_submission.initial_label_stack, loc);
for (vvl::CommandBuffer *secondary_cb : gpu_cb->linkedCommandBuffers) {
auto secondary_gpu_cb = static_cast<CommandBuffer *>(secondary_cb);
auto secondary_guard = secondary_gpu_cb->WriteLock();
secondary_gpu_cb->PostProcess(VkHandle(), loc);
secondary_gpu_cb->PostProcess(VkHandle(), cb_submission.initial_label_stack, loc);
}
}
}
retiring_.clear();
}
}

} // namespace gpuav
} // namespace gpuav
Loading

0 comments on commit 19102ba

Please sign in to comment.