All notable changes to VCK are documented here. Format: Keep a Changelog. Versioning: SemVer.
Post-release patch that fixes CI failures introduced by the v0.5.0 merge, corrects two design-rule violations in the new HotReload class, and standardises the factory-method naming convention across the library. No new public API surface. No behaviour change for code that was compiling correctly against v0.5.0.
VulkanImage::Create(…)→VulkanImage::Initialize(device, w, h, format, usage, aspect[, samples])—Createwas an inconsistent outlier; every other VCK class usesInitialize. All 27 call sites updated (core headers, expansion, examples). (breaking within 0.5.x)VulkanSampler::CreateLinear(device)/CreateNearest(device)→VulkanSampler::Initialize(device, filter = LINEAR, mipMode = LINEAR)— single entry point, filter and mip mode are explicit parameters. (breaking within 0.5.x)Window::Create(info)→Window::Initialize(info)— naming parity with the rest of the library. (breaking within 0.5.x)HotReload::Initializegains requiredstd::function<void()> drainFnfinal parameter — callers supply a lambda (e.g.[&]{ scheduler.DrainInFlight(); }) that retires in-flight GPU work before each pipeline rebuild. The expansion layer never imports execution types directly (R2). Stored asm_DrainFn; cleared inShutdown. (breaking within 0.5.x — no examples calledHotReload::Initializein v0.5.0)
- R2 layering violation in
HotReload— v0.5.0 shippedHotReload::Initializewith aFrameScheduler¶meter, which pulled an execution-layer type into the expansion-layer header. Parameter removed; drain responsibility delegated to the caller viadrainFn. - R4 violation in
HotReload::Tick— the interim fix for the R2 violation replacedFrameScheduler::DrainInFlight()withvkDeviceWaitIdle, which is banned on the runtime hot path. Now callsm_DrainFn()instead. DynamicRenderingExamplecompile errors —VulkanSwapchain::Config/VulkanDevice::Config(do not exist) replaced withVCK::Config; non-existent fieldpipeCfg.rendering.moderemoved.BindlessExamplecompile errors —VulkanDevice::Config→VCK::Config;GetLayout()→GetPipelineLayout().OffscreenTarget::Initialize— was calling the non-existentVulkanImage::Configstruct andVulkanImage::Create(). Replaced with the correctVulkanImage::Initialize(device, w, h, format, usage, aspect)signature.OffscreenTargetExample—sampler.CreateLinear(device)updated tosampler.Initialize(device)following the naming-convention rename.- Post-0.5.0 audit sweep (B1–B5, C1–C10, D1–D10) — compiler-warning clean-up (B), correctness fixes on newly-added code paths (C), and design-rule alignment pass (D) applied 2026-05-20.
0.5.0 – 2026-05-18
RenderingMode::Dynamicend-to-end:DynamicRenderingExampleshowsvkCmdBeginRendering/vkCmdEndRenderingwith barrier transitionscfg.device.enableBindlessfully wired:VulkanDescriptorAllocator::InitializeBindless()+WriteBindless()+BindlessExampleVK_KHR_synchronization2: all barriers usevkCmdPipelineBarrier2/VkImageMemoryBarrier2FrameData<T>per-frame typed resource ring [23]RenderGraphdeclarative barrier-aware skeleton [24]VCK::HotReload[31] — drives ShaderWatcher→DrainInFlight→Reinitialize→RecreateVCK::OffscreenTarget[32] — VulkanImage + VkRenderPass/VkFramebuffer for render-to-textureVCK::FullscreenPass[33] — fullscreen triangle with sampler inputVulkanPipeline::Reinitializefor hot-reload + live-resizeFrameScheduler::SlotCount()getterVulkanSwapchain::GetImage(uint32_t)/GetImageView(uint32_t)index accessorsVulkanDescriptorAllocator::InitializeBindless/WriteBindless/GetBindlessSet/GetBindlessLayoutDebugTimeline::InitQueryPool/BeginGpuSpan/EndGpuSpan/ResolveGpuSpans— GPU timestamp pipelineDynamicRenderingExample,BindlessExample,OffscreenTargetExample,RenderGraphExample- ASan + UBSan CI job
linux-sanitize
VulkanDescriptorAllocator::Initialize:std::initializer_list<PoolSize>→const std::vector<PoolSize>&(MSVC ABI fix)VulkanDeviceR23 notice updated to point atInitializeBindlessVCK.hexpansion header now covers[1]-[12] + [26]-[36]VCK.hexample count: 13 → 14; actual dirs now 18
- Stale QueueSet [16] and TimelineSemaphore [14] comments in
VCKExecution.h ShaderWatcherdebug-only warning when instantiated outside debug modeVulkanDescriptorAllocator::Shutdownnow destroysm_BindlessLayout
0.4.0 - 2026-04-27
- Shader tooling layer (5 new expansion classes, PR #10). A grouped layer that owns the shader-side ceremony so users never write their own SPIR-V loaders, hot-reload polling, specialization constant buffers, or per-stage descriptor declarations. All five live in
layers/expansion/VCKExpansion.{h,cpp}undernamespace VCKand follow the standing rules — zero state until first call (R19), escape hatches everywhere (R9),VCKLog::Erroron every failure (R14),VCKLog::Noticeon every behavioral decision (R23), no GPU state held except the descriptor layoutBuildSetLayoutreturns to the caller (R10).ShaderLoader—LoadFromFile(path, stage)reads pre-compiled.spv.LoadFromGLSL(glslPath, stage)is a debug-only helper that shells out toglslangValidatoronPATH.GetShaderInfo()produces a ready-to-passVulkanPipeline::ShaderInfo.GetSpirv(stage)exposes the raw word-vector.ShaderWatcher—Watch(path, stage)registers a.spvand stores itslast_write_time.HasChanged()polls all watched files (one timestamp compare per file, never throws).Reload()rereads the SPIR-V; the user drives the pipeline rebuild + framebuffer recreate. Conceptually debug-only.SpecConstants— builder aroundVkSpecializationInfo+VkSpecializationMapEntry.Set(constantID, value)overloads foruint32_t / int32_t / float / bool(bool stored as 0/1 uint32). Re-Seton the sameconstantIDoverwrites in place when sizes match, otherwise the data buffer is rebuilt and downstream offsets shift accordingly.GetInfo()returnsnullptrwhen empty.ShaderStage— pure-data per-stage declaration.Vertex()returnsVertexLayout&,Push()returnsPushConstants&,Uniform/Sampler/Storage(set, binding)declare descriptor bindings. No GPU objects.ShaderInterface— merges multipleShaderStages.VertexInput()pullsBindings[0] / Attributes[0]from the vertex stage.PipelineConfig()pre-fillspushConstantRangesfrom the merged push block.BuildSetLayout(device, setIndex)returns a caller-ownedVkDescriptorSetLayout.Push()returns the shared push block. Warns viaVCKLog::Warnwhen two stages declare push blocks of different sizes.ApplyToConfig(spec, cfg)free function — convenience for wiring oneSpecConstantsinto both vert + frag fields ofVulkanPipeline::Config.
PushConstants::Declare(name, type, count)— array overload, reservescount * sizeof(type)bytes.PushConstants::SetRaw(name, data, size)— typed-Setescape hatch. Returnsfalse + VCKLog::Erroron unknown name or size mismatch.VulkanPipeline::Config::vertSpecialization/fragSpecialization—const VkSpecializationInfo*, defaultnullptr.CreateGraphicsPipelineplumbs them intoVkPipelineShaderStageCreateInfo::pSpecializationInfofor both stages.VCK.hclass index extended to 20 expansion classes ([26]–[30]).
v0.4.0 is a feature release — minor SemVer bump because the shader tooling adds new public surface but does not change any existing class signature, behavior, or example. CI green on Linux / macOS / Windows MinGW / Windows MSVC at merge.
0.3.3 - 2026-04-27
tests/test_r11_r12_reliability.cpp— direct include oflayers/execution/VCKExecution.h. That header forward-usesVulkanDevice/VulkanCommand/VulkanSyncwithout including their core headers, so it only compiles when the umbrella has already pulled them in. Switched the include toVCK.hto match the working tests. CI broke on all 4 jobs (Linux / macOS / Windows MinGW / Windows MSVC) on the post-merge run of v0.3.2.tests/test_r19_r15_r16_cost_scope.cpp— usedVCK::Test::LogCapturewithoutvck_log_capture.h. Added the include.tests/test_vckmath.cpp—Mat4access mismatch.Mat4storesfloat m[16]flat (column-major) with anAt(row, col)accessor; the tests indexed it asm[col][row]. Switched toAt(row, col).tests/test_vckmath.cpp—lookat_z_axis_points_to_targetasserted positive view-space Z. VCK is right-handed (the third row ofLookAtnegatesf, matching thePerspectiveconvention which negateszintow), so a target one unit ahead at world(0, 0, -1)lands at view-spacez = -1. Fixed assertion.
v0.3.3 is a test-harness fix release on top of v0.3.2 — no library code changed, no behaviour change. If your tree was on v0.3.2 with green CI on PR #8, you don't need to take this; it only matters for the maintainer's a9f3e92 "Moar tests" commit that landed post-merge.
0.3.2 - 2026-04-27
- VMM
SubmitStagingCmd— uncheckedvkEndCommandBuffer. If End failed, the staging cmd was malformed, the nextvkQueueSubmitwould VUID-fail, AND any pending acquire barriers would issue layout transitions against resources still inUNDEFINED(the release halves never actually ran). VUID-VkImageMemoryBarrier-oldLayout-01197. Now bails with cmd-buffer free + dropsm_PendingAcquire{Buffers,Images}. - VMM cross-family acquire path — unchecked
vkBeginCommandBuffer/vkEndCommandBuffer. Recording into a not-begun cmd is undefined; submitting a not-ended cmd is a VUID violation. Both nowVK_CHECKand bail with cmd-free + pending-acquire drop on failure. - VMM cross-family acquire path — fence path could silently skip the submit. If
vkCreateFenceor the fencedvkQueueSubmitfailed, the acquire barriers never ran, leaving resources stranded in "released to graphics family with no matching acquire" state (UB per spec §7.7.4). Added avkQueueWaitIdle-based fallback so the acquire submit always actually runs (matches the staging fallback). - Swapchain
CreateSwapchain— uncheckedvkCreateSwapchainKHRand bothvkGetSwapchainImagesKHR. Continuing past these on failure left a half-built swapchain; now returns false on device-lost so the caller can teardown (rule 14). VulkanOneTimeCommand::Begin— leaked the allocated cmd buffer whenvkBeginCommandBufferfailed.m_Cmdstayed populated so the caller couldn't tell Begin failed; a laterEnd()would VUID-fail on a never-begun cmd, or never get called and the allocation leaked until pool teardown. Free + zerom_Cmdon Begin failure.
.spvoutputs no longer tracked.glslangValidatorregenerates them on every build and bytes differ across glslang versions, so tracking them dirtied every local build against a CI-built tree. Added to.gitignore.
- De-AI rewrite pass. Every comment, doc, README, and CONTRIBUTING that read like marketing copy got the AI tells removed (no more "leverages", "seamlessly", "robust", "this ensures"). Voice is terser, comments explain why not what, README leads with a 3-line elevator pitch, CONTRIBUTING has opinions. Technical accuracy preserved; only the voice changed.
- CHANGELOG, VCK.h header block, and
docs/*.mdresynced to v0.3.2 state. - Wiki tarball rebuilt:
VCK.wiki.v0.3.2.tar.gz.
0.3.1 - 2026-04-27
- CMake + Ninja replaces
build.bat/build.shas the canonical build path.example/CMakeLists.txtis now the single source of truth for all 4 platforms (Windows MinGW, Windows MSVC, Linux, macOS). Auto-detectsclfrom a Developer Cmd Prompt org++/clang++fromPATH— no--toolchainflag. - Lib-once compile model. All 12 VCK sources compile once into
vck.lib/libvck.a; the 13 example exes + the R14 test exe link against it. Eliminates 143 redundant TU recompilations. Wall-clock cold build-all on a modern 8c box: Linux/macOS ~30-45s (was 10-12 min), Windows MSVC ~1-2 min, Windows MinGW ~2-3 min. - Vulkan-Headers via FetchContent. CMakeLists.txt fetches the
vulkan-sdk-1.4.321.0tag itself, so thevk_video/*.hgap on Ubuntu 22.04 (which ships 1.3.x) is gone. CI no longer needs the manual sparse-checkout dance. - R14 unit test harness (
tests/). Header-only assertion micro-framework, no GoogleTest dep. Asserts everyInitialize()failure returnsfalseAND emits exactly oneVCKLog::Error. Wired throughctest. 14/14 pass on all 4 platforms. build.bat/build.share now thin wrappers aroundcmake --buildthat preserve the interactive[1-13/A/T/0]menu UX.
- CI matrix: Linux + macOS jobs —
.github/workflows/build.ymlnow also runs onubuntu-latest(apt:libvulkan-dev libglfw3-dev vulkan-tools glslang-tools pkg-config g++,./build.sh A) andmacos-latest(brew:vulkan-headers vulkan-loader glfw glslang molten-vk pkg-config,CXX=clang++ ./build.sh A). The Windows job (build.bat [A] on MinGW + LunarG SDK) is unchanged and remains the canonical platform; Linux + macOS catch POSIX regressions inVCK::Window/VCKCrossplatform/build.shthat the Windows runner can't. - Design rule R23 — Extension transparency — every instance- / device-level extension VCK enables on the user's behalf is announced via
VCKLog::Notice("Context", ...)/VCKLog::Notice("Device", ...)at init, including the extension name, the support verdict from the driver, and the fallback path. The user can grep the init log forextand see exactly what's bound to the device. - Design rule R24 —
cfgis the contract — every behavioural difference VCK can express that the user can reasonably want to choose between lives incfg. Litmus test: "If it changes how the user writes their renderer →cfg. If it changes how VCK works underneath → silent bundle." Codified indocs/Design.mdtogether with R23 and the new six-category index (Explicitness / Ownership / Synchronisation / Cost & Scope / Reliability / Transparency). - Silent extension bundle (R24 silent path, R23 logged) —
VulkanDevice::CreateLogicalDevicenow probes for and enables the following on-demand when the device advertises them, with oneNoticeline per result:VK_KHR_synchronization2,VK_KHR_buffer_device_address,VK_EXT_memory_budget,VK_EXT_device_fault,VK_KHR_present_wait,VK_KHR_present_id. No public API surface; symbols become reachable for v0.4 use sites (sync2 inFrameScheduler, BDA in VMM,memory_budgetpolling inDebugTimeline,present_wait/present_idpacing inFrameScheduler). cfgextension knobs (R24 user-visible path, R23 logged) —cfg.rendering.mode = RenderingMode::{Classic, Dynamic}—DynamicrequestsVK_KHR_dynamic_renderingand announces it; the dynamic-rendering codepath itself ships in v0.4, today the request is acknowledged with a fallbackNoticeand rendering stays Classic.cfg.device.enableBindless—truerequestsVK_EXT_descriptor_indexingand announces it; bindless descriptor helpers (DescriptorPool::AddBindlessSet,VulkanPipeline::EnableBindless) ship in v0.4.cfg.swapchain.presentMode = PresentMode::FifoLatestReady— selectsVK_PRESENT_MODE_FIFO_LATEST_READY_EXTwhenVK_EXT_present_mode_fifo_latest_readyis advertised, otherwise falls back toFIFOwith aNotice(rule 23 — never silently substitute a present mode).
- Example menu reordered low → high VCK assist —
example/build.batandexample/build.shnow present examples in tiers (raw core → debug + tooling → expansion → execution layer → mostly VCK) so the menu narrates the design surface from "you write everything" to "VCK does the boring parts". New numbering:[1] RGBTriangle,[2] MipmapExample,[3] VMMExample,[4] SecondaryCmdExample,[5] DebugTimelineExample,[6] DebugShowcaseExample,[7] AAShowcaseExample,[8] JobGraphExample,[9] SubmissionBatchingExample,[10] TimelineExample,[11] SchedulerPolicyExample,[12] HelloExample,[13] EasyCubeExample. No example code or behaviour changes — menu, dispatch, build-all, anddocs/Examples.mdreflect the new ordering. Historical[#]references in the v0.3.0 / v0.2.x sections below are kept as shipped at the time. - Cookbook expanded to 24 recipes — added recipes 12-24 covering compute dispatch, GPU particles, indirect draw, async compute, shadow mapping, skybox / cubemap, PBR Cook-Torrance + IBL, deferred shading, HDR + tonemapping, bloom, shader hot-reload, GPU picking, and frustum culling. Cookbook now covers most rule-16 gaps (things VCK explicitly refuses to ship but every renderer ends up needing). Doc-only.
- Linux + macOS build noise silenced —
example/build.shnow compiles with-w -Werror=return-type(matchingbuild.bat's silent-on-warnings behaviour); VMA single-header impl, GLFW Cocoa deprecations on macOS, andvulkan_core.h-Wmissing-field-initializersno longer surface as user-visible warnings. CI Linux + macOS jobs gainapt-get -qq/brew install -qflags so the workflow log isn't dominated byGet:/Setting up:/Suggested:lines from package install.
0.3.0 - 2026-04-26
v0.3 is a synchronisation-layer release. The runtime no longer calls
vkDeviceWaitIdle outside Shutdown; frame retirement is consolidated on
one per-scheduler timeline semaphore (with a fence fallback when the device
doesn't expose the feature); VMM staging gets its own transfer-family
command pool with release/acquire ownership barriers; swapchain recreate
is scheduler-aware; and secondary command buffers are supported.
- Dedicated compute + transfer queues —
VulkanDevice::FindQueueFamiliesnow picks dedicated compute-only and transfer-only families where the vendor exposes them (AMD / NVIDIA almost always; Intel often does not).VulkanDevice::GetComputeQueue()/GetTransferQueue()return the dedicatedVkQueues (rule 9 escape hatch). Fallback to the graphics queue is logged viaVCKLog::Noticewhen separate families aren't available. Thread safety: differentVkQueues = different external-sync scopes per rule 18 — callers can submit graphics + compute in parallel without locking. - Timeline semaphore feature enable —
VulkanDevice::InitializechainsVkPhysicalDeviceTimelineSemaphoreFeaturesintoVkDeviceCreateInfo::pNextwhen the adapter supports it (Vulkan 1.2+, functionally every modern GPU).VulkanDevice::HasTimelineSemaphores()exposes the capability to the rest of the library.TimelineSemaphore::Initializenow returnstrueon supporting adapters instead of silently failing. - Scheduler-owned timeline —
FrameSchedulerallocates oneTimelineSemaphoreatInitialize(gated oncfg.enableTimelineanddevice.HasTimelineSemaphores()— rule 19, zero cost when disabled).EndFramesignals a monotonically increasing per-slot value (m_SlotTimelineValue[slot] = ++m_NextTimelineValue).RetireCompletedFramesuses onevkGetSemaphoreCounterValuecall instead of NvkGetFenceStatuscalls (O(1) device chatter). New publicFrameScheduler::FrameTimeline()+FrameScheduler::SlotToken(slot)expose the timeline to external waiters. FrameScheduler::DrainInFlight()— waits on the scheduler's own in-flight work (timeline when active, per-slot fences otherwise) without touchingvkDeviceWaitIdle. Replaces the global device wait on window resize.- Scheduler-aware
HandleLiveResizeoverload —VCK::HandleLiveResize(window, swapchain, framebuffers, pipeline, scheduler [, depth])drains the scheduler and recreates the swapchain without a global wait. The old(window, device, ...)overload remains available for scheduler-free code. - VMM release/acquire ownership barriers —
VulkanStagingAllocatorrecords a release barrier on the transfer queue, waits on the per-submit fence, then records an acquire barrier on the graphics queue before first use. Preserves async-upload on dedicated transfer families without violating Vulkan §7.7.4 ownership rules onVK_SHARING_MODE_EXCLUSIVEresources. CPU-serialised for v0.3; a semaphore-driven async acquire can follow in v0.4. - Secondary command buffer API —
VulkanCommand::AllocateSecondary()/FreeSecondary(cb)/BeginSecondary(cb, inheritance, extraFlags = 0)/EndSecondary(cb)/ staticExecuteSecondaries(primary, cbs, count).BeginSecondarysetsVK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BITby default; callers may OR inONE_TIME_SUBMIT/SIMULTANEOUS_USEviaextraFlags. Rule 18 (no internal lock) — callers serialise multi-threaded allocation themselves. - New example
[13] SecondaryCmdExample— records the RGB triangle's draw in a per-slot secondary, primary opens the render pass withVK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERSand dispatches it viavkCmdExecuteCommands. Exercises the secondary-command API plus the scheduler-awareHandleLiveResizeoverload. Rule 20.
- Per-submit fence in VMM staging —
VulkanStagingAllocator::SubmitStagingCmdno longer callsvkQueueWaitIdle; it creates a one-shotVkFence, submits with it, andvkWaitForFences/ destroys on the CPU side (rule 4 allow-list shrinks). When the transfer queue is dedicated, staging and graphics submits overlap. - Frame retirement consolidated on one word — when the timeline is active,
BeginFrame/EndFrame/ lockstep prefervkWaitSemaphoresover per-slot fence waits. Per-slot fences remain as the fallback path when the feature isn't supported. VulkanSwapchain::Recreate(w, h, drainedExternally = false)— opt-in flag skips the internalvkDeviceWaitIdlewhen the caller has already drained (scheduler-awareHandleLiveResizepassestrue). Default behaviour unchanged for existing users.VulkanDevice::Shutdown— now resetsm_ComputeQueue/m_TransferQueuesoGetComputeQueue/GetTransferQueuedon't return dangling handles post-shutdown.LogVk→VCKLog::{Info,Notice,Warn,Error}migration — every call site in core / expansion / execution / vmm / example now routes throughVCKLogwith a subsystem tag.LogVkstays as a shim for user code that hasn't migrated yet.build.bat/build.sh— menu now[1]-[13];[A]builds all 13 examples.
VulkanOneTimeCommand::Endinfinite hang — previously calledvkWaitForFences(UINT64_MAX)unconditionally; ifvkQueueSubmitfailed the fence would never be signalled and the call would block forever. Now short-circuits on submit failure.- Cross-family submit during staging — first v0.3 iteration submitted a graphics-pool-allocated command buffer to the transfer queue (spec violation on dedicated-transfer GPUs). Fixed by giving VMM its own transfer-family command pool.
- VMM fallback path missing
VK_CHECK— fence-creation-failed branch submitted without the standardVK_CHECKwrapper, silently droppingVK_ERROR_OUT_OF_DEVICE_MEMORY/ friends (rule 14). - Stale acquire barriers on failed transfer submit — if the transfer submit failed the CPU-side acquire barrier list would still run on the graphics queue with
oldLayout = TRANSFER_DST_OPTIMALon images actually stillUNDEFINED. The acquire list is now cleared when the release submit fails.
0.2.1 - 2026-04-24
- Rules 18-22 in
docs/Design.md:- R18 External synchronisation — codifies Vulkan's per-handle external-sync requirement;
JobGraphis the one exception. - R19 Zero cost for unused features — un-
Initialized modules allocate nothing, spawn no thread, emit no log line. - R20 Every public API has an example — public classes in
VCK.hmust be exercised by at least one example underexample/. - R21
VCK.his the API surface — layer headers are implementation detail; breaking changes toVCK.hbump the minor version until v1.0.0. - R22 VCK never owns user handles — completes rule 9; VCK destroys only handles it created.
- R18 External synchronisation — codifies Vulkan's per-handle external-sync requirement;
VCKMath.h—Vec2/Vec3/Vec4/Mat4POD structs, free-functionTranslate/Rotate/Scale/Perspective/LookAt/Radians/Degrees. No templates, no SIMD, row-major.VertexLayout— fluentAdd(name, VertexAttrType)→Binding(0)+Attributes()builder; returns plainVkVertexInput*structs the caller hands toVulkanModelPipeline(rule 22, no ownership).PushConstants—Declare(name, type)cold path,Set(name, value)+Apply(cb, layout, stages)hot path. Name → offset resolved atDeclare; no hashing /std::any/std::variantin the hot path.Primitives::Cube/Plane/Sphere/Quad/Line— return-by-valueMesh { positions, normals, uvs, indices }. Shrinks cube setup from ~40 lines of vertex tables to one call.DebugTimeline::DumpChromeTracing(path)— emits a Chrome-tracing JSON array you can load inchrome://tracingorui.perfetto.dev. No viewer bundled.- New example
[10] DebugShowcaseExample— guided tour of everyVCKLoglevel,cfg.debuggating, dedup,VK_CHECKfail-loud path, GPU / driver / memory / surface dump. No draw loop. - New example
[11] AAShowcaseExample—DetectRecommendedAAdecision matrix acrossforwardRenderer×supportsMotionVectors, live swapchain auto-pick echoed viaGetAATechnique()+GetMSAASamples(), RGB triangle drawn with the picked AA. - New example
[12] EasyCubeExample—Primitives::Cube()+VertexLayout+PushConstants+VCKMathin one screen. Rule 20 parity for the v0.2.1 ergonomic API. - Wiki
Cookbook— one-stop recipe book: image / OBJ / cube / text / line / circle / FXAA / SMAA / TAA skeletons / ImGui bootstrap / offscreen PNG readback.
- Rule 14 tightened — now explicitly requires
VCKLog::Errorwith a subsystem tag on every failure; areturn falsewithout a matchingErroris a bug. VulkanModelPipeline::Initialize(4-arg overload) emitsVCKLog::Warnwhen called; the hardcodedVK_SAMPLE_COUNT_1_BITis hazardous when the render pass uses MSAA. Use the 5-arg overload and passswapchain.GetMSAASamples().build.bat/build.sh— menu grew to[1]-[12].
- Top-left quadrant rendering in
MipmapExample+VMMExample— caused by pipeline-vs-render-pass sample-count mismatch (pipeline was 1x, render pass was MSAA 4x — undefined per spec, on NVIDIA confines rasterisation to the top-left quadrant). Both examples now passswapchain.GetMSAASamples()to the 5-argVulkanModelPipeline::Initialize. - Windows ANSI colour output —
VCKLog::Init()now callsSetConsoleModewithENABLE_VIRTUAL_TERMINAL_PROCESSINGonce on startup so Windows CMD renders colours instead of←[96mliterals. build.batline endings —.gitattributesforces CRLF on*.batso Windows CMD stops fragmenting comment lines into garbage tokens.EasyCubeExamplesizeofbug —VulkanMesh::Uploadtakes total byte count, not per-vertex stride; was uploading 1 of 24 vertices.DebugTimeline::DumpChromeTracingunderflow guard —endUs - startUsnow matchesDump()'sendUs > startUs ? endUs - startUs : 0pattern.
0.2.0 - 2026-04-23
- Cross-platform support (Windows / Linux / macOS) via
VCK::Window+VCKCrossplatformfacade over GLFW.VCK_PLATFORM_WINDOWS/LINUX/MACOSmacros gate platform includes. example/build.sh— Linux + macOS builder with the same[1]-[9] / [A] / [0]menu asbuild.bat; auto-detects OS, usespkg-configfor Vulkan + GLFW.- Live resize as first-class —
VCK::HandleLiveResize(window, dev, sc, fb, pipe[, depth])handles any OS resize (720p ↔ 4K) in one call per frame. Timeline-aware overloads inlayers/execution/emit aDebugTimelineCPU span (rule 12). - Anti-aliasing framework —
VCK::AATechniqueenum (Auto, Off, MSAA, MSAA_A2C, SampleRate, FXAA, SMAA_1x, SMAA_T2x, TAA, TAAU).cfg.aa.technique = AATechnique::Autoruns a 5-step decision tree atVulkanSwapchain::Initialize. Sample-based techniques implemented pipeline-side; post-process names returned viaswapchain.GetAATechnique()for renderer to implement (rules 15/16). VCK::VCKLogstructured logger —Info(debug-gated) /Notice/Warn/Error. Console-spam dedup of identical consecutive(tag, body)lines. Classify helper parses legacyLogVk("[Tag] body")into the new levels.cfg.debugflag (defaultfalse) —VulkanContext::Initializewires it intoVCKLog::SetDebug().cfg.pipeline.alphaToCoverage— flipsalphaToCoverageEnablein pipeline multisample state.cfg.pipeline.sampleRateShading+minSampleShading— enables per-sample shading.- Repo reorganisation:
layers/{core,expansion,execution,vmm}/+vendor/{vulkan_headers,glfw,vma}/.VCK.hat root is the single source of truth for API documentation. - Wiki —
Hello-VCK.md(per-line walkthrough targeting 1-hour onboarding budget),_Sidebar.md(navigation). LICENSE,CHANGELOG.md,CONTRIBUTING.md,.editorconfig,.gitignoreat repo root.
VK_CHECKnow routes failures directly toVCKLog::Error(…)instead of the debug-gatedLogVk(…)— fail loud regardless ofcfg.debug(rule 14 fix).VulkanContext::InitializetakesVCK::Window&(wasHWNDon Windows only); raw-handle overload preserved as escape hatch (rule 9).<windows.h>/<vulkan_win32.h>guarded behindVCK_PLATFORM_WINDOWSinVulkanHelpers.handVCK.h— no more platform leakage in the public surface.docs/Design.mdrule 4 allow-list updated to includeVulkanSwapchain::RecreateandHandleLiveResizevkDeviceWaitIdlecalls.- Examples 1-9 ported to
VCK::Window+VCK::HandleLiveResize— dropped rawGLFWwindow*,HWND,g_Resized,g_Minimized,OnFramebufferResize.
core/VulkanHelpers.cpp(empty shell).core/at repo root (moved tolayers/core/).VMM/at repo root (moved tolayers/vmm/).BuildRequiredExtensionshelper inVulkanContext.cpp(dead code from pre-crossplatform era, no matching header decl).
0.1.0 - 2026-04-22
The first release under the VCK name. Project was rebranded from VVCS
("Vulkan-VCS") to VCK — Vulkan Core Kit in commit deced77. This
release establishes the public surface (VCK.h amalgam header), the
three-layer architecture (core / expansion / execution), the in-tree
example builder (build.bat + ANSI menu), the structured logger, and
a Windows CI gate. The project is Windows-only at this point;
cross-platform support lands in v0.2.0.
- Project rebrand —
VVCS → VCK (Vulkan Core Kit). README, build scripts, header guards, and namespaceVCK::finalised. VCK.hamalgam header — single public include surface; per-class declarations stop being duplicated and the amalgam now#includes the layer headers directly (rule 21 precursor).- Three-layer architecture —
core/(VulkanContext,VulkanDevice,VulkanSwapchain,VulkanPipeline,VulkanCommand,VulkanSync,VulkanBuffer,VulkanImage,VulkanHelpers), expansion (framebuffers, depth, samplers, textures, model pipelines, descriptor sets, mipmaps), execution (FrameScheduler,JobGraph,GpuSubmissionBatcher,BackpressureGovernor,DebugTimeline,TimelineSemaphore). VCK::Configmaster init-chain control struct —cfg.device,cfg.swapchain,cfg.pipeline,cfg.scheduler,cfg.aa,cfg.debugknobs; passed once toVulkanContext::Initialize.VulkanPipeline::Config— cull mode, front-face winding, blend state, push-constant ranges, descriptor-set layouts.- Mailbox present mode by default with FIFO fallback when the surface doesn't expose Mailbox.
- Six VCKExpansion examples —
HelloExample,ModelExample,VMMExample,FrameSchedulerExample,TripleBufferExample,LockstepExample, plus three execution-layer examples (SubmissionBatchingExample,JobGraphExample,DebugTimelineExample). example/build.bat— Windows MinGW builder with[1]-[9] / [A] / [0]ANSI-coloured menu, BUILD_ALL section that compiles every example in one pass, and CRLF-safe shader compile viaglslangValidator.- VMM (Vulkan Memory Manager) — three-layer allocator
(
VmmPersistent/VmmTransient/VmmStaging) wrapping VMA's pool-aware allocators.VmmBuffer/VmmImageare typed POD-by-handle wrappers.LogStatsdump every N frames for the example. VCKLog— coloured[VCK] [Tag] bodylogger withInfo/Notice/Warn/Errorlevels and an init-time global toggle for debug-gatedInfolines.docs/at repo root — split out from README intoBuild.md,Examples.md,Design.md,Home.md. README slimmed to badges + 60-second tour + pointers.- GitHub wiki — initial structure;
_Sidebar.md, design rules. - CI: Windows workflow —
.github/workflows/build.ymlrunsbuild.bat Aonwindows-latestfor every push / PR. SDK installervk_video/*.hsparse-checkout patch (the LunarG installer'svulkan_videocomponent is optional butvulkan_core.hhard-includes it).
.gitattributes— forces CRLF on*.batso Windows CMD doesn't fragment comment lines into garbage tokens.
build.batredesigned with an ANSI UI;chcp 65001for UTF-8; em-dashes scrubbed from console-bound strings (CMD prints them as?on default codepages).AllocConsoleremoved in favour of g++'s default console-subsystem stdout — no flicker on launch, no leftover console if the program crashes.VulkanContext::Initializedrops the leftoverBuildRequiredExtensionshelper (Win32-only dead code with no header declaration).
- VMM lifecycle bugs — wrong destruction order between
VmmTransientring slots andVmmStagingwas leaking allocations onShutdown. Routed VMM logs to a Windows console. FrameSchedulerLockstep + AsyncMax deadlocks — Lockstep was waiting on the slot fence before signalling the previous frame's release; AsyncMax could double-acquire the same slot under contention.build.batBUILD_ALL trailing whitespace inset EX=...causing the all-build pass to skip examples whose name had a trailing space.- MinGW compile —
SubmitInfoandVCK::Configneed explicit default ctors; gcc 13 wouldn't aggregate-init through inheritance. JobGraph::Add— counted invalid (out-of-range) deps toward the job's wait count, soExecute()could deadlock waiting for a job that would never run.VCKExpansion.h— forward-declaredVulkanDepthBufferbeforeVulkanFramebufferSet(compile order fix).HelloExample— quad winding flipped so the embedded "Hello, World" text isn't back-face culled.
The original project was named VVCS (Vulkan-VCS). These commits are preserved in git history but never shipped under the VCK name; they're listed here for repo archaeologists. No SemVer was applied during this period.
- Initial drop — bare-bones
VulkanModule.h+ samplemain.cpp/App.cpp/App.hexercising context + device + swapchain + pipeline. - VMM iteration — first staging / persistent / transient layers; early lifecycle bug fixes.
- Windows console plumbing —
AllocConsoleroute for log output (later replaced by g++ console subsystem in v0.1.0). - README iteration — multiple README rewrites before the v0.1.0 rebrand.
core/(9 primitive classes +VulkanHelpers),VCKExpansion([1]-[12] rendering building blocks), execution layer ([13]-[22] frame scheduling),VMM/(three-layer memory manager).- 17 design rules documented in
docs/Design.md. - 9 example applications (
HelloExample,ModelExample,VMMExample,FrameSchedulerExample,TripleBufferExample,LockstepExample,SubmissionBatchingExample,JobGraphExample,DebugTimelineExample). example/build.batWindows MinGW builder with[1]-[9] / [A] / [0]menu.- GitHub Actions CI (
.github/workflows/build.yml) runningbuild.bat [A]on Windows.