From 8e3583bf8e2e884611587381683d9a3b7562a071 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Aug 2026 00:35:29 +0000 Subject: [PATCH 1/2] Initial plan From 82f7b3c056d5ea4a91b75631ac76176907de6d02 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Aug 2026 00:38:32 +0000 Subject: [PATCH 2/2] Fix Metal tests to skip instead of fail when Apple Silicon GPU is unavailable Co-authored-by: Kwizatz <2333297+Kwizatz@users.noreply.github.com> --- tests/ComputeTests.cpp | 5 ++- tests/RenderTestWindow.h | 27 +++++++++++++ tests/RendererParityTests.cpp | 71 +++++++++++++++++++++++++++-------- 3 files changed, 86 insertions(+), 17 deletions(-) diff --git a/tests/ComputeTests.cpp b/tests/ComputeTests.cpp index 2db4d549..2aa054f3 100644 --- a/tests/ComputeTests.cpp +++ b/tests/ComputeTests.cpp @@ -849,7 +849,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); Matrix4x4 projection{}; diff --git a/tests/RenderTestWindow.h b/tests/RenderTestWindow.h index d60e960a..f2275657 100644 --- a/tests/RenderTestWindow.h +++ b/tests/RenderTestWindow.h @@ -206,5 +206,32 @@ namespace AeonGames return nullptr; } } + + /** @brief Construct a renderer with custom settings, returning nullptr + * (instead of throwing) when the backend is unavailable on the host. */ + inline std::unique_ptr TryConstructRenderer ( const char* aRendererName, void* aWindow, const RendererSettings& aSettings ) + { +#ifdef AEON_TEST_HAVE_VULKAN + if ( std::string_view{ aRendererName } == "Vulkan" && !IsVulkanAvailableOnHost() ) + { + std::cerr << aRendererName << " renderer unavailable on this host: no compatible Vulkan driver." << std::endl; + return nullptr; + } +#endif + try + { + return ConstructRenderer ( std::string ( aRendererName ), aWindow, aSettings ); + } + catch ( const std::exception& e ) + { + std::cerr << aRendererName << " renderer unavailable on this host: " << e.what() << std::endl; + return nullptr; + } + catch ( ... ) + { + std::cerr << aRendererName << " renderer unavailable on this host." << std::endl; + return nullptr; + } + } } #endif diff --git a/tests/RendererParityTests.cpp b/tests/RendererParityTests.cpp index aa898a90..d1d86ed4 100644 --- a/tests/RendererParityTests.cpp +++ b/tests/RendererParityTests.cpp @@ -287,7 +287,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); Mesh mesh; @@ -338,7 +341,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); Mesh mesh; @@ -379,7 +385,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); renderer->SetClearColor ( window, 0.0f, 0.0f, 0.0f, 1.0f ); const SolidGuiOverlay overlay{64, 64, {0, 0, 128, 128}}; @@ -416,7 +425,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); renderer->SetClearColor ( window, 0.0f, 0.0f, 0.0f, 1.0f ); // Premultiplied BGRA: the top half is red, the bottom half fully @@ -451,7 +463,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); Pipeline pipeline; @@ -497,7 +512,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); renderer->SetClearColor ( window, 0.0f, 0.0f, 0.0f, 1.0f ); @@ -560,8 +578,11 @@ namespace AeonGames settings.mDirectionalShadowMapResolution = 32; settings.mSpotShadowMapResolution = 32; settings.mPointShadowMapResolution = 32; - std::unique_ptr renderer = ConstructRenderer ( std::string {"Metal"}, window, settings ); - ASSERT_NE ( renderer, nullptr ); + std::unique_ptr renderer = TryConstructRenderer ( "Metal", window, settings ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); renderer->SetClearColor ( window, 0.0f, 0.25f, 0.5f, 1.0f ); @@ -623,8 +644,11 @@ namespace AeonGames ASSERT_NE ( window, nullptr ); RendererSettings settings{}; settings.mDirectionalShadowMapResolution = 32; - std::unique_ptr renderer = ConstructRenderer ( std::string {"Metal"}, window, settings ); - ASSERT_NE ( renderer, nullptr ); + std::unique_ptr renderer = TryConstructRenderer ( "Metal", window, settings ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); renderer->SetClearColor ( window, 0.0f, 0.0f, 0.0f, 1.0f ); renderer->SetProjectionMatrix ( window, Matrix4x4{} ); @@ -705,8 +729,11 @@ namespace AeonGames settings.mSkyboxEnvironmentFaceSize = 8; settings.mPrefilteredEnvironmentFaceSize = 8; settings.mPrefilteredEnvironmentMipCount = 3; - std::unique_ptr renderer = ConstructRenderer ( std::string {"Metal"}, window, settings ); - ASSERT_NE ( renderer, nullptr ); + std::unique_ptr renderer = TryConstructRenderer ( "Metal", window, settings ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); std::vector environment_pixels ( 16 * 8 * 3 ); @@ -748,7 +775,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); renderer->SetClearColor ( window, 0.0f, 0.0f, 0.0f, 1.0f ); Matrix4x4 projection{}; @@ -789,7 +819,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); Matrix4x4 projection{}; projection.Perspective ( 60.0f, 1.0f, 1.0f, 100.0f ); @@ -833,7 +866,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 64, 64 ); Matrix4x4 projection{}; projection.Perspective ( 60.0f, 1.0f, 1.0f, 100.0f ); @@ -906,7 +942,10 @@ namespace AeonGames void* window = CreateHiddenRenderWindow(); ASSERT_NE ( window, nullptr ); std::unique_ptr renderer = TryConstructRenderer ( "Metal", window ); - ASSERT_NE ( renderer, nullptr ); + if ( renderer == nullptr ) + { + GTEST_SKIP() << "Metal renderer unavailable on this host."; + } renderer->ResizeViewport ( window, 0, 0, 320, 180 ); Scene scene; const size_t scene_size = GetResourceSize ( "scenes/main.txt" );