YACReader Flow RHI Implementation
This directory contains the QRhiWidget-based implementation of the YACReader 3D cover flow, providing cross-platform 3D rendering support for Qt 6.7+.
Overview
The RHI (Rendering Hardware Interface) implementation is a modern replacement for the OpenGL-based flow (yacreader_flow_gl) that:
- ✅ Supports multiple graphics APIs: Vulkan, Metal, Direct3D 11/12, OpenGL
- ✅ Provides native performance on modern platforms (Metal on macOS, D3D on Windows)
- ✅ Maintains 100% API compatibility with the OpenGL version
- ✅ Works seamlessly with Qt 6.7+ while Qt5 continues using OpenGL
- ✅ Enables future-proof rendering infrastructure
Architecture
Class Hierarchy
QRhiWidget (Qt base class)
└── YACReaderFlow3D (Base implementation)
├── YACReaderComicFlow3D (File path-based loading for library)
└── YACReaderPageFlow3D (Byte array-based loading for viewer)
Files
- yacreader_flow_rhi.h - Header with class definitions
- yacreader_flow_rhi.cpp - Implementation
- shaders/ - GLSL 450 shader source files (compiled to .qsb at build time by
qt_add_shaders) - README.md - This file
Key Features
Graphics Pipeline
The implementation uses:
- Instanced rendering for efficient batch drawing
- Dual-pass rendering (reflections + covers)
- MSAA (4x by default) for anti-aliasing
- Depth testing and back-face culling
- Alpha blending for transparency
Resource Management
QRhi resources managed:
QRhiBufferfor vertices, instance data, and uniformsQRhiTexturefor cover images, marks, and default textureQRhiSamplerfor texture filteringQRhiGraphicsPipelinefor render stateQRhiShaderResourceBindingsfor uniform/texture bindings
Shader System
Shaders are written in GLSL 4.50 and compiled to .qsb format at build time
via qt_add_shaders() in CMake, supporting:
- OpenGL ES 2.0, 3.0
- OpenGL 2.1, 3.0+
- HLSL (Direct3D 11/12)
- Metal Shading Language (macOS/iOS)
Integration
Qt5 vs Qt6 Selection
The build system automatically selects the appropriate implementation:
Qt 5.x: Uses YACReaderFlowGL (OpenGL-based)
Qt 6.0-6.6: Uses YACReaderFlowGL (OpenGL-based)
Qt 6.7+: Uses YACReaderFlow3D (RHI-based) if YACREADER_USE_RHI is defined
Type Aliases
Applications use type aliases for seamless switching:
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) && defined(YACREADER_USE_RHI)
using YACReaderPageFlowImpl = YACReaderPageFlow3D;
using YACReaderComicFlowImpl = YACReaderComicFlow3D;
#else
using YACReaderPageFlowImpl = YACReaderPageFlowGL;
using YACReaderComicFlowImpl = YACReaderComicFlowGL;
#endif
Example Usage (YACReader Viewer)
// goto_flow_gl.cpp
flow = new YACReaderPageFlowImpl(this);
flow->setShowMarks(false);
flow->populate(numPages);
connect(flow, &YACReaderPageFlowImpl::selected, this, &GoToFlowGL::goToPage);
Example Usage (YACReaderLibrary)
// comic_flow_widget.cpp
flow = new YACReaderComicFlowImpl(parent);
flow->setImagePaths(pathsList);
connect(flow, &YACReaderComicFlowImpl::centerIndexChanged,
this, &ComicFlowWidget::centerIndexChanged);
API Compatibility
All public methods from YACReaderFlowGL are preserved:
Navigation
showPrevious(),showNext()setCurrentIndex(int),setCenterIndex(unsigned int)showSlide(int),centerIndex()
Configuration
setPreset(const Preset &)setPerformance(Performance)setFlowRightToLeft(bool)setZoom(int),setRotation(int)setCF_RX/RY/RZ(int),setCF_Y/Z(int)setX_Distance(int),setCenter_Distance(int), etc.
Appearance
setBackgroundColor(const QColor &)setTextColor(const QColor &)setShadingColor(const QColor &)setShowMarks(bool),setMarks(QVector<...>)
Content Management
populate(int),clear(),reset(),reload()insert(),remove(int),add(int),replace()- Subclass-specific:
setImagePaths(),resortCovers(), etc.
Building
Prerequisites
- Qt 6.7 or later (with ShaderTools module)
- CMake 3.25+
- C++20 compiler
Build YACReader
Shaders are compiled automatically at build time via qt_add_shaders():
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
No manual shader compilation step is needed.
Graphics API Selection
QRhiWidget auto-selects the best API per platform:
- macOS/iOS: Metal (native)
- Windows: Direct3D 11 (default) or Direct3D 12
- Linux: Vulkan or OpenGL
- Android: OpenGL ES 3.0 or Vulkan
You can force a specific API via environment variables (for testing):
# Force OpenGL
export QSG_RHI_BACKEND=opengl
# Force Vulkan
export QSG_RHI_BACKEND=vulkan
# Force Direct3D 11 (Windows)
set QSG_RHI_BACKEND=d3d11
Performance
Performance tiers match the OpenGL version:
- Low: 8 covers loaded, 128px textures (page flow) / 200px (comic flow)
- Medium: 10 covers, 196px / 256px textures
- High: 12 covers, 256px / 320px textures
- Ultra High: 14-16 covers, full resolution textures
Texture loading happens asynchronously via worker threads (ImageLoader3D, ImageLoaderByteArray3D).
Debugging
Enable Validation Layers
For debugging graphics issues, enable validation:
flow->setDebugLayerEnabled(true); // Call before widget is shown
This activates:
- Vulkan: VK_LAYER_KHRONOS_validation
- Direct3D: D3D11 debug layer
- Metal: Metal API validation
Check Active Graphics API
QRhi *rhi = flow->rhi();
qDebug() << "Backend:" << rhi->backend();
qDebug() << "Driver:" << rhi->driverInfo();
Common Issues
Problem: Shaders fail to load
Solution: Ensure Qt ShaderTools module is installed and qt_add_shaders() ran during build
Problem: Black screen on Qt 6.7
Solution: Check if YACREADER_USE_RHI is defined in build
Problem: Crashes on resize/reparent
Solution: releaseResources() properly cleans up all QRhi objects
Migration from OpenGL
The RHI version is a drop-in replacement requiring no application code changes beyond the build system.
What's Different (Internal)
| OpenGL API | QRhi Equivalent |
|---|---|
glDrawArraysInstanced() |
cb->drawIndexed(instanceCount) |
glUniform*() |
Update QRhiBuffer with uniform data |
glBindTexture() |
QRhiShaderResourceBindings |
glBlendFunc() |
QRhiGraphicsPipeline::setTargetBlends() |
glEnable(GL_DEPTH_TEST) |
pipeline->setDepthTest(true) |
What's the Same
- All public API methods and signatures
- Animation system and timing
- Preset configurations
- Event handling (mouse, keyboard, wheel)
- Worker thread texture loading
- Performance tiers
Known Limitations
- Qt Version: Requires Qt 6.7+ (released April 2024)
- QRhi Stability: QRhi APIs may change in minor Qt releases
- Mixed Renderers: Only one graphics API per window
- Shader Compilation: Shaders are recompiled automatically when source files change
Future Improvements
Potential enhancements:
- GPU-side frustum culling
- Compute shader for texture generation
- HDR/wide color gamut support
- Ray-traced reflections (via RHI compute)
- Dynamic LOD based on distance
References
License
Same as YACReader project license.
Author
Generated as part of the YACReader OpenGL modernization initiative.