Repository navigation
Summary
Methane Kit v0.8.2 update restores build compatibility with the latest compilers, updates all external dependencies and fixes a large number of graphics API validation errors, thread-safety issues and runtime stability bugs, most of which were found with the newly added automated applications run test:
- New compilers support: build was fixed for Visual Studio 2026 (MSVC 19.5+), GCC 15.2 on Ubuntu 26.04 and AppleClang from Xcode 26 on MacOS Sequoia. New
VS2026-*CMake presets were added along with the existingVS2022-*presets. - Graphics API validation messages logging: validation and runtime messages of all three graphics APIs are now printed with the same severity and category format - with
ID3D12InfoQueue1message callback in DirectX 12,VK_EXT_debug_utilsmessenger in Vulkan andMTLLogStatewith command buffer error reporting in Metal. New test scriptBuild/Unix/CI/RunApplicationsTest.shruns all applications and fails on any validation or runtime error printed to the console output. It's not used in CI yet, because build environment has no GUI and GPU support. - Vulkan RHI stability: swap-chain image acquisition semaphore lifecycle, surface-lost recovery, runtime rendering device switching on multi-GPU systems, mutable descriptor sets copying, pipeline barrier stage masks and primitive restart on MoltenVK were fixed (close #158).
- Thread safety: race conditions were fixed in
Base::CommandQueueTracking,Vulkan::QueueFamilyReservation,Vulkan::CommandListSetand in the timestamp query pools, which caused sporadic hangs and crashes in multi-threaded rendering.
Graphics libraries
Base::CommandQueueTracking:GetNextExecutingCommandListSet()was replaced withPopNextExecutingCommandListSet(), which atomically pops the command list set and waits for it, eliminating the race betweenWaitUntilCompleted,CompleteExecutionand the background execution-waiting thread; template helperProcessExecutingCommandListSetandIsExecutingOnFrameIndexwere added for the FIFO-ordered frame completion. Timestamp query pool initialization was guarded with a mutex andICommandQueue::GetTimestampQueryPoolPtr()now returnsPtrby value instead of a reference, which could dangle.- Fixed logic inversion in
Base::RenderCommandList::UpdateDrawingState, which incorrectly skipped tracking of the primitive type change. CommandListSet::GetCombinedName()was madeconstandBase::CommandQueueTrackingexecution thread was switched tostd::jthread.- Added
Methane/StbImage.hwrapper header, which suppresses external code compiler warnings and disables SIMD in GCC debug builds, replacing ad-hocstb_image.hinclusions inImageLoader.cppandAppLin.cpp. - Fixed self-assignment in
Camera::ResetOrientationand reduced enums verbosity inQuadMeshwithusing enum(SonarQube issues). Base::Context: lazily created default command kits were guarded with a mutex;m_requested_actionandm_is_completing_initializationwere replaced with atomics, with the deferred action escalated by a compare-exchange loop and cleared only when performed.Base::CommandKit: lazily created command queue, lists, fences and list sets were guarded with a mutex, with the*Unlocked()helpers added for the nested access.Base::CommandQueueTracking:CompleteCommandListSetExecution()does not pop the executing queue any more, becausePopNextExecutingCommandListSet()already pops the command list set atomically with waiting for it.Base::RenderPass: stencil attachment texture is invalidated onUpdate()together with the other attachment texture caches, under the mutex guarding their initialization.GetFrameScissorRect()computes bounds in a signed 64-bit type and clamps them to the render attachment size, fixing the unsigned underflow of the offset and extent for a frame rect moved outside of the attachment.Rhi::TextureViewandRhi::CommandListSetconstructors were madeexplicit.
DirectX RHI
- Debug layer message callback was registered with
ID3D12InfoQueue1to print DirectX 12 validation messages to the platform debug output and unregistered on device release. - Fixed resource state transitions done with the command lists of
COPYtype: resources are kept inCommonstate, which is implicitly promoted by the copy queue, fixing validation errorD3D12_MESSAGE_ID_RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE. - Fixed
RenderStatepipeline description:ForcedSampleCountis left zero (errorCREATEGRAPHICSPIPELINESTATE_INVALID_FORCED_SAMPLE_COUNT) andDSVFormatalways matches the render pattern depth attachment format (errorCOMMAND_LIST_DRAW_DEPTH_STENCIL_VIEW_NOT_SET). - Removed assertion on the failed switch of GPU to the stable power state, which requires Windows Developer Mode enabled.
Vulkan RHI
- Frame semaphores lifecycle: per-frame
vk::Fencewas removed fromRenderContext::FrameSync; image acquisition now waits for completion of the render submission which consumed the image-available semaphore, satisfyingVUID-vkAcquireNextImageKHR-semaphore-01779. Bounded acquisition timeout and retries count were added instead of the infiniteUINT64_MAXtimeout. - Execution-completed semaphore:
CommandListSetexecution-completed semaphore is created lazily and is signalled only for the command list sets targeting a specific frame buffer, fixingVUID-vkQueueSubmit-pSignalSemaphores-00067caused by permanently signalled semaphores of non-frame command lists. - Surface lost recovery: swap-chain resources are released before the lost surface is destroyed (
VUID-vkDestroySurfaceKHR-surface-01266) and the swap-chain is re-initialized directly to avoid recursive re-entrance toGetNextFrameBufferIndex(). - Runtime device switching:
VULKAN_HPP_DEFAULT_DISPATCHERis no longer specialized withvk::Device, because the single global dispatcher was resolving device-level entry points of the last created device and dispatched calls to a wrong ICD on multi-GPU systems. Native device handle is now updated inRenderContext::Initialize()and descriptor pools are destroyed instead of being reset, because they can not be reused with another device. - HLSL reflection extensions:
VK_GOOGLE_HLSL_FUNCTIONALITY_1andVK_GOOGLE_USER_TYPEdevice extensions were enabled and SPIRV byte code is stripped of the reflection instructions withRemoveHlslReflectionFromSpirv()when they are not supported, fixingVUID-VkShaderModuleCreateInfo-pCode-08742. - Mutable descriptor sets copying in
ProgramBindingswas fixed to iterate per-binding instead of using a single flat descriptors count, which caused out-of-bounds descriptor access with non-contiguous bindings. - Pipeline barriers: empty
srcStageMask/dstStageMaskare replaced witheTopOfPipe/eBottomOfPipe, fixingVUID-vkCmdPipelineBarrier-srcStageMask-03937anddstStageMask-03937. - Primitive restart:
RenderStatedetectsVK_KHR_portability_subsetand enables primitive restart for strip and dynamic topologies on devices which can not disable it, silencing MoltenVK warning "Metal does not support disabling primitive restart". - Timestamp queries: unbounded CPU-GPU calibration loop was replaced with a bounded number of attempts with relaxation of the acceptable deviation, which was hanging the command queue tracking thread and all threads waiting for the command lists execution under load.
- Queue family reservation free indices set and the deferred pipelines release queue were guarded with mutexes.
RenderPass::CreateNativeFrameBuffernow validates attachment texture dimensions against the render pass frame size.- Removed MoltenVK workarounds for
VkSubmitInfowithVkTimelineSemaphoreSubmitInfoand stale message-ID filters of the debug messenger callback, which are not needed with the current Vulkan SDK. Debug messenger callback signature was migrated tovk::types. - Disabled Objective-C ARC for
RenderContext.mmandPlatformExt.mmon Apple platforms (workaround ofvulkan.hppconstant-expression issue withCAMetalLayer) and added explicit release of the Metal view in theRenderContextdestructor. Vulkan::TimestampQueryPooltakes the first CPU time domain supported by the device from the platform preference list instead of one hard-coded domain, because MoltenVK exposesCLOCK_MONOTONIC_RAWonly.- Query pool is created with exactly as many queries as its data buffer can hold timestamps: over-allocating made MoltenVK fail to create
MTLCounterSampleBufferand fall back to emulated timestamps.
Metal RHI
- Added
Metal::DebugMessageswhich prints GPU shader validation messages (MTLLogState,MTLFunctionLog) and command buffer execution errors to the platform debug output when the Metal debug layer is enabled withMTL_DEBUG_LAYER/MTL_SHADER_VALIDATIONenvironment variables. - All native command buffers are created via
CommandQueue::CreateNativeCommandBuffer()with per-encoder execution status error reporting enabled in debug builds. Metal::ProgramArgumentBindingnative resources were moved to the immutableNativeResourceViewssnapshot, which is built locally and published under the mutex, so thatMetal::ProgramBindingsreaders keep using the previous one until it is complete.
Platform libraries
- Added
Platform::SetPrintToConsoleEnabled()and application command line flag--print_debug_messages_to_console, which redirects debug output tostd::coutinstead ofOutputDebugStringon Windows andNSLogon MacOS, so that graphics API validation messages can be captured by the CI test script. - MacOS
AppDelegatedisables window state restoration, which is not implemented, and opts in to the secure restorable state coding to silence the AppKit warning.
Common changes
- Dropped GitPod (Uno) support (removed gitpod config, docker, references and description).
Tutorial applications
- Fixed prerequisite binaries copying for the
ConsoleComputetutorial withadd_prerequisite_binaries(...)extended with theIS_CONSOLE_APPargument. ConsoleComputenow waits for the compute command list completion instead of the whole context, fixing the GPU wait done in the invalid command list state, usesstd::jthreadfor the UI refresh thread and declares the image format in theGameOfLife.hlslcompute shader.- Fixed
Typographytutorial crash on resizing done before the text items were created byInit(). AppBase::IsResizing()returnsfalseafter an initialization error, so that partially constructed application state is not resized.
Tests
- Added unit-tests covering
RenderCommandListdrawing with multiple primitive types in a single command list (DrawandDrawIndexed), which cover the fixed primitive type change tracking bug. RenderPassunit-tests were extended to cover invalidation of the attachment texture caches on settings update, with a separate stencil attachment added to the test render pattern.
External libraries
- DirectXShaderCompilerBinary was updated to
v1.9.2602 - VulkanHeaders were updated to
v1.4.357.0 - DirectXHeaders was updated to
v1.619.5 - DirectXTex was updated to
v2.1.1(may 2026) - Tracy was updated to
v0.14.1 - FMT was updated to
v12.2.0 - FTXUI was updated to
v7.0.3 - TaskFlow was updated to
v4.1.0 - HLSL++ was updated to
v3.9 - Catch2 was updated to
v3.15.3 - CLI11 was updated to
v2.7.2 - MagicEnum was updated to
v0.9.8 - IttApi was updated to
v3.28.2 - CPM.cmake was updated to
v0.43.1 - iOS-Toolchain.cmake was updated to
v4.6.0 - CMakeModules was updated to the latest commit from
methanebranch
Build
- Added
VS2026-*CMake configure and build presets usingVisual Studio 18 2026generator for Win64/Win32 x DX/VK x Default/Profile/Scan variants (require CMake 4.2+). Build\Windows\Build.batuses Visual Studio 2026 generator by default,--vs2022option was added for backward compatibility. Support of Visual Studio 2019 build was dropped.- Added
Build/Unix/CI/InstallMacOsPrerequisites.shscript, which downloads and installs the Metal Toolchain required since Xcode 26. - Fixed ARM64 architecture detection in
CMake/MethaneModules.cmakefor the different spellings ofCMAKE_SYSTEM_PROCESSOR. - Fixed Tracy, FMT, HLSL++ and TaskFlow builds with the new compilers by disabling the newly introduced warnings.
- Fixed or silenced with comment all static analysis issues from SonarQube .
- Dropped GitPod (Uno) support (removed gitpod config, docker, references and description).
Continuous Integration
- All CI workflows were switched to the
VS2026-*presets on Windows and were updated to the latest GitHub actions:actions/checkout@v7,actions/cache@v6,actions/upload-artifact@v7,github/codeql-action/*@v4. - Sonar Scanner was migrated from the legacy
RunSonarScanner.shscript toSonarSource/sonarqube-scan-action@v8.2.0with separate steps for push and pull-request events; images were excluded from the analysis to fix invalid encoding errors. - Added MacOS prerequisites installation step to the CI Build, CodeQL and Sonar Scan workflows. CodeQL scan on MacOS was temporarily disabled because of the Metal Toolchain availability issue.
- Added
Build/Unix/CI/RunApplicationsTest.shscript, which runs all applications in GUI mode and checks the console output for the graphics API validation and runtime errors on all platforms. - Vulkan SDK was updated to
v1.4.350.1and Tracy release binaries tov0.14.0.1.
Documentation
- Added Docs/Performance.md with the measured comparison of the DirectX 12 and Vulkan backends frame rates on Windows and with the explanation of the present rate drop after switching the rendering device in runtime.
- Updated
Build/README.mdwith the new build presets, andExternals/README.mdwith the updated dependency versions. - Added
CLAUDE.mdwith the project guidance for Claude Code.
Note
For MacOS users: In case of error "App Is Damaged and Can't Be Opened" on attempt to run bundled application, try removing application from quarantine using the following command:
sudo xattr -d com.apple.quarantine MethaneHelloTriangle.app
open MethaneHelloTriangle.app