Skip to content

Feature/vulkan 1.3 - #650

Draft
F1r3w477 wants to merge 29 commits into
dpaulat:developfrom
F1r3w477:feature/vulkan-1.3
Draft

Feature/vulkan 1.3#650
F1r3w477 wants to merge 29 commits into
dpaulat:developfrom
F1r3w477:feature/vulkan-1.3

Conversation

@F1r3w477

@F1r3w477 F1r3w477 commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

initial draft pr for move to vulkan. Very early stages, feel free to pull the branch and play around with it. CI build will probably fail a bunch initially.

Will update the PR with more information as more progress is made.

F1r3w477 added 2 commits June 12, 2026 17:11
….0.0.

The top-level maplibre-native fork was never wired into CMake; MapLibre
builds from maplibre-native-qt/vendor/maplibre-native. Point
maplibre-native-qt at upstream 4.0.0 for Vulkan/RHI support.
Replace the OpenGL application rendering path with QRhi/Vulkan overlays and remove GL build dependencies so performance work starts from a verified Vulkan baseline.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR is an early-stage migration of Supercell Wx’s rendering stack from an OpenGL/QOpenGLWidget-based approach to a Vulkan 1.3 + Qt QRhi-based renderer, including new QRhi overlay renderers, Vulkan device/context setup, and local smoke-test tooling to validate visible Vulkan output.

Changes:

  • Introduces Vulkan/QRhi render infrastructure (context, overlays/pipelines, shader loading, projections) and wires it into map rendering.
  • Refactors map layers/draw items to accept a RenderContext and (when enabled) render via Vulkan overlay paths.
  • Updates build/deps/docs for Vulkan (MapLibre Qt Vulkan config, ImGui Vulkan backend, removes OpenGL/GLU/glad usage) and adds Vulkan smoke tooling.

Reviewed changes

