Port of CookedNick's JaiRenderThreadExample with more complex animations: https://github.com/CookedNick/JaiRenderThreadExample
Smooth, artifact-free window resizing and moving on Windows by delegating all rendering to a background thread and synchronizing WM_PAINT with frame completion.
renderDemo.mp4
- Continuous 60+ FPS while sizing/moving the window (no hitching).
- No stretch / unpainted artifacts: WM_PAINT returns only after the new-size frame is rendered.
- Render thread sleeps when nothing animates (near 0% CPU/GPU idle).
- Safe, minimal cross‑thread state handoff (one CRITICAL_SECTION + one CONDITION_VARIABLE).
- OpenGL 1.1 compatible path with a few extension calls (vsync + optional ARB_sync fence).
- Additional visuals: particles, rotating/pulsing geometric shapes, color‑cycling quads, FPS counter.
- Alt+Enter borderless fullscreen toggle.
- Per‑monitor DPI awareness (PER_MONITOR_AWARE_V2 if available, fallback to system DPI).
Typical Windows apps stutter or show artifacts during interactive resize because:
- The OS enters a modal loop and throttles WM_PAINT issuance.
- Apps often paint asynchronously relative to WM_PAINT, so the window shows old contents.
This demo blocks inside WM_PAINT until the render thread finishes a frame at the new size, guaranteeing correctness while still achieving high frame cadence thanks to continuous background rendering during animation.
- Main thread only processes messages.
- WM_PAINT:
- Writes desired FrameInfo (size + flags) under lock.
- Wakes render thread and waits on condition variable.
- Resumes only after render thread signals completion; then EndPaint -> return.
- Render thread:
- Renders continuously only while animation is active (or a frame is explicitly requested).
- Sleeps on the same condition variable when idle.
- Flags (bitfield):
- FRAME_WINDOW_SIZE_CHANGED
- FRAME_TERMINATE_RENDER_THREAD
- FRAME_TOGGLE_ANIM_PLAYBACK
- FRAME_WAKE_MAIN_WHEN_COMPLETED (indicates main is blocked in WM_PAINT waiting for this frame)
Bidirectional use of a single condition variable keeps the design compact.
WM_PAINT -> set flags -> wake render thread -> render thread draws -> signal -> WM_PAINT continues (SwapBuffers already done).
Shared struct: FrameInfo nextFrame (simple scalar copy; double buffering unnecessary here).
- Legacy fixed pipeline for broad compatibility.
- Orthographic projection adjusted per frame size.
- Optional ARB_sync fence aligns CPU pacing with GPU completion (avoids presenting half-finished frames on some drivers).
- Bitmap font (wglUseFontBitmaps) for FPS text (no extra dependencies).
- Tries to choose modern pixel format with multisampling + sRGB when available, falls back gracefully.
| Aspect | Jai Version | This C Port |
|---|---|---|
| Language/runtime | Jai beta | ISO C + Win32 |
| Rendering API | Simp wrapper | Raw WGL + GL 1.1 |
| Demo visuals | 3 moving quads | Quads + particles + shapes + FPS |
| DPI handling | N/A | Per-monitor V2 (if available) |
| Fullscreen | N/A | Alt+Enter toggle |
| GPU sync | Basic | Optional ARB_sync fence |
Single source file (main.c). CMake project provided.
cl /O2 /Zi /FeResponsiveWin32RenderThread.exe main.c user32.lib gdi32.lib opengl32.lib winmm.lib
git clone https://github.com/idrassi/ResponsiveWin32RenderThread.git
cd ResponsiveWin32RenderThread
cmake -S . -B build -G "Visual Studio 17 2022"
cmake --build build --config Release
build\Release\ResponsiveWin32RenderThread.exe
cmake -S . -B build -G "NMake Makefiles"
cmake --build build
build\ResponsiveWin32RenderThread.exe
cmake -S . -B build -G "MinGW Makefiles"
cmake --build build
build/ResponsiveWin32RenderThread.exe
- Space: Pause / resume animation.
- Alt+Enter: Toggle borderless fullscreen.
- Resize / move window: Observe smooth, artifact-free updates.
- Close button / Alt+F4: Graceful shutdown (render thread terminates first).
- When animation is paused and no resize occurs, render thread sleeps (no busy loop).
- With vsync enabled (default), pacing comes from the GPU swap + optional fence.
- Particle / shape counts are configurable via MAX_PARTICLES / MAX_GEOMETRIC_SHAPES.
Released under The Unlicense (public domain). (Provide full text if distributing.)
- Original concept and Jai implementation: CookedNick.
- WM_PAINT blocking inspiration: Patrik Smělý.
- Win32 + OpenGL baseline APIs by Microsoft / Khronos.
Educational demo. No warranty. For production: expand error handling, context loss recovery, robust DPI handling, logging, and graceful fallback paths.