mirror of
https://github.com/YACReader/yacreader
synced 2026-03-01 18:33:09 -05:00
Add an initial rhi implementation that mimics the opengl implementation
This commit is contained in:
287
common/rhi/README.md
Normal file
287
common/rhi/README.md
Normal file
@ -0,0 +1,287 @@
|
||||
# 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 shaders and compiled .qsb files
|
||||
- **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:
|
||||
- `QRhiBuffer` for vertices, instance data, and uniforms
|
||||
- `QRhiTexture` for cover images, marks, and default texture
|
||||
- `QRhiSampler` for texture filtering
|
||||
- `QRhiGraphicsPipeline` for render state
|
||||
- `QRhiShaderResourceBindings` for uniform/texture bindings
|
||||
|
||||
### Shader System
|
||||
|
||||
Shaders are written in **GLSL 4.50** and compiled to `.qsb` format 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:
|
||||
|
||||
```cpp
|
||||
#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)
|
||||
|
||||
```cpp
|
||||
// goto_flow_gl.cpp
|
||||
flow = new YACReaderPageFlowImpl(this);
|
||||
flow->setShowMarks(false);
|
||||
flow->populate(numPages);
|
||||
connect(flow, &YACReaderPageFlowImpl::selected, this, &GoToFlowGL::goToPage);
|
||||
```
|
||||
|
||||
### Example Usage (YACReaderLibrary)
|
||||
|
||||
```cpp
|
||||
// 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
|
||||
|
||||
1. **Qt 6.7 or later**
|
||||
2. **qsb tool** (Qt Shader Baker) in PATH
|
||||
3. **C++17 compiler**
|
||||
|
||||
### Compile Shaders
|
||||
|
||||
Before building YACReader, compile the shaders:
|
||||
|
||||
```bash
|
||||
cd common/rhi/shaders
|
||||
# Windows
|
||||
compile_shaders.bat
|
||||
|
||||
# Unix/macOS
|
||||
chmod +x compile_shaders.sh
|
||||
./compile_shaders.sh
|
||||
```
|
||||
|
||||
This generates `flow.vert.qsb` and `flow.frag.qsb` which are embedded via `shaders.qrc`.
|
||||
|
||||
### Build YACReader
|
||||
|
||||
The `.pro` files automatically include RHI sources for Qt 6.7+:
|
||||
|
||||
```bash
|
||||
qmake YACReader.pro
|
||||
make
|
||||
```
|
||||
|
||||
For Qt 5 builds, the OpenGL version is used automatically.
|
||||
|
||||
## 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):
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```cpp
|
||||
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
|
||||
|
||||
```cpp
|
||||
QRhi *rhi = flow->rhi();
|
||||
qDebug() << "Backend:" << rhi->backend();
|
||||
qDebug() << "Driver:" << rhi->driverInfo();
|
||||
```
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Problem**: Shaders fail to load
|
||||
**Solution**: Ensure `.qsb` files are compiled and included in resources
|
||||
|
||||
**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
|
||||
|
||||
1. **Qt Version**: Requires Qt 6.7+ (released April 2024)
|
||||
2. **QRhi Stability**: QRhi APIs may change in minor Qt releases
|
||||
3. **Mixed Renderers**: Only one graphics API per window
|
||||
4. **Shader Compilation**: Must recompile shaders when modifying source
|
||||
|
||||
## 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
|
||||
|
||||
- [QRhiWidget Class Documentation](https://doc.qt.io/qt-6/qrhiwidget.html)
|
||||
- [QRhi Overview](https://doc.qt.io/qt-6/qrhi.html)
|
||||
- [Qt RHI Examples](https://doc.qt.io/qt-6/qtwidgets-rhi-cuberhiwidget-example.html)
|
||||
- [Qt Shader Tools (qsb)](https://doc.qt.io/qt-6/qtshadertools-index.html)
|
||||
|
||||
## License
|
||||
|
||||
Same as YACReader project license.
|
||||
|
||||
## Author
|
||||
|
||||
Generated as part of the YACReader OpenGL modernization initiative.
|
||||
Reference in New Issue
Block a user