Copilot reviewed 137 out of 150 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
wxdata/wxdata.cmake Adjusts GCC warning suppressions for -Werror builds.
tools/vulkan-smoke.sh Adds a local Vulkan backend smoke-runner script.
tools/analyze-vulkan-capture.py Adds screenshot analysis to validate Vulkan-visible output.
scwx-qt/source/scwx/qt/vk/vk_context.hpp Declares a Vulkan device/context wrapper.
scwx-qt/source/scwx/qt/vk/vk_context.cpp Implements Vulkan instance + physical/logical device selection and setup.
scwx-qt/source/scwx/qt/vk/vk_check.hpp Adds a VkResult checking helper/macro.
scwx-qt/source/scwx/qt/util/texture_atlas.hpp Refactors atlas API toward Vulkan/QRhi consumption.
scwx-qt/source/scwx/qt/util/texture_atlas.cpp Exposes atlas layer geometry/pixels for non-OpenGL upload paths.
scwx-qt/source/scwx/qt/util/polygon_triangulation.hpp Adds polygon triangulation API (earcut wrapper).
scwx-qt/source/scwx/qt/util/polygon_triangulation.cpp Implements triangulation via mapbox/earcut.
scwx-qt/source/scwx/qt/ui/imgui_debug_widget.hpp Updates ImGui debug widget to no longer depend on QOpenGLWidget.
scwx-qt/source/scwx/qt/ui/imgui_debug_widget.cpp Removes OpenGL ImGui backend usage from debug widget.
scwx-qt/source/scwx/qt/types/imgui_font.cpp Adjusts ImGui font creation to respect the active atlas/context.
scwx-qt/source/scwx/qt/render/rhi_vulkan_overlay.hpp Defines a resource bundle passed into Vulkan overlay render calls.
scwx-qt/source/scwx/qt/render/rhi_texture_array_overlay.hpp Declares texture-array overlay renderer for Vulkan/QRhi.
scwx-qt/source/scwx/qt/render/rhi_texture_array_overlay.cpp Implements QRhi pipelines/resources for texture array overlays and atlas sync.
scwx-qt/source/scwx/qt/render/rhi_shader_util.hpp Declares SPIR-V shader loading helper.
scwx-qt/source/scwx/qt/render/rhi_shader_util.cpp Implements SPIR-V shader loading into QShader.
scwx-qt/source/scwx/qt/render/rhi_radar_overlay.hpp Declares Vulkan radar overlay renderer (uniforms + buffers).
scwx-qt/source/scwx/qt/render/rhi_radar_overlay.cpp Implements Vulkan radar overlay rendering via QRhi.
scwx-qt/source/scwx/qt/render/rhi_imgui_util.hpp Declares helper to render ImGui draw data via Vulkan command buffers.
scwx-qt/source/scwx/qt/render/rhi_imgui_util.cpp Implements ImGui Vulkan render call bridging from QRhi command buffers.
scwx-qt/source/scwx/qt/render/rhi_geo_uniforms.hpp Declares geo uniform packing for Vulkan pipelines.
scwx-qt/source/scwx/qt/render/rhi_geo_uniforms.cpp Implements geo uniform construction for Vulkan paths.
scwx-qt/source/scwx/qt/render/rhi_geo_colored_geometry.hpp Declares Vulkan geo-colored geometry renderer.
scwx-qt/source/scwx/qt/render/rhi_geo_colored_geometry.cpp Implements Vulkan geo-colored geometry rendering pipeline/buffers.
scwx-qt/source/scwx/qt/render/rhi_colored_geometry.hpp Declares Vulkan screen-space colored geometry renderer.
scwx-qt/source/scwx/qt/render/rhi_colored_geometry.cpp Implements Vulkan colored geometry pipeline/buffers.
scwx-qt/source/scwx/qt/render/rhi_color_table_overlay.hpp Declares Vulkan color table overlay renderer.
scwx-qt/source/scwx/qt/render/rhi_color_table_overlay.cpp Implements Vulkan color table rendering (QRhi texture upload + draw).
scwx-qt/source/scwx/qt/render/rhi_buffer_util.hpp Declares helper for resizing/creating dynamic QRhi buffers.
scwx-qt/source/scwx/qt/render/rhi_buffer_util.cpp Implements dynamic buffer ensure/resize logic.
scwx-qt/source/scwx/qt/render/render_init.hpp Declares graphics initialization entry point.
scwx-qt/source/scwx/qt/render/render_init.cpp Logs/initializes selected render backend.
scwx-qt/source/scwx/qt/render/render_context.hpp Introduces backend-agnostic RenderContext interface.
scwx-qt/source/scwx/qt/render/render_context.cpp Adds a (currently stub) Vulkan render context factory.
scwx-qt/source/scwx/qt/render/render_backend.hpp Defines render backend enum and default selection.
scwx-qt/source/scwx/qt/render/projection.hpp Adds projection/CPU-transform helpers for Vulkan rendering paths.
scwx-qt/source/scwx/qt/render/projection.cpp Implements CPU transforms for map-colored vertex data.
scwx-qt/source/scwx/qt/model/imgui_context_model.hpp Extends ImGui context creation to allow atlas sharing control.
scwx-qt/source/scwx/qt/model/imgui_context_model.cpp Implements atlas-sharing option + atlas selection for NewFrame updates.
scwx-qt/source/scwx/qt/map/radar_site_layer.hpp Converts layer to accept RenderContext and adds Vulkan overlay hooks.
scwx-qt/source/scwx/qt/map/radar_site_layer.cpp Refactors visibility/transform logic and adds Vulkan overlay + ImGui split rendering.
scwx-qt/source/scwx/qt/map/radar_product_layer.hpp Converts layer to accept RenderContext and adds Vulkan overlay hook.
scwx-qt/source/scwx/qt/map/placefile_layer.hpp Converts layer to accept RenderContext and adds Vulkan overlay hooks.
scwx-qt/source/scwx/qt/map/placefile_layer.cpp Adds Vulkan overlay + ImGui split rendering paths for placefiles.
scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp Converts layer to accept RenderContext.
scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp Migrates to RenderContext and removes OpenGL error checking.
scwx-qt/source/scwx/qt/map/overlay_layer.hpp Converts layer to accept RenderContext and adds Vulkan overlay hooks.
scwx-qt/source/scwx/qt/map/marker_layer.hpp Converts layer to accept RenderContext.
scwx-qt/source/scwx/qt/map/marker_layer.cpp Migrates to RenderContext and removes OpenGL error checking.
scwx-qt/source/scwx/qt/map/map_widget.hpp Switches map widget base to QRhiWidget and updates lifecycle overrides.
scwx-qt/source/scwx/qt/map/map_rhi_renderer.hpp Adds a QRhi-to-MapLibre renderer bridge.
scwx-qt/source/scwx/qt/map/map_rhi_renderer.cpp Implements Vulkan-native handle wiring for MapLibre rendering.
scwx-qt/source/scwx/qt/map/map_overlay_renderer.hpp Adds Vulkan overlay renderer orchestrator for layers + ImGui.
scwx-qt/source/scwx/qt/map/map_overlay_renderer.cpp Implements overlay render pass creation + per-layer Vulkan overlay dispatch.
scwx-qt/source/scwx/qt/map/map_imgui_vulkan_renderer.hpp Adds an ImGui Vulkan backend manager for map panes.
scwx-qt/source/scwx/qt/map/map_imgui_vulkan_renderer.cpp Implements ImGui Vulkan init/reinit, per-frame, and texture updates.
scwx-qt/source/scwx/qt/map/map_annotation_layer.hpp Converts layer to accept RenderContext and adds Vulkan overlay hook.
scwx-qt/source/scwx/qt/map/map_annotation_layer.cpp Adds Vulkan overlay rendering path and disables legacy Render under Vulkan.
scwx-qt/source/scwx/qt/map/layer_wrapper.cpp Disables MapLibre custom-layer render callback when using Vulkan backend.
scwx-qt/source/scwx/qt/map/generic_layer.hpp Migrates base layer to hold RenderContext and introduces Vulkan overlay virtual.
scwx-qt/source/scwx/qt/map/generic_layer.cpp Implements RenderContext storage and no-op default Vulkan overlay.
scwx-qt/source/scwx/qt/map/draw_layer.hpp Migrates draw-layer base to RenderContext and adds Vulkan overlay helpers.
scwx-qt/source/scwx/qt/map/draw_layer.cpp Removes OpenGL draw path and adds Vulkan ImGui frame helpers + Vulkan draw dispatch.
scwx-qt/source/scwx/qt/map/color_table_layer.hpp Migrates to RenderContext and adds Vulkan overlay hook.
scwx-qt/source/scwx/qt/map/color_table_layer.cpp Replaces OpenGL color table rendering with Vulkan/QRhi overlay path.
scwx-qt/source/scwx/qt/map/alert_layer.hpp Migrates to RenderContext.
scwx-qt/source/scwx/qt/map/alert_layer.cpp Migrates to RenderContext and removes OpenGL error checking.
scwx-qt/source/scwx/qt/manager/font_manager.hpp Adds ImGui font build helper for Vulkan/multi-atlas usage.
scwx-qt/source/scwx/qt/manager/font_manager.cpp Refactors ImGui font caching to be per-ImFontAtlas and supports multi-atlas backends.
scwx-qt/source/scwx/qt/main/main.cpp Replaces OpenGL init with render backend initialization.
scwx-qt/source/scwx/qt/main/main_window.cpp Replaces GlContext storage with RenderContext and updates MapWidget construction.
scwx-qt/source/scwx/qt/gl/shader_program.hpp Removes OpenGL shader program wrapper (deleted).
scwx-qt/source/scwx/qt/gl/shader_program.cpp Removes OpenGL shader program implementation (deleted).
scwx-qt/source/scwx/qt/gl/gl.hpp Removes OpenGL error macro header (deleted).
scwx-qt/source/scwx/qt/gl/gl_context.hpp Removes OpenGL context wrapper (deleted).
scwx-qt/source/scwx/qt/gl/gl_context.cpp Removes OpenGL context implementation (deleted).
scwx-qt/source/scwx/qt/gl/draw/rectangle.hpp Updates draw item to accept RenderContext and adds Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp Ports triangle rendering toward Vulkan with CPU-side transform path.
scwx-qt/source/scwx/qt/gl/draw/placefile_text.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp Adds no-op Vulkan render stub for text (placeholder).
scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/placefile_lines.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/placefile_images.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/placefile_images_xy.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/placefile_icons.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/map_annotations_draw_item.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/linked_vectors.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp Adds Vulkan render hook wiring for linked vectors.
scwx-qt/source/scwx/qt/gl/draw/icons.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/icons.cpp Ports icon drawing toward Vulkan texture-array overlay rendering.
scwx-qt/source/scwx/qt/gl/draw/geo_lines.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp Updates draw item for RenderContext and Vulkan render hook.
scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp Adds Vulkan render virtual and migrates away from GL helpers.
scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp Removes OpenGL projection helpers and adds default Vulkan no-op.
scwx-qt/scwx-qt.qrc Adds Vulkan SPIR-V shader resources to Qt resource system.
scwx-qt/gl/vulkan/texture1d.vert Adds Vulkan GLSL shader source for texture1d vertex stage.
scwx-qt/gl/vulkan/texture1d.frag Adds Vulkan GLSL shader source for texture1d fragment stage.
scwx-qt/gl/vulkan/texture_lut.frag Adds LUT sampling fragment shader source.
scwx-qt/gl/vulkan/screen_texture_array.vert Adds screen-space texture-array vertex shader source.
scwx-qt/gl/vulkan/screen_texture_array.frag Adds screen-space texture-array fragment shader source.
scwx-qt/gl/vulkan/radar.vert Adds radar overlay vertex shader source.
scwx-qt/gl/vulkan/radar.frag Adds radar overlay fragment shader source.
scwx-qt/gl/vulkan/geo_texture_array.vert Adds geo texture-array vertex shader source.
scwx-qt/gl/vulkan/geo_texture_array.frag Adds geo texture-array fragment shader source.
scwx-qt/gl/vulkan/geo_color.vert Adds geo colored-geometry vertex shader source.
scwx-qt/gl/vulkan/geo_color.frag Adds geo colored-geometry fragment shader source.
scwx-qt/gl/vulkan/color.vert Adds colored-geometry vertex shader source.
scwx-qt/gl/vulkan/color.frag Adds colored-geometry fragment shader source.
README.md Updates Linux rendering requirements to Vulkan 1.3.
external/maplibre-native-qt.cmake Configures MapLibre Qt build for Vulkan, disables OpenGL, adjusts warnings/includes.
external/imgui.cmake Enables ImGui Vulkan backend when building with Vulkan and links Vulkan.
external/CMakeLists.txt Stops including glad external when OpenGL is removed.
conanfile.py Removes Linux OpenGL/GLU system requirements.
CMakePresets.json Adds a Vulkan-enabled Linux preset.
CMakeLists.txt Adds SCWX_RENDER_BACKEND cache variable with Vulkan default.
AGENTS.md Updates contributor guide to reflect Vulkan/QRhi primitives path.
ACKNOWLEDGEMENTS.md Updates Qt module list wording (drops Qt OpenGL mention).
.gitmodules Switches MapLibre Qt submodule upstream URL and removes maplibre-native submodule.
.github/workflows/ci.yml Removes GLU copy step from Flatpak packaging.

