diff --git a/README.md b/README.md index 81180c12f..2929018bb 100644 --- a/README.md +++ b/README.md @@ -235,6 +235,10 @@ Remove-Item Env:WGPU_BACKEND # restore the default for later An explicit `gl` override can bring the driver crash back on affected systems. The macOS, Linux and web backend defaults are unchanged. +The **32-bit** build uses OpenGL even when a DirectX 12 graphics card is present. On 32-bit +Windows, creating a DirectX 12 graphics pipeline fails immediately and the app exits before the +window appears. `WGPU_BACKEND=vulkan` (or `dx12`) still overrides that. + **If the app quits right after its window appears with "Parent device is lost" in the log:** WordCraft compiles DirectX 12 shaders with FXC, the compiler built into Windows, so it needs no `dxcompiler.dll`/`dxil.dll` and ignores any copy another program put on `PATH` (#603). diff --git a/ROADMAP.md b/ROADMAP.md index 731d7715d..169f9ad4d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,7 +2,7 @@ **Stage: alpha** · next: beta, ~15 points (60% → 75% ready for real work) and ~150–230 h away -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** trivial (Turkish interface catalog completed, #774; previously trivial: Hungarian interface landed; previously trivial: Quick Access Toolbar KeyTips and a saved enable/disable option, #620; previously trivial: new documents follow the system region, #838; previously minor: Polish interface and Polish proofing; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 +> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-12 · **Change:** trivial (32-bit Windows starts on OpenGL so launch no longer exits; previously trivial: every measurement follows the Options unit, #755; previously trivial: Insert › SmartArt landed, #497: catalog 429/451 → 437/458 (95.4%); previously trivial: Turkish interface landed; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 WordCraft aims for complete parity with Microsoft Word, then goes further on speed, openness and agent control. This page is the summary; the assessment is @@ -132,6 +132,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm ## Progress log | Date | What landed | +| 2026-10-12 | 32-bit Windows starts on OpenGL. DirectX 12 graphics pipeline creation returns "The parameter is incorrect" and the app exited before the window appeared | | 2026-10-12 | New documents follow the system region (#838): A4 and centimetres outside the US (Letter in the CLDR Letter territories, inches in the US), lengths written with the region's decimal separator (`2,54 cm`) and typed with either; an explicit Measurement units choice wins; `file.options {"region"}` for agents | | 2026-10-12 | Paste from other programs keeps their formatting (#687): Ctrl+V and Home › Paste read the system clipboard's HTML (and RTF on Windows and Wayland); Merge Formatting takes the destination's font and paragraph and keeps bold, italic, underline and strikethrough; Paste Special lists what the system clipboard holds (HTML, RTF, picture, text). Linux: pictures copied in a browser or Spectacle paste on KDE and other Wayland desktops (data-control clipboard), and a paste that finds nothing usable names what the clipboard holds instead of "empty" (#833) | | 2026-10-12 | PDF export of long documents with many internal links (a linked table of contents) is linear: NIH's 67-page protocol template 10.6 s → 0.9 s | diff --git a/apps/wordcraft/src/graphics.rs b/apps/wordcraft/src/graphics.rs index 3ef515797..564b6ed29 100644 --- a/apps/wordcraft/src/graphics.rs +++ b/apps/wordcraft/src/graphics.rs @@ -20,18 +20,28 @@ pub struct Dx12Adapter { /// The backends to initialize on Windows. /// /// An explicit `backend_override` (normally `Backends::from_env()`, i.e. `WGPU_BACKEND`) always -/// wins. Otherwise DirectX 12 only, as long as `dx12_adapters` (what a DirectX 12-only probe found) -/// contains a usable hardware GPU. Without one, OpenGL is the way to the GPU: graphics chips whose -/// driver has no DirectX 12 support (Intel 4th generation on Windows 11, #316) still have an -/// OpenGL driver, and GL can't reach the AMD driver crash described in [`configure_backends`], -/// because an AMD GPU with a driver shows up as a DirectX 12 adapter and keeps us on DirectX 12. -/// When DirectX 12 offers only WARP, it stays enabled next to GL as a last resort for machines -/// without an OpenGL driver either (virtual machines): wgpu prefers any GPU over a software -/// adapter, so it's only picked when GL has nothing better. -pub fn choose_backends(backend_override: Option, dx12_adapters: &[Dx12Adapter]) -> Backends { +/// wins. Otherwise DirectX 12 only, as long as `dx12_graphics` is set and `dx12_adapters` (what a +/// DirectX 12-only probe found) contains a usable hardware GPU. Without one, OpenGL is the way to +/// the GPU: graphics chips whose driver has no DirectX 12 support (Intel 4th generation on Windows +/// 11, #316) still have an OpenGL driver, and GL can't reach the AMD driver crash described in +/// [`configure_backends`], because an AMD GPU with a driver shows up as a DirectX 12 adapter and +/// keeps us on DirectX 12. When DirectX 12 offers only WARP, it stays enabled next to GL as a last +/// resort for machines without an OpenGL driver either (virtual machines): wgpu prefers any GPU +/// over a software adapter, so it's only picked when GL has nothing better. +/// +/// `dx12_graphics` is false on 32-bit Windows. wgpu creates the graphics pipeline through +/// `ID3D12Device2::CreatePipelineState`, and that stream is aligned to 8 bytes. The 32-bit runtime +/// expects pointer alignment (4), so creation returns `E_INVALIDARG` ("The parameter is incorrect") +/// and the process exits before the first frame. Compute pipelines use the older API and succeed, +/// which is why startup gets as far as the egui pipeline and then quits. OpenGL does not use that +/// stream. +pub fn choose_backends(backend_override: Option, dx12_adapters: &[Dx12Adapter], dx12_graphics: bool) -> Backends { if let Some(backends) = backend_override { return backends; } + if !dx12_graphics { + return Backends::GL; + } let hardware = |a: &&Dx12Adapter| a.device_type != DeviceType::Cpu; if dx12_adapters.iter().filter(hardware).any(|a| a.meets_limits) { Backends::DX12 @@ -94,9 +104,16 @@ pub fn configure(options: &mut NativeOptions, backend_override: Option backends } None => { - let adapters = probe_dx12(options); - let backends = choose_backends(None, &adapters); - log::info!("graphics: {} DirectX 12 adapter(s) {adapters:?}, backends {backends:?}", adapters.len()); + // 32-bit: skip the DirectX 12 probe. A capable GPU would be selected, then + // CreatePipelineState fails and the app exits with no window. + let dx12_graphics = cfg!(not(target_arch = "x86")); + let adapters = if dx12_graphics { probe_dx12(options) } else { Vec::new() }; + let backends = choose_backends(None, &adapters, dx12_graphics); + if dx12_graphics { + log::info!("graphics: {} DirectX 12 adapter(s) {adapters:?}, backends {backends:?}", adapters.len()); + } else { + log::info!("graphics: 32-bit Windows uses OpenGL; DirectX 12 graphics pipeline creation fails"); + } backends } }; @@ -157,7 +174,7 @@ mod tests { }; assert!(eframe_default.instance_descriptor.backends.contains(Backends::GL)); let gpu = [adapter(DeviceType::IntegratedGpu, true)]; - assert_eq!(configured_backends(choose_backends(None, &gpu)), Backends::DX12); + assert_eq!(configured_backends(choose_backends(None, &gpu, true)), Backends::DX12); } #[test] @@ -165,8 +182,8 @@ mod tests { let warp_only = [adapter(DeviceType::Cpu, true)]; for backends in [Backends::VULKAN, Backends::GL, Backends::DX12, Backends::VULKAN | Backends::DX12, Backends::empty()] { // Whatever the probe would have found, the override wins (the probe doesn't run then). - assert_eq!(choose_backends(Some(backends), &[]), backends); - assert_eq!(choose_backends(Some(backends), &warp_only), backends); + assert_eq!(choose_backends(Some(backends), &[], true), backends); + assert_eq!(choose_backends(Some(backends), &warp_only, true), backends); assert_eq!(configured_backends(backends), backends); } } @@ -192,13 +209,23 @@ mod tests { fn gl_when_dx12_has_no_usable_gpu() { // #316: no DirectX 12 driver, so DirectX 12 offers only WARP (or nothing) and lags. let warp_only = [adapter(DeviceType::Cpu, true)]; - assert_eq!(choose_backends(None, &warp_only), Backends::GL | Backends::DX12); - assert_eq!(choose_backends(None, &[]), Backends::GL); + assert_eq!(choose_backends(None, &warp_only, true), Backends::GL | Backends::DX12); + assert_eq!(choose_backends(None, &[], true), Backends::GL); // A GPU that can't create eframe's device: GL alone, so it isn't picked over the GL one. let weak_gpu = [adapter(DeviceType::IntegratedGpu, false), adapter(DeviceType::Cpu, true)]; - assert_eq!(choose_backends(None, &weak_gpu), Backends::GL); + assert_eq!(choose_backends(None, &weak_gpu, true), Backends::GL); // Any usable GPU keeps DirectX 12 only, next to WARP or a weaker GPU. let mixed = [adapter(DeviceType::Cpu, true), adapter(DeviceType::IntegratedGpu, false), adapter(DeviceType::DiscreteGpu, true)]; - assert_eq!(choose_backends(None, &mixed), Backends::DX12); + assert_eq!(choose_backends(None, &mixed, true), Backends::DX12); + } + + /// 32-bit Windows: a usable DirectX 12 GPU still starts on OpenGL. `WGPU_BACKEND` still wins. + #[test] + fn x86_uses_opengl_even_with_a_usable_gpu() { + let gpu = [adapter(DeviceType::IntegratedGpu, true)]; + assert_eq!(choose_backends(None, &gpu, false), Backends::GL); + assert_eq!(choose_backends(Some(Backends::DX12), &gpu, false), Backends::DX12); + assert_eq!(choose_backends(Some(Backends::VULKAN), &[], false), Backends::VULKAN); + assert_eq!(configured_backends(choose_backends(None, &gpu, false)), Backends::GL); } } diff --git a/apps/wordcraft/src/main.rs b/apps/wordcraft/src/main.rs index 40acc27b9..b4221d5e5 100644 --- a/apps/wordcraft/src/main.rs +++ b/apps/wordcraft/src/main.rs @@ -274,8 +274,8 @@ fn main() -> eframe::Result { options.viewport = options.viewport.with_icon(icon); } // Before eframe creates the wgpu instance: default Windows to DirectX 12 only, or OpenGL when - // DirectX 12 has no GPU driver, and compile DirectX 12 shaders with FXC, which needs no - // DLL of ours (#603; see graphics.rs). + // DirectX 12 has no GPU driver or this is a 32-bit build, and compile DirectX 12 shaders with + // FXC, which needs no DLL of ours (#603; see graphics.rs). #[cfg(target_os = "windows")] graphics::configure(&mut options, eframe::wgpu::Backends::from_env()); load_user_fonts(); diff --git a/contributors/people.toml b/contributors/people.toml index 558b5a5d7..2a9d72941 100644 --- a/contributors/people.toml +++ b/contributors/people.toml @@ -64,3 +64,6 @@ sync_github_name = false [people.alexanderalber] real_name = "Alexander Alber" [people.edurbs] +sync_github_name = true + +[people.odedigo] diff --git a/docs/gaps.md b/docs/gaps.md index 94ca91d1f..d6b35ed29 100644 --- a/docs/gaps.md +++ b/docs/gaps.md @@ -1,6 +1,6 @@ # Where WordCraft falls short of Word -> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** trivial (formatted paste from other programs and Wayland clipboard pictures, #687, #833; previously trivial: DOCX complex-script formatting inheritance fixed; broader RTL work remains; previously trivial: #24 narrowed: Customize Keyboard and Customize Ribbon landed; previously trivial: formatting revisions landed, #41; previously trivial: Draw Table and Eraser landed, #303; previously minor: beta distance restated: ~15 points, ~150–230 h; previously: first version; every known shortfall from the 2026-10-10 re-measure, ranked) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 +> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-12 · **Change:** trivial (32-bit Windows no longer exits at launch on DirectX 12; previously trivial: Word XML Document and Word 2003 XML landed, #548) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 The work list. One entry per shortfall, ranked by how much it stops a Word user from switching (**B** = blocks beta). Each says what's missing, the evidence, who it hurts, an Opus 5.5 agent @@ -15,7 +15,7 @@ Native save reliability: synthetic cases on macOS reproduced loss through the pr |---|---|---|---|---|---|---| | 1 | **DOCX never tested on real-world files.** No corpus of files from Word, Google Docs, LibreOffice and Pages has been opened, rendered and round-tripped and compared with Word page by page | B | No corpus in the repo; `crates/docx/tests` are synthetic fixtures (including omitted/empty paragraph defaults and imported TOC range preservation); "DOCX fidelity corpus: not started" since 2026-10-06 | Everyone: the files people receive are the files that break | 30–50 | [file-format-parity.md](file-format-parity.md) | | 2 | **Remaining native ink forms are dropped on open and lost on save, silently**; OLE objects show only their picture | B | Drawing-level native ink is preserved with its optional picture fallback; direct run-level content parts and ink nested in groups/canvases remain unsupported. Drawing canvases are read and written (#344); group shapes (`wpg`) read and written (#267). Charts and SmartArt are drawn (#292) and, with OLE objects, written back with all their parts on save (#319) | Documents with diagrams drawn in Word or pen notes lose content without warning | 4–8 to preserve remaining native ink forms; 45–70 to render and edit charts and SmartArt (#13) | [file-format-parity.md](file-format-parity.md) | -| 3 | **Crashes and freezes in the field**: startup crash on Intel UHD Graphics (#170) (lag on GPUs without a DirectX 12 driver fixed, #316), freezes (#77, #59 Thai fonts, #31 font selector), no writes without admin on Windows 11 (#218), broken shape tool (#142), images can't be moved (#82) | B | 62 open issues, ~15 of them crashes, hangs or data-path failures | Anyone hit loses work or trust; the never-crash standard covers panics, not hangs or GPU driver faults | 20–30 | [target-app-parity.md](target-app-parity.md) (Stability) | +| 3 | **Crashes and freezes in the field**: startup crash on Intel UHD Graphics (#170) (lag on GPUs without a DirectX 12 driver fixed, #316; 32-bit Windows exited at launch because DirectX 12 graphics pipeline creation failed, now OpenGL), freezes (#77, #59 Thai fonts, #31 font selector), no writes without admin on Windows 11 (#218), broken shape tool (#142), images can't be moved (#82) | B | 62 open issues, ~15 of them crashes, hangs or data-path failures | Anyone hit loses work or trust; the never-crash standard covers panics, not hangs or GPU driver faults | 20–30 | [target-app-parity.md](target-app-parity.md) (Stability) | | 4 | **Pagination differs from Word**: Aptos has no metric-matched substitute; legacy compatibility options ignored; no page-by-page comparison harness | B | [layout-parity.md](layout-parity.md); [typing-parity.md](typing-parity.md) Known gaps | Page counts and line breaks differ, which matters for forms, legal and academic work | 30–50 + owner (font) | [layout-parity.md](layout-parity.md) | | 5 | **Content controls** landed (#381): `w:sdt` kept, shown and edited (Developer tab, Design Mode, Properties). Move tracking landed (#400): `w:moveFrom`/`w:moveTo` with their named ranges round-trip, a tracked cut and paste of a paragraph or sentence records a move, either end accepts/rejects both, green double strike/underline markup and "Moved from/to" balloons; still missing: drag-and-drop moves (no text drag yet) and move options in Track Changes Options. Formatting revisions landed (#41): `w:rPrChange`/`w:pPrChange`/`w:tblPrChange`/`w:trPrChange`/`w:tcPrChange`/`w:sectPrChange`/`w:numberingChange` round-trip, are recorded while tracking, accepted/rejected and shown in balloons; still missing: tracked style-definition changes and table/section changes made in WordCraft. Opaque custom XML backing stores now survive saves; binding evaluation remains absent. | B | Issues #41, #400; source grep | Legal and editorial review workflows; templates with form controls | 5–8 | [file-format-parity.md](file-format-parity.md) | | 6 | **No native printing** on desktop: File › Print opens the PDF in the system viewer, which prints (#286); File › Print has a preview, page range, odd/even, copies and collate (#641); printer choice, duplex and pages per sheet are still the system's; web prints through the browser (#209) | B | `ui.print` → `apps/wordcraft/src/print.rs`; issue #15 | Everyone who prints | 5–8 | [hardware-parity.md](hardware-parity.md) | @@ -72,6 +72,7 @@ The same gaps grouped the way the parity documents are, for agents working in on | Date | Change | Summary | |---|---|---| +| 2026-10-12 | trivial | #3: 32-bit Windows no longer exits at launch; DirectX 12 graphics pipelines fail to create, so that build starts on OpenGL | | 2026-10-12 | trivial | Custom dictionary persists across sessions (`custom-dictionary.txt` in the settings folder; #40) | | 2026-10-11 | trivial | #8 narrowed: runs in a proofing language without a dictionary are skipped instead of flagged against the English dictionary (#100); dictionaries still English-only | | 2026-10-11 | trivial | #16: DOCX open/save preserves independent complex-script formatting inheritance; RTL sections, tables and typography remain open | diff --git a/docs/hardware-parity.md b/docs/hardware-parity.md index ebcfb96ab..e91b5f31c 100644 --- a/docs/hardware-parity.md +++ b/docs/hardware-parity.md @@ -1,6 +1,6 @@ # Hardware parity with Microsoft Word -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (first version) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 and Word for Windows +> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-12 · **Change:** trivial (32-bit Windows starts on OpenGL; previously major: first version) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4 and Word for Windows Word is not a hardware-heavy app, but a few devices matter to its users: printers above all, then pens, microphones (Dictate) and speakers (Read Aloud), and displays. @@ -11,7 +11,7 @@ pens, microphones (Dictate) and speakers (Read Aloud), and displays. | Hardware | Word | WordCraft macOS | Windows | Linux / BSD | Web | Parity | Hours | |---|---|---|---|---|---|---|---| | Printers: native print dialog, printer choice, copies, duplex, page ranges, tray, scaling | ✅ (`WordPDE.plugin` print-dialog extension on Mac) | 🟡 PDF opens in Preview to print (#286) | 🟡 PDF opens in the default viewer (#286) | 🟡 PDF opens in the default viewer (#286) | ✅ browser print dialog (#209) | 35% | 5–8 | -| GPU rendering, HiDPI/Retina, pixel-aligned text | ✅ | ✅ wgpu + vello_cpu rasteriser, whole-pixel text (#110, #165) | ✅ DirectX 12 default (#50), OpenGL when DirectX 12 has no GPU driver (#316); startup crash on Intel UHD (#170) | ✅ (soft text on KDE at some zooms, #140) | ✅ | 80% | 3–5 (bugs) | +| GPU rendering, HiDPI/Retina, pixel-aligned text | ✅ | ✅ wgpu + vello_cpu rasteriser, whole-pixel text (#110, #165) | ✅ DirectX 12 default (#50), OpenGL when DirectX 12 has no GPU driver (#316) or on 32-bit; startup crash on Intel UHD (#170) | ✅ (soft text on KDE at some zooms, #140) | ✅ | 80% | 3–5 (bugs) | | Multiple monitors, per-monitor DPI, remembered window position | ✅ | ✅ (#38, #76) | ✅ (winit DPI fix pending, #155) | ✅ | — | 85% | 1 | | Pen / stylus: ink, pressure, eraser, ink to shape/math | ✅ (Draw tab, `InkRender.bundle`) | ❌ | ❌ | ❌ | ❌ | 0% | (Draw tab, 15–25) | | Microphone: Dictate | ✅ (cloud speech service) | ❌ | ❌ | ❌ | ❌ | 0% | 8–15 + owner (speech model choice) | @@ -23,6 +23,7 @@ pens, microphones (Dictate) and speakers (Read Aloud), and displays. | Date | Change | Summary | |---|---|---| +| 2026-10-12 | trivial | 32-bit Windows starts on OpenGL: DirectX 12 graphics pipeline creation returns "The parameter is incorrect" and the app exited before the window appeared | | 2026-10-10 | trivial | Windows falls back to OpenGL when DirectX 12 offers only the software adapter (#316) | | 2026-10-10 | trivial | Desktop File › Print opens the PDF in the system viewer (#286) | | 2026-10-10 | trivial | Inertial touchpad scrolling landed (#252) |