feat: replace glslang+spirv-cross with glslpp for GLSL→HLSL shadertoy compilation#370
Draft
deblasis wants to merge 286 commits into
Draft
feat: replace glslang+spirv-cross with glslpp for GLSL→HLSL shadertoy compilation#370deblasis wants to merge 286 commits into
deblasis wants to merge 286 commits into
Conversation
…osition) (#92) * renderer/dx11: add IDXGIResource interface with GetSharedHandle * renderer/dx11: add D3D11_RESOURCE_MISC_SHARED constant and Flush binding * renderer/dx11: add shared texture ownership to Target * renderer/dx11: extend Device for shared texture mode (no swap chain) * renderer/dx11: wire shared texture mode through renderer backend Add shared_target field to DirectX11 to own the texture and RTV in shared texture mode. Update init() to detect the new surface variant and create the Target immediately. Update deinit(), initTarget(), and beginFrame() to route through shared_target when present, keeping swap chain mode unchanged. * renderer/dx11: simplify shared texture log statement * ghostty.h: add shared texture fields to Windows platform struct * apprt/embedded: add shared texture fields to Windows platform * docs: update surface support from dual to triple (shared texture) * renderer/dx11: add shared texture lifecycle test Tests init, resize, and deinit of the shared texture path on a real D3D11 device. Skips on non-Windows platforms. Signed-off-by: Alessandro De Blasis <alex@deblasis.net> * renderer/dx11: fix gpu_test for optional swap_chain field * renderer/dx11: fix shared texture ownership and add tests Fix initTarget copying owned COM pointers into borrowed Target (potential double-release). Skip DXGI factory/adapter queries in shared texture mode since no swap chain is needed. Merge InitError/ResizeError into single SharedTextureError. Strengthen resize test to assert handle changes. Add two new tests: borrowed target deinit safety and Device init in shared texture mode (swap chain null, present flushes, resize updates dimensions). * ghostty: expose D3D11 device for shared texture consumers Add ghostty_surface_get_d3d11_device() so shared texture consumers can open the DXGI handle on ghostty's own device, avoiding cross-device synchronization issues that cause blank reads. * ghostty: expose D3D11 context and texture for shared texture consumers Add ghostty_surface_get_d3d11_context() and ghostty_surface_get_d3d11_texture() so same-process consumers can CopyResource directly from ghostty's render texture without going through OpenSharedResource. Avoids cross-device sync issues entirely. * renderer/dx11: clean up shared texture review items Use idiomatic if-capture instead of force-unwrap (.?) in beginFrame. Set self.* = undefined in Target.deinit for double-deinit safety. Remove redundant shared_texture_mode bool from Device (swap_chain == null is the canonical check). Extract createTestDevice helper in Target tests. --------- Signed-off-by: Alessandro De Blasis <alex@deblasis.net>
* renderer/dx11: add DirectComposition COM bindings * renderer/dx11: wire DirectComposition into HWND surface init Replace CreateSwapChainForHwnd with a DirectComposition visual tree plus CreateSwapChainForComposition for the HWND surface path. Creates IDCompositionDevice/Target/Visual, binds the swap chain as the visual content, roots the visual on the HWND target, and commits before returning so DWM sees the first frame immediately. Cleanup releases dcomp objects in reverse creation order in deinit(). The swap_chain_panel path is unchanged. * renderer/dx11: add dcomp Commit to present and cleanup to deinit Call IDCompositionDevice::Commit() after each Present() so DWM picks up the new frame. The call is a no-op for non-HWND surfaces since dcomp_device is null there. * renderer/dx11: update HWND test for DirectComposition, add negative test
MVWT breakdown: - Build infra: 95% (15% weight) - DX11 infra: 95% (15% weight) - DirectComposition + shared texture done - App scaffold: 70% (10% weight) - 6 .NET examples - Cell rendering: 90% (20% weight) - full pipeline wired end-to-end - DirectWrite: 0% (15% weight) - ConPTY: 25% (10% weight) - Keyboard/mouse/clipboard: 30% (10% weight) - DPI/theming: 20% (5% weight) MVT: 0/30 checkboxes in #26
Shared textures created for cross-process interop only had D3D11_BIND_RENDER_TARGET, preventing consumers from creating a Shader Resource View directly on the shared handle. This forced every consumer to create an intermediate copy texture and copy each frame, adding unnecessary GPU overhead. Adding D3D11_BIND_SHADER_RESOURCE allows consumers to create an SRV directly on the shared texture, enabling zero-copy texture sharing.
* refactor: extract shared COM primitives to src/os/windows_com.zig Move GUID, HRESULT, IUnknown and helpers out of the DX11 renderer into a shared location so the upcoming DirectWrite font backend can reuse them. The renderer's com.zig re-exports everything so all existing imports are unchanged. * font: add directwrite_freetype backend variant New backend for Windows that will use DirectWrite for font discovery with FreeType rendering and HarfBuzz shaping. Currently maps to the same behavior as plain freetype -- discovery implementation comes next. Made the default on Windows, replacing plain freetype. * font: add DirectWrite COM interface bindings Define the DirectWrite COM interfaces needed for font discovery: IDWriteFactory3, IDWriteFontCollection/1, IDWriteFontFamily, IDWriteFont (through Font2 for IsColorFont), IDWriteFontFace, IDWriteFontFile, IDWriteLocalFontFileLoader, IDWriteFontFallback, IDWriteLocalizedStrings, IDWriteTextAnalysisSource. Includes runtime dwrite.dll loading and a UTF-16 to UTF-8 helper for reading localized font name strings. * font: implement DirectWrite font discovery Add DirectWrite discovery struct with discover() for family name matching and discoverFallback() using IDWriteFontFallback::MapCharacters for glyph coverage. Includes a minimal IDWriteTextAnalysisSource implementation and scored sorting matching the CoreText pattern. Also adds IDWriteFont::AddRef wrapper needed by DiscoverIterator. * font: wire DirectWrite through DeferredFace Add dw field with IDWriteFont handle for deferred loading. Implement familyName, name (via GetInformationalStrings), hasCodepoint (via HasCharacter + IsColorFont for presentation), and loadDirectWrite (extract file path from IDWriteLocalFontFileLoader, hand to FreeType via Face.initFile). * font: add DirectWrite integration tests Test discovery by family name (Consolas), codepoint matching, bold style filtering, emoji fallback via MapCharacters, and full DeferredFace load through to FreeType. Fix CreateNumberSubstitution to use NONE method (was using FROM_CULTURE which requires a non-null locale). * font: use std.unicode for UTF-16/UTF-8 conversions in DirectWrite Replace manual UTF-16-to-UTF-8 encoder in loadDirectWrite with std.unicode.utf16LeToUtf8 which handles surrogate pairs correctly. Replace ASCII-only utf8ToUtf16Le helper with std.unicode.utf8ToUtf16Le so non-ASCII font family names work. Extract magic number 2 to DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE.
* refactor: extract shared COM primitives to src/os/windows_com.zig Move GUID, HRESULT, IUnknown and helpers out of the DX11 renderer into a shared location so the upcoming DirectWrite font backend can reuse them. The renderer's com.zig re-exports everything so all existing imports are unchanged. * font: add directwrite_freetype backend variant New backend for Windows that will use DirectWrite for font discovery with FreeType rendering and HarfBuzz shaping. Currently maps to the same behavior as plain freetype -- discovery implementation comes next. Made the default on Windows, replacing plain freetype. * font: add DirectWrite COM interface bindings Define the DirectWrite COM interfaces needed for font discovery: IDWriteFactory3, IDWriteFontCollection/1, IDWriteFontFamily, IDWriteFont (through Font2 for IsColorFont), IDWriteFontFace, IDWriteFontFile, IDWriteLocalFontFileLoader, IDWriteFontFallback, IDWriteLocalizedStrings, IDWriteTextAnalysisSource. Includes runtime dwrite.dll loading and a UTF-16 to UTF-8 helper for reading localized font name strings. * font: implement DirectWrite font discovery Add DirectWrite discovery struct with discover() for family name matching and discoverFallback() using IDWriteFontFallback::MapCharacters for glyph coverage. Includes a minimal IDWriteTextAnalysisSource implementation and scored sorting matching the CoreText pattern. Also adds IDWriteFont::AddRef wrapper needed by DiscoverIterator. * font: wire DirectWrite through DeferredFace Add dw field with IDWriteFont handle for deferred loading. Implement familyName, name (via GetInformationalStrings), hasCodepoint (via HasCharacter + IsColorFont for presentation), and loadDirectWrite (extract file path from IDWriteLocalFontFileLoader, hand to FreeType via Face.initFile). * font: add DirectWrite integration tests Test discovery by family name (Consolas), codepoint matching, bold style filtering, emoji fallback via MapCharacters, and full DeferredFace load through to FreeType. Fix CreateNumberSubstitution to use NONE method (was using FROM_CULTURE which requires a non-null locale). * font: use std.unicode for UTF-16/UTF-8 conversions in DirectWrite Replace manual UTF-16-to-UTF-8 encoder in loadDirectWrite with std.unicode.utf16LeToUtf8 which handles surrogate pairs correctly. Replace ASCII-only utf8ToUtf16Le helper with std.unicode.utf8ToUtf16Le so non-ASCII font family names work. Extract magic number 2 to DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE. * font: add Segoe UI Emoji as Windows fallback font Mirror the macOS Apple Color Emoji pattern for Windows: discover "Segoe UI Emoji" via DirectWrite and add it as the preferred emoji fallback. Skip embedded Noto Color Emoji on Windows when discovery is available, same as macOS. * font: improve emoji fallback comment and guard readability Match the macOS comment style for the Windows emoji block. Simplify the embedded emoji guard using positive-sense grouping so it reads as "not (macOS or Windows), or no discovery" -- easier to extend. * font: document light hinting as intentional default on Windows Light hinting (TARGET_LIGHT) preserves glyph shapes rather than snapping to the pixel grid, matching the CoreText approach on macOS. Native ClearType rendering would require a DirectWrite rasterization backend (Phase 2). Add test confirming default load flags and update freetype-load-flags doc to mention Windows. * font: trim comment verbosity per review feedback
* refactor: extract shared COM primitives to src/os/windows_com.zig Move GUID, HRESULT, IUnknown and helpers out of the DX11 renderer into a shared location so the upcoming DirectWrite font backend can reuse them. The renderer's com.zig re-exports everything so all existing imports are unchanged. * font: add directwrite_freetype backend variant New backend for Windows that will use DirectWrite for font discovery with FreeType rendering and HarfBuzz shaping. Currently maps to the same behavior as plain freetype -- discovery implementation comes next. Made the default on Windows, replacing plain freetype. * font: add DirectWrite COM interface bindings Define the DirectWrite COM interfaces needed for font discovery: IDWriteFactory3, IDWriteFontCollection/1, IDWriteFontFamily, IDWriteFont (through Font2 for IsColorFont), IDWriteFontFace, IDWriteFontFile, IDWriteLocalFontFileLoader, IDWriteFontFallback, IDWriteLocalizedStrings, IDWriteTextAnalysisSource. Includes runtime dwrite.dll loading and a UTF-16 to UTF-8 helper for reading localized font name strings. * font: implement DirectWrite font discovery Add DirectWrite discovery struct with discover() for family name matching and discoverFallback() using IDWriteFontFallback::MapCharacters for glyph coverage. Includes a minimal IDWriteTextAnalysisSource implementation and scored sorting matching the CoreText pattern. Also adds IDWriteFont::AddRef wrapper needed by DiscoverIterator. * font: wire DirectWrite through DeferredFace Add dw field with IDWriteFont handle for deferred loading. Implement familyName, name (via GetInformationalStrings), hasCodepoint (via HasCharacter + IsColorFont for presentation), and loadDirectWrite (extract file path from IDWriteLocalFontFileLoader, hand to FreeType via Face.initFile). * font: add DirectWrite integration tests Test discovery by family name (Consolas), codepoint matching, bold style filtering, emoji fallback via MapCharacters, and full DeferredFace load through to FreeType. Fix CreateNumberSubstitution to use NONE method (was using FROM_CULTURE which requires a non-null locale). * font: use std.unicode for UTF-16/UTF-8 conversions in DirectWrite Replace manual UTF-16-to-UTF-8 encoder in loadDirectWrite with std.unicode.utf16LeToUtf8 which handles surrogate pairs correctly. Replace ASCII-only utf8ToUtf16Le helper with std.unicode.utf8ToUtf16Le so non-ASCII font family names work. Extract magic number 2 to DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE. * font: add Segoe UI Emoji as Windows fallback font Mirror the macOS Apple Color Emoji pattern for Windows: discover "Segoe UI Emoji" via DirectWrite and add it as the preferred emoji fallback. Skip embedded Noto Color Emoji on Windows when discovery is available, same as macOS. * font: improve emoji fallback comment and guard readability Match the macOS comment style for the Windows emoji block. Simplify the embedded emoji guard using positive-sense grouping so it reads as "not (macOS or Windows), or no discovery" -- easier to extend.
* font: verify variable font variations through DirectWrite discovery Add test confirming that font-variation axes flow through DirectWrite discovery into DeferredFace for application at load time. Document that DirectWrite does not need variation-based scoring because GetWeight/GetStyle already return instance-level values. * font: simplify variation test assertions per review
* font: fix review findings in DirectWrite backend - Replace hand-rolled UTF-16-to-UTF-8 encoder in getLocalizedString with std.unicode.utf16LeToUtf8 (handles surrogate pairs correctly) - Fix stale "ASCII fast path" comment in discovery.zig - Document why undefined Collection is safe in fallback test * font: remove stale BMP/surrogate doc comment from getLocalizedString
* renderer: rename directx11/ to directx12/, delete DX11-specific files * renderer: extract surface.zig and gpu_data.zig for DX12 * chore: nits (#115) Remove redundant CellText test block (comptime assertions cover it), add doc comment explaining cross-backend drift gap, document handle_out out-parameter in SharedTextureConfig. * renderer: fix broken gpu_test.zig import, update stale DX11 comment
Update backend.zig enum to directx12, swap d3d11->d3d12 in GhosttyLib.zig, and create a stub DirectX12.zig that satisfies the full GenericRenderer contract. All functions are no-ops returning defaults. Delete DX11-specific files (d3d11.zig, device.zig, cell_grid.zig, cell_pipeline.zig, gpu_test.zig) and replace with DX12 stubs for Target, Frame, RenderPass, Pipeline, Sampler, Texture, Buffer, and Shaders. Carry forward com.zig, dxgi.zig, dcomp.zig unchanged. Extract surface.zig and gpu_data.zig as new DX12-specific modules. Guard DX11 C API exports in embedded.zig with @Hasfield checks so they compile cleanly against the DX12 backend.
* renderer: rename directx11/ to directx12/, delete DX11-specific files * renderer: update backend enum and imports for directx12 Switch the renderer backend from directx11 to directx12: - backend.zig: rename enum variant and Windows default - renderer.zig: import DirectX12 instead of DirectX11 - GhosttyLib.zig: link d3d12 instead of d3d11 - embedded.zig: use @Hasfield guards for DX11-specific C API exports so they compile (returning null) with any backend - com.zig: remove gpu_test.zig reference (deleted in rename PR) - com_test.zig: remove D3D11-specific struct size tests * build: switch HLSL compilation from fxc/SM5.0 to dxc/SM6.0 HlslStep.zig now uses dxc.exe instead of fxc.exe. Targets Shader Model 6.0, outputs DXIL bytecode. dxc.exe found via Windows SDK first, then PATH fallback (for Vulkan SDK installs). SharedDeps.zig profiles updated from vs_5_0/ps_5_0 to vs_6_0/ps_6_0. No HLSL source changes needed -- existing shaders are SM 6.0 compatible. * docs: fix stale cell_pipeline.zig reference in HLSL README
* renderer: update backend enum and imports for directx12 Switch the renderer backend from directx11 to directx12: - backend.zig: rename enum variant and Windows default - renderer.zig: import DirectX12 instead of DirectX11 - GhosttyLib.zig: link d3d12 instead of d3d11 - embedded.zig: use @Hasfield guards for DX11-specific C API exports so they compile (returning null) with any backend - com.zig: remove gpu_test.zig reference (deleted in rename PR) - com_test.zig: remove D3D11-specific struct size tests * renderer: add D3D12 COM interface bindings * fix: correct D3D12_RESOURCE_STATES values, move GUIDs into structs - DEPTH_WRITE was 0x8 (collided with UNORDERED_ACCESS), fixed to 0x10 - Add missing INDIRECT_ARGUMENT (0x200) enum variant - Move all IID constants from module-level into interface structs as pub const IID, matching the dxgi.zig pattern - Type D3D12_DEPTH_STENCIL_DESC fields with proper enums (D3D12_STENCIL_OP, D3D12_DEPTH_WRITE_MASK, D3D12_COMPARISON_FUNC) - Improve tests: actual expected GUID values, more struct size checks, COM vtable pointer layout verification * fix: correct D3D12 struct size tests, fix PRESENT enum duplicate - D3D12_HEAP_PROPERTIES: 32 -> 20 (5 x u32, not padded) - D3D12_RANGE: hardcoded 8 -> 2 * @sizeof(usize) (SIZE_T is pointer-sized) - D3D12_RESOURCE_STATES.PRESENT: move to pub const to avoid duplicate enum tag - Add size tests for D3D12_RESOURCE_DESC, D3D12_RESOURCE_BARRIER, D3D12_ROOT_PARAMETER, D3D12_GRAPHICS_PIPELINE_STATE_DESC
- "DX11 renderer" -> "DirectX renderer" - "fxc/dxc" -> "dxc" (fxc is no longer used) - directx11/shaders.zig -> directx12/gpu_data.zig - Remove DX11-specific qualifiers from blend state comments
* renderer: DX12 device creation with command queue and fence Add device.zig with ID3D12Device, DIRECT command queue, and fence for CPU/GPU synchronization. Supports all three surface modes (HWND with DirectComposition, SwapChainPanel, SharedTexture). Triple-buffered swap chain, debug layer enabled in debug builds. Also fix D3D12_RESOURCE_STATES: convert from enum to u32 constants because several D3D12 state values alias (DEPTH_WRITE and UNORDERED_ACCESS both 0x8, COMMON and PRESENT both 0). Add CreateDXGIFactory2 extern to dxgi.zig. * fix: remove unused Allocator import in device.zig Signed-off-by: Alessandro De Blasis <alex@deblasis.net> * fix: use inline IID constants for D3D12 COM interfaces device.zig referenced standalone IID_ID3D12* constants that don't exist in d3d12.zig. The codebase defines GUIDs as pub const IID on each struct (e.g. ID3D12Device.IID), matching the pattern already used for DXGI and DComp in the same file. Zig's lazy evaluation hid this because init() isn't called yet, but it would fail at runtime. --------- Signed-off-by: Alessandro De Blasis <alex@deblasis.net>
* build: switch HLSL compilation from fxc/SM5.0 to dxc/SM6.0 HlslStep.zig now uses dxc.exe instead of fxc.exe. Targets Shader Model 6.0, outputs DXIL bytecode. dxc.exe found via Windows SDK first, then PATH fallback (for Vulkan SDK installs). SharedDeps.zig profiles updated from vs_5_0/ps_5_0 to vs_6_0/ps_6_0. No HLSL source changes needed -- existing shaders are SM 6.0 compatible. * renderer: DX12 descriptor heap management Linear allocator for CBV/SRV/UAV, sampler, and RTV descriptor heaps. Tracks CPU and GPU handles with per-descriptor increment size. * fix: add reset(), fix doc wording, add RTV and reset tests - Add reset() method so the linear allocator can be reused per-frame - Fix doc comment: "Callers typically create" instead of stating as fact - Add test for gpuHandle returning zero on non-shader-visible (RTV) heaps - Add test verifying reset() allows slot reuse after exhaustion Signed-off-by: Alessandro De Blasis <alex@deblasis.net> * fix: use inline IID, guard gpuHandle for non-shader-visible heaps - Use ID3D12DescriptorHeap.IID instead of removed standalone constant - Return zeroed GPU handle when gpu_start is 0 (RTV heaps) - Add debug bounds assertions in cpuHandle/gpuHandle --------- Signed-off-by: Alessandro De Blasis <alex@deblasis.net>
* build: switch HLSL compilation from fxc/SM5.0 to dxc/SM6.0 HlslStep.zig now uses dxc.exe instead of fxc.exe. Targets Shader Model 6.0, outputs DXIL bytecode. dxc.exe found via Windows SDK first, then PATH fallback (for Vulkan SDK installs). SharedDeps.zig profiles updated from vs_5_0/ps_5_0 to vs_6_0/ps_6_0. No HLSL source changes needed -- existing shaders are SM 6.0 compatible. * renderer: DX12 Frame with command allocator and command list Each in-flight frame owns a command allocator and graphics command list. Reset per frame, closes on complete, reports health to GenericRenderer. * fix(renderer/dx12): use optional pointers in Frame, remove UB on stub path Command allocator and command list fields are now optional (?*T) so that beginFrame() can safely return a stub frame with null D3D objects instead of undefined pointers. complete() and reset() guard against null, avoiding undefined behavior when the device isn't wired yet. Also: remove scoped blocks around HR checks, add hrFmt helper to dedupe HRESULT formatting, close command list before release in deinit(), and replace trivial tests with error-set field and type assertions. * fix: use inline IIDs and Zig 0.15 @typeinfo in Frame.zig - Replace standalone d3d12.IID_ID3D12CommandAllocator/GraphicsCommandList with inline d3d12.ID3D12CommandAllocator.IID to match codebase convention - Fix error set tests to use Zig 0.15 @typeinfo API (.@"fn" and .error_union.error_set) instead of removed .Fn.return_error_set
…ing) (#117) * renderer: DX12 Target (RTV + barriers) and RenderPass (command recording) Replace stubs with real implementations. Target wraps a swap chain back buffer resource with its RTV descriptor handle. RenderPass records into an ID3D12GraphicsCommandList following the same begin/step/complete pattern as Metal and OpenGL -- transitions barriers, sets viewport and scissor, clears, and will bind pipelines once those types are real. Wires Frame.renderPass() to create a RenderPass with the frame's command list. * fix: collect RTV handles for single OMSetRenderTargets call Per-attachment OMSetRenderTargets calls silently overwrote each other, leaving only the last target bound. Now all RTV handles are collected into a stack array and bound with a single call. Viewport and scissor are also set once from the first valid target instead of per-attachment. * fix: correct compile errors in Target/RenderPass/Frame - Fix invalid D3D12_RESOURCE_STATE_* references to use D3D12_RESOURCE_STATES enum members (PRESENT, RENDER_TARGET) - Fix optional-to-non-optional type mismatch in Frame.renderPass by unwrapping command_list with stub fallback - Make Target.transitionBarrier a method on self instead of a free function taking a bare resource pointer - Null resource in Target.deinit to prevent use-after-free - Make RenderPass.command_list optional to support stub path - Name the magic 8 as D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT
* renderer: DX12 clear-to-color through real device + command list Wire DirectX12.zig stubs to real GPU init. Device creation, swap chain (via DirectComposition), command queue, fence sync, triple- buffered command recording, clear render target, and present. Add IDXGISwapChain3 binding for GetCurrentBackBufferIndex. Make Device and DescriptorHeap types pub for use from DirectX12.zig. * fix: address PR review feedback for DX12 clear-to-color - Remove @constcast escape in beginFrame, use renderer.api for mutable access instead (matches DX11 pattern) - Replace @Panic with error.NoWindowsSurface at surface boundary - Use specific error names (NoSwapChain, NoDevice, FrameSyncFailed, FrameNotReady) instead of overloaded error.PresentFailed - Add comments on @ptrCast(@aligncast) pointer coercion chains - Document single-threaded assumption on fence_value mutation - Improve surfaceSize TODO about per-frame GetDesc1 cost - Document unused alloc parameter (COM-based allocation) * fix: correct compile error and review findings in DX12 clear-to-color - Fix IID_ID3D12Resource -> ID3D12Resource.IID (would not compile on Windows) - Write back Frame to gpu_frames after mutation to keep stored copy current - Remove unused apprt import - Add log.warn on GetDesc1 failure in surfaceSize - Document SharedTexture path, presentLastTarget fence safety, TDR TODO
* renderer: DX12 Buffer with upload heap and persistent mapping Single ID3D12Resource per Buffer(T) in D3D12_HEAP_TYPE_UPLOAD, mapped once at creation. Regrows at 2x when sync data exceeds capacity. Per-frame isolation handled by GenericRenderer's FrameState, so no ring buffer segmentation needed. * fix: address code review findings in DX12 buffer implementation - RawBuffer.size: u32 -> u64 to prevent silent truncation on large buffers - copy(): void -> !void, returns error.BufferMapFailed instead of silently swallowing null mapped pointer, consistent with Metal's error.MetalFailed - syncFromArrayLists: replace ad-hoc error.BufferNotMapped with same error.BufferMapFailed + log.warn pattern for consistency - Add errdefer self.release() in init/initFill to prevent resource leaks on partial failure (matches Metal/OpenGL backend patterns) - Add comment explaining ignored heap_props fields for non-CUSTOM types - Remove unsafe @intcast(byte_size) since size is now u64 * fix: deinit must fully reset buffer state, not just Release() deinit() was only calling Release() on the resource but left mapped, len, and buffer fields with stale/dangling values. Delegate to release() for complete cleanup, matching the pattern used by sync() and the errdefer in init/initFill. Signed-off-by: Alessandro De Blasis <alex@deblasis.net> * fix: correct compile errors in DX12 buffer -- enum/IID references, unused import --------- Signed-off-by: Alessandro De Blasis <alex@deblasis.net>
…or) (#126) * renderer: DX12 Texture (DEFAULT heap + staging) and Sampler (descriptor) Texture uses a committed resource in DEFAULT heap with SRV descriptor. Uploads go through a staging buffer copied via CopyTextureRegion. Sampler is a descriptor in the sampler heap, not a standalone object. * fix: review cleanup for DX12 Texture/Sampler implementation - Replace magic numbers with D3D12_TEXTURE_COPY_TYPE enum - Remove unused com import from Sampler.zig - Add log.err for staging buffer creation and Map failures - Add log.warn for unknown pixel formats in bppForFormat - Deduplicate transition call in Texture.init * fix: correct build-breaking bugs and improve safety in DX12 Texture - Fix IID_ID3D12Resource (nonexistent) to ID3D12Resource.IID (matching Buffer.zig) - Fix D3D12_RESOURCE_STATE_* C-style names to D3D12_RESOURCE_STATES.* enum variants - Fix staging buffer comment: DX12 does NOT extend resource lifetimes for recorded commands (unlike D3D11), document the actual safety precondition - Add log.err on null early returns in uploadRegion for debuggability - Document replaceRegion silent failure as intentional (Metal API parity) - Note descriptor slot leak on failed init (linear allocator, not fixable) - Replace break :switch with return in bppForFormat, upgrade warn to err
* renderer: DX12 Pipeline with root signature and PSO Shared root signature with inline CBV (b0), SRV descriptor table (t0..t2), and sampler descriptor table (s0). Per-pipeline PSO creation from DXIL bytecode with configurable blend mode and input layout. * fix: correct build-breaking bugs and improve safety in DX12 Pipeline Use nested IID constants (ID3D12RootSignature.IID, ID3D12PipelineState.IID) instead of non-existent top-level aliases, matching the convention used throughout the codebase (device.zig, Frame.zig, buffer.zig, etc.). Add root_signature ownership to Shaders so the shared root signature gets released on deinit, preventing a COM leak.
* renderer: DX12 shader loading from embedded DXIL bytecode Replace the shaders.zig stub with DXIL bytecode loading via @embedfile and input element descriptions for all 5 pipelines. Shaders.init() creates a shared root signature and PSOs for bg_color, cell_bg, cell_text, image, and bg_image. * fix: review cleanup for DX12 shader loading - Remove unused dxgi import - Move root signature ownership to explicit Shaders.root_signature field instead of burying it in bg_color pipeline - Add errdefer cleanup in init() to prevent COM resource leaks on error (root signature + already-created PSOs) - Remove redundant byte-offset runtime tests that duplicate the comptime assertions already validating struct layouts - Use inline for in deinit() instead of listing each pipeline * fix: root_signature ownership tests and pre-existing compile errors Add tests verifying Pipeline.deinit does not touch root_signature (owned by Shaders, released separately in Shaders.deinit). A bogus sentinel pointer catches accidental double-free if the contract changes. Also fix two pre-existing compile errors: - Pipeline.zig: DepthStencilState enum fields expected enums not ints - Frame.zig: @typeof on struct field is not valid Zig syntax * fix: review cleanup for DX12 shader loading - Fix deinit order: release PSOs before root signature to match init order and DX12 convention - Replace duplicated struct size assertions with cross-referencing input layout byte offsets against gpu_data struct offsets - Add TODO(#127) for root signature v1.1 upgrade - Fix misleading test name in Frame.zig
* renderer: DX12 wire all 5 render pipelines end-to-end RenderPass.step() now binds PSO, root signature, uniforms (inline CBV), textures (SRV descriptor table), samplers, and instance vertex buffers, then issues DrawInstanced calls. Shader-visible CBV/SRV/UAV and sampler descriptor heaps created at init. initShaders() creates the 5 PSOs via Shaders.init(). Texture and sampler options wired with device and heap pointers so atlas textures get real SRV descriptors. RawBuffer gains a stride field so the vertex buffer view knows the per-instance element size without losing type info. * fix: code review fixes for DX12 pipeline wiring - Remove dead srv_heap/sampler_heap fields from RenderPass struct (stored but never read via self.*, only used in begin() via opts) - Extract magic heap size numbers (64/16) into named constants (srv_heap_capacity, sampler_heap_capacity) with doc comments - Add @constcast safety rationale comments at all call sites - Clarify DX12 descriptor table vs Metal per-texture binding in texture/sampler comments (table-based, not individual indices) - Add TODO for multi-buffer binding (buffers[1..] as storage) - Update tests to remove assertions on deleted fields * fix: replace TODOs with tracked issues, document RawBuffer u32 choice Replace inline TODOs with GitHub issue references: - #128: multi-buffer binding for cell_text pipeline - #129: custom shader support (.hlsl shadertoy target) - #130: TDR recovery (DXGI_ERROR_DEVICE_REMOVED) - #131: cache surfaceSize dimensions - #132: frame pool fence wait wiring Add why-comment on RawBuffer.size/stride u32 types matching D3D12_VERTEX_BUFFER_VIEW fields. * docs: update Win32 example comments from DX11 to DX12 The renderer backend defaulted to DX12 since the pivot (backend.zig:22). The example code is renderer-agnostic but the comments still said DX11.
* renderer: DX12 GPU integration tests
Tests device creation, command queue, fence signaling, descriptor heaps,
buffers, textures, samplers, PSO creation, frame lifecycle, and swap
chain modes (HWND with DirectComposition, SharedTexture) against a real
D3D12 device.
* fix: execute GPU commands in texture integration tests
Texture tests recorded CopyTextureRegion and ResourceBarrier commands
on the command list but never submitted them. This left staging buffers
in limbo and meant assertions only checked CPU-side state tracking.
- Add executeAndWait() + reset() after texture creation with initial data
- Add executeAndWait() + reset() after replaceRegion
- Change silent catch {} to catch return in replaceRegion test
* fix: errdefer cleanup, consistent error handling in GPU tests
- Rewrite createTestDevice() to return !TestDevice with errdefer for
each COM object, matching device.zig convention. Removes ~30 lines
of manual cascading Release() calls.
- Standardize all callers from 'orelse return' to 'catch return'.
- Add comment noting Frame.init's undefined renderer/target fields.
- Rename 'all 5 PSOs' test to avoid coupling to pipeline count.
- Use expectEqual for exact 2x growth factor assertion.
* fix: code review fixes for DX12 GPU integration tests
- Check WaitForSingleObject return value instead of discarding
- Propagate executeAndWait errors in texture tests instead of swallowing
- Use real DefWindowProcW for HWND test window procedure
- Remove unused dcomp import, use idiomatic null checks
- Add self.* = undefined in TestDevice.deinit
- Simplify comment that referenced removed DX11 code
* renderer: DX12 fix surface creation crash (#133) * renderer: DX12 use @max for swap chain dimension clamp, add HWND 0x0 test Use @max(width, 1) to match codebase style (see embedded.zig:811-812). Add HWND-mode test that exercises the createCompositionSwapChain clamp path with 0x0 dimensions, verifying the swap chain is created at 1x1.
* renderer: DX12 cache surfaceSize dimensions (#131) * renderer: DX12 add why-comments to surfaceSize cache Explain why the cache is the primary source of truth: DX12 uses composition swap chains for all surface types, so there is no GetClientRect equivalent. Document the GetDesc1 fallback limits and the setTargetSize contract.
* renderer: DX12 upgrade root signature to v1.1 (#127) * renderer: DX12 root signature v1.1 review fixes - Replace magic Version=2 with typed D3D_ROOT_SIGNATURE_VERSION enum - Remove dead D3D12SerializeRootSignature v1.0 extern - Add size tests for D3D12_ROOT_SIGNATURE_DESC1, D3D12_VERSIONED_ROOT_SIGNATURE_DESC - Consolidate v1.1 size tests into main struct sizes test block
Adds IsInternalKey alongside IsProfileSubkey in WindowsOnlyKeys, and wires it into ConfigService's diagnostic loop so app-private knobs (currently internal.update-simulator) stop leaking into the settings notice list. Surfaced during PR # 349 work after the user noticed "unknown field: internal.update-simulator" in the warnings InfoBar.
Reframes the 4 WinUI smoke stubs in Ghostty.Tests.Windows as manual-smoke specs and converts TitleBarPassthroughTests from a failing Assert.Fail to [Fact(Skip=...)]. Headers document what to check by hand; Skip messages explain why XAML+dispatcher hosting is out of scope here. Counts: 11 pass / 4 skip / 0 fail (was 11 / 3 / 1).
Closes # 344. Vertical-strip users now get the same profile-aware new-tab control as horizontal mode (Click / Alt+Click / Shift+Click + dropdown). New FlyoutPlacement DP on NewTabSplitButton; vertical sets it to Right. Collapsed strip widens 40 -> 56 so the dropdown chevron is visible in collapsed mode (LayoutCoordinator.VerticalStripCollapsedWidth is the single source of truth).
Replaces SplitButton inside NewTabSplitButton with a StackPanel + paired Button + chevron Button + shared MenuFlyout. New Orientation DP picks stack direction (Horizontal default; Vertical for VerticalTabStrip). Reverts # 354's 40 -> 56 strip-width bump; the chevron is now visible-stacked instead of visible-wider. Click semantics unchanged. Follow-up to # 354.
) Visual polish on # 355. Wraps the paired Buttons in a rounded outer Border with a 1px separator and transparent inner Buttons; theme key overrides at UserControl.Resources scope (per-button scope crashed Window.SystemBackdrop at startup). Chevron glyph derives from the existing Orientation DP: ChevronDown horizontal, ChevronRight vertical. Closes # 343.
Folds the two reviewer items deferred from # 356: SymbolThemeFontFamily + BodyTextBlockFontSize on the FontIcons (chevron stays at FontSize=10 with a why comment since no theme ramp entry matches), and orientation switching moves from the imperative OnOrientationChanged callback to a VisualStateManager group with HorizontalState + VerticalState. Behavior unchanged.
Fixes pwsh under default config on non-UTF-8 OEM Windows (e.g. Italian CP-850): encoding lands at 65001, Nerd Font glyphs render, full PSReadLine line-editing works. Two key changes: * `termio: inject utf-8 preamble on bypass transport ( # 341)` drops the `mode != .conpty` early-return so PR # 308's preamble fires on `.bypass` for pwsh under the user's actual repro path. * `termio: force conpty for pwsh + suppress csi response under bypass+pwsh` matches WezTerm / Alacritty / libghostty-vt-dotnet: pwsh's PSReadLine needs a console handle for VT input. Other VT-aware shells (bash, wsl, ssh, nu, fish, zsh, elvish, xonsh) keep using bypass. Plus the supporting infrastructure: `utf8-console = auto | always | never` config knob with CJK-aware default, `isCjkAnsiCodePage` and `resolveUtf8Console` helpers, removal of the obsolete `ensureUtf8Console` runtime hack (replaced by `<activeCodePage>UTF-8</activeCodePage>` in the Zig GUI manifest), and a `WriteKind` tag on termio messages for transport-aware response suppression. Manual probe on Italian CP-850 Windows: chcp reports 65001, [Console]::OutputEncoding reports CodePage 65001, [Console]::IsInputRedirected reports False, Oh-My-Posh Nerd Font glyphs render, backspace + Enter + arrow-up history + tab completion all work. `utf8-console = never` kill switch verified. Refs deblasis/wintty # 341
Upstream's freetype_windows landed `Discover.init(lib)` across all backends. Our directwrite_freetype was still init() with no args, so list_fonts and SharedGridSet failed to compile after the rebase. Make DirectWrite.init accept (and ignore) a Library handle. Tests pass undefined since the parameter is unused.
Promote WarnIfNoLibghostty to ErrorIfNoLibghostty in windows/Ghostty/Ghostty.csproj. The Condition="Exists(...)" on the <None Include> for ghostty.dll above is evaluated at MSBuild project-load time, not target-execution time. A missing dll silently drops the copy item and the produced binary throws DllNotFoundException at startup -- the process stays alive in Task Manager but no window paints because async-void OnLaunched exception plumbing reaches Application.UnhandledException with Handled=false without reliably tearing the process down. Not gated on \$(PublishAot) because that property is set unconditionally in this csproj's main PropertyGroup: it only enables AOT analyzers, not AOT compilation. dotnet build always produces a managed assembly that loads ghostty.dll via runtime DllImport. A clean zig build -Dapp-runtime=none produces both ghostty.dll and ghostty-static.lib together, so requiring the dll covers every consumer including AOT publish (which resolves ghostty.dll when launched from bin\ rather than publish\). Error text uses [System.IO.Path]::GetFullPath to surface the absolute path of the missing artifact, and instructs the user to run zig in the directory containing build.zig (unambiguous in both the source tree and the materialised wintty-release tier tree). Layer B follow-up to deblasis/wintty-release # 82 / # 83. Closes deblasis/wintty-release # 84.
) The <Content Include=\"\$(GeneratedBrandingDir)AppIcon.scale-*.png\"> uses a wildcard, which expands at MSBuild evaluation time. The GenerateBrandingAssets target above runs in BeforeBuild, after evaluation, so on a clean build the wildcard matches zero files, no Content items are added, and bin\Assets\ never appears. The AppIconBadge then resolves ms-appx:///Assets/AppIcon.png to nothing and renders the broken-image placeholder where the Ghostty ghost should be. Replacing the wildcard with explicit scale names (100/150/200/400 to match PngWriter.ScaleTargets) lets MSBuild add the items at evaluation regardless of whether the files exist yet; the Copy task at build time succeeds because GenerateBrandingAssets has produced them by then. The WinUI 3 _GenerateProjectPriFileCore target runs after BeforeBuild, so the PRI resolves ms-appx://Assets/AppIcon.png to the scale-qualified file at runtime as before. Second instance of the same evaluation-time-vs-target-execution-time anti-pattern in this csproj. The first was the ghostty.dll <None Include> Condition=\"Exists(...)\" trap, fixed in # 360.
* nit: toning down comments verbosity and slop * nit: round 2 — Zig renderer + COM vtable slot counts + CI + IconGen
* feat(libghostty): add ghostty_build_info FFI export Exposes version, commit, channel, Zig version, and build mode as a single struct readable without ghostty_init. Used by the Windows host for +version output and the Version command-palette dialog. * feat(libghostty): declare ghostty_build_info in ghostty.h Header companion to the FFI export landed in the previous commit. * fixup(libghostty): match Zig type-naming pattern in ghostty_build_info - Rename Zig type ghostty_build_info_s -> BuildInfo, matching the existing Info / String pattern in main_c.zig where the C-side typedef name lives in a doc comment above the PascalCase Zig alias. - Replace emdash with semicolon in the doc comment per ASCII-only rule. - Document the b ++ "" idiom so future readers understand the comptime sentinel coercion. * style(libghostty): match comptimePrint idiom and trim doc comments - Use comptimePrint for the commit-hash literal, matching the sibling version-string block. The b ++ "" trick worked but isn't used elsewhere in the codebase. - Trim the over-explanatory comment blocks above both file-scope constants. comptimePrint makes the comptime requirement self-evident. - Move the lifetime / encoding / commit-empty paragraph from the type doc onto the function doc, leaving the type doc as just the C name — matches the Info / String pattern in the same file.
* feat(core): add Edition enum for version output Single-value Oss in the public repo. Overlay extends with Sponsor and Pro. * feat(core): add EditionLabel.Format Pure formatter for Edition. Public path returns oss. Single-arg signature; overlay extends to (Edition, Channel) when adding sponsor/pro cases. * feat(core): add LibGhosttyBuildInfo record + P/Invoke bridge Reads libghostty's ghostty_build_info FFI. Blittable struct, NativeAOT-compatible. Strings marshalled to managed copies; native lifetimes are static so no free is required. * feat(core): add VersionInfo record * feat(core): add VersionRenderer with plain and ANSI rendering Single renderer used by the +version CLI and the Version palette dialog. ANSI variant wraps the header in OSC 8; plain variant is used for the dialog and for redirected stdout. xUnit fixtures cover both paths plus the unknown-commit fallback. * feat(core): add MSBuild target to generate BuildInfo.g.cs Emits Wintty version, commit (with -dirty suffix), MSBuild config, and Edition.Oss as compile-time constants. WriteOnlyWhenDifferent avoids spurious rebuilds. Git unavailable falls back to commit unknown. * feat(core): add VersionRenderer.Build() integration Combines BuildInfo (MSBuild), libghostty FFI, and runtime probes into a VersionInfo. Used by the +version CLI and the palette dialog. * fixup(core): minor cleanups from review pass - Document why <Compile Include> stays inside GenerateBuildInfo: the reviewer suggested moving it to top-level for IDE IntelliSense, but $(IntermediateOutputPath) is set by Microsoft.NET.Sdk.targets which imports after csproj XML evaluation, so a top-level Include resolves to a wrong path and creates a duplicate Compile item. Verified by trying it. - Drop redundant System. prefix on ArgumentOutOfRangeException; the csproj has ImplicitUsings enabled. - Pull the field-padding column out of Field() into a class-level FieldValueColumn const so it stops looking like a magic number. The Channel-propagation flag from review is not a bug for this codebase: local Release builds correctly stay on the "tip" channel string. CI Stable releases pass -p:Channel=Stable as a global property, which does propagate to Ghostty.Core via ProjectReference.
* feat(host): add CommandCategory.About Bucket for the Version palette item (and future About-flavored entries like Open Logs Folder, Report a Bug). * feat(host): add CliActions.PrintVersion Renders VersionInfo to stdout. Picks ANSI vs plain via Console.IsOutputRedirected. No AttachConsole - Wintty.exe is a console-subsystem app and inherits the parent terminal natively. * feat(host): intercept +version / --version / -v before libghostty dispatch Routes to CliActions.PrintVersion which uses the C#-side VersionRenderer shared with the Version command-palette dialog. Skips ghostty_init since ghostty_build_info is callable without it. Also extends RegisterNativeResolver to cover Ghostty.Core.dll so that LibGhosttyBuildInfoBridge (which lives in Core) can resolve ghostty.dll via the same native/ path as the host assembly. * feat(host): add Version palette command and dialog VersionCommandSource exposes a single Version palette item under the About category. VersionDialog renders the same plain text the CLI emits and offers a Copy button (no dismiss; brief Copied confirm) for bug-report use. Uses DialogTracker so in-flight dialog is drained before window teardown, consistent with RenameTabDialog and close-confirmation flows. Uses WinClipboard alias to resolve the Clipboard static against Windows.ApplicationModel.DataTransfer rather than Ghostty.Clipboard. * feat(host): register VersionCommandSource in palette * fixup(host): clipboard hardening and icon escape on Version dialog VersionDialog.xaml.cs: - Wrap WinClipboard.SetContent in try/catch (COMException) to match the existing CO_E_NOTINITIALIZED / CLIPBRD_E_CANT_OPEN handling in WinUiClipboardBackend. An unhandled COMException on an async void event handler tears the process down. - Capture the original primary-button label once at construction and add a _copyInProgress guard so a rapid double-click on Copy doesn't end up reading "Copied" as the rest state and leave the button stuck on "Copied" indefinitely. VersionCommandSource.cs: - Replace the embedded U+E946 PUA glyph with the escape sequence to keep the source ASCII per the keyboard-chars-only rule, matching the existing BuiltInCommandSource convention.
…366) * feat(core): add RenderPlainBody and CommitUrl helpers VersionRenderer now exposes: - RenderPlainBody(VersionInfo): the Version + Build Config blocks without the leading "Wintty <version>" header line. Lets the dialog show just the body, since its title bar already carries the version. - CommitUrl(VersionInfo): the github.com commit URL or null when no commit is known. Used by the dialog's clickable hyperlink and by ANSI rendering's OSC 8 wrap. RenderPlain stays unchanged so the CLI output and the clipboard payload keep the full text (header + URL line + body), which is what bug-report pastes need. * feat(host): polish Version dialog with app icon and inline hyperlink - Title row now has the 40x40 app icon (via AppIconSource.Current) next to "Wintty <version>". Drops the redundant "Wintty <version>" line the body used to repeat from the title bar. - The commit URL is rendered as an inline Hyperlink inside a TextBlock rather than a HyperlinkButton, so it reads as colored monospace text in the same flow as the body, with no button border or focus chrome. Clicking opens the commit page in the default browser. - Dialog body uses VersionRenderer.RenderPlainBody (no header / URL line). Clipboard payload still uses RenderPlain so paste keeps every field for bug-report use.
* termio: document canonical CSI 6 n reply shape The cursor-position DSR handler has been emitting the canonical ESC [ <row> ; <col> R form, but a downstream wintty-bench probe reported an 18-byte payload before the terminating R. The libghostty emit path is unambiguously canonical (matching tests already exist in stream_terminal.zig), so add an inline note pointing future investigators at the more likely sources: PTY transport interleaving and out-of-band replies such as the mode 2048 size report. No behavioral change. * docs(termio): tighten CSI 6 n reviewer notes Address review feedback on PR #368: trim the speculative transport-interleaving parenthetical and reference size_report.zig by filename so the mode 2048 disambiguation is anchored to a real symbol. Signed-off-by: Alessandro De Blasis <alex@deblasis.net> --------- Signed-off-by: Alessandro De Blasis <alex@deblasis.net>
The AttentionValueInfoBadgeStyle resource key isn't defined anywhere in this codebase, so the previous raw cast would throw a KeyNotFoundException the first time the sidebar tried to render an info badge for a page with a nonzero search-hit count. Mirror the TryGetValue + is pattern from TabColorPalettePicker.GetBrushResource and fall back to the InfoBadge default style when the key is missing.
- Add glslpp as Zig dependency (pure-Zig, no C++ runtime) - Replace shader_wrapper.dll path with glslpp.compileGlslToHlsl() - Skip 8MB stack thread spawn for HLSL target (no C++ ABI issues) - Keep glslang+spirv-cross for MSL/GLSL paths (separate thread still needed) - CRT shader validates through DXC with 0 errors
- Remove shader_wrapper.cpp (MSVC-compiled C++ DLL for GLSL→HLSL) - Remove wrapper.zig (DLL loader) - Remove wrapper import from pkg/glslang/main.zig - Update Pipeline.zig comment: 'shader_wrapper' -> 'glslpp binding_shift' - glslpp (pure Zig) now handles GLSL→HLSL for the shadertoy path - Keep glslang+spirv-cross for MSL/GLSL cross-compilation paths - Add .zig-version and mise.toml for Zig 0.15.2 pinning
… recipe - Add 'ci' recipe: check-zig + test + build-release (local CI equivalent) - Add 'check-zig' recipe to verify Zig 0.15.2 - Add 'build-release' recipe (ReleaseSafe, what CI uses) - Rename deploy-shader-wrapper -> deploy (no more shader_wrapper.dll) - Mark build-shader-wrapper as -legacy (kept for reference) - Fix typo: depploy -> deploy
The production shader compilation path now uses glslpp exclusively for all three targets. This eliminates the need for: - 8MB stack thread for glslang+spirv-cross on Windows - C++ runtime dependencies (glslang DLL, spirv-cross) - Thread isolation for MSL/GLSL compilation glslang and spirv-cross imports are kept for existing tests only. The next step is to remove them entirely once tests are migrated.
- shadertoy.zig: Remove glslang/spirv-cross imports, legacy functions (spirvFromGlsl, mslFromSpv, hlslFromSpv, glslFromSpv, spvCross, SpirvLog) - shadertoy.zig: Rewrite tests to use glslpp convenience APIs - global.zig: Remove glslang initialization - SharedDeps.zig: Remove glslang/spirv-cross build setup - Config.zig: Remove glslang/spirv-cross system integration options - build.zig.zon: Remove glslang/spirv-cross dependency entries - generic.zig, main_c.zig: Update comments All shader compilation now goes through glslpp (pure-Zig). Both wintty shaders render pixel-perfect vs spirv-cross reference. Pre-existing test failures in Exec.zig and message.zig are unrelated.
These C++ dependencies are no longer needed — glslpp handles all shader compilation (GLSL → SPIR-V → HLSL/GLSL/MSL) natively in Zig. Saves ~60MB from the repository.
- Exec.zig: Add missing 4th argument (utf8_console=.never) to execCommand calls in Windows tests. The parameter was added to execCommand but the tests weren't updated. - message.zig: Make Message size test platform-aware. On 64-bit Windows with MSVC ABI, alignment padding causes the struct to be larger than 41 bytes. Test now uses a reasonable upper bound on 64-bit platforms.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replace the glslang + SPIRV-Cross pipeline (C++ via DLL) with glslpp (pure Zig) for the shadertoy GLSL→HLSL compilation path on Windows/DX12.
What changed
src/renderer/shadertoy.zig— HLSL target now callsglslpp.compileGlslToHlsl()instead of the glslang+spirv-cross DLL pipeline. No more 8MB stack thread spawn for HLSL.build.zig.zon/src/build/SharedDeps.zig— glslpp added as a Zig dependency.pkg/glslang/main.zig— Removedwrapperimport.pkg/glslang/shader_wrapper.cpp— Deleted (290 lines of MSVC-compiled C++ wrapper DLL).pkg/glslang/wrapper.zig— Deleted (DLL loader).src/renderer/directx12/Pipeline.zig— Updated comment to reference glslpp binding_shift.justfile— Addedcirecipe, removed shader_wrapper deployment references..zig-version/mise.toml— Pin Zig 0.15.2.What stayed the same
shaders.hlsl,cell.hlsl) are pre-written HLSL compiled by DXC at build time — not affected.pkg/glslang/build_msvc.batand the glslang static library — still needed for MSL/GLSL.Correctness verification
Both CRT and focus shadertoy shaders produce HLSL that:
register(b0)for the cbuffer (matches DX12 root signature)register(t0)/register(s0)for texture/samplerSV_Positioninput andSV_Targetoutput semanticsmainImage(out float4, float2)signature preserved correctlySide-by-side comparison with spirv-cross reference output shows:
oricolvariable)Performance
~73x faster average, eliminates process spawn, C++ runtime, and DLL isolation hacks.
glslpp repo
The corresponding glslpp commits (already on
main):033ff25— Fixbinding_shift=-1for register(b0), fix for-loop test, fix leakf56c80d— CI-equivalent justfile2bba2e6— Regenerate focus HLSL outputHow to test
Remaining work