diff --git a/src/view/src/compute/rocprofvis_compute_roofline.cpp b/src/view/src/compute/rocprofvis_compute_roofline.cpp index 2c1af1afb..acc964f76 100644 --- a/src/view/src/compute/rocprofvis_compute_roofline.cpp +++ b/src/view/src/compute/rocprofvis_compute_roofline.cpp @@ -51,6 +51,8 @@ constexpr const char* DISPLAY_NAMES_KERNEL_INTENSITY[] = { "L1 Intensity", // kRPVControllerRooflineKernelIntensityTypeL1 "LDS Intensity", // kRPVControllerRooflineKernelIntensityTypeLDS }; +constexpr const char* MEMORY_LEVEL_NAMES[] = { "HBM", "L2", "L1", "LDS" }; +constexpr const char* FILTER_OPTION_ALL = "All"; constexpr const char* DISPLAY_NAMES_PRESET[] = { "FP4", // PresetModel::Type::FP4 "FP6", // PresetModel::Type::FP6 @@ -70,6 +72,8 @@ Roofline::Roofline(DataProvider& data_provider, KernelMode kernel_mode) , m_menus_placement(InsideTopRight) , m_scale_intensity(true) , m_line_thickness(LINE_THICKNESS_DEFAULT) +, m_active_preset(PresetModel::FP32) +, m_memory_peak_filter(std::nullopt) , m_menus_rendered_height(0.0f) , m_hovered_item_distance(FLT_MAX) , m_workload_changed(false) @@ -81,6 +85,8 @@ Roofline::Roofline(DataProvider& data_provider, KernelMode kernel_mode) , m_requested_workload_id(0) , m_kernel(nullptr) , m_requested_kernel_id(0) +, m_isolated_kernel(nullptr) +, m_isolated_bandwidth(std::nullopt) { m_widget_name = GenUniqueName("roofline"); m_items.resize(static_cast(__KRPVControllerRooflineCeilingComputeTypeLast + @@ -120,6 +126,10 @@ Roofline::Update() { if(m_workload_changed) { + // Kernel pointers are rebuilt below, so drop any stale filters. + m_isolated_kernel = nullptr; + m_isolated_bandwidth = std::nullopt; + m_memory_peak_filter = std::nullopt; m_workload = m_data_provider.ComputeModel().GetWorkload(m_requested_workload_id); if(m_workload) @@ -253,6 +263,41 @@ Roofline::Update() static_cast(kernel_duration_scale)) }); } } + // Build filter dropdown options from what the workload actually has; + // empty memory levels should not be offered. + m_available_intensities.clear(); + m_available_bandwidths.clear(); + bool intensity_present[IM_ARRAYSIZE(MEMORY_LEVEL_NAMES)] = {}; + for(const std::pair& kernel : m_workload->kernels) + { + for(const std::pair< + const rocprofvis_controller_roofline_kernel_intensity_type_t, + KernelInfo::Roofline::Intensity>& intensity : + kernel.second.roofline.intensities) + { + intensity_present[intensity.second.type] = true; + } + } + for(uint32_t i = 0; i < IM_ARRAYSIZE(MEMORY_LEVEL_NAMES); i++) + { + if(intensity_present[i]) + { + m_available_intensities.emplace_back( + static_cast< + rocprofvis_controller_roofline_kernel_intensity_type_t>(i)); + } + } + for(uint32_t i = __KRPVControllerRooflineCeilingBandwidthTypeFirst; + i < __KRPVControllerRooflineCeilingBandwidthTypeLast; i++) + { + rocprofvis_controller_roofline_ceiling_bandwidth_type_t bandwidth = + static_cast( + i); + if(m_workload->roofline.ceiling_bandwidth.count(bandwidth) > 0) + { + m_available_bandwidths.emplace_back(bandwidth); + } + } ApplyPreset(PresetModel::FP32); } m_workload_changed = false; @@ -264,6 +309,7 @@ Roofline::Update() { m_kernel = &m_workload->kernels.at(m_requested_kernel_id); } + RecomputeVisibility(); m_kernel_changed = false; } if(m_options_changed) @@ -333,6 +379,15 @@ Roofline::Render() ImGuiChildFlags_Borders | ImGuiChildFlags_AlwaysUseWindowPadding); SectionTitle("Roofline Analysis"); + bool has_roofline = + m_workload && !m_workload->roofline.ceiling_bandwidth.empty() && + !m_workload->roofline.ceiling_compute.empty() && + !(m_kernel_mode == SingleKernel && + (!m_kernel || m_kernel->roofline.intensities.empty())); + if(has_roofline) + { + RenderToolbar(); + } ImGui::BeginChild("roofline"); const ImVec2 region = ImGui::GetContentRegionAvail(); const ImGuiStyle& style = ImGui::GetStyle(); @@ -434,9 +489,7 @@ Roofline::Render() } case ItemModel::Type::Intensity: { - display = - m_items[i].info.intensity && - (m_kernel ? m_items[i].parent_info.kernel == m_kernel : true); + display = m_items[i].info.intensity; } } display &= m_items[i].visible; @@ -602,7 +655,29 @@ Roofline::Render() } bool menus_item_hovered = false; RenderMenus(region, plot_pos, plot_size, style, plot_style, menus_item_hovered); - if(!m_plot_zoom_enabled && roofline_hovered && + bool dot_hovered = + !menus_item_hovered && m_kernel_mode == AllKernels && m_hovered_item_idx && + m_items[m_hovered_item_idx.value()].type == ItemModel::Type::Intensity; + bool bandwidth_line_hovered = + !menus_item_hovered && m_hovered_item_idx && + m_items[m_hovered_item_idx.value()].type == + ItemModel::Type::CeilingBandwidth; + // Drag check so panning a zoomed plot is not treated as a click. + if(roofline_hovered && IsMouseReleasedWithDragCheck(ImGuiMouseButton_Left)) + { + if(dot_hovered) + { + ToggleKernelIsolation( + m_items[m_hovered_item_idx.value()].parent_info.kernel); + } + else if(bandwidth_line_hovered) + { + ToggleBandwidthIsolation( + m_items[m_hovered_item_idx.value()].subtype.bandwidth); + } + } + if(!m_plot_zoom_enabled && roofline_hovered && !dot_hovered && + !bandwidth_line_hovered && !menus_item_hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { m_plot_zoom_enabled = true; @@ -641,6 +716,176 @@ Roofline::SetKernel(uint32_t id) m_kernel_changed = true; } +void +Roofline::RenderToolbar() +{ + const ImGuiStyle& style = ImGui::GetStyle(); + int count = 1; // Compute peak is always present. + if(!m_available_bandwidths.empty()) + { + count++; + } + if(m_kernel_mode == AllKernels) + { + count++; + } + if(!m_available_intensities.empty()) + { + count++; + } + float cell = (ImGui::GetContentRegionAvail().x - + style.ItemSpacing.x * static_cast(count - 1)) / + static_cast(count); + cell = std::max(cell, ImGui::GetFontSize() * 4.0f); + + // Draw "