Fixed two critical bugs preventing multiple textured sprites from rendering correctly:
1. **setState consumed by submit**: Render state was set once at the beginning,
but bgfx consumes state at each submit(). Batches 2+ had no state → invisible.
FIX: Call setState() before EACH batch, not once globally.
2. **Buffer overwrite race condition**: updateBuffer() is immediate but submit()
is deferred. When batch 2 called updateBuffer(), it overwrote batch 1's data
BEFORE bgfx executed the draw calls. All batches used the last batch's data
→ all sprites rendered at the same position (superimposed).
FIX: Use transient buffers (one per batch, frame-local) instead of reusing
the same dynamic buffer. Each batch gets its own isolated memory.
Changes:
- SpritePass: setState before each batch + transient buffer allocation per batch
- UIRenderer: Retained mode rendering (render:sprite:add/update/remove)
- test_ui_showcase: Added 3 textured buttons demo section
- test_3buttons_minimal: Minimal test case for multi-texture debugging
Tested: 3 textured buttons now render at correct positions with correct textures.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix JsonDataNode::getChildReadOnly() to handle JSON array access by numeric index
- Fix test_ui_showcase to use JSON array for children (matching test_single_button pattern)
- Add visual test files: test_single_button, test_ui_showcase, test_sprite_debug
- Clean up debug logging from SpritePass, SceneCollector, UIButton, BgfxDevice
The root cause was that UITree couldn't access array children in JSON layouts.
UIButton hover/click now works correctly in both test files.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add BGFX_CONFIG_MULTITHREADED=0 to fix TLS crash when bgfx runs from DLL
- Add -include stdint.h for MinGW GCC 15+ compatibility with bgfx third-party code
- Guard SDL2-dependent visual tests with if(SDL2_FOUND)
- Clean up debug logging in BgfxDevice::frame() and BgfxRendererModule::process()
- Re-enable all modules in test_full_stack_interactive.cpp
- Add grove::fs namespace for cross-platform filesystem operations
- Add InputModule C export for feedEvent across DLL boundary
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix texture state management in BgfxDevice: defer setTexture until submit()
- Add transient instance buffer support for multi-batch rendering
- Add ParticlePass with fire, smoke and sparkle particle systems
- Load multiple textures from config (texture1..texture10)
- Visual test now demonstrates multi-texture sprites and multi-particle effects
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Phase 7 - Text Rendering:
- Add BitmapFont with embedded 8x8 CP437 font (ASCII 32-126)
- Add TextPass for instanced glyph rendering
- Fix SceneCollector::parseText() to copy strings to FrameAllocator
Phase 8A - Multi-texture Support:
- Add numeric texture ID system in ResourceCache
- SpritePass sorts by textureId and batches per texture
- Flush batch on texture change for efficient rendering
Phase 8B - Tilemap Rendering:
- Add TilemapPass for grid-based tile rendering
- Support tileData as comma-separated string
- Tiles rendered as instanced quads
Window Resize:
- Handle window resize via process() input
- Call bgfx::reset() on size change
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create DebugOverlay class using bgfx debug text API
- Display FPS (color-coded: green >55, yellow >30, red <30)
- Show frame time, sprite count, draw calls
- Show GPU/CPU timing and texture stats from bgfx
- Add "debugOverlay" config option to enable at startup
- Smooth FPS display over 250ms intervals
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add TextureLoader class using stb_image for PNG/JPG/etc loading
- Integrate TextureLoader with ResourceCache for cached texture loading
- Add SpritePass::setTexture() for binding textures to sprites
- Add "defaultTexture" config option to load texture at startup
- Create assets/textures folder structure
- Add 1f440.png (eyes emoji) test texture
Visual test confirms textured sprites render correctly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add test_23_bgfx_sprites_visual.cpp: full visual test with SDL2 + IIO
- Fix IRHIDevice::init() to accept nativeDisplayHandle for X11/Linux
- Fix BgfxDevice::createBuffer() with proper VertexLayout for dynamic buffers
- Use double for native handle config values (preserves 64-bit pointers)
- Add debug logging in BgfxRendererModule initialization
Pipeline verified working:
- Module loads and initializes with Vulkan
- IIO messages routed correctly (sprites, camera, clear)
- SceneCollector collects and builds FramePacket
- RenderGraph executes passes
- ~500 FPS throughput
Note: Sprites not visually rendered yet (shader needs instancing support)
This will be addressed in a future phase.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Refactor ShaderManager to use RHI abstraction (no bgfx:: exposed)
- Implement Option E: inject ShaderHandle via pass constructors
- SpritePass/DebugPass now receive shader in constructor
- RenderPass::execute() takes IRHIDevice& for dynamic buffer updates
- SpritePass::execute() updates instance buffer from FramePacket
- Integrate ShaderManager lifecycle in BgfxRendererModule
- Add test_22_bgfx_sprites.cpp (visual test with SDL2)
- Add test_22_bgfx_sprites_headless.cpp (headless data structure test)
- Update PLAN_BGFX_RENDERER.md with Phase 4 completion and Phase 6.5
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>