From fb422e931ef6dc83dd635255822110a1d27b3c84 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 8 Oct 2026 13:15:21 +0000 Subject: [PATCH] core: Vulkan and D3D12 glass draws the lens and follows the slider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 0 of `docs/WINDOWS_LINUX_GLASS_PLAN.md`. `compiled/{spv,dxil}/liquid_glass.fragment.*` were last built in #206; the HLSL changed in #227 (Apple's lens, `glass_look`'s one slider), and the binaries embedded for Vulkan and D3D12 still drew the earlier glass whatever `publishLook` said. So on Linux and Windows the in-window glass had no lens and did not follow the slider. The HLSL needed nothing. Apart from what each language declares for its inputs, textures and uniforms, it is `liquid_glass.glsl` and `liquid_glass.metal` line for line, with three differences that are deliberate and documented: the loop runs `first..first + count` (GLSL ES wants a constant bound and skips), the samples are at level 0 (HLSL refuses an implicit level after `discard`; the frost has no mips), and the dither's noise takes `uv` rather than the fragment position (D3D12 links inputs by register). `LiquidField.sample` agrees with them on the field — outline, coverage, the way out, steepness, material — over every shape rather than one group's, and does not model the lens's band, which nothing it answers depends on. Both compiled with the commands at the top of the HLSL, by SDL_shadercross with its vendored DXC (libsdl-org/DirectXShaderCompiler at 2c84a1c5, the submodule SDL_shadercross pins): the toolchain #206 used, which compiles the #206 HLSL to #206's SPIR-V and DXIL byte for byte. The DXIL is signed (validator 1.9, as before) and passes `dxv`; the SPIR-V passes `spirv-val`. The interface is unchanged: two samplers, one uniform buffer, colour at location 0 and uv at 1. (That DXC wants clang on Linux: built with GCC 13 it corrupts its heap compiling DXIL.) Drawn through SDL_GPU on lavapipe, as `GpuRenderer` draws a program (frost at sampler 0, sharp at 1, the punch and add passes), with the uniforms of `pack` and `applyLook` and the look from `glass_look.inApp` at window opacity 0, 0.35, 0.7 and 1 — a dialog (`forText`) and three drops running together beside a carried card (`forDrops`), over an opaque window and a translucent one: the new SPIR-V is within 1/255 of `liquid_glass.glsl` (built with glslang) at every pixel of every case. With no look published it is the old SPIR-V exactly — the earlier glass is untouched — and with one published the old SPIR-V was off by up to 204/255. `publishLook`'s comment says every form of the program draws the lens now, and that the web publishes none. Step 0 of `docs/WINDOWS_LINUX_GLASS_PLAN.md` and the "still to do" in `docs/NATIVE_WINDOWS_PLAN.md`'s materials library are marked done. Not seen in the app: fizzy itself was not built here (the environment's network policy denies gitlab.freedesktop.org and sndio.org, which sdl_zig fetches from). `core`, with `LiquidField` and the new programs embedded, compiles for x86_64-linux and x86_64-windows-gnu. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Vci2bBhv2EH5QxygzWxmx8 --- core/gfx/LiquidField.zig | 8 +++--- .../compiled/dxil/liquid_glass.fragment.dxil | Bin 7580 -> 8444 bytes .../compiled/spv/liquid_glass.fragment.spv | Bin 10580 -> 13412 bytes docs/NATIVE_WINDOWS_PLAN.md | 8 +++--- docs/WINDOWS_LINUX_GLASS_PLAN.md | 25 +++++++++--------- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/core/gfx/LiquidField.zig b/core/gfx/LiquidField.zig index 89631dc92..2b9268d38 100644 --- a/core/gfx/LiquidField.zig +++ b/core/gfx/LiquidField.zig @@ -275,10 +275,10 @@ fn opaqueWindow() bool { /// The app's glass at the window opacity this frame (`glass_look.inApp`), published by the app /// before anything draws: every field — dialogs, menus, drops — is drawn as it says, Apple's lens -/// on the one slider. Null (nothing published, a plugin's own window): the earlier glass, as each -/// field's own tint, lift and blur say. The precompiled Vulkan and D3D12 programs draw the earlier -/// glass whatever is published until they are compiled again from the HLSL (the commands are at -/// its top); the GLSL (the web) and the Metal draw the lens. +/// on the one slider. Null (nothing published: the web, a plugin's own window): the earlier glass, +/// as each field's own tint, lift and blur say. Every form of the program draws the lens — the +/// GLSL, the Metal, and the SPIR-V and DXIL compiled from the HLSL — as long as the last two are +/// compiled again whenever the HLSL changes (the commands are at its top). pub fn publishLook(slider_look: ?glass_look.InApp) void { if (dvui.current_window == null) return; if (slider_look) |l| dvui.dataSet(null, enabled_id, "_liquid_look", l) else dvui.dataRemove(null, enabled_id, "_liquid_look"); diff --git a/core/gfx/shaders/compiled/dxil/liquid_glass.fragment.dxil b/core/gfx/shaders/compiled/dxil/liquid_glass.fragment.dxil index ceb25f8290ff338ee4dd6c477f6643789917a86d..e8a82f9af2fac2f23dcd403ae2a1e93bab673e91 100644 GIT binary patch delta 4676 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 H6-yIH5fnA`f(vG>6A~)1rGmn0duwWP zLd3uX6N+Q0_=w_oxxPw-`ntB0#3)hY0FKjztvZ2~)zS{j2}oxJ>vZmpIq6!HKhD{E z|Gxd5Z-4vu`}WQY`H`YjMNLU*>{~qB?rT+nB`?nZNiF~JdkO?WM;3RdrqXlS5LE71 z^>@lL7=a)a7^hGnNKsQ!2>~M%^k@B$-{MdJtV_@QcV-R$@=LEf+LiGGV&!fDTW2kIc&Cx|mmAt%%=%b~YN7+BB-#sBBC$8Nb1+ z)Pr>bKOP%U#ZIdRXeF^Ts#3kE5k2$vjeMs(-Ah?A=8`en(gQBWWbC}*_QAg{s_uPM z%X^6WJ$#abMMyPZ?NAy zOphtJbXj!mDvSDtqr9cBzpoERQ#vGt;gMbAz3Yp9QfGo85!Q8ec<8fLt20{P`rvmv zn|8mO`@{W5)89&Er~J%6s@VTyVE?b3eb&i7FJoMAUN5QcnTgHPzrHws%_pmdMHln0 zo-VwYf9Vy<=63Gr>lYfIp5M6hT;tAl{_2byEhp}_<#2Yl?CIz9uiw+s*O$@jN_`-> z(c)O2^MC6z`c88CbNUj7g{!Zw8Mqt{?-e4u6&UgMoNejP>FMiBxDKcg*~2%$ zy8tny4^<*T%IZ$~YTfe>(fp>0M#|>3miuA4R3=8~^B4F(=_3K-QTp70d)848522hj zj9(|xASe-5p&VeJ1H7Ml;6$M0WlDx3X@~6U!Ag13`q|`iSJH1^Ik;7D@J`R3_+^~s z+m2r>EDPQbez>RSY<#BPfFo0X5|u$lyMDh5b9G(T+`R``;=!=dE-D)wdHcFv18Xll z`V{7#2my_nTai*qgM7HsJ#uR!w&1AsDqOj2be}+hnG`;+% zM1EbTl~t{)%=T-Hl;e{~SCYBunk%_dfE}2qBtoatRFq`nBtlCzHLY})( zdJ@fy>{JK+HNy?QMF_iciF~CP>DY)5aXBp(EIs^R@F*Yo&}q#r z8NUE|j>!|}#3zLTjcJ2-#N1~aH4_wr9>)|z<0+nS8#IR}e`$U``%Ci@WsxZc*5zV; zjSJ!z90=9ac}7e`u@Idn3FR#;>mPjkR{;$HcKlk%mrzAZrj;&uBucU9;HFBDD!IcW zNssS^!Lqk*5v2?4@a%@dqe08*LDeBVZ2)^fHw+S;#G4QsbRNCzP`177 z1n72Fqg`!Z1Z4pW*EZ;w6YyF`(JQIIbe?Vqqy7j=)I*Xm+Cyv93e>7FPr5r^tW}kw$4Svtc?yjW2JLn$ozUer$1HHy zia4_m-$7LQKFw%A`I5I=DqipJ<;b$VUty+X#ESYWn(zxJ0@Jgt9y zCR6k?0y6bdQTp1W*S$L5ZEXoYfsTzB{~e(vpyHm*nPf$f?9Irm(vxagF;~X%=ckw?|ABQ5|%!tp@LLpaZAYi1wP1S%=eL?ee00PHe~`Om}Ok z`89fhcLb3~!}hHE6cOb|BI`QW+ks}1y7RFQBLyT7bN*C^3;=Q9;85LWAN3*@gg7v5 zK6{1TH|EurKo%k5(z+Ul|OF|-pg;@CQ=8(Owk{@5WIaLVE)+L z(L2$3evD-$iDyBV$4aHv}^A7!X`>2*G zw$^Ue`97Y~97^J+t&P6mA)^9&*=@- zIGJ-|A}*kz@x3F*D8>Ke1|1Cs>plhb_&EGNmW#6%urGoNGC+Gr-^au!&Y5K(L+&+* z5T18HzYCDskAHlnQWPlzZ#*93ZkG%BH`bMbAQ>P?bn@Q4dLcaLFc_@#<(YhrzJ^hp zvUHBOVP%JFa|Wmo%QBBgv}rDBXrSh_eHuQcbu)-xQ-kxrp+*mdp4G1=+I{3naOPP7 zai<1@gANhu*VKueBgiMjC<%U6AT`}3Q$j1MFTEa}<@hft?2F1OvuJy%CyETUNj<*k z=~J|$bSw&d-Y-?$BLPj(JEar8$gOY9rGi4yv;2lODY?vtu}|QXb6p@`TyXio-HX3q zfBz4CKVLHd diff --git a/core/gfx/shaders/compiled/spv/liquid_glass.fragment.spv b/core/gfx/shaders/compiled/spv/liquid_glass.fragment.spv index ed2941c6452377d227d837f9b01b31f1d3034fd3..f9d667b32a85e7185a2275b93ff279ba27d1b113 100644 GIT binary patch literal 13412 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