Comment on lines +52 to +66
if (floatVertices.empty())
{
return {};
}

const GeoUniforms uniforms =
BuildGeoUniforms(params, thresholded, selectedTime);
const glm::vec2 mapScreenCoord = util::maplibre::LatLongToScreenCoordinate(
{params.latitude, params.longitude});

const std::size_t vertexCount =
floatVertices.size() / kMapColorFloatsPerVertex_;
std::vector<float> transformed;
transformed.reserve(vertexCount * kColoredFloatsPerVertex_);

Comment on lines +460 to +463
const boost::gil::rgba8_image_t& image = p->atlasArray_[layer];
const boost::gil::rgba8c_view_t view = boost::gil::const_view(image);
byteSize = image.width() * image.height() * sizeof(boost::gil::rgba8_pixel_t);
return reinterpret_cast<const std::uint8_t*>(&view(0, 0));
Comment on lines +129 to +135
uint32_t extensionCount = 0;
vkEnumerateDeviceExtensionProperties(
device, nullptr, &extensionCount, nullptr);

std::vector<VkExtensionProperties> extensions(extensionCount);
vkEnumerateDeviceExtensionProperties(
device, nullptr, &extensionCount, extensions.data());
Comment thread tools/vulkan-smoke.sh
Comment on lines +13 to +16
if [[ ! -x "${BIN}" ]]; then
echo "Missing binary: ${BIN}" >&2
exit 1
fi
F1r3w477 added 15 commits June 14, 2026 00:59
Cache radar and geo line GPU uploads, coalesce resize and splitter work,
and route alert/STI updates through the Vulkan overlay path so loaded
polygons no longer stall pan and resize.
Upstream ImGui bump moved RenderPass into PipelineInfoMain and renamed
descriptor pool size constants.
Build alert polygons once per phenomenon across panes instead of per
MapWidget. Post refresh timer signals on the Qt main thread. Remove
ImGuiSelectContext on radar-site click so Vulkan keeps MapWidget context.
Move CI and review workflows to clang-21, add ccache and libvulkan-dev
on Linux, and ship helper scripts that mirror pipeline checks locally.
Relax clang-tidy rules that are noisy for Qt/QRhi and graphics code.
Remove OpenGL shader assets and the old Vulkan context wrapper now that
rendering goes through Qt QRhi with SPIR-V resources in scwx-qt.cmake.
Add RHI helpers for colored geometry, radar sweeps, texture arrays, and
color tables used by the Vulkan map overlay path.
Route map paint through RHI/Vulkan renderers, share basemap textures across
linked panes, and replace layer_wrapper with focused helpers.
Update geo/placefile draw paths for QRhi buffers and stroke styling,
including texture atlas and annotation layer integration.
Capture geo-line weak_ptr by value in event handlers, guard segment lookup
with a mutex, and batch alert geometry refresh during warnings backfill.
Hide incomplete radar products, simplify radar-site overlay ImGui, and
align overlay, marker, and placefile layers with the RHI map path.
Add unit tests for geo stroke banding, basemap texture sharing, and map
perf counters introduced with the QRhi map refactor.
Use portable env helpers instead of getenv, fix ImGui shared atlas
lifetime, align overlay forward declarations, gate Clang-only MapLibre
flags, and update CI workflows for the Vulkan migration.
Gate unsupported Clang warning flags, allow macOS MapLibre configure
without Qt Vulkan headers, and route env-var tests through wxdata helpers.
Remove dead OpenGL branches and glad, move draw code out of gl/, and
add pipeline cache persistence plus device-lost recovery. Unify Clang CI
and macOS dev tooling on LLVM 22.
@dpaulat

