From 0525ccb5eb39ef9e969479feb836c1dca74eba6c Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 8 Jan 2025 15:26:00 +0100 Subject: [PATCH 01/43] enable screenshot tests on all platforms --- .../re_component_ui/tests/test_all_components_ui.rs | 8 +------- crates/viewer/re_time_panel/tests/time_panel_tests.rs | 3 --- crates/viewer/re_ui/tests/arrow_ui_test.rs | 3 --- crates/viewer/re_ui/tests/list_item_tests.rs | 3 --- crates/viewer/re_ui/tests/modal_tests.rs | 3 --- crates/viewer/re_view_graph/tests/basic.rs | 3 --- 6 files changed, 1 insertion(+), 22 deletions(-) diff --git a/crates/viewer/re_component_ui/tests/test_all_components_ui.rs b/crates/viewer/re_component_ui/tests/test_all_components_ui.rs index 1c966332a2a7..a67a8d835336 100644 --- a/crates/viewer/re_component_ui/tests/test_all_components_ui.rs +++ b/crates/viewer/re_component_ui/tests/test_all_components_ui.rs @@ -227,13 +227,7 @@ fn test_single_component_ui_as_list_item( }); harness.run(); - - //TODO(#8245): enable this everywhere when we have a software renderer setup - if cfg!(target_os = "macos") { - harness.try_snapshot_options(&format!("{test_case}"), _snapshot_options) - } else { - Ok(()) - } + harness.try_snapshot_options(&format!("{test_case}"), _snapshot_options) } // --- diff --git a/crates/viewer/re_time_panel/tests/time_panel_tests.rs b/crates/viewer/re_time_panel/tests/time_panel_tests.rs index ae93eac6531e..15e7d5dfd754 100644 --- a/crates/viewer/re_time_panel/tests/time_panel_tests.rs +++ b/crates/viewer/re_time_panel/tests/time_panel_tests.rs @@ -103,8 +103,5 @@ fn run_time_panel_and_save_snapshot(mut test_context: TestContext, _snapshot_nam }); harness.run(); - - //TODO(#8245): enable this everywhere when we have a software renderer setup - #[cfg(target_os = "macos")] harness.snapshot(_snapshot_name); } diff --git a/crates/viewer/re_ui/tests/arrow_ui_test.rs b/crates/viewer/re_ui/tests/arrow_ui_test.rs index 3e84288104b9..d3ed71595fec 100644 --- a/crates/viewer/re_ui/tests/arrow_ui_test.rs +++ b/crates/viewer/re_ui/tests/arrow_ui_test.rs @@ -17,9 +17,6 @@ pub fn test_arrow_ui() { harness.fit_contents(); harness.run(); - - //TODO(#8245): enable this everywhere when we have a software renderer setup - #[cfg(target_os = "macos")] harness.snapshot("arrow_ui"); } diff --git a/crates/viewer/re_ui/tests/list_item_tests.rs b/crates/viewer/re_ui/tests/list_item_tests.rs index dcabc9d28a0d..86db31082935 100644 --- a/crates/viewer/re_ui/tests/list_item_tests.rs +++ b/crates/viewer/re_ui/tests/list_item_tests.rs @@ -200,8 +200,5 @@ pub fn test_list_items_should_match_snapshot() { }); harness.run(); - - //TODO(#8245): enable this everywhere when we have a software renderer setup - #[cfg(target_os = "macos")] harness.snapshot("list_items"); } diff --git a/crates/viewer/re_ui/tests/modal_tests.rs b/crates/viewer/re_ui/tests/modal_tests.rs index 75f5f4b61068..42e8c58b6f6c 100644 --- a/crates/viewer/re_ui/tests/modal_tests.rs +++ b/crates/viewer/re_ui/tests/modal_tests.rs @@ -61,8 +61,5 @@ fn run_modal_test( }); harness.run(); - - //TODO(#8245): enable this everywhere when we have a software renderer setup - #[cfg(target_os = "macos")] harness.snapshot(_test_name); } diff --git a/crates/viewer/re_view_graph/tests/basic.rs b/crates/viewer/re_view_graph/tests/basic.rs index a394fe5b6c27..4701354e814c 100644 --- a/crates/viewer/re_view_graph/tests/basic.rs +++ b/crates/viewer/re_view_graph/tests/basic.rs @@ -247,9 +247,6 @@ fn run_graph_view_and_save_snapshot( }); harness.run(); - - //TODO(#8245): enable this everywhere when we have a software renderer setup - #[cfg(target_os = "macos")] harness.snapshot(_name); Ok(()) From 38de20e7ce7826867b4af22de49e2d72c63c4f00 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 8 Jan 2025 15:30:17 +0100 Subject: [PATCH 02/43] wgpu setup in test context is now mandatory --- .../re_viewer_context/src/test_context.rs | 79 ++++++++----------- 1 file changed, 33 insertions(+), 46 deletions(-) diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index cd9354ab1adb..1156d4fd73b0 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -6,7 +6,6 @@ use parking_lot::Mutex; use re_chunk_store::LatestAtQuery; use re_entity_db::EntityDb; -use re_log::ResultExt as _; use re_log_types::{StoreId, StoreKind}; use re_types_core::reflection::Reflection; @@ -89,12 +88,10 @@ impl Default for TestContext { } /// Create an `egui_wgpu::RenderState` for tests. -/// -/// May be `None` if we failed to initialize the wgpu renderer setup. -fn create_egui_renderstate() -> Option { +fn create_egui_renderstate() -> egui_wgpu::RenderState { re_tracing::profile_function!(); - let shared_wgpu_setup = (*SHARED_WGPU_RENDERER_SETUP).as_ref()?; + let shared_wgpu_setup = &*SHARED_WGPU_RENDERER_SETUP; let config = egui_wgpu::WgpuConfiguration { wgpu_setup: egui_wgpu::WgpuSetupExisting { @@ -142,7 +139,8 @@ fn create_egui_renderstate() -> Option { ) .expect("Failed to initialize re_renderer"), ); - Some(render_state) + + render_state } /// Instance & adapter @@ -156,54 +154,50 @@ struct SharedWgpuResources { queue: Arc, } -static SHARED_WGPU_RENDERER_SETUP: Lazy> = - Lazy::new(try_init_shared_renderer_setup); +static SHARED_WGPU_RENDERER_SETUP: Lazy = + Lazy::new(init_shared_renderer_setup); -fn try_init_shared_renderer_setup() -> Option { +fn init_shared_renderer_setup() -> SharedWgpuResources { // TODO(andreas, emilk/egui#5506): Use centralized wgpu setup logic that… // * lives mostly in re_renderer and is shared with viewer & renderer examples // * can be told to prefer software rendering // * can be told to match a specific device tier // For the moment we just use wgpu defaults. - // TODO(#8245): Should we require this to succeed? - let instance = wgpu::Instance::default(); let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::default(), force_fallback_adapter: false, compatible_surface: None, - }))?; + })) + .expect("Failed to request adapter"); let device_caps = re_renderer::config::DeviceCaps::from_adapter(&adapter) - .warn_on_err_once("Failed to determine device capabilities")?; + .expect("Failed to determine device capabilities"); let (device, queue) = pollster::block_on(adapter.request_device(&device_caps.device_descriptor(), None)) - .warn_on_err_once("Failed to request device.")?; + .expect("Failed to request device."); - Some(SharedWgpuResources { + SharedWgpuResources { instance: Arc::new(instance), adapter: Arc::new(adapter), device: Arc::new(device), queue: Arc::new(queue), - }) + } } impl TestContext { pub fn setup_kittest_for_rendering(&self) -> egui_kittest::HarnessBuilder<()> { - if let Some(new_render_state) = create_egui_renderstate() { - let builder = egui_kittest::Harness::builder().renderer( - // Note that render state clone is mostly cloning of inner `Arc`. - // This does _not_ duplicate re_renderer's context. - egui_kittest::wgpu::WgpuTestRenderer::from_render_state(new_render_state.clone()), - ); - - // Egui kittests insists on having a fresh render state for each test. - self.egui_render_state.lock().replace(new_render_state); - builder - } else { - egui_kittest::Harness::builder() - } + let new_render_state = create_egui_renderstate(); + let builder = egui_kittest::Harness::builder().renderer( + // Note that render state clone is mostly cloning of inner `Arc`. + // This does _not_ duplicate re_renderer's context. + egui_kittest::wgpu::WgpuTestRenderer::from_render_state(new_render_state.clone()), + ); + // Egui kittests insists on having a fresh render state for each test. + self.egui_render_state.lock().replace(new_render_state); + + builder } /// Timeline the recording config is using by default. @@ -237,19 +231,14 @@ impl TestContext { let drag_and_drop_manager = crate::DragAndDropManager::new(ItemCollection::default()); - let context_render_state = self.egui_render_state.lock(); - let mut renderer; - let render_ctx = if let Some(render_state) = context_render_state.as_ref() { - renderer = render_state.renderer.write(); - let render_ctx = renderer - .callback_resources - .get_mut::() - .expect("No re_renderer::RenderContext in egui_render_state"); - render_ctx.begin_frame(); - Some(render_ctx) - } else { - None - }; + let mut context_render_state = self.egui_render_state.lock(); + let render_state = context_render_state.get_or_insert_with(create_egui_renderstate); + let mut egui_renderer = render_state.renderer.write(); + let render_ctx = egui_renderer + .callback_resources + .get_mut::() + .expect("No re_renderer::RenderContext in egui_render_state"); + render_ctx.begin_frame(); let ctx = ViewerContext { app_options: &Default::default(), @@ -266,7 +255,7 @@ impl TestContext { selection_state: &self.selection_state, blueprint_query: &self.blueprint_query, egui_ctx, - render_ctx: render_ctx.as_deref(), + render_ctx: Some(render_ctx), command_sender: &self.command_sender, focused_item: &None, drag_and_drop_manager: &drag_and_drop_manager, @@ -274,9 +263,7 @@ impl TestContext { func(&ctx); - if let Some(render_ctx) = render_ctx { - render_ctx.before_submit(); - } + render_ctx.before_submit(); } /// Run the given function with a [`ViewerContext`] produced by the [`Self`], in the context of From 4873ebd434ccb68785a7a91461e0d6a696cc0a8a Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 8 Jan 2025 18:11:19 +0100 Subject: [PATCH 03/43] install llvmpipe on Linux & Windows for testing --- .github/workflows/contrib_checks.yml | 3 + .github/workflows/reusable_checks_rust.yml | 30 +++- .gitignore | 5 + .../re_viewer_context/src/test_context.rs | 2 + scripts/ci/setup_software_rasterizer.py | 148 ++++++++++++++++++ 5 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 scripts/ci/setup_software_rasterizer.py diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index d93730a7db40..266c745a3c23 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -97,6 +97,9 @@ jobs: with: pixi-version: v0.39.0 + - name: Setup software rasterizer + run: pixi run python ./scripts/ci/setup_software_rasterizer.py + - name: Rust checks & tests run: pixi run rs-check --skip individual_crates docs_slow diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index b245aeabe635..1b0f47b946d0 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -65,11 +65,18 @@ jobs: with: pixi-version: v0.39.0 - - name: Rust checks & tests + - name: Setup software rasterizer + run: pixi run python ./scripts/ci/setup_software_rasterizer.py + + - name: Rust checks (PR subset) if: ${{ inputs.CHANNEL == 'pr' }} - run: pixi run rs-check --skip individual_crates tests docs_slow + run: pixi run rs-check --only base_checks sdk_variations cargo_deny wasm docs - - name: Rust checks & tests + - name: Run tests (`cargo test --all-targets --all-features`) + if: ${{ inputs.CHANNEL == 'pr' }} + run: pixi run cargo test --all-targets --all-features + + - name: Rust most checks & tests if: ${{ inputs.CHANNEL == 'main' }} run: pixi run rs-check --skip individual_crates docs_slow @@ -79,14 +86,17 @@ jobs: # Run some basics tests on Mac and Windows mac-windows-tests: + #if: ${{ inputs.CHANNEL != 'pr' }} # TODO: uncomment this, only here for quicker testing of ci. name: Test on ${{ matrix.name }} strategy: matrix: include: # TODO(#8245): we run mac tests on `main` because that's the only platform where UI snapshot tests are covered. # When the linux runners are able to run these tests (with a software renderer), we can move that back to all nightly. - - os: ${{ inputs.CHANNEL == 'main' && 'macos-latest' || 'windows-latest-8-cores' }} - name: ${{ inputs.CHANNEL == 'main' && 'macos' || 'windows' }} + - os: "macos-latest" + name: "macos" + - os: "windows-latest-8-cores" + name: "windows" # Note: we can't use `matrix.os` here because its evaluated before the matrix stuff. if: ${{ inputs.CHANNEL == 'main' || inputs.CHANNEL == 'nightly' }} @@ -104,6 +114,9 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} + - name: Setup software rasterizer + run: pixi run python ./scripts/ci/setup_software_rasterizer.py + # Building with `--all-features` requires extra build tools like `nasm`. - uses: prefix-dev/setup-pixi@v0.8.1 with: @@ -112,5 +125,10 @@ jobs: - name: Download test assets run: pixi run python ./tests/assets/download_test_assets.py - - name: pixi run cargo test --all-targets --all-features + - name: Run tests (`cargo test --all-targets --all-features`) + if: ${{ inputs.CHANNEL != 'nightly' }} run: pixi run cargo test --all-targets --all-features + + - name: Rust all checks & tests + if: ${{ inputs.CHANNEL == 'nightly' }} + run: pixi run rs-check diff --git a/.gitignore b/.gitignore index 43b4208ba656..63e2180b00ad 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,11 @@ wheels **/tests/snapshots/**/*.diff.png **/tests/snapshots/**/*.new.png +# Mesa install +mesa +mesa.7z +mesa.tar.xz + *.rrd /meilisearch diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 1156d4fd73b0..d97da6f1118d 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -172,6 +172,8 @@ fn init_shared_renderer_setup() -> SharedWgpuResources { })) .expect("Failed to request adapter"); + re_log::info!("Picked adapter: {:?}", adapter.get_info()); + let device_caps = re_renderer::config::DeviceCaps::from_adapter(&adapter) .expect("Failed to determine device capabilities"); let (device, queue) = diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py new file mode 100644 index 000000000000..3e82bc8b0974 --- /dev/null +++ b/scripts/ci/setup_software_rasterizer.py @@ -0,0 +1,148 @@ +""" +Sets up software rasterizers for CI. + +Borrows heavily from wgpu's CI setup. +See https://github.com/gfx-rs/wgpu/blob/a8a91737b2d2f378976e292074c75817593a0224/.github/workflows/ci.yml#L10 +In fact we're the exact same Mesa builds that wgpu produces, +see https://github.com/gfx-rs/ci-build +""" + +from __future__ import annotations + +import os +import platform +import subprocess +import sys +from distutils.dir_util import copy_tree +from pathlib import Path + +# Sourced from https://archive.mesa3d.org/. Bumping this requires +# updating the mesa build in https://github.com/gfx-rs/ci-build and creating a new release. +MESA_VERSION = "24.2.3" + +# Corresponds to https://github.com/gfx-rs/ci-build/releases +CI_BINARY_BUILD = "build19" + +TARGET_DIR = Path("target/debug") + + +def run( + args: list[str], *, env: dict[str, str] | None = None, timeout: int | None = None, cwd: str | None = None +) -> None: + print(f"> {subprocess.list2cmdline(args)}") + result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) + assert ( + result.returncode == 0 + ), f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" + + +def set_environment_variables(variables: dict[str, str]) -> None: + """ + Sets environment variables in the GITHUB_ENV file. + + If `GITHUB_ENV` is not set (i.e. when running locally), prints the variables to stdout. + """ + + github_env = os.environ.get("GITHUB_ENV") + if github_env is None: + print(f"GITHUB_ENV is not set. The following environment variables need to be set:\n{variables}") + else: + print(f"Setting environment variables in {github_env}:\n{variables}") + with open(github_env, "a", encoding="utf-8") as f: + for key, value in variables.items(): + f.write(f"{key}={value}\n") + + +def setup_llvmpipe_for_linux() -> None: + """Sets up llvmpipe mesa driver for Linux (x64).""" + # Download mesa + run([ + "curl", + "-L", + "--retry", + "5", + f"https://github.com/gfx-rs/ci-build/releases/download/{CI_BINARY_BUILD}/mesa-{MESA_VERSION}-linux-x86_64.tar.xz", + "-o", + "mesa.tar.xz", + ]) + + # Create mesa directory and extract + os.makedirs("mesa", exist_ok=True) + run(["tar", "xpf", "mesa.tar.xz", "-C", "mesa"]) + + # The ICD provided by the mesa build is hardcoded to the build environment. + # We write out our own ICD file to point to the mesa vulkan + icd_json = f"""{{ + "ICD": {{ + "api_version": "1.1.255", + "library_path": "{os.getcwd()}/mesa/lib/x86_64-linux-gnu/libvulkan_lvp.so" + }}, + "file_format_version": "1.0.0" +}}""" + with open("icd.json", "w", encoding="utf-8") as f: + f.write(icd_json) + + # Update environment variables + set_environment_variables({ + "VK_DRIVER_FILES": f"{os.getcwd()}/icd.json", + "LD_LIBRARY_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/:{os.environ.get('LD_LIBRARY_PATH', '')}", + "LIBGL_DRIVERS_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/dri", + }) + + +def setup_llvmpipe_for_windows() -> None: + """Sets up llvmpipe mesa driver for Windows (x64).""" + + # Download mesa + run([ + "curl.exe", + "-L", + "--retry", + "5", + f"https://github.com/pal1000/mesa-dist-win/releases/download/{MESA_VERSION}/mesa3d-{MESA_VERSION}-release-msvc.7z", + "-o", + "mesa.7z", + ]) + + # Extract needed files + run([ + "7z.exe", + "e", + "mesa.7z", + "-aoa", + "-omesa", + "x64/opengl32.dll", + "x64/libgallium_wgl.dll", + "x64/libglapi.dll", + "x64/vulkan_lvp.dll", + "x64/lvp_icd.x86_64.json", + ]) + + # Copy files to target directory. + copy_tree("mesa", TARGET_DIR) + copy_tree("mesa", TARGET_DIR / "deps") + + # Set environment variables, make sure to use windows path style. + mesa_json_path = ( + Path(os.path.join(os.getcwd(), "mesa", "lvp_icd.x86_64.json")).resolve().as_posix().replace("/", "\\") + ) + set_environment_variables({"VK_DRIVER_FILES": mesa_json_path, "GALLIUM_DRIVER": "llvmpipe"}) + + +def main() -> None: + if os.name == "nt" and platform.machine() == "AMD64": + # Note that we could also use WARP, the DX12 software rasterizer. + # (wgpu tests with both llvmpip and WARP) + # But practically speaking we prefer Vulkan anyways on Windows today and as such this is + # both less variation and closer to what Rerun uses when running on a "real" machine. + setup_llvmpipe_for_windows() + elif os.name == "posix" and sys.platform != "darwin" and platform.machine() == "x86_64": + setup_llvmpipe_for_linux() + elif os.name == "posix" and sys.platform == "darwin": + pass # We don't have a software rasterizer for macOS. + else: + raise ValueError(f"Unsupported OS / architecture: {os.name} / {platform.machine()}") + + +if __name__ == "__main__": + main() From 2974284332f915e4fc757bbd5ef46d5bee33ecf0 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 8 Jan 2025 19:20:16 +0100 Subject: [PATCH 04/43] prefer software rasterizers, only use Vulkan & Metal for testing --- .gitignore | 1 + .../re_viewer_context/src/test_context.rs | 35 +++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 63e2180b00ad..112556bde879 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,7 @@ wheels mesa mesa.7z mesa.tar.xz +icd.json *.rrd diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index d97da6f1118d..898e50e10bf4 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -165,13 +165,36 @@ fn init_shared_renderer_setup() -> SharedWgpuResources { // For the moment we just use wgpu defaults. let instance = wgpu::Instance::default(); - let adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::default(), - force_fallback_adapter: false, - compatible_surface: None, - })) - .expect("Failed to request adapter"); + let mut adapters = instance.enumerate_adapters(wgpu::Backends::VULKAN | wgpu::Backends::METAL); + if adapters.is_empty() { + panic!("No graphics adapter found!"); + } + re_log::info!("Found the following adapters:"); + for adapter in &adapters { + re_log::info!("* {}", egui_wgpu::adapter_info_summary(&adapter.get_info())); + } + + // Adapters are already sorted by preferred backend by wgpu, but let's be explicit. + adapters.sort_by_key(|a| match a.get_info().backend { + wgpu::Backend::Metal => 0, + wgpu::Backend::Vulkan => 1, + wgpu::Backend::Dx12 => 2, + wgpu::Backend::Gl => 4, + wgpu::Backend::BrowserWebGpu => 6, + wgpu::Backend::Empty => 7, + }); + + // Prefer CPU adapters, otherwise if we can't, prefer discrete GPU over integrated GPU. + adapters.sort_by_key(|a| match a.get_info().device_type { + wgpu::DeviceType::Cpu => 0, // CPU is the best for our purposes! + wgpu::DeviceType::DiscreteGpu => 1, + wgpu::DeviceType::Other + | wgpu::DeviceType::IntegratedGpu + | wgpu::DeviceType::VirtualGpu => 2, + }); + + let adapter = adapters.remove(0); re_log::info!("Picked adapter: {:?}", adapter.get_info()); let device_caps = re_renderer::config::DeviceCaps::from_adapter(&adapter) From 95d76197eb0fabe80f82b21735aa8afdcb1ab3ad Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 8 Jan 2025 19:25:41 +0100 Subject: [PATCH 05/43] fix temp ci guard being in wrong place --- .github/workflows/reusable_checks_rust.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 1b0f47b946d0..d99141ecc0e0 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -86,7 +86,6 @@ jobs: # Run some basics tests on Mac and Windows mac-windows-tests: - #if: ${{ inputs.CHANNEL != 'pr' }} # TODO: uncomment this, only here for quicker testing of ci. name: Test on ${{ matrix.name }} strategy: matrix: @@ -99,7 +98,7 @@ jobs: name: "windows" # Note: we can't use `matrix.os` here because its evaluated before the matrix stuff. - if: ${{ inputs.CHANNEL == 'main' || inputs.CHANNEL == 'nightly' }} + #if: ${{ inputs.CHANNEL == 'main' || inputs.CHANNEL == 'nightly' }} # TODO: uncomment this, only here for quicker testing of ci. runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 From dd522250b554bc7947101472225c7231c8828067 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 8 Jan 2025 19:27:03 +0100 Subject: [PATCH 06/43] fix clippy warning --- crates/viewer/re_viewer_context/src/test_context.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 898e50e10bf4..e22781b7d916 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -167,9 +167,7 @@ fn init_shared_renderer_setup() -> SharedWgpuResources { let instance = wgpu::Instance::default(); let mut adapters = instance.enumerate_adapters(wgpu::Backends::VULKAN | wgpu::Backends::METAL); - if adapters.is_empty() { - panic!("No graphics adapter found!"); - } + assert!(!adapters.is_empty(), "No graphics adapter found!"); re_log::info!("Found the following adapters:"); for adapter in &adapters { re_log::info!("* {}", egui_wgpu::adapter_info_summary(&adapter.get_info())); From bbbe8ae6b42a33ff714a4748ccb096b7612d966a Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 8 Jan 2025 19:28:58 +0100 Subject: [PATCH 07/43] move pixi setup to the right place --- .github/workflows/reusable_checks_rust.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index d99141ecc0e0..c545769b658c 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -113,14 +113,14 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - name: Setup software rasterizer - run: pixi run python ./scripts/ci/setup_software_rasterizer.py - # Building with `--all-features` requires extra build tools like `nasm`. - uses: prefix-dev/setup-pixi@v0.8.1 with: pixi-version: v0.39.0 + - name: Setup software rasterizer + run: pixi run python ./scripts/ci/setup_software_rasterizer.py + - name: Download test assets run: pixi run python ./tests/assets/download_test_assets.py From a1d083546376a68949f8f4be427aa297b790f7e5 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 8 Jan 2025 19:29:30 +0100 Subject: [PATCH 08/43] temp comment out rs-checks --- .github/workflows/reusable_checks_rust.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index c545769b658c..bcdb7049d889 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -68,9 +68,10 @@ jobs: - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py - - name: Rust checks (PR subset) - if: ${{ inputs.CHANNEL == 'pr' }} - run: pixi run rs-check --only base_checks sdk_variations cargo_deny wasm docs + # TODO: re-enable + # - name: Rust checks (PR subset) + # if: ${{ inputs.CHANNEL == 'pr' }} + # run: pixi run rs-check --only base_checks sdk_variations cargo_deny wasm docs - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL == 'pr' }} From 78ff58340cbcf8145cd47528f8cab3236c409a43 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 8 Jan 2025 20:21:54 +0100 Subject: [PATCH 09/43] allow non-compliant adapters --- .../viewer/re_viewer_context/src/test_context.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index e22781b7d916..823dbb79d5bf 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -162,11 +162,19 @@ fn init_shared_renderer_setup() -> SharedWgpuResources { // * lives mostly in re_renderer and is shared with viewer & renderer examples // * can be told to prefer software rendering // * can be told to match a specific device tier - // For the moment we just use wgpu defaults. - let instance = wgpu::Instance::default(); - - let mut adapters = instance.enumerate_adapters(wgpu::Backends::VULKAN | wgpu::Backends::METAL); + // We don't test on GL & DX12 right now (and don't want to do so by mistake!). + let backends = wgpu::Backends::VULKAN | wgpu::Backends::METAL; + let flags = (wgpu::InstanceFlags::ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER + | wgpu::InstanceFlags::VALIDATION + | wgpu::InstanceFlags::GPU_BASED_VALIDATION) + .with_env(); // Allow overwriting flags via env vars. + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends, + flags, + ..Default::default() + }); + let mut adapters = instance.enumerate_adapters(backends); assert!(!adapters.is_empty(), "No graphics adapter found!"); re_log::info!("Found the following adapters:"); for adapter in &adapters { From bdd32bbc60c7676e3cecca2dc594df4e793373b3 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 00:38:23 +0100 Subject: [PATCH 10/43] try with installing vulkan sdk, don't install gallium etc. --- .github/workflows/reusable_checks_rust.yml | 19 +++++++++++++++++++ scripts/ci/setup_software_rasterizer.py | 20 ++++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index bcdb7049d889..0f4827c998fa 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -65,6 +65,14 @@ jobs: with: pixi-version: v0.39.0 + - name: Install Vulkan SDK + uses: jakoch/install-vulkan-sdk-action@v1.0.0 + with: + vulkan_version: 1.3.231.1 # TODO: set as variable + install_runtime: true + cache: true + stripdown: true + - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py @@ -119,6 +127,17 @@ jobs: with: pixi-version: v0.39.0 + # TODO: if this works, also put it on user ci + # TODO: explain here and in script + - name: Install Vulkan SDK + if: ${{ matrix.name != 'macos' }} + uses: jakoch/install-vulkan-sdk-action@v1.0.0 + with: + vulkan_version: 1.3.231.1 # TODO: set as variable + install_runtime: true + cache: true + stripdown: true + - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 3e82bc8b0974..a9fe999bc9b4 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -53,8 +53,8 @@ def set_environment_variables(variables: dict[str, str]) -> None: f.write(f"{key}={value}\n") -def setup_llvmpipe_for_linux() -> None: - """Sets up llvmpipe mesa driver for Linux (x64).""" +def setup_lavapipe_for_linux() -> None: + """Sets up lavapipe mesa driver for Linux (x64).""" # Download mesa run([ "curl", @@ -85,13 +85,12 @@ def setup_llvmpipe_for_linux() -> None: # Update environment variables set_environment_variables({ "VK_DRIVER_FILES": f"{os.getcwd()}/icd.json", - "LD_LIBRARY_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/:{os.environ.get('LD_LIBRARY_PATH', '')}", - "LIBGL_DRIVERS_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/dri", + "LD_LIBRARY_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/:{os.environ.get('LD_LIBRARY_PATH', '')}" }) -def setup_llvmpipe_for_windows() -> None: - """Sets up llvmpipe mesa driver for Windows (x64).""" +def setup_lavapipe_for_windows() -> None: + """Sets up lavapipe mesa driver for Windows (x64).""" # Download mesa run([ @@ -111,9 +110,6 @@ def setup_llvmpipe_for_windows() -> None: "mesa.7z", "-aoa", "-omesa", - "x64/opengl32.dll", - "x64/libgallium_wgl.dll", - "x64/libglapi.dll", "x64/vulkan_lvp.dll", "x64/lvp_icd.x86_64.json", ]) @@ -126,7 +122,7 @@ def setup_llvmpipe_for_windows() -> None: mesa_json_path = ( Path(os.path.join(os.getcwd(), "mesa", "lvp_icd.x86_64.json")).resolve().as_posix().replace("/", "\\") ) - set_environment_variables({"VK_DRIVER_FILES": mesa_json_path, "GALLIUM_DRIVER": "llvmpipe"}) + set_environment_variables({"VK_DRIVER_FILES": mesa_json_path}) def main() -> None: @@ -135,9 +131,9 @@ def main() -> None: # (wgpu tests with both llvmpip and WARP) # But practically speaking we prefer Vulkan anyways on Windows today and as such this is # both less variation and closer to what Rerun uses when running on a "real" machine. - setup_llvmpipe_for_windows() + setup_lavapipe_for_windows() elif os.name == "posix" and sys.platform != "darwin" and platform.machine() == "x86_64": - setup_llvmpipe_for_linux() + setup_lavapipe_for_linux() elif os.name == "posix" and sys.platform == "darwin": pass # We don't have a software rasterizer for macOS. else: From 7e5b35395de7a0ea5d50f7753180a3f476733b42 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 00:59:27 +0100 Subject: [PATCH 11/43] enable trace logging --- .github/workflows/reusable_checks_rust.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 0f4827c998fa..a3678b4546e3 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -83,7 +83,7 @@ jobs: - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL == 'pr' }} - run: pixi run cargo test --all-targets --all-features + run: RUST_LOG=trace cargo test --all-targets --all-features - name: Rust most checks & tests if: ${{ inputs.CHANNEL == 'main' }} @@ -146,7 +146,7 @@ jobs: - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL != 'nightly' }} - run: pixi run cargo test --all-targets --all-features + run: pixi run RUST_LOG=trace cargo test --all-targets --all-features - name: Rust all checks & tests if: ${{ inputs.CHANNEL == 'nightly' }} From cc06340cd719aa0ac6a9af362dba36f7ac6dd3ee Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 10:43:40 +0100 Subject: [PATCH 12/43] more diagnostics by default on ci --- .github/workflows/reusable_checks_rust.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index a3678b4546e3..925c7e6b20b6 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -15,7 +15,6 @@ concurrency: cancel-in-progress: true env: - PYTHON_VERSION: "3.8" # web_sys_unstable_apis is required to enable the web_sys clipboard API which egui_web uses # https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Clipboard.html # https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html @@ -34,6 +33,9 @@ env: # these incremental artifacts when running on CI. CARGO_INCREMENTAL: "0" + # Improve diagnostics for crashes. + RUST_BACKTRACE: full + defaults: run: shell: bash @@ -83,7 +85,7 @@ jobs: - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL == 'pr' }} - run: RUST_LOG=trace cargo test --all-targets --all-features + run: cargo test --all-targets --all-features - name: Rust most checks & tests if: ${{ inputs.CHANNEL == 'main' }} @@ -146,7 +148,7 @@ jobs: - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL != 'nightly' }} - run: pixi run RUST_LOG=trace cargo test --all-targets --all-features + run: cargo test --all-targets --all-features - name: Rust all checks & tests if: ${{ inputs.CHANNEL == 'nightly' }} From 594f050cdaf513f09f14adb6db280be72a0b42c0 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 10:46:11 +0100 Subject: [PATCH 13/43] debug vk_driver_files --- crates/viewer/re_viewer_context/src/test_context.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 823dbb79d5bf..8cd3f9ebd78e 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -50,7 +50,8 @@ impl Default for TestContext { fn default() -> Self { // We rely a lot on logging in the viewer to identify issues. // Make sure logging is set up if it hasn't been done yet. - let _ = env_logger::builder().is_test(true).try_init(); + //let _ = env_logger::builder().is_test(true).try_init(); + let _ = env_logger::builder().is_test(false).try_init(); let recording_store = EntityDb::new(StoreId::random(StoreKind::Recording)); let blueprint_store = EntityDb::new(StoreId::random(StoreKind::Blueprint)); @@ -93,6 +94,11 @@ fn create_egui_renderstate() -> egui_wgpu::RenderState { let shared_wgpu_setup = &*SHARED_WGPU_RENDERER_SETUP; + // TODO: temp + let vk_driver_files = std::env::var("VK_DRIVER_FILES").unwrap_or_default(); + println!("VK_DRIVER_FILES: {}", vk_driver_files); + println!("{}", std::fs::read_to_string(vk_driver_files).unwrap()); + let config = egui_wgpu::WgpuConfiguration { wgpu_setup: egui_wgpu::WgpuSetupExisting { instance: shared_wgpu_setup.instance.clone(), From 19558ecbcb1c60ed4a567c18f3d953de816fe611 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 11:00:34 +0100 Subject: [PATCH 14/43] re-enable run via pixi --- .github/workflows/reusable_checks_rust.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 925c7e6b20b6..554047bd8c58 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -85,7 +85,8 @@ jobs: - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL == 'pr' }} - run: cargo test --all-targets --all-features + # Need to use pixi due to NASM dependency. + run: pixi run cargo test --all-targets --all-features - name: Rust most checks & tests if: ${{ inputs.CHANNEL == 'main' }} @@ -148,7 +149,8 @@ jobs: - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL != 'nightly' }} - run: cargo test --all-targets --all-features + # Need to use pixi due to NASM dependency. + run: pixi run cargo test --all-targets --all-features - name: Rust all checks & tests if: ${{ inputs.CHANNEL == 'nightly' }} From 73c067ec7eb44e57da8fee551159512ab7f8fb58 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 11:00:44 +0100 Subject: [PATCH 15/43] disable all ci but rust for temporarily --- .github/workflows/on_pull_request.yml | 181 +++++++++++++------------- 1 file changed, 91 insertions(+), 90 deletions(-) diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 0d4cfc2040cd..b95233ea0fb3 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -105,96 +105,97 @@ jobs: CHANNEL: pr secrets: inherit - python-checks: - name: "Python Checks" - needs: [paths-filter] - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.python_changes == 'true' - uses: ./.github/workflows/reusable_checks_python.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - secrets: inherit - - cpp-tests: - name: "C++ tests" - needs: [paths-filter] - if: needs.paths-filter.outputs.cpp_changes == 'true' - uses: ./.github/workflows/reusable_checks_cpp.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - CHANNEL: pr - secrets: inherit - - min-cli-build: - name: "Minimum CLI Build" - needs: [paths-filter] - if: needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true' - uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - PLATFORM: linux-x64 - secrets: inherit + # TODO: + # python-checks: + # name: "Python Checks" + # needs: [paths-filter] + # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.python_changes == 'true' + # uses: ./.github/workflows/reusable_checks_python.yml + # with: + # CONCURRENCY: pr-${{ github.event.pull_request.number }} + # secrets: inherit + + # cpp-tests: + # name: "C++ tests" + # needs: [paths-filter] + # if: needs.paths-filter.outputs.cpp_changes == 'true' + # uses: ./.github/workflows/reusable_checks_cpp.yml + # with: + # CONCURRENCY: pr-${{ github.event.pull_request.number }} + # CHANNEL: pr + # secrets: inherit + + # min-cli-build: + # name: "Minimum CLI Build" + # needs: [paths-filter] + # if: needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true' + # uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml + # with: + # CONCURRENCY: pr-${{ github.event.pull_request.number }} + # PLATFORM: linux-x64 + # secrets: inherit # Build and test a single wheel to limit CI cost. We use linux-x64 because it's fast. linux-arm64 would also be a good # choice, but reusable_test_wheels.yml is broken for that target (https://github.com/rerun-io/rerun/issues/5525) - min-wheel-build: - name: "Minimum Wheel Build" - needs: [min-cli-build, paths-filter] - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true') - uses: ./.github/workflows/reusable_build_and_upload_wheels.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - MODE: "pr" - PLATFORM: linux-x64 - WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" - secrets: inherit - - min-wheel-test: - name: "Minimum Wheel Test" - needs: [min-wheel-build, paths-filter] - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true') - uses: ./.github/workflows/reusable_test_wheels.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - PLATFORM: linux-x64 - WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" - FAST: true - secrets: inherit - - build-js: - name: "Build rerun_js" - needs: [paths-filter] - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.web_changes == 'true' - uses: ./.github/workflows/reusable_build_js.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - secrets: inherit - - build-web: - name: "Build web viewer" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.web_changes == 'true' - needs: [paths-filter] - uses: ./.github/workflows/reusable_build_web.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - CHANNEL: main - secrets: inherit - - upload-web: - name: "Upload Web" - needs: [build-web] - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' - uses: ./.github/workflows/reusable_upload_web.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - PR_NUMBER: ${{ github.event.pull_request.number }} - secrets: inherit - - deploy-landing-preview: - name: "Deploy Landing Preview" - needs: [paths-filter] - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.docs_changes == 'true' - uses: ./.github/workflows/reusable_deploy_landing_preview.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - PR_NUMBER: ${{ github.event.pull_request.number }} - secrets: inherit + # min-wheel-build: + # name: "Minimum Wheel Build" + # needs: [min-cli-build, paths-filter] + # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true') + # uses: ./.github/workflows/reusable_build_and_upload_wheels.yml + # with: + # CONCURRENCY: pr-${{ github.event.pull_request.number }} + # MODE: "pr" + # PLATFORM: linux-x64 + # WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" + # secrets: inherit + + # min-wheel-test: + # name: "Minimum Wheel Test" + # needs: [min-wheel-build, paths-filter] + # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true') + # uses: ./.github/workflows/reusable_test_wheels.yml + # with: + # CONCURRENCY: pr-${{ github.event.pull_request.number }} + # PLATFORM: linux-x64 + # WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" + # FAST: true + # secrets: inherit + + # build-js: + # name: "Build rerun_js" + # needs: [paths-filter] + # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.web_changes == 'true' + # uses: ./.github/workflows/reusable_build_js.yml + # with: + # CONCURRENCY: pr-${{ github.event.pull_request.number }} + # secrets: inherit + + # build-web: + # name: "Build web viewer" + # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.web_changes == 'true' + # needs: [paths-filter] + # uses: ./.github/workflows/reusable_build_web.yml + # with: + # CONCURRENCY: pr-${{ github.event.pull_request.number }} + # CHANNEL: main + # secrets: inherit + + # upload-web: + # name: "Upload Web" + # needs: [build-web] + # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' + # uses: ./.github/workflows/reusable_upload_web.yml + # with: + # CONCURRENCY: pr-${{ github.event.pull_request.number }} + # PR_NUMBER: ${{ github.event.pull_request.number }} + # secrets: inherit + + # deploy-landing-preview: + # name: "Deploy Landing Preview" + # needs: [paths-filter] + # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.docs_changes == 'true' + # uses: ./.github/workflows/reusable_deploy_landing_preview.yml + # with: + # CONCURRENCY: pr-${{ github.event.pull_request.number }} + # PR_NUMBER: ${{ github.event.pull_request.number }} + # secrets: inherit From 798e8c96cacba177c9200154bc4a242d40ee5ab1 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 12:20:48 +0100 Subject: [PATCH 16/43] more diagnostic hacks --- crates/utils/re_log/src/setup.rs | 9 +++++++++ .../viewer/re_viewer_context/src/test_context.rs | 14 +++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/crates/utils/re_log/src/setup.rs b/crates/utils/re_log/src/setup.rs index 59b7e44e4a14..72ac8932efc2 100644 --- a/crates/utils/re_log/src/setup.rs +++ b/crates/utils/re_log/src/setup.rs @@ -36,6 +36,15 @@ pub fn setup_logging() { let log_file_line = false; if log_file_line { stderr_logger.format(|buf, record| { + // TODO: HACK + println!( + "{} {}:{} {}", + record.level(), + record.file().unwrap_or_default(), + record.line().unwrap_or_default(), + record.args() + ); + use std::io::Write as _; writeln!( buf, diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 8cd3f9ebd78e..5bd49e55b8a0 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -94,11 +94,6 @@ fn create_egui_renderstate() -> egui_wgpu::RenderState { let shared_wgpu_setup = &*SHARED_WGPU_RENDERER_SETUP; - // TODO: temp - let vk_driver_files = std::env::var("VK_DRIVER_FILES").unwrap_or_default(); - println!("VK_DRIVER_FILES: {}", vk_driver_files); - println!("{}", std::fs::read_to_string(vk_driver_files).unwrap()); - let config = egui_wgpu::WgpuConfiguration { wgpu_setup: egui_wgpu::WgpuSetupExisting { instance: shared_wgpu_setup.instance.clone(), @@ -180,6 +175,15 @@ fn init_shared_renderer_setup() -> SharedWgpuResources { flags, ..Default::default() }); + + // TODO: temp + let vk_driver_files = std::env::var("VK_DRIVER_FILES").unwrap_or_default(); + println!("VK_DRIVER_FILES: {vk_driver_files}"); + println!( + "{}", + std::fs::read_to_string(vk_driver_files).expect("Failed to read VK_DRIVER_FILES") + ); + let mut adapters = instance.enumerate_adapters(backends); assert!(!adapters.is_empty(), "No graphics adapter found!"); re_log::info!("Found the following adapters:"); From 8363b1267649f738d186e65606d13b0c08b69cdf Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 13:00:59 +0100 Subject: [PATCH 17/43] install vulkan sdk the wgpu way --- .github/workflows/reusable_checks_rust.yml | 32 +++++++++++++++---- .../re_viewer_context/src/test_context.rs | 8 ----- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 554047bd8c58..bbab13a592a6 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -36,6 +36,11 @@ env: # Improve diagnostics for crashes. RUST_BACKTRACE: full + # Sourced from https://vulkan.lunarg.com/sdk/home#linux + # + # We don't include the 4th version number, as it's not used in any URL. + VULKAN_SDK_VERSION: "1.3.290" + defaults: run: shell: bash @@ -67,13 +72,26 @@ jobs: with: pixi-version: v0.39.0 - - name: Install Vulkan SDK - uses: jakoch/install-vulkan-sdk-action@v1.0.0 - with: - vulkan_version: 1.3.231.1 # TODO: set as variable - install_runtime: true - cache: true - stripdown: true + # - name: Install Vulkan SDK + # uses: jakoch/install-vulkan-sdk-action@v1.0.0 + # with: + # vulkan_version: 1.3.231.1 # TODO: set as variable + # install_runtime: true + # cache: true + # stripdown: true + + - name: (linux) install vulkan sdk + run: | + set -e + + sudo apt-get update -y -qq + + # vulkan sdk + wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add - + sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-$VULKAN_SDK_VERSION-jammy.list https://packages.lunarg.com/vulkan/$VULKAN_SDK_VERSION/lunarg-vulkan-$VULKAN_SDK_VERSION-jammy.list + + sudo apt-get update + sudo apt install -y vulkan-sdk - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 5bd49e55b8a0..97c225a42975 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -176,14 +176,6 @@ fn init_shared_renderer_setup() -> SharedWgpuResources { ..Default::default() }); - // TODO: temp - let vk_driver_files = std::env::var("VK_DRIVER_FILES").unwrap_or_default(); - println!("VK_DRIVER_FILES: {vk_driver_files}"); - println!( - "{}", - std::fs::read_to_string(vk_driver_files).expect("Failed to read VK_DRIVER_FILES") - ); - let mut adapters = instance.enumerate_adapters(backends); assert!(!adapters.is_empty(), "No graphics adapter found!"); re_log::info!("Found the following adapters:"); From cd2d20561add1fd35df3bdeb5abc2d964c102ae9 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 13:06:00 +0100 Subject: [PATCH 18/43] more random log things --- crates/utils/re_log/src/lib.rs | 6 ++---- crates/viewer/re_viewer_context/src/test_context.rs | 8 ++++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/utils/re_log/src/lib.rs b/crates/utils/re_log/src/lib.rs index debe25a13802..71940f21633d 100644 --- a/crates/utils/re_log/src/lib.rs +++ b/crates/utils/re_log/src/lib.rs @@ -60,10 +60,8 @@ const CRATES_AT_ERROR_LEVEL: &[&str] = &[ const CRATES_AT_WARN_LEVEL: &[&str] = &[ // wgpu crates spam a lot on info level, which is really annoying // TODO(emilk): remove once https://github.com/gfx-rs/wgpu/issues/3206 is fixed - "naga", - "tracing", - "wgpu_core", - "wgpu_hal", + "naga", "tracing", // "wgpu_core", + // "wgpu_hal", "zbus", ]; diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 97c225a42975..679de9222984 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -164,6 +164,14 @@ fn init_shared_renderer_setup() -> SharedWgpuResources { // * can be told to prefer software rendering // * can be told to match a specific device tier + // We rely a lot on logging in the viewer to identify issues. + // Make sure logging is set up if it hasn't been done yet. + //let _ = env_logger::builder().is_test(true).try_init(); + let _ = env_logger::builder() + .filter_level(re_log::external::log::LevelFilter::Trace) + .is_test(false) + .try_init(); + // We don't test on GL & DX12 right now (and don't want to do so by mistake!). let backends = wgpu::Backends::VULKAN | wgpu::Backends::METAL; let flags = (wgpu::InstanceFlags::ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER From c3f5f83e5d1c0e7efc5e7a3843c62b8c014cc1de Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 13:42:51 +0100 Subject: [PATCH 19/43] run vulkan info on setup_software_rasterizer --- scripts/ci/setup_software_rasterizer.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index a9fe999bc9b4..fe5b79b9a821 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -31,9 +31,9 @@ def run( ) -> None: print(f"> {subprocess.list2cmdline(args)}") result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) - assert ( - result.returncode == 0 - ), f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" + assert result.returncode == 0, ( + f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" + ) def set_environment_variables(variables: dict[str, str]) -> None: @@ -48,6 +48,7 @@ def set_environment_variables(variables: dict[str, str]) -> None: print(f"GITHUB_ENV is not set. The following environment variables need to be set:\n{variables}") else: print(f"Setting environment variables in {github_env}:\n{variables}") + # Write to GITHUB_ENV file. with open(github_env, "a", encoding="utf-8") as f: for key, value in variables.items(): f.write(f"{key}={value}\n") @@ -85,7 +86,7 @@ def setup_lavapipe_for_linux() -> None: # Update environment variables set_environment_variables({ "VK_DRIVER_FILES": f"{os.getcwd()}/icd.json", - "LD_LIBRARY_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/:{os.environ.get('LD_LIBRARY_PATH', '')}" + "LD_LIBRARY_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/:{os.environ.get('LD_LIBRARY_PATH', '')}", }) @@ -125,6 +126,19 @@ def setup_lavapipe_for_windows() -> None: set_environment_variables({"VK_DRIVER_FILES": mesa_json_path}) +def vulkan_info_windows() -> None: + vulkan_sdk_path = os.environ.get("VULKAN_SDK") + print(f"VULKAN_SDK: {vulkan_sdk_path}") + if vulkan_sdk_path is None: + print("WARNING: VULKAN_SDK is not set") + else: + run([f"{vulkan_sdk_path}/runtime/x64/vulkaninfo.exe", "--summary"]) + + +def vulkan_info_linux() -> None: + run(["vulkaninfo", "--summary"]) + + def main() -> None: if os.name == "nt" and platform.machine() == "AMD64": # Note that we could also use WARP, the DX12 software rasterizer. @@ -132,8 +146,10 @@ def main() -> None: # But practically speaking we prefer Vulkan anyways on Windows today and as such this is # both less variation and closer to what Rerun uses when running on a "real" machine. setup_lavapipe_for_windows() + vulkan_info_windows() elif os.name == "posix" and sys.platform != "darwin" and platform.machine() == "x86_64": setup_lavapipe_for_linux() + vulkan_info_linux() elif os.name == "posix" and sys.platform == "darwin": pass # We don't have a software rasterizer for macOS. else: From 401fff6a3385ee3c7a0632f27a010642799d876c Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 13:43:00 +0100 Subject: [PATCH 20/43] enable lfs, even more limited tests --- .github/workflows/reusable_checks_rust.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index bbab13a592a6..eb04d33575b8 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -59,6 +59,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} + lfs: true - name: Set up Rust uses: ./.github/actions/setup-rust @@ -80,6 +81,8 @@ jobs: # cache: true # stripdown: true + # TODO: why does this one work and the other one doesn't? + # This takes 4m 8s - name: (linux) install vulkan sdk run: | set -e @@ -122,8 +125,8 @@ jobs: include: # TODO(#8245): we run mac tests on `main` because that's the only platform where UI snapshot tests are covered. # When the linux runners are able to run these tests (with a software renderer), we can move that back to all nightly. - - os: "macos-latest" - name: "macos" + # - os: "macos-latest" + # name: "macos" - os: "windows-latest-8-cores" name: "windows" @@ -162,13 +165,15 @@ jobs: - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py - - name: Download test assets - run: pixi run python ./tests/assets/download_test_assets.py + # TODO: + # - name: Download test assets + # run: pixi run python ./tests/assets/download_test_assets.py - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL != 'nightly' }} # Need to use pixi due to NASM dependency. - run: pixi run cargo test --all-targets --all-features + #run: pixi run cargo test --all-targets --all-features + run: RUST_LOG=trace cargo test -p re_component_ui --all-features - name: Rust all checks & tests if: ${{ inputs.CHANNEL == 'nightly' }} From 55514efaff474370ce6b6f770eaf5eea259cf1ed Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 13:47:13 +0100 Subject: [PATCH 21/43] set env vars for setup script process --- scripts/ci/setup_software_rasterizer.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index fe5b79b9a821..89161f700929 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -38,11 +38,16 @@ def run( def set_environment_variables(variables: dict[str, str]) -> None: """ - Sets environment variables in the GITHUB_ENV file. + Sets environment variables for current process and in the GITHUB_ENV file. If `GITHUB_ENV` is not set (i.e. when running locally), prints the variables to stdout. """ + # Set to current process (relevant for things called from this script). + for key, value in variables.items(): + os.environ[key] = value + + # Set in GITHUB_ENV file (relevant for things called after this script). github_env = os.environ.get("GITHUB_ENV") if github_env is None: print(f"GITHUB_ENV is not set. The following environment variables need to be set:\n{variables}") From 74404532ab5fbe280af4ce97fcb9a16a4e64600f Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 13:47:56 +0100 Subject: [PATCH 22/43] focus linux test as well --- .github/workflows/reusable_checks_rust.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index eb04d33575b8..8989b951d248 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -107,7 +107,8 @@ jobs: - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL == 'pr' }} # Need to use pixi due to NASM dependency. - run: pixi run cargo test --all-targets --all-features + #run: pixi run cargo test --all-targets --all-features + run: RUST_LOG=trace cargo test -p re_component_ui --all-features - name: Rust most checks & tests if: ${{ inputs.CHANNEL == 'main' }} From 9fb8f82fc80433c8ceb3c471630173d7ae0ba6b6 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 13:59:14 +0100 Subject: [PATCH 23/43] make sure env vars in setup_software_rasterizer are set --- scripts/ci/setup_software_rasterizer.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 89161f700929..b7cc11a3367a 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -25,15 +25,19 @@ TARGET_DIR = Path("target/debug") +# Environment variables for calls to `run()` within this script. +env_for_run_calls: dict[str, str] | None = os.environ.copy() -def run( - args: list[str], *, env: dict[str, str] | None = None, timeout: int | None = None, cwd: str | None = None -) -> None: + +def run(args: list[str], *, timeout: int | None = None, cwd: str | None = None) -> subprocess.CompletedProcess[str]: print(f"> {subprocess.list2cmdline(args)}") - result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) + result = subprocess.run( + args, env=env_for_run_calls, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True + ) assert result.returncode == 0, ( f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" ) + return result def set_environment_variables(variables: dict[str, str]) -> None: @@ -42,12 +46,17 @@ def set_environment_variables(variables: dict[str, str]) -> None: If `GITHUB_ENV` is not set (i.e. when running locally), prints the variables to stdout. """ + # Set for subsequent calls within this script via `run()`. + global env_for_run_calls + if env_for_run_calls is not None: + env_for_run_calls.update(variables) + else: + env_for_run_calls = variables - # Set to current process (relevant for things called from this script). for key, value in variables.items(): os.environ[key] = value - # Set in GITHUB_ENV file (relevant for things called after this script). + # Set in GITHUB_ENV file. github_env = os.environ.get("GITHUB_ENV") if github_env is None: print(f"GITHUB_ENV is not set. The following environment variables need to be set:\n{variables}") @@ -137,11 +146,11 @@ def vulkan_info_windows() -> None: if vulkan_sdk_path is None: print("WARNING: VULKAN_SDK is not set") else: - run([f"{vulkan_sdk_path}/runtime/x64/vulkaninfo.exe", "--summary"]) + print(run([f"{vulkan_sdk_path}/runtime/x64/vulkaninfo.exe", "--summary"]).stdout) def vulkan_info_linux() -> None: - run(["vulkaninfo", "--summary"]) + print(run(["vulkaninfo", "--summary"]).stdout) def main() -> None: From e9b653bcc7bfa6e9f23d3dddc8e8586a31d21eb1 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 14:03:11 +0100 Subject: [PATCH 24/43] try direct vulkan sdk install again --- .github/workflows/reusable_checks_rust.yml | 40 ++++++++++------------ 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 8989b951d248..7721a477e985 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -73,29 +73,25 @@ jobs: with: pixi-version: v0.39.0 - # - name: Install Vulkan SDK - # uses: jakoch/install-vulkan-sdk-action@v1.0.0 - # with: - # vulkan_version: 1.3.231.1 # TODO: set as variable - # install_runtime: true - # cache: true - # stripdown: true + - name: Install Vulkan SDK + uses: jakoch/install-vulkan-sdk-action@v1.0.0 + with: + vulkan_version: ${{ env.VULKAN_SDK_VERSION }} + install_runtime: true + cache: true + stripdown: true # TODO: why does this one work and the other one doesn't? - # This takes 4m 8s - - name: (linux) install vulkan sdk - run: | - set -e - - sudo apt-get update -y -qq - - # vulkan sdk - wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add - - sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-$VULKAN_SDK_VERSION-jammy.list https://packages.lunarg.com/vulkan/$VULKAN_SDK_VERSION/lunarg-vulkan-$VULKAN_SDK_VERSION-jammy.list - - sudo apt-get update - sudo apt install -y vulkan-sdk - + # This takes about 4m + # - name: (linux) install vulkan sdk + # run: | + # set -e + # sudo apt-get update -y -qq + # # vulkan sdk + # wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add - + # sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-$VULKAN_SDK_VERSION-jammy.list https://packages.lunarg.com/vulkan/$VULKAN_SDK_VERSION/lunarg-vulkan-$VULKAN_SDK_VERSION-jammy.list + # sudo apt-get update + # sudo apt install -y vulkan-sdk - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py @@ -108,7 +104,7 @@ jobs: if: ${{ inputs.CHANNEL == 'pr' }} # Need to use pixi due to NASM dependency. #run: pixi run cargo test --all-targets --all-features - run: RUST_LOG=trace cargo test -p re_component_ui --all-features + run: RUST_LOG=debug cargo test -p re_component_ui --all-features - name: Rust most checks & tests if: ${{ inputs.CHANNEL == 'main' }} From 817a4d859719df6efe72d955806c5fccd566c2b6 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 14:45:53 +0100 Subject: [PATCH 25/43] improved vulkaninfo --- .github/workflows/reusable_checks_rust.yml | 2 +- scripts/ci/setup_software_rasterizer.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 7721a477e985..faea1e29b34e 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -74,7 +74,7 @@ jobs: pixi-version: v0.39.0 - name: Install Vulkan SDK - uses: jakoch/install-vulkan-sdk-action@v1.0.0 + uses: jakoch/install-vulkan-sdk-action@v1.0.5 with: vulkan_version: ${{ env.VULKAN_SDK_VERSION }} install_runtime: true diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index b7cc11a3367a..03561833c091 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -140,17 +140,17 @@ def setup_lavapipe_for_windows() -> None: set_environment_variables({"VK_DRIVER_FILES": mesa_json_path}) -def vulkan_info_windows() -> None: +def vulkan_info() -> None: vulkan_sdk_path = os.environ.get("VULKAN_SDK") print(f"VULKAN_SDK: {vulkan_sdk_path}") if vulkan_sdk_path is None: print("WARNING: VULKAN_SDK is not set") else: - print(run([f"{vulkan_sdk_path}/runtime/x64/vulkaninfo.exe", "--summary"]).stdout) - - -def vulkan_info_linux() -> None: - print(run(["vulkaninfo", "--summary"]).stdout) + if os.name == "nt": + vulkaninfo_path = f"{vulkan_sdk_path}/runtime/x64/vulkaninfo.exe" + else: + vulkaninfo_path = f"{vulkan_sdk_path}/x86_64/bin/vulkaninfo" + print(run([vulkaninfo_path, "--summary"]).stdout) def main() -> None: @@ -160,10 +160,10 @@ def main() -> None: # But practically speaking we prefer Vulkan anyways on Windows today and as such this is # both less variation and closer to what Rerun uses when running on a "real" machine. setup_lavapipe_for_windows() - vulkan_info_windows() + vulkan_info() elif os.name == "posix" and sys.platform != "darwin" and platform.machine() == "x86_64": setup_lavapipe_for_linux() - vulkan_info_linux() + vulkan_info() elif os.name == "posix" and sys.platform == "darwin": pass # We don't have a software rasterizer for macOS. else: From 33771e10c8e85250c55106b48a0db49f7af95d35 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 14:47:17 +0100 Subject: [PATCH 26/43] newer vulkan sdk version --- .github/workflows/reusable_checks_rust.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index faea1e29b34e..8c96e1c02936 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -37,9 +37,7 @@ env: RUST_BACKTRACE: full # Sourced from https://vulkan.lunarg.com/sdk/home#linux - # - # We don't include the 4th version number, as it's not used in any URL. - VULKAN_SDK_VERSION: "1.3.290" + VULKAN_SDK_VERSION: "1.3.296.0" defaults: run: @@ -154,7 +152,7 @@ jobs: if: ${{ matrix.name != 'macos' }} uses: jakoch/install-vulkan-sdk-action@v1.0.0 with: - vulkan_version: 1.3.231.1 # TODO: set as variable + vulkan_version: ${{ env.VULKAN_SDK_VERSION }} install_runtime: true cache: true stripdown: true From 5059b7c0926b4e9d9f5e37cb9ecf4671932182be Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 14:57:37 +0100 Subject: [PATCH 27/43] poke poke --- .github/workflows/reusable_checks_rust.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 8c96e1c02936..887165a9d4ba 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -63,7 +63,7 @@ jobs: uses: ./.github/actions/setup-rust with: cache_key: "build-linux" - save_cache: true + save_cache: false workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} @@ -150,7 +150,7 @@ jobs: # TODO: explain here and in script - name: Install Vulkan SDK if: ${{ matrix.name != 'macos' }} - uses: jakoch/install-vulkan-sdk-action@v1.0.0 + uses: jakoch/install-vulkan-sdk-action@v1.0.5 with: vulkan_version: ${{ env.VULKAN_SDK_VERSION }} install_runtime: true From 7ae5270d942ad63d2610a753477aacc5d0e376b6 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 14:59:14 +0100 Subject: [PATCH 28/43] add env info to `run` --- scripts/ci/setup_software_rasterizer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 03561833c091..456d1709f075 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -31,6 +31,7 @@ def run(args: list[str], *, timeout: int | None = None, cwd: str | None = None) -> subprocess.CompletedProcess[str]: print(f"> {subprocess.list2cmdline(args)}") + print(f"env: {env_for_run_calls}") result = subprocess.run( args, env=env_for_run_calls, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True ) From 4e80dcd5bd8d76b38e896fee0ff6debe0240a4e3 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 15:04:30 +0100 Subject: [PATCH 29/43] print icd file on windows --- scripts/ci/setup_software_rasterizer.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 456d1709f075..6f6af6634eeb 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -134,11 +134,14 @@ def setup_lavapipe_for_windows() -> None: copy_tree("mesa", TARGET_DIR) copy_tree("mesa", TARGET_DIR / "deps") + # Print icd file that should be used. + mesa_json_path = Path(os.path.join(os.getcwd(), "mesa", "lvp_icd.x86_64.json")) + print(f"Using ICD file at '{mesa_json_path}':") + with open(mesa_json_path, encoding="utf-8") as f: + print(f.read()) + # Set environment variables, make sure to use windows path style. - mesa_json_path = ( - Path(os.path.join(os.getcwd(), "mesa", "lvp_icd.x86_64.json")).resolve().as_posix().replace("/", "\\") - ) - set_environment_variables({"VK_DRIVER_FILES": mesa_json_path}) + set_environment_variables({"VK_DRIVER_FILES": mesa_json_path.resolve().as_posix().replace("/", "\\")}) def vulkan_info() -> None: From 4ab51909424a96cc3cd66224cce6161d9065b0e9 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 15:06:08 +0100 Subject: [PATCH 30/43] poke poke --- .github/workflows/reusable_checks_rust.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 887165a9d4ba..2b7fbe70304f 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -63,7 +63,7 @@ jobs: uses: ./.github/actions/setup-rust with: cache_key: "build-linux" - save_cache: false + save_cache: true workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} @@ -76,7 +76,7 @@ jobs: with: vulkan_version: ${{ env.VULKAN_SDK_VERSION }} install_runtime: true - cache: true + cache: false stripdown: true # TODO: why does this one work and the other one doesn't? From 863f5ac4da623c4383f539418fb42908551408b6 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 15:35:06 +0100 Subject: [PATCH 31/43] don't do summary on vulkaninfo, try vulkaninfoSDK --- scripts/ci/setup_software_rasterizer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 6f6af6634eeb..065e2697fedc 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -151,10 +151,10 @@ def vulkan_info() -> None: print("WARNING: VULKAN_SDK is not set") else: if os.name == "nt": - vulkaninfo_path = f"{vulkan_sdk_path}/runtime/x64/vulkaninfo.exe" + vulkaninfo_path = f"{vulkan_sdk_path}/bin/vulkaninfoSDK.exe" else: vulkaninfo_path = f"{vulkan_sdk_path}/x86_64/bin/vulkaninfo" - print(run([vulkaninfo_path, "--summary"]).stdout) + print(run([vulkaninfo_path]).stdout) # "--summary" ? def main() -> None: From 3227d351db594acdff74864e66b6bac6e1bb9fbd Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 15:40:44 +0100 Subject: [PATCH 32/43] explicit icd file passing, enable loader debug --- scripts/ci/setup_software_rasterizer.py | 54 ++++++++++++------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 065e2697fedc..74d3b7b7a5f8 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -25,16 +25,11 @@ TARGET_DIR = Path("target/debug") -# Environment variables for calls to `run()` within this script. -env_for_run_calls: dict[str, str] | None = os.environ.copy() - -def run(args: list[str], *, timeout: int | None = None, cwd: str | None = None) -> subprocess.CompletedProcess[str]: - print(f"> {subprocess.list2cmdline(args)}") - print(f"env: {env_for_run_calls}") - result = subprocess.run( - args, env=env_for_run_calls, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True - ) +def run( + args: list[str], *, env: dict[str, str] | None = None, timeout: int | None = None, cwd: str | None = None +) -> subprocess.CompletedProcess[str]: + result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) assert result.returncode == 0, ( f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" ) @@ -43,17 +38,10 @@ def run(args: list[str], *, timeout: int | None = None, cwd: str | None = None) def set_environment_variables(variables: dict[str, str]) -> None: """ - Sets environment variables for current process and in the GITHUB_ENV file. + Sets environment variables in the GITHUB_ENV file. If `GITHUB_ENV` is not set (i.e. when running locally), prints the variables to stdout. """ - # Set for subsequent calls within this script via `run()`. - global env_for_run_calls - if env_for_run_calls is not None: - env_for_run_calls.update(variables) - else: - env_for_run_calls = variables - for key, value in variables.items(): os.environ[key] = value @@ -69,7 +57,7 @@ def set_environment_variables(variables: dict[str, str]) -> None: f.write(f"{key}={value}\n") -def setup_lavapipe_for_linux() -> None: +def setup_lavapipe_for_linux() -> Path: """Sets up lavapipe mesa driver for Linux (x64).""" # Download mesa run([ @@ -95,17 +83,19 @@ def setup_lavapipe_for_linux() -> None: }}, "file_format_version": "1.0.0" }}""" - with open("icd.json", "w", encoding="utf-8") as f: + icd_json_path = Path("icd.json") + with open(icd_json_path, "w", encoding="utf-8") as f: f.write(icd_json) # Update environment variables set_environment_variables({ - "VK_DRIVER_FILES": f"{os.getcwd()}/icd.json", + "VK_DRIVER_FILES": f"{os.getcwd()}/{icd_json_path}", "LD_LIBRARY_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/:{os.environ.get('LD_LIBRARY_PATH', '')}", }) + return icd_json_path -def setup_lavapipe_for_windows() -> None: +def setup_lavapipe_for_windows() -> Path: """Sets up lavapipe mesa driver for Windows (x64).""" # Download mesa @@ -135,26 +125,32 @@ def setup_lavapipe_for_windows() -> None: copy_tree("mesa", TARGET_DIR / "deps") # Print icd file that should be used. - mesa_json_path = Path(os.path.join(os.getcwd(), "mesa", "lvp_icd.x86_64.json")) + mesa_json_path = Path(os.path.join(os.getcwd(), "mesa", "lvp_icd.x86_64.json")).resolve() print(f"Using ICD file at '{mesa_json_path}':") with open(mesa_json_path, encoding="utf-8") as f: print(f.read()) # Set environment variables, make sure to use windows path style. - set_environment_variables({"VK_DRIVER_FILES": mesa_json_path.resolve().as_posix().replace("/", "\\")}) + set_environment_variables({"VK_DRIVER_FILES": mesa_json_path.as_posix().replace("/", "\\")}) + return mesa_json_path -def vulkan_info() -> None: +def vulkan_info(icd_json_path: Path) -> None: vulkan_sdk_path = os.environ.get("VULKAN_SDK") print(f"VULKAN_SDK: {vulkan_sdk_path}") if vulkan_sdk_path is None: print("WARNING: VULKAN_SDK is not set") else: + env = os.environ.copy() + env["VK_LOADER_DEBUG"] = "all" + if os.name == "nt": + env["VK_DRIVER_FILES"] = icd_json_path.as_posix().replace("/", "\\") vulkaninfo_path = f"{vulkan_sdk_path}/bin/vulkaninfoSDK.exe" else: + env["VK_DRIVER_FILES"] = icd_json_path.as_posix() vulkaninfo_path = f"{vulkan_sdk_path}/x86_64/bin/vulkaninfo" - print(run([vulkaninfo_path]).stdout) # "--summary" ? + print(run([vulkaninfo_path], env=env).stdout) # "--summary" ? def main() -> None: @@ -163,11 +159,11 @@ def main() -> None: # (wgpu tests with both llvmpip and WARP) # But practically speaking we prefer Vulkan anyways on Windows today and as such this is # both less variation and closer to what Rerun uses when running on a "real" machine. - setup_lavapipe_for_windows() - vulkan_info() + icd_json_path = setup_lavapipe_for_windows() + vulkan_info(icd_json_path) elif os.name == "posix" and sys.platform != "darwin" and platform.machine() == "x86_64": - setup_lavapipe_for_linux() - vulkan_info() + icd_json_path = setup_lavapipe_for_linux() + vulkan_info(icd_json_path) elif os.name == "posix" and sys.platform == "darwin": pass # We don't have a software rasterizer for macOS. else: From 12912f834c8b82ad7524d439a40cfdb0a4f706b7 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 16:03:38 +0100 Subject: [PATCH 33/43] copy icd file to one of the presumed search paths --- scripts/ci/setup_software_rasterizer.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 74d3b7b7a5f8..360c50099e9c 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -11,6 +11,7 @@ import os import platform +import shutil import subprocess import sys from distutils.dir_util import copy_tree @@ -92,6 +93,17 @@ def setup_lavapipe_for_linux() -> Path: "VK_DRIVER_FILES": f"{os.getcwd()}/{icd_json_path}", "LD_LIBRARY_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/:{os.environ.get('LD_LIBRARY_PATH', '')}", }) + + # On CI it seems that VK_DRIVER_FILES is ignored unless we install the Vulkan SDK via apt + # (which takes quite a while since it drags in a lot of other dependencies). + # According to https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderInterfaceArchitecture.md#elevated-privilege-caveats + # this can happen when running with elevated privileges. + # Unclear if that's the case, but in any case we're on the safe side if we copy the icd file into one of the standard search paths. + target_path = Path("~/.config/vulkan/icd.d").expanduser() + print(f"Copying icd file to {target_path}") + target_path.mkdir(parents=True, exist_ok=True) + shutil.copy(icd_json_path, target_path) + return icd_json_path From 3f52f1861341c06ac17eee58598b6fb7e1b056c5 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 16:12:41 +0100 Subject: [PATCH 34/43] more logging, add vulkan runtime to PATH --- scripts/ci/setup_software_rasterizer.py | 49 +++++++++++++++++-------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 360c50099e9c..ed95f138d0ab 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -58,7 +58,7 @@ def set_environment_variables(variables: dict[str, str]) -> None: f.write(f"{key}={value}\n") -def setup_lavapipe_for_linux() -> Path: +def setup_lavapipe_for_linux() -> dict[str, str]: """Sets up lavapipe mesa driver for Linux (x64).""" # Download mesa run([ @@ -89,10 +89,11 @@ def setup_lavapipe_for_linux() -> Path: f.write(icd_json) # Update environment variables - set_environment_variables({ + env_vars = { "VK_DRIVER_FILES": f"{os.getcwd()}/{icd_json_path}", "LD_LIBRARY_PATH": f"{os.getcwd()}/mesa/lib/x86_64-linux-gnu/:{os.environ.get('LD_LIBRARY_PATH', '')}", - }) + } + set_environment_variables(env_vars) # On CI it seems that VK_DRIVER_FILES is ignored unless we install the Vulkan SDK via apt # (which takes quite a while since it drags in a lot of other dependencies). @@ -104,10 +105,10 @@ def setup_lavapipe_for_linux() -> Path: target_path.mkdir(parents=True, exist_ok=True) shutil.copy(icd_json_path, target_path) - return icd_json_path + return env_vars -def setup_lavapipe_for_windows() -> Path: +def setup_lavapipe_for_windows() -> dict[str, str]: """Sets up lavapipe mesa driver for Windows (x64).""" # Download mesa @@ -143,24 +144,42 @@ def setup_lavapipe_for_windows() -> Path: print(f.read()) # Set environment variables, make sure to use windows path style. - set_environment_variables({"VK_DRIVER_FILES": mesa_json_path.as_posix().replace("/", "\\")}) - return mesa_json_path + vulkan_runtime_path = f"{os.environ.get('VULKAN_SDK', '')}/runtime" + env_vars = { + "VK_DRIVER_FILES": mesa_json_path.as_posix().replace("/", "\\"), + "PATH": f"{os.environ.get('PATH', '')};{vulkan_runtime_path}", + } + set_environment_variables(env_vars) + + # For debugging: List files in Vulkan runtime path. + if vulkan_runtime_path: + print(f"\nListing files in Vulkan runtime path '{vulkan_runtime_path}':") + try: + files = os.listdir(vulkan_runtime_path) + for file in files: + print(f" {file}") + except Exception as e: + print(f"Error listing Vulkan runtime directory: {e}") + else: + print("No Vulkan runtime path available") + + return env_vars -def vulkan_info(icd_json_path: Path) -> None: +def vulkan_info(extra_env_vars: dict[str, str]) -> None: vulkan_sdk_path = os.environ.get("VULKAN_SDK") print(f"VULKAN_SDK: {vulkan_sdk_path}") if vulkan_sdk_path is None: print("WARNING: VULKAN_SDK is not set") else: env = os.environ.copy() - env["VK_LOADER_DEBUG"] = "all" + env["VK_LOADER_DEBUG"] = "all" # Enable verbose logging of vulkan loader for debugging. + for key, value in extra_env_vars.items(): + env[key] = value if os.name == "nt": - env["VK_DRIVER_FILES"] = icd_json_path.as_posix().replace("/", "\\") vulkaninfo_path = f"{vulkan_sdk_path}/bin/vulkaninfoSDK.exe" else: - env["VK_DRIVER_FILES"] = icd_json_path.as_posix() vulkaninfo_path = f"{vulkan_sdk_path}/x86_64/bin/vulkaninfo" print(run([vulkaninfo_path], env=env).stdout) # "--summary" ? @@ -171,11 +190,11 @@ def main() -> None: # (wgpu tests with both llvmpip and WARP) # But practically speaking we prefer Vulkan anyways on Windows today and as such this is # both less variation and closer to what Rerun uses when running on a "real" machine. - icd_json_path = setup_lavapipe_for_windows() - vulkan_info(icd_json_path) + env_vars = setup_lavapipe_for_windows() + vulkan_info(env_vars) elif os.name == "posix" and sys.platform != "darwin" and platform.machine() == "x86_64": - icd_json_path = setup_lavapipe_for_linux() - vulkan_info(icd_json_path) + env_vars = setup_lavapipe_for_linux() + vulkan_info(env_vars) elif os.name == "posix" and sys.platform == "darwin": pass # We don't have a software rasterizer for macOS. else: From 9480efd41afa5a0f56c136eaac7b67cde1ec8d35 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 16:19:31 +0100 Subject: [PATCH 35/43] start cleaning up a little bit --- .github/workflows/reusable_checks_rust.yml | 12 +---- scripts/ci/setup_software_rasterizer.py | 54 ++++++++++++---------- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 2b7fbe70304f..ab3ca5f3087a 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -71,6 +71,7 @@ jobs: with: pixi-version: v0.39.0 + # Install the Vulkan SDK, so we can use the software rasterizer. - name: Install Vulkan SDK uses: jakoch/install-vulkan-sdk-action@v1.0.5 with: @@ -79,17 +80,6 @@ jobs: cache: false stripdown: true - # TODO: why does this one work and the other one doesn't? - # This takes about 4m - # - name: (linux) install vulkan sdk - # run: | - # set -e - # sudo apt-get update -y -qq - # # vulkan sdk - # wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add - - # sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-$VULKAN_SDK_VERSION-jammy.list https://packages.lunarg.com/vulkan/$VULKAN_SDK_VERSION/lunarg-vulkan-$VULKAN_SDK_VERSION-jammy.list - # sudo apt-get update - # sudo apt install -y vulkan-sdk - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index ed95f138d0ab..fd921995dbbb 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -144,44 +144,48 @@ def setup_lavapipe_for_windows() -> dict[str, str]: print(f.read()) # Set environment variables, make sure to use windows path style. - vulkan_runtime_path = f"{os.environ.get('VULKAN_SDK', '')}/runtime" + vulkan_runtime_path = f"{os.environ['VULKAN_SDK']}/runtime" env_vars = { "VK_DRIVER_FILES": mesa_json_path.as_posix().replace("/", "\\"), + # Vulkan runtime install should do this, but the CI action we're using right now for instance doesn't, + # causing `vulkaninfo` to fail since it can't find the vulkan loader. "PATH": f"{os.environ.get('PATH', '')};{vulkan_runtime_path}", } set_environment_variables(env_vars) # For debugging: List files in Vulkan runtime path. - if vulkan_runtime_path: - print(f"\nListing files in Vulkan runtime path '{vulkan_runtime_path}':") - try: - files = os.listdir(vulkan_runtime_path) - for file in files: - print(f" {file}") - except Exception as e: - print(f"Error listing Vulkan runtime directory: {e}") - else: - print("No Vulkan runtime path available") + print(f"\nListing files in Vulkan runtime path '{vulkan_runtime_path}':") + try: + files = os.listdir(vulkan_runtime_path) + for file in files: + print(f" {file}") + except Exception as e: + print(f"Error listing Vulkan runtime directory: {e}") return env_vars def vulkan_info(extra_env_vars: dict[str, str]) -> None: - vulkan_sdk_path = os.environ.get("VULKAN_SDK") - print(f"VULKAN_SDK: {vulkan_sdk_path}") - if vulkan_sdk_path is None: - print("WARNING: VULKAN_SDK is not set") + vulkan_sdk_path = os.environ["VULKAN_SDK"] + env = os.environ.copy() + env["VK_LOADER_DEBUG"] = "all" # Enable verbose logging of vulkan loader for debugging. + for key, value in extra_env_vars.items(): + env[key] = value + + if os.name == "nt": + vulkaninfo_path = f"{vulkan_sdk_path}/bin/vulkaninfoSDK.exe" else: - env = os.environ.copy() - env["VK_LOADER_DEBUG"] = "all" # Enable verbose logging of vulkan loader for debugging. - for key, value in extra_env_vars.items(): - env[key] = value + vulkaninfo_path = f"{vulkan_sdk_path}/x86_64/bin/vulkaninfo" + print(run([vulkaninfo_path], env=env).stdout) - if os.name == "nt": - vulkaninfo_path = f"{vulkan_sdk_path}/bin/vulkaninfoSDK.exe" - else: - vulkaninfo_path = f"{vulkan_sdk_path}/x86_64/bin/vulkaninfo" - print(run([vulkaninfo_path], env=env).stdout) # "--summary" ? + +def check_for_vulkan_sdk() -> None: + vulkan_sdk_path = os.environ.get("VULKAN_SDK") + if vulkan_sdk_path is None: + print( + "ERROR: VULKAN_SDK is not set. The sdk needs to be installed prior including runtime & vulkaninfo utility." + ) + sys.exit(1) def main() -> None: @@ -190,9 +194,11 @@ def main() -> None: # (wgpu tests with both llvmpip and WARP) # But practically speaking we prefer Vulkan anyways on Windows today and as such this is # both less variation and closer to what Rerun uses when running on a "real" machine. + check_for_vulkan_sdk() env_vars = setup_lavapipe_for_windows() vulkan_info(env_vars) elif os.name == "posix" and sys.platform != "darwin" and platform.machine() == "x86_64": + check_for_vulkan_sdk() env_vars = setup_lavapipe_for_linux() vulkan_info(env_vars) elif os.name == "posix" and sys.platform == "darwin": From 0672127df3c58dda03acba6e0b23b3f3c38a176e Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 16:19:41 +0100 Subject: [PATCH 36/43] fix picking wrong folder for vulkan runtime --- scripts/ci/setup_software_rasterizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index fd921995dbbb..426895ec6c66 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -144,7 +144,7 @@ def setup_lavapipe_for_windows() -> dict[str, str]: print(f.read()) # Set environment variables, make sure to use windows path style. - vulkan_runtime_path = f"{os.environ['VULKAN_SDK']}/runtime" + vulkan_runtime_path = f"{os.environ['VULKAN_SDK']}/runtime/x64" env_vars = { "VK_DRIVER_FILES": mesa_json_path.as_posix().replace("/", "\\"), # Vulkan runtime install should do this, but the CI action we're using right now for instance doesn't, From e02bf87bcb65f40851ab38a02d91ff675cc379ba Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 16:20:57 +0100 Subject: [PATCH 37/43] more cleanup of things that work already --- .github/workflows/reusable_checks_rust.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index ab3ca5f3087a..176e55c84a4d 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -72,6 +72,7 @@ jobs: pixi-version: v0.39.0 # Install the Vulkan SDK, so we can use the software rasterizer. + # TODO(andreas): It would be nice if `setup_software_rasterizer.py` could do that for us as well! - name: Install Vulkan SDK uses: jakoch/install-vulkan-sdk-action@v1.0.5 with: @@ -83,16 +84,14 @@ jobs: - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py - # TODO: re-enable - # - name: Rust checks (PR subset) - # if: ${{ inputs.CHANNEL == 'pr' }} - # run: pixi run rs-check --only base_checks sdk_variations cargo_deny wasm docs + - name: Rust checks (PR subset) + if: ${{ inputs.CHANNEL == 'pr' }} + run: pixi run rs-check --only base_checks sdk_variations cargo_deny wasm docs - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL == 'pr' }} # Need to use pixi due to NASM dependency. - #run: pixi run cargo test --all-targets --all-features - run: RUST_LOG=debug cargo test -p re_component_ui --all-features + run: pixi run cargo test --all-targets --all-features - name: Rust most checks & tests if: ${{ inputs.CHANNEL == 'main' }} @@ -137,7 +136,7 @@ jobs: pixi-version: v0.39.0 # TODO: if this works, also put it on user ci - # TODO: explain here and in script + # Install the Vulkan SDK, so we can use the software rasterizer. - name: Install Vulkan SDK if: ${{ matrix.name != 'macos' }} uses: jakoch/install-vulkan-sdk-action@v1.0.5 From 62da1b01d6b4f6a4723da08db359dc7babfd99ee Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 16:33:38 +0100 Subject: [PATCH 38/43] write windows registry key for finding icd --- scripts/ci/setup_software_rasterizer.py | 51 ++++++++++++++++--------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 426895ec6c66..caade5dfa8a4 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -14,6 +14,7 @@ import shutil import subprocess import sys +import winreg from distutils.dir_util import copy_tree from pathlib import Path @@ -31,9 +32,9 @@ def run( args: list[str], *, env: dict[str, str] | None = None, timeout: int | None = None, cwd: str | None = None ) -> subprocess.CompletedProcess[str]: result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) - assert result.returncode == 0, ( - f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" - ) + assert ( + result.returncode == 0 + ), f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" return result @@ -95,11 +96,10 @@ def setup_lavapipe_for_linux() -> dict[str, str]: } set_environment_variables(env_vars) - # On CI it seems that VK_DRIVER_FILES is ignored unless we install the Vulkan SDK via apt - # (which takes quite a while since it drags in a lot of other dependencies). + # On CI we run with elevated priviledges, therefore VK_DRIVER_FILES is ignored. # According to https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderInterfaceArchitecture.md#elevated-privilege-caveats - # this can happen when running with elevated privileges. - # Unclear if that's the case, but in any case we're on the safe side if we copy the icd file into one of the standard search paths. + # (curiously, when installing the Vulkan SDK via apt, it seems to work fine). + # Therefore, we copy the icd file into one of the standard search paths. target_path = Path("~/.config/vulkan/icd.d").expanduser() print(f"Copying icd file to {target_path}") target_path.mkdir(parents=True, exist_ok=True) @@ -138,15 +138,16 @@ def setup_lavapipe_for_windows() -> dict[str, str]: copy_tree("mesa", TARGET_DIR / "deps") # Print icd file that should be used. - mesa_json_path = Path(os.path.join(os.getcwd(), "mesa", "lvp_icd.x86_64.json")).resolve() - print(f"Using ICD file at '{mesa_json_path}':") - with open(mesa_json_path, encoding="utf-8") as f: + icd_json_path = Path(os.path.join(os.getcwd(), "mesa", "lvp_icd.x86_64.json")).resolve() + print(f"Using ICD file at '{icd_json_path}':") + with open(icd_json_path, encoding="utf-8") as f: print(f.read()) + icd_json_path = icd_json_path.as_posix().replace("/", "\\") # Set environment variables, make sure to use windows path style. vulkan_runtime_path = f"{os.environ['VULKAN_SDK']}/runtime/x64" env_vars = { - "VK_DRIVER_FILES": mesa_json_path.as_posix().replace("/", "\\"), + "VK_DRIVER_FILES": icd_json_path, # Vulkan runtime install should do this, but the CI action we're using right now for instance doesn't, # causing `vulkaninfo` to fail since it can't find the vulkan loader. "PATH": f"{os.environ.get('PATH', '')};{vulkan_runtime_path}", @@ -154,13 +155,25 @@ def setup_lavapipe_for_windows() -> dict[str, str]: set_environment_variables(env_vars) # For debugging: List files in Vulkan runtime path. - print(f"\nListing files in Vulkan runtime path '{vulkan_runtime_path}':") - try: - files = os.listdir(vulkan_runtime_path) - for file in files: - print(f" {file}") - except Exception as e: - print(f"Error listing Vulkan runtime directory: {e}") + if False: + print(f"\nListing files in Vulkan runtime path '{vulkan_runtime_path}':") + try: + files = os.listdir(vulkan_runtime_path) + for file in files: + print(f" {file}") + except Exception as e: + print(f"Error listing Vulkan runtime directory: {e}") + + # On CI we run with elevated priviledges, therefore VK_DRIVER_FILES is ignored. + # According to https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderInterfaceArchitecture.md#elevated-privilege-caveats + # Therefore, we have to set one of the registry keys that is checked to find the driver. + # See https://vulkan.lunarg.com/doc/view/1.3.243.0/windows/LoaderDriverInterface.html#user-content-driver-discovery-on-windows + + # Write registry keys to configure Vulkan drivers + key_path = "SOFTWARE\\Khronos\\Vulkan\\Drivers" + key = winreg.CreateKeyEx(winreg.HKEY_LOCAL_MACHINE, key_path) + winreg.SetValueEx(key, icd_json_path, 0, winreg.REG_DWORD, 0) + winreg.CloseKey(key) return env_vars @@ -202,7 +215,7 @@ def main() -> None: env_vars = setup_lavapipe_for_linux() vulkan_info(env_vars) elif os.name == "posix" and sys.platform == "darwin": - pass # We don't have a software rasterizer for macOS. + print("Skipping software rasterizer setup for macOS - we have to rely on a real GPU here.") else: raise ValueError(f"Unsupported OS / architecture: {os.name} / {platform.machine()}") From 0f0aa44dde68d0155e47369e60bd4f89dd746bdc Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 16:36:30 +0100 Subject: [PATCH 39/43] import winreg only on windows --- scripts/ci/setup_software_rasterizer.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index caade5dfa8a4..f487b3229d5c 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -14,7 +14,6 @@ import shutil import subprocess import sys -import winreg from distutils.dir_util import copy_tree from pathlib import Path @@ -32,9 +31,9 @@ def run( args: list[str], *, env: dict[str, str] | None = None, timeout: int | None = None, cwd: str | None = None ) -> subprocess.CompletedProcess[str]: result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) - assert ( - result.returncode == 0 - ), f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" + assert result.returncode == 0, ( + f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" + ) return result @@ -170,6 +169,8 @@ def setup_lavapipe_for_windows() -> dict[str, str]: # See https://vulkan.lunarg.com/doc/view/1.3.243.0/windows/LoaderDriverInterface.html#user-content-driver-discovery-on-windows # Write registry keys to configure Vulkan drivers + import winreg + key_path = "SOFTWARE\\Khronos\\Vulkan\\Drivers" key = winreg.CreateKeyEx(winreg.HKEY_LOCAL_MACHINE, key_path) winreg.SetValueEx(key, icd_json_path, 0, winreg.REG_DWORD, 0) From 9f705ea43a97b49ab38270d88e0cfb9cd69f8cdd Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 16:49:57 +0100 Subject: [PATCH 40/43] undo all sort of hacks, getting this ready for shiping --- .github/workflows/contrib_checks.yml | 13 ++ .github/workflows/on_pull_request.yml | 181 +++++++++--------- .github/workflows/reusable_checks_rust.yml | 20 +- crates/utils/re_log/src/lib.rs | 6 +- crates/utils/re_log/src/setup.rs | 9 - .../re_viewer_context/src/test_context.rs | 3 +- scripts/ci/setup_software_rasterizer.py | 10 +- 7 files changed, 121 insertions(+), 121 deletions(-) diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 266c745a3c23..967edbacb36b 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -31,6 +31,9 @@ env: # these incremental artifacts when running on CI. CARGO_INCREMENTAL: "0" + # Sourced from https://vulkan.lunarg.com/sdk/home#linux + VULKAN_SDK_VERSION: "1.3.296.0" + defaults: run: shell: bash @@ -97,6 +100,16 @@ jobs: with: pixi-version: v0.39.0 + # Install the Vulkan SDK, so we can use the software rasterizer. + # TODO(andreas): It would be nice if `setup_software_rasterizer.py` could do that for us as well (note though that this action here is very fast when cached!) + - name: Install Vulkan SDK + uses: jakoch/install-vulkan-sdk-action@v1.0.5 + with: + vulkan_version: ${{ env.VULKAN_SDK_VERSION }} + install_runtime: true + cache: false + stripdown: true + - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index b95233ea0fb3..0d4cfc2040cd 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -105,97 +105,96 @@ jobs: CHANNEL: pr secrets: inherit - # TODO: - # python-checks: - # name: "Python Checks" - # needs: [paths-filter] - # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.python_changes == 'true' - # uses: ./.github/workflows/reusable_checks_python.yml - # with: - # CONCURRENCY: pr-${{ github.event.pull_request.number }} - # secrets: inherit - - # cpp-tests: - # name: "C++ tests" - # needs: [paths-filter] - # if: needs.paths-filter.outputs.cpp_changes == 'true' - # uses: ./.github/workflows/reusable_checks_cpp.yml - # with: - # CONCURRENCY: pr-${{ github.event.pull_request.number }} - # CHANNEL: pr - # secrets: inherit - - # min-cli-build: - # name: "Minimum CLI Build" - # needs: [paths-filter] - # if: needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true' - # uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml - # with: - # CONCURRENCY: pr-${{ github.event.pull_request.number }} - # PLATFORM: linux-x64 - # secrets: inherit + python-checks: + name: "Python Checks" + needs: [paths-filter] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.python_changes == 'true' + uses: ./.github/workflows/reusable_checks_python.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + secrets: inherit + + cpp-tests: + name: "C++ tests" + needs: [paths-filter] + if: needs.paths-filter.outputs.cpp_changes == 'true' + uses: ./.github/workflows/reusable_checks_cpp.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + CHANNEL: pr + secrets: inherit + + min-cli-build: + name: "Minimum CLI Build" + needs: [paths-filter] + if: needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true' + uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + PLATFORM: linux-x64 + secrets: inherit # Build and test a single wheel to limit CI cost. We use linux-x64 because it's fast. linux-arm64 would also be a good # choice, but reusable_test_wheels.yml is broken for that target (https://github.com/rerun-io/rerun/issues/5525) - # min-wheel-build: - # name: "Minimum Wheel Build" - # needs: [min-cli-build, paths-filter] - # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true') - # uses: ./.github/workflows/reusable_build_and_upload_wheels.yml - # with: - # CONCURRENCY: pr-${{ github.event.pull_request.number }} - # MODE: "pr" - # PLATFORM: linux-x64 - # WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" - # secrets: inherit - - # min-wheel-test: - # name: "Minimum Wheel Test" - # needs: [min-wheel-build, paths-filter] - # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true') - # uses: ./.github/workflows/reusable_test_wheels.yml - # with: - # CONCURRENCY: pr-${{ github.event.pull_request.number }} - # PLATFORM: linux-x64 - # WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" - # FAST: true - # secrets: inherit - - # build-js: - # name: "Build rerun_js" - # needs: [paths-filter] - # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.web_changes == 'true' - # uses: ./.github/workflows/reusable_build_js.yml - # with: - # CONCURRENCY: pr-${{ github.event.pull_request.number }} - # secrets: inherit - - # build-web: - # name: "Build web viewer" - # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.web_changes == 'true' - # needs: [paths-filter] - # uses: ./.github/workflows/reusable_build_web.yml - # with: - # CONCURRENCY: pr-${{ github.event.pull_request.number }} - # CHANNEL: main - # secrets: inherit - - # upload-web: - # name: "Upload Web" - # needs: [build-web] - # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' - # uses: ./.github/workflows/reusable_upload_web.yml - # with: - # CONCURRENCY: pr-${{ github.event.pull_request.number }} - # PR_NUMBER: ${{ github.event.pull_request.number }} - # secrets: inherit - - # deploy-landing-preview: - # name: "Deploy Landing Preview" - # needs: [paths-filter] - # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.docs_changes == 'true' - # uses: ./.github/workflows/reusable_deploy_landing_preview.yml - # with: - # CONCURRENCY: pr-${{ github.event.pull_request.number }} - # PR_NUMBER: ${{ github.event.pull_request.number }} - # secrets: inherit + min-wheel-build: + name: "Minimum Wheel Build" + needs: [min-cli-build, paths-filter] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true') + uses: ./.github/workflows/reusable_build_and_upload_wheels.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + MODE: "pr" + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" + secrets: inherit + + min-wheel-test: + name: "Minimum Wheel Test" + needs: [min-wheel-build, paths-filter] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.paths-filter.outputs.python_changes == 'true' || needs.paths-filter.outputs.rust_changes == 'true') + uses: ./.github/workflows/reusable_test_wheels.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" + FAST: true + secrets: inherit + + build-js: + name: "Build rerun_js" + needs: [paths-filter] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.web_changes == 'true' + uses: ./.github/workflows/reusable_build_js.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + secrets: inherit + + build-web: + name: "Build web viewer" + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.web_changes == 'true' + needs: [paths-filter] + uses: ./.github/workflows/reusable_build_web.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + CHANNEL: main + secrets: inherit + + upload-web: + name: "Upload Web" + needs: [build-web] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' + uses: ./.github/workflows/reusable_upload_web.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + PR_NUMBER: ${{ github.event.pull_request.number }} + secrets: inherit + + deploy-landing-preview: + name: "Deploy Landing Preview" + needs: [paths-filter] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.paths-filter.outputs.docs_changes == 'true' + uses: ./.github/workflows/reusable_deploy_landing_preview.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + PR_NUMBER: ${{ github.event.pull_request.number }} + secrets: inherit diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 176e55c84a4d..f2b123a1ebe5 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -72,7 +72,7 @@ jobs: pixi-version: v0.39.0 # Install the Vulkan SDK, so we can use the software rasterizer. - # TODO(andreas): It would be nice if `setup_software_rasterizer.py` could do that for us as well! + # TODO(andreas): It would be nice if `setup_software_rasterizer.py` could do that for us as well (note though that this action here is very fast when cached!) - name: Install Vulkan SDK uses: jakoch/install-vulkan-sdk-action@v1.0.5 with: @@ -107,15 +107,13 @@ jobs: strategy: matrix: include: - # TODO(#8245): we run mac tests on `main` because that's the only platform where UI snapshot tests are covered. - # When the linux runners are able to run these tests (with a software renderer), we can move that back to all nightly. - # - os: "macos-latest" - # name: "macos" + - os: "macos-latest" + name: "macos" - os: "windows-latest-8-cores" name: "windows" # Note: we can't use `matrix.os` here because its evaluated before the matrix stuff. - #if: ${{ inputs.CHANNEL == 'main' || inputs.CHANNEL == 'nightly' }} # TODO: uncomment this, only here for quicker testing of ci. + if: ${{ inputs.CHANNEL == 'main' || inputs.CHANNEL == 'nightly' }} runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -135,8 +133,8 @@ jobs: with: pixi-version: v0.39.0 - # TODO: if this works, also put it on user ci # Install the Vulkan SDK, so we can use the software rasterizer. + # TODO(andreas): It would be nice if `setup_software_rasterizer.py` could do that for us as well (note though that this action here is very fast when cached!) - name: Install Vulkan SDK if: ${{ matrix.name != 'macos' }} uses: jakoch/install-vulkan-sdk-action@v1.0.5 @@ -149,15 +147,13 @@ jobs: - name: Setup software rasterizer run: pixi run python ./scripts/ci/setup_software_rasterizer.py - # TODO: - # - name: Download test assets - # run: pixi run python ./tests/assets/download_test_assets.py + - name: Download test assets + run: pixi run python ./tests/assets/download_test_assets.py - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL != 'nightly' }} # Need to use pixi due to NASM dependency. - #run: pixi run cargo test --all-targets --all-features - run: RUST_LOG=trace cargo test -p re_component_ui --all-features + run: pixi run cargo test --all-targets --all-features - name: Rust all checks & tests if: ${{ inputs.CHANNEL == 'nightly' }} diff --git a/crates/utils/re_log/src/lib.rs b/crates/utils/re_log/src/lib.rs index 71940f21633d..debe25a13802 100644 --- a/crates/utils/re_log/src/lib.rs +++ b/crates/utils/re_log/src/lib.rs @@ -60,8 +60,10 @@ const CRATES_AT_ERROR_LEVEL: &[&str] = &[ const CRATES_AT_WARN_LEVEL: &[&str] = &[ // wgpu crates spam a lot on info level, which is really annoying // TODO(emilk): remove once https://github.com/gfx-rs/wgpu/issues/3206 is fixed - "naga", "tracing", // "wgpu_core", - // "wgpu_hal", + "naga", + "tracing", + "wgpu_core", + "wgpu_hal", "zbus", ]; diff --git a/crates/utils/re_log/src/setup.rs b/crates/utils/re_log/src/setup.rs index 72ac8932efc2..59b7e44e4a14 100644 --- a/crates/utils/re_log/src/setup.rs +++ b/crates/utils/re_log/src/setup.rs @@ -36,15 +36,6 @@ pub fn setup_logging() { let log_file_line = false; if log_file_line { stderr_logger.format(|buf, record| { - // TODO: HACK - println!( - "{} {}:{} {}", - record.level(), - record.file().unwrap_or_default(), - record.line().unwrap_or_default(), - record.args() - ); - use std::io::Write as _; writeln!( buf, diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 679de9222984..88cf099941bb 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -50,8 +50,7 @@ impl Default for TestContext { fn default() -> Self { // We rely a lot on logging in the viewer to identify issues. // Make sure logging is set up if it hasn't been done yet. - //let _ = env_logger::builder().is_test(true).try_init(); - let _ = env_logger::builder().is_test(false).try_init(); + let _ = env_logger::builder().is_test(true).try_init(); let recording_store = EntityDb::new(StoreId::random(StoreKind::Recording)); let blueprint_store = EntityDb::new(StoreId::random(StoreKind::Blueprint)); diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index f487b3229d5c..1f505cab6a79 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -95,8 +95,8 @@ def setup_lavapipe_for_linux() -> dict[str, str]: } set_environment_variables(env_vars) - # On CI we run with elevated priviledges, therefore VK_DRIVER_FILES is ignored. - # According to https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderInterfaceArchitecture.md#elevated-privilege-caveats + # On CI we run with elevated privileges, therefore VK_DRIVER_FILES is ignored. + # See: https://github.com/KhronosGroup/Vulkan-Loader/blob/sdk-1.3.261/docs/LoaderInterfaceArchitecture.md#elevated-privilege-caveats # (curiously, when installing the Vulkan SDK via apt, it seems to work fine). # Therefore, we copy the icd file into one of the standard search paths. target_path = Path("~/.config/vulkan/icd.d").expanduser() @@ -163,10 +163,10 @@ def setup_lavapipe_for_windows() -> dict[str, str]: except Exception as e: print(f"Error listing Vulkan runtime directory: {e}") - # On CI we run with elevated priviledges, therefore VK_DRIVER_FILES is ignored. - # According to https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderInterfaceArchitecture.md#elevated-privilege-caveats + # On CI we run with elevated privileges, therefore VK_DRIVER_FILES is ignored. + # See: https://github.com/KhronosGroup/Vulkan-Loader/blob/sdk-1.3.261/docs/LoaderInterfaceArchitecture.md#elevated-privilege-caveats # Therefore, we have to set one of the registry keys that is checked to find the driver. - # See https://vulkan.lunarg.com/doc/view/1.3.243.0/windows/LoaderDriverInterface.html#user-content-driver-discovery-on-windows + # See: https://vulkan.lunarg.com/doc/view/1.3.243.0/windows/LoaderDriverInterface.html#user-content-driver-discovery-on-windows # Write registry keys to configure Vulkan drivers import winreg From 5eb2294527b2ac7315a58707e99358af4cd88ae5 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 17:37:40 +0100 Subject: [PATCH 41/43] fix missing download test assets --- .github/workflows/reusable_checks_rust.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index f2b123a1ebe5..4f1d4f2fe869 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -88,6 +88,9 @@ jobs: if: ${{ inputs.CHANNEL == 'pr' }} run: pixi run rs-check --only base_checks sdk_variations cargo_deny wasm docs + - name: Download test assets + run: pixi run python ./tests/assets/download_test_assets.py + - name: Run tests (`cargo test --all-targets --all-features`) if: ${{ inputs.CHANNEL == 'pr' }} # Need to use pixi due to NASM dependency. From 9d84f7ea26d08b70d15fe6efb6fc527ab8f28476 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 17:37:57 +0100 Subject: [PATCH 42/43] python fmt --- scripts/ci/setup_software_rasterizer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/ci/setup_software_rasterizer.py b/scripts/ci/setup_software_rasterizer.py index 1f505cab6a79..850528a3eb3b 100644 --- a/scripts/ci/setup_software_rasterizer.py +++ b/scripts/ci/setup_software_rasterizer.py @@ -31,9 +31,9 @@ def run( args: list[str], *, env: dict[str, str] | None = None, timeout: int | None = None, cwd: str | None = None ) -> subprocess.CompletedProcess[str]: result = subprocess.run(args, env=env, cwd=cwd, timeout=timeout, check=False, capture_output=True, text=True) - assert result.returncode == 0, ( - f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" - ) + assert ( + result.returncode == 0 + ), f"{subprocess.list2cmdline(args)} failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}" return result From 25206ca0da651494a5333195bb4ac155a93cc4db Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 9 Jan 2025 18:26:09 +0100 Subject: [PATCH 43/43] Add sanity check that setup_kittest_for_rendering is called when needed --- crates/viewer/re_renderer/src/context.rs | 5 ++++ crates/viewer/re_renderer/src/view_builder.rs | 4 +++ .../re_viewer_context/src/test_context.rs | 26 +++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/crates/viewer/re_renderer/src/context.rs b/crates/viewer/re_renderer/src/context.rs index 191b8d6174f3..5e50341e77c0 100644 --- a/crates/viewer/re_renderer/src/context.rs +++ b/crates/viewer/re_renderer/src/context.rs @@ -173,6 +173,7 @@ impl RenderContext { before_view_builder_encoder: Mutex::new(FrameGlobalCommandEncoder::new(&device)), frame_index: STARTUP_FRAME_IDX, top_level_error_scope, + num_view_builders_created: AtomicU64::new(0), }; // Register shader workarounds for the current device. @@ -316,6 +317,7 @@ This means, either a call to RenderContext::before_submit was omitted, or the pr before_view_builder_encoder: Mutex::new(FrameGlobalCommandEncoder::new(&self.device)), frame_index: self.active_frame.frame_index.wrapping_add(1), top_level_error_scope: Some(WgpuErrorScope::start(&self.device)), + num_view_builders_created: AtomicU64::new(0), }; let frame_index = self.active_frame.frame_index; @@ -485,6 +487,9 @@ pub struct ActiveFrameContext { /// /// The only time this is allowed to be `None` is during shutdown and when closing an old and opening a new scope. top_level_error_scope: Option, + + /// Number of view builders created in this frame so far. + pub num_view_builders_created: AtomicU64, } fn log_adapter_info(info: &wgpu::AdapterInfo) { diff --git a/crates/viewer/re_renderer/src/view_builder.rs b/crates/viewer/re_renderer/src/view_builder.rs index 2455595e7e66..efe1d8b58d01 100644 --- a/crates/viewer/re_renderer/src/view_builder.rs +++ b/crates/viewer/re_renderer/src/view_builder.rs @@ -518,6 +518,10 @@ impl ViewBuilder { frame_uniform_buffer_content, }; + ctx.active_frame + .num_view_builders_created + .fetch_add(1, std::sync::atomic::Ordering::Release); + Self { setup, queued_draws: vec![composition_draw.into()], diff --git a/crates/viewer/re_viewer_context/src/test_context.rs b/crates/viewer/re_viewer_context/src/test_context.rs index 88cf099941bb..8b0b5c74d6ee 100644 --- a/crates/viewer/re_viewer_context/src/test_context.rs +++ b/crates/viewer/re_viewer_context/src/test_context.rs @@ -1,3 +1,4 @@ +use std::sync::atomic::AtomicBool; use std::sync::Arc; use ahash::HashMap; @@ -43,7 +44,9 @@ pub struct TestContext { command_sender: CommandSender, command_receiver: CommandReceiver, + egui_render_state: Mutex>, + called_setup_kittest_for_rendering: AtomicBool, } impl Default for TestContext { @@ -83,6 +86,7 @@ impl Default for TestContext { // Created lazily since each egui_kittest harness needs a new one. egui_render_state: Mutex::new(None), + called_setup_kittest_for_rendering: AtomicBool::new(false), } } } @@ -228,15 +232,18 @@ fn init_shared_renderer_setup() -> SharedWgpuResources { impl TestContext { pub fn setup_kittest_for_rendering(&self) -> egui_kittest::HarnessBuilder<()> { + // Egui kittests insists on having a fresh render state for each test. let new_render_state = create_egui_renderstate(); let builder = egui_kittest::Harness::builder().renderer( // Note that render state clone is mostly cloning of inner `Arc`. - // This does _not_ duplicate re_renderer's context. + // This does _not_ duplicate re_renderer's context contained within. egui_kittest::wgpu::WgpuTestRenderer::from_render_state(new_render_state.clone()), ); - // Egui kittests insists on having a fresh render state for each test. self.egui_render_state.lock().replace(new_render_state); + self.called_setup_kittest_for_rendering + .store(true, std::sync::atomic::Ordering::Relaxed); + builder } @@ -303,6 +310,21 @@ impl TestContext { func(&ctx); + // If re_renderer was used, `setup_kittest_for_rendering` should have been called. + // (if not, then we clearly didn't render anything since that requires writing to a texture!). + if render_ctx + .active_frame + .num_view_builders_created + .load(std::sync::atomic::Ordering::Acquire) + != 0 + && !self + .called_setup_kittest_for_rendering + .load(std::sync::atomic::Ordering::Relaxed) + { + panic!("Rendering with `re_renderer` requires setting up kittest with `TestContext::setup_kittest_for_rendering` + to ensure that kittest & re_renderer use the same graphics device."); + } + render_ctx.before_submit(); }