dpaulat commented Jun 25, 2026

Copy link
Copy Markdown
Owner

cursor review verbose=true

@cursor

cursor Bot commented Jun 25, 2026

Copy link
Copy Markdown

Bugbot request id: serverGenReqId_b9852a76-803c-4044-8640-6dbad1cfb395

Gate LLVM 22 install to Linux, add a local git-diff fallback for oversized
clang-tidy PR diffs, apply clang-format, and remove an unused storm-track
constant. Fix alert geo-line click crashes via AlertLayerHandler and keep
hover tooltips visible while the cursor is stationary.
@dpaulat

dpaulat commented Jun 25, 2026

Copy link
Copy Markdown
Owner

@cursor Please review this PR for bugs, threading/lifetime safety, and missing Vulkan error handling. Focus on the QRhi/Vulkan render path. Post findings as a summary comment with file:line references. Do not commit or push changes.

@dpaulat

dpaulat commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Code review: QRhi/Vulkan render path

Focused on bugs, threading/lifetime safety, and missing Vulkan error handling. File:line refs are against the PR branch (pr-650).


Critical / high

1. Global SetVulkanResultHandler captures widget this without lifetime management

MapWidget::initialize() installs a process-global handler that captures this and queues releaseResources() on device loss:

  • scwx-qt/source/scwx/qt/map/map_widget.cpp:2583-2607
  • scwx-qt/source/scwx/qt/render/rhi_vulkan_result.cpp:11-16

Problems:

  • Each pane overwrites the global handler on init; only the last initialized pane receives recovery callbacks (map_widget.cpp:2583).
  • releaseResources() and ~MapWidgetImpl() never call SetVulkanResultHandler(nullptr) (map_widget.cpp:2625-2641, 276-307). After a pane is destroyed, a late VkResult callback can invoke QMetaObject::invokeMethod(this, …) on a dangling MapWidget.

Suggested fix: store handler per-QRhi/per-widget with QPointer<MapWidget> or weak_ptr; clear on releaseResources()/destruction; or route recovery through a non-widget singleton that tracks live panes.


2. Basemap sharing copies a leader QRhiTexture via the follower's QRhi

Follower path:

  • scwx-qt/source/scwx/qt/map/map_widget.cpp:2957-2967CopyColorTexture(widget_->rhi(), …, followerTexture, leaderTexture)
  • Leader texture source: scwx-qt/source/scwx/qt/main/main_window.cpp:1246-1254MapWidget::basemap_color_texture() (map_widget.cpp:1684-1686), allocated on the leader widget's rhi() (2828-2830).

QRhi resources are owned by the QRhi instance that created them; QRhi::copyTexture expects both textures to belong to the same QRhi. This conflicts with the explicit per-pane Vulkan backend model documented in scwx-qt/source/scwx/qt/manager/font_manager.cpp:83-85.

If panes truly have independent QRhi instances (one per QRhiWidget), this copy is undefined and may fail silently or corrupt rendering.


3. isPainting_ stuck true on early return

RenderFrameVulkan sets isPainting_ = true at map_widget.cpp:2900, then returns early when renderWidth/renderHeight <= 0 at 2913-2916 without resetting it. Subsequent QEvent::Paint events are swallowed as "recursive" (2053-2058), which can freeze repaints for that pane until restart.


Threading / lifetime (medium)

4. Basemap share has no frame synchronization despite tracking generation

MapBasemapShareState::NotifyBasemapRendered() increments basemapGeneration_ (map_basemap_share.cpp:108-112), but followers never read it. Followers copy leaderTexture_ whenever they render (map_widget.cpp:2952-2973) with no guarantee the leader has rendered this frame first.

With multiple MapWidgets, paint order is not tied to leaderIndex_, so followers can display a stale basemap (previous frame) or copy before the leader's SnapshotBasemap() (2860-2864) completes.

Suggested fix: expose generation via callbacks; skip follower copy until basemapGeneration advances, or explicitly render leader panes before followers in a coordinated pass.


5. MapLibre basemap render is issued outside the active QRhiCommandBuffer

RenderMapAndSnapshot() calls rhiRenderer_.RenderMap() (MapLibre's own Vulkan submission via setExternalDrawable / render()) before SnapshotBasemap() records copyTexture on the widget CB:

  • scwx-qt/source/scwx/qt/map/map_rhi_renderer.cpp:55-72
  • scwx-qt/source/scwx/qt/map/map_widget.cpp:2860-2864

There is no explicit queue submission / semaphore / barrier between MapLibre finishing its write to colorTexture and the QRhi copy + overlay beginPass(..., PreserveColorContents) (map_overlay_renderer.cpp:235-239). This relies on implicit ordering; worth validating on MoltenVK / multi-pane loads.


6. ~MapWidgetImpl() does not shut down overlay/RHI overlay pipelines

releaseResources() shuts down overlayRenderer_ (map_widget.cpp:2637), but the destructor path only shuts down ImGui + basemap texture + MapLibre renderer (276-304). If releaseResources() is not invoked before impl destruction (abnormal teardown), overlay pipelines/render targets may leak or outlive QRhi.


Missing Vulkan / QRhi error handling (medium)

7. nextResourceUpdateBatch() null is not checked before dereference

Several hot-path render uploads assume a non-null batch:

File Lines
rhi_radar_overlay.cpp 310-333
rhi_colored_geometry.cpp 168-173
rhi_geo_colored_geometry.cpp 210-223
rhi_color_table_overlay.cpp 219-231
rhi_texture_array_overlay.cpp 418-435, 482-493, 545-556

Only init path in rhi_color_table_overlay.cpp:58-62 guards null. Under device loss / OOM, these will crash instead of failing gracefully (especially relevant given the global device-lost handler above).


8. Direct vk* calls bypass ReportVulkanResult

Pipeline cache helpers call Vulkan directly without logging or the installed handler:

  • rhi_pipeline_cache.cpp:193vkCreatePipelineCache
  • rhi_pipeline_cache.cpp:207-215vkGetPipelineCacheData (errors silently clear blob)
  • map_imgui_vulkan_renderer.cpp:85,165vkDestroyPipelineCache (unchecked)

ImGui integration wires CheckVkResultFn (map_imgui_vulkan_renderer.cpp:67), but the app's own pipeline-cache path does not, so failures there won't trigger the recovery path in map_widget.cpp:2586-2607.


9. EnsureDynamicBuffer failure leaves a destroyed but non-null buffer

On recreate failure (rhi_buffer_util.cpp:43-46), capacity is zeroed but the stale QRhiBuffer* is retained. Subsequent render retries call setSize/create() on a buffer that was destroy()'d (22-25), which may fail repeatedly without recreating the object.


Notes / lower severity

  • MapImGuiVulkanRenderer::UpdateRenderPass() is implemented (map_imgui_vulkan_renderer.cpp:131-153) but never called; reinit relies on overlay generation bumps instead. Fine if intentional, but dead API surface.
  • ImGui_ImplVulkan_UpdateTexture() runs before overlayRenderer_.Render() opens the external-content pass (map_widget.cpp:3048 vs 3084-3089). Worth confirming this is safe with QRhi's command-buffer lifetime rules when panes share a swapchain thread.

Happy to re-review after fixes. I did not run the build on this pass; findings are from static analysis of the PR branch.

Repository owner deleted a comment from coderabbitai Bot Jun 25, 2026
@dpaulat

dpaulat commented Jun 25, 2026

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 211 files, which is 61 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b5dad86b-141c-476f-acf7-be65b2a3b7d1

📥 Commits

Reviewing files that changed from the base of the PR and between 5db1f72 and a33d2db.

📒 Files selected for processing (211)
  • .clang-tidy
  • .github/workflows/ci.yml
  • .github/workflows/clang-format-check.yml
  • .github/workflows/clang-tidy-review.yml
  • .gitmodules
  • ACKNOWLEDGEMENTS.md
  • AGENTS.md
  • CMakeLists.txt
  • CMakePresets.json
  • README.md
  • conanfile.py
  • external/CMakeLists.txt
  • external/glad.cmake
  • external/imgui.cmake
  • external/maplibre-native
  • external/maplibre-native-qt
  • external/maplibre-native-qt.cmake
  • scwx-qt/gl/annotation_geo.vert
  • scwx-qt/gl/annotation_stroke.frag
  • scwx-qt/gl/color.frag
  • scwx-qt/gl/color.vert
  • scwx-qt/gl/geo_line.vert
  • scwx-qt/gl/geo_texture2d.vert
  • scwx-qt/gl/map_color.vert
  • scwx-qt/gl/radar.frag
  • scwx-qt/gl/radar.vert
  • scwx-qt/gl/texture1d.frag
  • scwx-qt/gl/texture1d.vert
  • scwx-qt/gl/texture2d.frag
  • scwx-qt/gl/texture2d_array.frag
  • scwx-qt/gl/texture2d_array.vert
  • scwx-qt/gl/threshold.geom
  • scwx-qt/gl/vulkan/color.frag
  • scwx-qt/gl/vulkan/color.vert
  • scwx-qt/gl/vulkan/geo_color.frag
  • scwx-qt/gl/vulkan/geo_color.vert
  • scwx-qt/gl/vulkan/geo_texture_array.frag
  • scwx-qt/gl/vulkan/geo_texture_array.vert
  • scwx-qt/gl/vulkan/radar.frag
  • scwx-qt/gl/vulkan/radar.vert
  • scwx-qt/gl/vulkan/screen_texture_array.frag
  • scwx-qt/gl/vulkan/screen_texture_array.vert
  • scwx-qt/gl/vulkan/spirv/color.frag.spv
  • scwx-qt/gl/vulkan/spirv/color.vert.spv
  • scwx-qt/gl/vulkan/spirv/geo_color.frag.spv
  • scwx-qt/gl/vulkan/spirv/geo_color.vert.spv
  • scwx-qt/gl/vulkan/spirv/geo_texture_array.frag.spv
  • scwx-qt/gl/vulkan/spirv/geo_texture_array.vert.spv
  • scwx-qt/gl/vulkan/spirv/radar.frag.spv
  • scwx-qt/gl/vulkan/spirv/radar.vert.spv
  • scwx-qt/gl/vulkan/spirv/screen_texture_array.frag.spv
  • scwx-qt/gl/vulkan/spirv/screen_texture_array.vert.spv
  • scwx-qt/gl/vulkan/spirv/texture1d.frag.spv
  • scwx-qt/gl/vulkan/spirv/texture1d.vert.spv
  • scwx-qt/gl/vulkan/spirv/texture_lut.frag.spv
  • scwx-qt/gl/vulkan/texture1d.frag
  • scwx-qt/gl/vulkan/texture1d.vert
  • scwx-qt/gl/vulkan/texture_lut.frag
  • scwx-qt/scwx-qt.cmake
  • scwx-qt/scwx-qt.qrc
  • scwx-qt/source/scwx/qt/draw/draw_item.cpp
  • scwx-qt/source/scwx/qt/draw/draw_item.hpp
  • scwx-qt/source/scwx/qt/draw/geo_icons.cpp
  • scwx-qt/source/scwx/qt/draw/geo_icons.hpp
  • scwx-qt/source/scwx/qt/draw/geo_lines.cpp
  • scwx-qt/source/scwx/qt/draw/geo_lines.hpp
  • scwx-qt/source/scwx/qt/draw/icons.cpp
  • scwx-qt/source/scwx/qt/draw/icons.hpp
  • scwx-qt/source/scwx/qt/draw/linked_vectors.cpp
  • scwx-qt/source/scwx/qt/draw/linked_vectors.hpp
  • scwx-qt/source/scwx/qt/draw/map_annotations_draw_item.cpp
  • scwx-qt/source/scwx/qt/draw/map_annotations_draw_item.hpp
  • scwx-qt/source/scwx/qt/draw/placefile_icons.cpp
  • scwx-qt/source/scwx/qt/draw/placefile_icons.hpp
  • scwx-qt/source/scwx/qt/draw/placefile_images.cpp
  • scwx-qt/source/scwx/qt/draw/placefile_images.hpp
  • scwx-qt/source/scwx/qt/draw/placefile_images_xy.cpp
  • scwx-qt/source/scwx/qt/draw/placefile_images_xy.hpp
  • scwx-qt/source/scwx/qt/draw/placefile_lines.cpp
  • scwx-qt/source/scwx/qt/draw/placefile_lines.hpp
  • scwx-qt/source/scwx/qt/draw/placefile_polygons.cpp
  • scwx-qt/source/scwx/qt/draw/placefile_polygons.hpp
  • scwx-qt/source/scwx/qt/draw/placefile_text.cpp
  • scwx-qt/source/scwx/qt/draw/placefile_text.hpp
  • scwx-qt/source/scwx/qt/draw/placefile_triangles.cpp
  • scwx-qt/source/scwx/qt/draw/placefile_triangles.hpp
  • scwx-qt/source/scwx/qt/draw/rectangle.cpp
  • scwx-qt/source/scwx/qt/draw/rectangle.hpp
  • scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp
  • scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp
  • scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.cpp
  • scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp
  • scwx-qt/source/scwx/qt/gl/draw/rectangle.cpp
  • scwx-qt/source/scwx/qt/gl/gl.hpp
  • scwx-qt/source/scwx/qt/gl/gl_context.cpp
  • scwx-qt/source/scwx/qt/gl/gl_context.hpp
  • scwx-qt/source/scwx/qt/gl/shader_program.cpp
  • scwx-qt/source/scwx/qt/gl/shader_program.hpp
  • scwx-qt/source/scwx/qt/main/main.cpp
  • scwx-qt/source/scwx/qt/main/main_window.cpp
  • scwx-qt/source/scwx/qt/manager/font_manager.cpp
  • scwx-qt/source/scwx/qt/manager/font_manager.hpp
  • scwx-qt/source/scwx/qt/manager/text_event_manager.cpp
  • scwx-qt/source/scwx/qt/manager/text_event_manager.hpp
  • scwx-qt/source/scwx/qt/map/alert_layer.cpp
  • scwx-qt/source/scwx/qt/map/alert_layer.hpp
  • scwx-qt/source/scwx/qt/map/color_table_layer.cpp
  • scwx-qt/source/scwx/qt/map/color_table_layer.hpp
  • scwx-qt/source/scwx/qt/map/draw_layer.cpp
  • scwx-qt/source/scwx/qt/map/draw_layer.hpp
  • scwx-qt/source/scwx/qt/map/generic_layer.cpp
  • scwx-qt/source/scwx/qt/map/generic_layer.hpp
  • scwx-qt/source/scwx/qt/map/geo_stroke.cpp
  • scwx-qt/source/scwx/qt/map/geo_stroke.hpp
  • scwx-qt/source/scwx/qt/map/layer_wrapper.cpp
  • scwx-qt/source/scwx/qt/map/layer_wrapper.hpp
  • scwx-qt/source/scwx/qt/map/map_annotation_layer.cpp
  • scwx-qt/source/scwx/qt/map/map_annotation_layer.hpp
  • scwx-qt/source/scwx/qt/map/map_basemap_share.cpp
  • scwx-qt/source/scwx/qt/map/map_basemap_share.hpp
  • scwx-qt/source/scwx/qt/map/map_imgui_vulkan_renderer.cpp
  • scwx-qt/source/scwx/qt/map/map_imgui_vulkan_renderer.hpp
  • scwx-qt/source/scwx/qt/map/map_overlay_renderer.cpp
  • scwx-qt/source/scwx/qt/map/map_overlay_renderer.hpp
  • scwx-qt/source/scwx/qt/map/map_perf.cpp
  • scwx-qt/source/scwx/qt/map/map_perf.hpp
  • scwx-qt/source/scwx/qt/map/map_rhi_renderer.cpp
  • scwx-qt/source/scwx/qt/map/map_rhi_renderer.hpp
  • scwx-qt/source/scwx/qt/map/map_widget.cpp
  • scwx-qt/source/scwx/qt/map/map_widget.hpp
  • scwx-qt/source/scwx/qt/map/marker_layer.cpp
  • scwx-qt/source/scwx/qt/map/marker_layer.hpp
  • scwx-qt/source/scwx/qt/map/overlay_layer.cpp
  • scwx-qt/source/scwx/qt/map/overlay_layer.hpp
  • scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp
  • scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp
  • scwx-qt/source/scwx/qt/map/placefile_layer.cpp
  • scwx-qt/source/scwx/qt/map/placefile_layer.hpp
  • scwx-qt/source/scwx/qt/map/radar_product_layer.cpp
  • scwx-qt/source/scwx/qt/map/radar_product_layer.hpp
  • scwx-qt/source/scwx/qt/map/radar_site_layer.cpp
  • scwx-qt/source/scwx/qt/map/radar_site_layer.hpp
  • scwx-qt/source/scwx/qt/model/imgui_context_model.cpp
  • scwx-qt/source/scwx/qt/model/imgui_context_model.hpp
  • scwx-qt/source/scwx/qt/render/projection.cpp
  • scwx-qt/source/scwx/qt/render/projection.hpp
  • scwx-qt/source/scwx/qt/render/render_backend.hpp
  • scwx-qt/source/scwx/qt/render/render_context.cpp
  • scwx-qt/source/scwx/qt/render/render_context.hpp
  • scwx-qt/source/scwx/qt/render/render_init.cpp
  • scwx-qt/source/scwx/qt/render/render_init.hpp
  • scwx-qt/source/scwx/qt/render/rhi_buffer_util.cpp
  • scwx-qt/source/scwx/qt/render/rhi_buffer_util.hpp
  • scwx-qt/source/scwx/qt/render/rhi_color_table_overlay.cpp
  • scwx-qt/source/scwx/qt/render/rhi_color_table_overlay.hpp
  • scwx-qt/source/scwx/qt/render/rhi_colored_geometry.cpp
  • scwx-qt/source/scwx/qt/render/rhi_colored_geometry.hpp
  • scwx-qt/source/scwx/qt/render/rhi_geo_colored_geometry.cpp
  • scwx-qt/source/scwx/qt/render/rhi_geo_colored_geometry.hpp
  • scwx-qt/source/scwx/qt/render/rhi_geo_uniforms.cpp
  • scwx-qt/source/scwx/qt/render/rhi_geo_uniforms.hpp
  • scwx-qt/source/scwx/qt/render/rhi_imgui_util.cpp
  • scwx-qt/source/scwx/qt/render/rhi_imgui_util.hpp
  • scwx-qt/source/scwx/qt/render/rhi_pipeline_cache.cpp
  • scwx-qt/source/scwx/qt/render/rhi_pipeline_cache.hpp
  • scwx-qt/source/scwx/qt/render/rhi_radar_overlay.cpp
  • scwx-qt/source/scwx/qt/render/rhi_radar_overlay.hpp
  • scwx-qt/source/scwx/qt/render/rhi_shader_util.cpp
  • scwx-qt/source/scwx/qt/render/rhi_shader_util.hpp
  • scwx-qt/source/scwx/qt/render/rhi_texture_array_overlay.cpp
  • scwx-qt/source/scwx/qt/render/rhi_texture_array_overlay.hpp
  • scwx-qt/source/scwx/qt/render/rhi_vulkan_overlay.hpp
  • scwx-qt/source/scwx/qt/render/rhi_vulkan_result.cpp
  • scwx-qt/source/scwx/qt/render/rhi_vulkan_result.hpp
  • scwx-qt/source/scwx/qt/types/imgui_font.cpp
  • scwx-qt/source/scwx/qt/ui/imgui_debug_widget.cpp
  • scwx-qt/source/scwx/qt/ui/imgui_debug_widget.hpp
  • scwx-qt/source/scwx/qt/util/maplibre.cpp
  • scwx-qt/source/scwx/qt/util/maplibre.hpp
  • scwx-qt/source/scwx/qt/util/polygon_triangulation.cpp
  • scwx-qt/source/scwx/qt/util/polygon_triangulation.hpp
  • scwx-qt/source/scwx/qt/util/texture_atlas.cpp
  • scwx-qt/source/scwx/qt/util/texture_atlas.hpp
  • test/source/scwx/qt/map/geo_stroke.test.cpp
  • test/source/scwx/qt/map/geo_stroke_band.test.cpp
  • test/source/scwx/qt/map/map_basemap_share.test.cpp
  • test/source/scwx/qt/map/map_perf.test.cpp
  • test/test.cmake
  • tools/analyze-vulkan-capture.py
  • tools/check-clang-format.sh
  • tools/check-clang-tidy.sh
  • tools/collapse-draw-namespace.py
  • tools/compile-vulkan-shaders.sh
  • tools/conan/profiles/scwx-macos_clang-22
  • tools/conan/profiles/scwx-macos_clang-22-debug
  • tools/conan/profiles/scwx-macos_clang-22_armv8-debug
  • tools/configure-environment.sh
  • tools/profile-vulkan-grid.sh
  • tools/profile-workflows.sh
  • tools/setup-macos-ninja-debug.sh
  • tools/setup-macos-ninja-release.sh
  • tools/setup-macos-xcode-debug.sh
  • tools/setup-macos-xcode-multi.sh
  • tools/setup-macos-xcode-release.sh
  • tools/strip-vulkan-ifdefs.py
  • tools/vulkan-smoke.sh
  • wxdata/include/scwx/provider/warnings_provider.hpp
  • wxdata/include/scwx/util/environment.hpp
  • wxdata/source/scwx/provider/warnings_provider.cpp
  • wxdata/source/scwx/util/environment.cpp
  • wxdata/wxdata.cmake

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@dpaulat

dpaulat commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Supplemental review — gaps not in the summary above

The main review covers handler lifetime, basemap sharing, isPainting_, MapLibre/QRhi ordering, and pipeline-cache error handling. A few additional QRhi/Vulkan issues worth tracking:


High — shared alert geometry caches GPU state per draw item, not per pane

AlertLayerHandler::SharedGeometry() shares one draw::GeoLines instance per phenomenon across all map panes (alert_layer.cpp:874-905). Each GeoLines::Impl owns a single geoRenderer_ (RhiGeoColoredGeometry) and only invalidates it when renderTargetGeneration_ != resources.renderTargetGeneration (geo_lines.cpp:169-189).

renderTargetGeneration_ is per-MapOverlayRenderer and increments from 0 → 1 on first render-target creation (map_overlay_renderer.cpp:65, 138). Multiple panes therefore share generation value 1 while owning different QRhi instances and native render passes.

After pane A initializes geoRenderer_ for its RHI/render pass, pane B can skip re-init and draw alert geometry through pane A’s pipeline/resources on pane B’s command buffer.

Suggested fix: key cached renderers by (QRhi*, native render pass handle) (or move GPU state into per-pane overlay resources). Same pattern exists in placefile_lines.cpp:158-177 if those draw items are ever shared.

Refs: geo_lines.cpp:122-124, 169-189; alert_layer.cpp:447-460, 899-905.


Medium — ImGui Vulkan shutdown order

MapImGuiVulkanRenderer::Shutdown() persists and destroys the app-owned VkPipelineCache before calling ImGui_ImplVulkan_Shutdown() (map_imgui_vulkan_renderer.cpp:159-174). If the ImGui backend still references that cache handle during shutdown, this is a Vulkan lifetime hazard.

Suggested fix: ImGui_ImplVulkan_Shutdown() first, then persist/destroy the pipeline cache.


Medium — MapLibre init fallback on Vulkan-only path

If native Vulkan handles are unavailable, MapRhiRenderer::InitializeMapRenderer() falls back to map->createRenderer(nullptr) and still sets initialized_ = true (map_rhi_renderer.cpp:50-52). On a Vulkan-only widget this may leave MapLibre non-functional while the pane believes rendering is ready.


Medium — TextureAtlas::LayerPixels() used after releasing atlas lock

TextureAtlas::LayerPixels() returns a raw pointer into atlasArray_ after releasing atlasMutex_ (texture_atlas.cpp). RhiTextureArrayOverlay::SyncAtlas() uses that pointer in a resource upload loop (rhi_texture_array_overlay.cpp:418-435). If another thread rebuilds the atlas between pointer fetch and upload, this is a data race / UAF (Copilot flagged the API; worth treating as part of the Vulkan upload path).

Suggested fix: copy layer pixels under lock (QByteArray / std::vector<uint8_t>) or upload inside a locked accessor.


Low

  • MapRhiRenderer::CopyColorTexture() ignores null/failure from nextResourceUpdateBatch() and resourceUpdate() (map_rhi_renderer.cpp:92-99) — basemap follower copies can fail silently (related to item Support for Storm Tracking Information (58) #7 in the main review, but this is the basemap-share hot path).
  • MapRhiRenderer::InitializeMapRenderer() only calls window->setVulkanInstance() when the window has no instance (map_rhi_renderer.cpp:35-38); a mismatched pre-existing instance is not reconciled.
  • RadarProductLayer::RenderVulkanOverlay() reads sweep vertex/moment buffers without holding sweep_mutex() (radar_product_layer.cpp:247-250, 317-327); OK if updates are render-thread-only, but fragile if background refresh is added later.

F1r3w477 added 11 commits July 7, 2026 20:45
Sync alternate providers, ONDAS support, dependency updates, and
clang-format workflow cleanup. Resolve conflicts keeping Vulkan render
paths while adopting RadarType-based site selection and develop GCC
warning suppressions.
Upload overlay resources before beginPass (batch is null inside ExternalContent),
wake linked basemap followers on leader render, and bake geo-line offsets in
screen space so diagonal alert polygons no longer staircase. Also keep SPIR-V
outputs as *.vert.spv/*.frag.spv and harden multi-pane smoke capture.
Match CI clang-format-check (clang-format-21) on lines changed since develop.
Share atlas/pipelines per QRhi, fix ImGui teardown on pop-out reparent,
and clear clang/MSVC/macOS/tidy CI failures on PR 650.
MapLibre re-find_package wiped Qt include stub; pre-seed
QT_VULKAN_HEADER instead. Save Conan/ccache always and enable
ccache on macOS so failed PR iterates stop rebuilding deps.
Stock aqt macOS Qt lacks QT_FEATURE_vulkan / QVulkan* headers, so
MapLibre Vulkan backend cannot compile. Disable macos CI matrix
entries until Metal (or custom Qt+MoltenVK). Keep both sites.hpp
and environment.hpp includes from the merge.
Use MapLibre/QRhi/ImGui Metal on Apple; keep Vulkan on Win/Linux.
Ship .qsb (SPIR-V+MSL) shaders and re-enable macOS CI.
Skip ObjC++ (.mm) in format checks; project .clang-format
does not support Language: ObjC.
Qt MTL* class ptrs need void* bridge to id<>; ImGui wants
attachment texture not pixelFormat. if constexpr for backend gate.
ObjC* → void* under -fobjc-arc needs __bridge, not C cast.
Comment thread .github/workflows/ci.yml
--settings:all build_type=${{ matrix.build_type }} `
--output-folder ./conan/ `
${{ matrix.conan_package_manager }}
conan cache clean

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conan cache clean should be kept. This significantly reduces the size of cached artifacts (by a factor of 5-10).

Comment thread .github/workflows/ci.yml
}
}

- name: Install LLVM 22

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-22 is available as an apt package on ubuntu-26.04.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may pull clang-19 to 22 into linux-x64 soon to ensure the code base compiles on a range of versions.

@dpaulat dpaulat added the coderabbit CodeRabbit should review this pull request label Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

coderabbit CodeRabbit should review this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants