Compare commits
4 Commits
e8b9571d25
...
fd9c1c89e6
| Author | SHA1 | Date |
|---|---|---|
|
|
fd9c1c89e6 | |
|
|
4b04a1adf7 | |
|
|
96a744bde0 | |
|
|
25e6159176 |
|
|
@ -60,6 +60,15 @@ endif()
|
||||||
|
|
||||||
find_package(Qt5 REQUIRED COMPONENTS ${QT_COMPONENTS})
|
find_package(Qt5 REQUIRED COMPONENTS ${QT_COMPONENTS})
|
||||||
|
|
||||||
|
# FreeType support (for text rendering in Vulkan)
|
||||||
|
find_package(Freetype)
|
||||||
|
if(FREETYPE_FOUND)
|
||||||
|
message(STATUS "FreeType found: ${FREETYPE_LIBRARIES}")
|
||||||
|
message(STATUS "FreeType include: ${FREETYPE_INCLUDE_DIRS}")
|
||||||
|
else()
|
||||||
|
message(WARNING "FreeType not found, text rendering may be limited")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Vulkan support (optional) - only headers needed, volk loads dynamically
|
# Vulkan support (optional) - only headers needed, volk loads dynamically
|
||||||
option(ENABLE_VULKAN "Enable Vulkan support" ON)
|
option(ENABLE_VULKAN "Enable Vulkan support" ON)
|
||||||
set(VULKAN_FOUND FALSE)
|
set(VULKAN_FOUND FALSE)
|
||||||
|
|
@ -190,6 +199,13 @@ if(VULKAN_FOUND)
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
volk
|
volk
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Add FreeType support for text rendering in Vulkan
|
||||||
|
if(FREETYPE_FOUND)
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE ${FREETYPE_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${FREETYPE_LIBRARIES})
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_FREETYPE)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Platform-specific linking
|
# Platform-specific linking
|
||||||
|
|
@ -235,6 +251,12 @@ if(VULKAN_FOUND)
|
||||||
message(STATUS "Vulkan headers: ${VULKAN_HEADERS_DIR}")
|
message(STATUS "Vulkan headers: ${VULKAN_HEADERS_DIR}")
|
||||||
message(STATUS "Volk directory: ${VOLK_DIR}")
|
message(STATUS "Volk directory: ${VOLK_DIR}")
|
||||||
message(STATUS "Note: No Vulkan library linking - volk loads dynamically at runtime")
|
message(STATUS "Note: No Vulkan library linking - volk loads dynamically at runtime")
|
||||||
|
if(FREETYPE_FOUND)
|
||||||
|
message(STATUS "FreeType support: ENABLED (for text rendering)")
|
||||||
|
message(STATUS "FreeType libraries: ${FREETYPE_LIBRARIES}")
|
||||||
|
else()
|
||||||
|
message(STATUS "FreeType support: DISABLED")
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
message(STATUS "Vulkan support: DISABLED")
|
message(STATUS "Vulkan support: DISABLED")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
# Text Rendering Implementation in VulkanWidget
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This document describes the text rendering implementation added to the VulkanWidget using FreeType library.
|
||||||
|
|
||||||
|
## Features Implemented
|
||||||
|
|
||||||
|
### 1. FreeType Integration
|
||||||
|
|
||||||
|
- **Library**: Uses system libfreetype.a (found at `/usr/local/lib/libfreetype.a`)
|
||||||
|
- **Font Loading**: Automatically searches common font paths:
|
||||||
|
- `/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf`
|
||||||
|
- `/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf`
|
||||||
|
- `/usr/share/fonts/TTF/DejaVuSans.ttf`
|
||||||
|
- `/System/Library/Fonts/Helvetica.ttc` (macOS)
|
||||||
|
- `/usr/local/share/fonts/DejaVuSans.ttf`
|
||||||
|
|
||||||
|
### 2. Font Atlas Generation
|
||||||
|
|
||||||
|
- **Size**: 512x512 texture atlas
|
||||||
|
- **Character Range**: ASCII 32-126 (95 printable characters)
|
||||||
|
- **Format**: Single-channel R8_UNORM texture
|
||||||
|
- **Packing**: Automatic row-based packing with 1-pixel padding
|
||||||
|
- **Storage**: CharInfo map stores texture coordinates, size, bearing, and advance for each character
|
||||||
|
|
||||||
|
### 3. Text Rendering Pipeline
|
||||||
|
|
||||||
|
- **Shaders**:
|
||||||
|
- `text.vert` - Converts pixel coordinates to NDC
|
||||||
|
- `text.frag` - Samples font atlas with alpha blending
|
||||||
|
- **Blending**: Alpha blending enabled for smooth text rendering
|
||||||
|
- **Descriptors**:
|
||||||
|
- Binding 0: Uniform Buffer (time, resolution, rotation, wavePhase)
|
||||||
|
- Binding 1: Font texture sampler
|
||||||
|
|
||||||
|
### 4. Text Content (Matching CustomWidget)
|
||||||
|
|
||||||
|
The text rendering displays the same information as CustomWidget:
|
||||||
|
|
||||||
|
#### Active State:
|
||||||
|
- **Title**: "Screen Lock Detector - Painting Active" (top center, white, scale 0.8)
|
||||||
|
- **Statistics Box** (top left, green, scale 0.6):
|
||||||
|
- Frame Count
|
||||||
|
- FPS: ~60
|
||||||
|
- Rotation angle
|
||||||
|
- Running Time
|
||||||
|
- **Lock Info Box** (below stats, magenta, scale 0.65/0.5):
|
||||||
|
- Last Lock Info title
|
||||||
|
- Lock time
|
||||||
|
- Duration
|
||||||
|
- Frame count at lock
|
||||||
|
- Total locks
|
||||||
|
- **Hint**: "Lock your screen..." (bottom center, yellow, scale 0.65)
|
||||||
|
|
||||||
|
#### Locked State:
|
||||||
|
- **Title**: "PAINTING DISABLED" (center, white, scale 1.2)
|
||||||
|
- **Subtitle**: "(Screen Locked)" (center, gray, scale 0.9)
|
||||||
|
- **Stats**: Total frames painted (bottom left, gray, scale 0.7)
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
### Code Structure
|
||||||
|
|
||||||
|
1. **VulkanRenderer::initializeTextRendering()**
|
||||||
|
- Initializes FreeType library
|
||||||
|
- Loads font face
|
||||||
|
- Generates character glyphs
|
||||||
|
- Creates font texture atlas
|
||||||
|
- Sets up Vulkan image, image view, and sampler
|
||||||
|
|
||||||
|
2. **VulkanRenderer::createTextPipeline()**
|
||||||
|
- Loads text vertex and fragment shaders
|
||||||
|
- Sets up vertex input (position, color, texCoord)
|
||||||
|
- Configures alpha blending
|
||||||
|
- Creates descriptor set layout with texture sampler
|
||||||
|
- Builds graphics pipeline
|
||||||
|
|
||||||
|
3. **VulkanRenderer::generateTextQuads()**
|
||||||
|
- Converts text string to quad vertices
|
||||||
|
- Handles newlines
|
||||||
|
- Uses pixel coordinates (shader converts to NDC)
|
||||||
|
- Sets texture coordinates from CharInfo map
|
||||||
|
- Applies scale and color
|
||||||
|
|
||||||
|
4. **VulkanRenderer::drawText()**
|
||||||
|
- Binds text pipeline
|
||||||
|
- Binds descriptor sets (UBO + font texture)
|
||||||
|
- Generates text quads based on painting state
|
||||||
|
- Creates temporary vertex/index buffers
|
||||||
|
- Issues draw calls
|
||||||
|
|
||||||
|
### Coordinate System
|
||||||
|
|
||||||
|
- **Input**: Pixel coordinates (0,0 = top-left, width,height = bottom-right)
|
||||||
|
- **Shader**: Converts to NDC (-1,-1 = bottom-left, 1,1 = top-right)
|
||||||
|
- **Y-axis**: Flipped in shader (Vulkan Y-down → traditional Y-up)
|
||||||
|
|
||||||
|
### Resource Management
|
||||||
|
|
||||||
|
- Font texture and sampler are persistent (created once)
|
||||||
|
- Text vertex/index buffers are recreated each frame (using static variables)
|
||||||
|
- Old buffers are destroyed before creating new ones
|
||||||
|
- Descriptor sets are updated after text rendering initialization
|
||||||
|
|
||||||
|
## CMake Configuration
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
# FreeType support (for text rendering in Vulkan)
|
||||||
|
find_package(Freetype)
|
||||||
|
if(FREETYPE_FOUND)
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE ${FREETYPE_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${FREETYPE_LIBRARIES})
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_FREETYPE)
|
||||||
|
endif()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
Debug output is enabled every ~5 seconds (300 frames):
|
||||||
|
|
||||||
|
```
|
||||||
|
Initializing text rendering with FreeType...
|
||||||
|
Text rendering initialized successfully with 95 characters
|
||||||
|
Font texture: OK
|
||||||
|
Font texture view: OK
|
||||||
|
Font sampler: OK
|
||||||
|
Creating text pipeline...
|
||||||
|
Text pipeline created successfully
|
||||||
|
Updating descriptor sets with font texture...
|
||||||
|
Descriptor sets updated with font texture
|
||||||
|
|
||||||
|
drawText called: charMap=95 pipeline=OK fontTexView=OK
|
||||||
|
Drawing text with 572 vertices, 858 indices
|
||||||
|
Window size: 756x425
|
||||||
|
First vertex pos: (30.4, 1.2)
|
||||||
|
First vertex color: (1, 1, 1, 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Known Issues and Future Improvements
|
||||||
|
|
||||||
|
### Current Limitations:
|
||||||
|
1. Text buffers are recreated every frame (performance impact)
|
||||||
|
2. No text caching or batching
|
||||||
|
3. Limited to ASCII characters only
|
||||||
|
4. Fixed font size (48pt base)
|
||||||
|
|
||||||
|
### Potential Improvements:
|
||||||
|
1. Implement text buffer caching for static text
|
||||||
|
2. Add support for Unicode/UTF-8
|
||||||
|
3. Multiple font sizes/styles
|
||||||
|
4. Text layout system (word wrapping, alignment)
|
||||||
|
5. Better memory management for text resources
|
||||||
|
6. Dynamic font atlas resizing
|
||||||
|
7. SDF (Signed Distance Field) rendering for scalable text
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
To verify text rendering:
|
||||||
|
|
||||||
|
1. Build project: `./build.sh`
|
||||||
|
2. Run application: `./run.sh`
|
||||||
|
3. Check console for text rendering initialization messages
|
||||||
|
4. Verify text appears on screen matching CustomWidget layout
|
||||||
|
5. Lock screen to test state changes
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- FreeType 2.x
|
||||||
|
- Vulkan 1.x
|
||||||
|
- Volk (for Vulkan function loading)
|
||||||
|
- Qt 5.15.x (for window management)
|
||||||
|
|
||||||
|
## Files Modified
|
||||||
|
|
||||||
|
- `CMakeLists.txt` - Added FreeType support
|
||||||
|
- `src/vulkanrenderer.h` - Added text rendering declarations
|
||||||
|
- `src/vulkanrenderer.cpp` - Implemented text rendering functions
|
||||||
|
- `shaders/text.vert` - Text vertex shader
|
||||||
|
- `shaders/text.frag` - Text fragment shader
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- FreeType Documentation: https://freetype.org/freetype2/docs/
|
||||||
|
- Vulkan Text Rendering: https://learnopengl.com/In-Practice/Text-Rendering
|
||||||
|
- Font Atlas Generation: https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_02
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
echo "Text Rendering Diagnostic Script"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if FreeType is installed
|
||||||
|
echo "1. Checking FreeType installation..."
|
||||||
|
if pkg-config --exists freetype2; then
|
||||||
|
echo " ✓ FreeType found:"
|
||||||
|
pkg-config --modversion freetype2
|
||||||
|
echo " Library: $(pkg-config --variable=libdir freetype2)/libfreetype.a"
|
||||||
|
echo " Include: $(pkg-config --cflags freetype2)"
|
||||||
|
else
|
||||||
|
echo " ✗ FreeType not found via pkg-config"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for font files
|
||||||
|
echo "2. Checking available fonts..."
|
||||||
|
FONTS=(
|
||||||
|
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
|
||||||
|
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf"
|
||||||
|
"/usr/share/fonts/TTF/DejaVuSans.ttf"
|
||||||
|
"/usr/local/share/fonts/DejaVuSans.ttf"
|
||||||
|
)
|
||||||
|
|
||||||
|
FOUND_FONT=false
|
||||||
|
for font in "${FONTS[@]}"; do
|
||||||
|
if [ -f "$font" ]; then
|
||||||
|
echo " ✓ Found: $font"
|
||||||
|
FOUND_FONT=true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$FOUND_FONT" = false ]; then
|
||||||
|
echo " ✗ No fonts found in standard locations"
|
||||||
|
echo " Installing DejaVu fonts might help:"
|
||||||
|
echo " sudo apt-get install fonts-dejavu-core"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if shaders are compiled
|
||||||
|
echo "3. Checking text shaders..."
|
||||||
|
if [ -f "src/shaders_spirv/text.vert.spv" ]; then
|
||||||
|
echo " ✓ text.vert.spv exists"
|
||||||
|
else
|
||||||
|
echo " ✗ text.vert.spv missing"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "src/shaders_spirv/text.frag.spv" ]; then
|
||||||
|
echo " ✓ text.frag.spv exists"
|
||||||
|
else
|
||||||
|
echo " ✗ text.frag.spv missing"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "src/shaders_spirv/text_vert.inc" ]; then
|
||||||
|
echo " ✓ text_vert.inc exists"
|
||||||
|
else
|
||||||
|
echo " ✗ text_vert.inc missing"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "src/shaders_spirv/text_frag.inc" ]; then
|
||||||
|
echo " ✓ text_frag.inc exists"
|
||||||
|
else
|
||||||
|
echo " ✗ text_frag.inc missing"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check build configuration
|
||||||
|
echo "4. Checking build configuration..."
|
||||||
|
if [ -f "build/CMakeCache.txt" ]; then
|
||||||
|
if grep -q "ENABLE_FREETYPE" build/CMakeCache.txt 2>/dev/null; then
|
||||||
|
echo " ✓ ENABLE_FREETYPE is defined"
|
||||||
|
else
|
||||||
|
echo " ✗ ENABLE_FREETYPE not found in build"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q "FREETYPE_LIBRARY" build/CMakeCache.txt 2>/dev/null; then
|
||||||
|
FREETYPE_LIB=$(grep "FREETYPE_LIBRARY" build/CMakeCache.txt | cut -d= -f2)
|
||||||
|
echo " ✓ FreeType library linked: $FREETYPE_LIB"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ⚠ Build directory not found - run ./build.sh first"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if executable exists and has FreeType symbols
|
||||||
|
echo "5. Checking executable..."
|
||||||
|
if [ -f "build/bin/ScreenLockDetector" ]; then
|
||||||
|
echo " ✓ Executable exists"
|
||||||
|
|
||||||
|
# Check for FreeType symbols
|
||||||
|
if nm build/bin/ScreenLockDetector 2>/dev/null | grep -q "FT_Init_FreeType"; then
|
||||||
|
echo " ✓ FreeType symbols found in executable"
|
||||||
|
else
|
||||||
|
echo " ⚠ FreeType symbols not found (might be dynamically linked)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for Vulkan symbols
|
||||||
|
if nm build/bin/ScreenLockDetector 2>/dev/null | grep -q "vkCreateGraphicsPipeline"; then
|
||||||
|
echo " ✓ Vulkan symbols found"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✗ Executable not found - build first with ./build.sh"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Run the application with text rendering debug output
|
||||||
|
echo "6. Testing text rendering (5 seconds)..."
|
||||||
|
echo " Starting application..."
|
||||||
|
if [ -f "build/bin/ScreenLockDetector" ]; then
|
||||||
|
timeout 5 ./run.sh 2>&1 | grep -E "Text|text|Font|font|FreeType|pipeline|charMap|Drawing text" | head -20
|
||||||
|
echo ""
|
||||||
|
echo " If you see 'Drawing text with X vertices' above, text rendering is working!"
|
||||||
|
else
|
||||||
|
echo " ✗ Cannot test - executable not found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
echo "========================================"
|
||||||
|
echo "Summary"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
echo "Text rendering requires:"
|
||||||
|
echo " 1. FreeType library installed ✓"
|
||||||
|
echo " 2. At least one font file available"
|
||||||
|
echo " 3. Text shaders compiled (text.vert/frag.spv)"
|
||||||
|
echo " 4. ENABLE_FREETYPE defined in build"
|
||||||
|
echo " 5. Application successfully initializes text pipeline"
|
||||||
|
echo ""
|
||||||
|
echo "If text is not visible but pipeline is created:"
|
||||||
|
echo " - Check shader coordinate system"
|
||||||
|
echo " - Verify alpha blending is enabled"
|
||||||
|
echo " - Ensure text color contrasts with background"
|
||||||
|
echo " - Check if text is positioned within viewport"
|
||||||
|
echo ""
|
||||||
|
echo "For more details, see: TEXT_RENDERING.md"
|
||||||
|
echo "========================================"
|
||||||
|
|
@ -20,13 +20,13 @@ void main() {
|
||||||
// Create dynamic gradient based on time
|
// Create dynamic gradient based on time
|
||||||
float t = ubo.time / 360.0;
|
float t = ubo.time / 360.0;
|
||||||
|
|
||||||
// Calculate color components with sine waves
|
// Calculate color components matching Qt CustomWidget
|
||||||
float r = 0.39 + 0.20 * sin(t * 6.28318);
|
float r = 0.392 + 0.196 * sin(t * 6.28318);
|
||||||
float g = 0.59 + 0.20 * sin(t * 6.28318 + 1.047);
|
float g = 0.588 + 0.196 * sin(t * 6.28318 + 1.047);
|
||||||
float b = 0.78 + 0.22 * sin(t * 6.28318 + 2.094);
|
float b = 0.784 + 0.216 * sin(t * 6.28318 + 2.094);
|
||||||
|
|
||||||
vec3 color1 = vec3(r, g, b);
|
vec3 color1 = vec3(r, g, b);
|
||||||
vec3 color2 = vec3(0.12, 0.12, 0.24);
|
vec3 color2 = vec3(0.118, 0.118, 0.235);
|
||||||
|
|
||||||
// Linear gradient from top-left to bottom-right
|
// Linear gradient from top-left to bottom-right
|
||||||
float gradient = uv.x * 0.5 + uv.y * 0.5;
|
float gradient = uv.x * 0.5 + uv.y * 0.5;
|
||||||
|
|
|
||||||
|
|
@ -7,24 +7,30 @@ layout(location = 2) in vec2 inTexCoord;
|
||||||
layout(location = 0) out vec4 fragColor;
|
layout(location = 0) out vec4 fragColor;
|
||||||
layout(location = 1) out vec2 fragTexCoord;
|
layout(location = 1) out vec2 fragTexCoord;
|
||||||
|
|
||||||
layout(binding = 0) uniform UniformBufferObject {
|
// Use std140 layout and separate floats instead of vec2 to avoid alignment issues
|
||||||
float time;
|
layout(binding = 0, std140) uniform UniformBufferObject {
|
||||||
vec2 resolution;
|
float time; // offset 0
|
||||||
float rotation;
|
float resX; // offset 4
|
||||||
float wavePhase;
|
float resY; // offset 8
|
||||||
|
float rotation; // offset 12
|
||||||
|
float wavePhase; // offset 16
|
||||||
|
float padding1; // offset 20
|
||||||
|
float padding2; // offset 24
|
||||||
} ubo;
|
} ubo;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Transform position from pixel coordinates to normalized device coordinates
|
// Input position is in pixel coordinates (0,0 = top-left)
|
||||||
vec2 pos = inPosition;
|
vec2 pos = inPosition;
|
||||||
|
|
||||||
// Convert to NDC: (0, 0) to (width, height) -> (-1, -1) to (1, 1)
|
// Convert to NDC: (0, 0) to (width, height) -> (-1, -1) to (1, 1)
|
||||||
vec2 ndc = (pos / ubo.resolution) * 2.0 - 1.0;
|
// Note: Vulkan NDC has Y pointing down, but we want traditional Y-up
|
||||||
|
float ndcX = (pos.x / ubo.resX) * 2.0 - 1.0;
|
||||||
|
float ndcY = (pos.y / ubo.resY) * 2.0 - 1.0;
|
||||||
|
|
||||||
// Flip Y axis (Vulkan has Y down, we want Y up for easier math)
|
// NO Y-flip needed here - text coordinates are already in screen space
|
||||||
ndc.y = -ndc.y;
|
// where (0,0) is top-left, which matches Vulkan's framebuffer coordinates
|
||||||
|
gl_Position = vec4(ndcX, ndcY, 0.0, 1.0);
|
||||||
|
|
||||||
gl_Position = vec4(ndc, 0.0, 1.0);
|
|
||||||
fragColor = inColor;
|
fragColor = inColor;
|
||||||
fragTexCoord = inTexCoord;
|
fragTexCoord = inTexCoord;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -29,13 +29,13 @@
|
||||||
0x00000006u, 0x00000007u, 0x00000006u, 0x00000006u, 0x00040020u, 0x00000015u, 0x00000002u, 0x00000014u,
|
0x00000006u, 0x00000007u, 0x00000006u, 0x00000006u, 0x00040020u, 0x00000015u, 0x00000002u, 0x00000014u,
|
||||||
0x0004003bu, 0x00000015u, 0x00000016u, 0x00000002u, 0x00040015u, 0x00000017u, 0x00000020u, 0x00000001u,
|
0x0004003bu, 0x00000015u, 0x00000016u, 0x00000002u, 0x00040015u, 0x00000017u, 0x00000020u, 0x00000001u,
|
||||||
0x0004002bu, 0x00000017u, 0x00000018u, 0x00000000u, 0x00040020u, 0x00000019u, 0x00000002u, 0x00000006u,
|
0x0004002bu, 0x00000017u, 0x00000018u, 0x00000000u, 0x00040020u, 0x00000019u, 0x00000002u, 0x00000006u,
|
||||||
0x0004002bu, 0x00000006u, 0x0000001cu, 0x43b40000u, 0x0004002bu, 0x00000006u, 0x0000001fu, 0x3ec7ae14u,
|
0x0004002bu, 0x00000006u, 0x0000001cu, 0x43b40000u, 0x0004002bu, 0x00000006u, 0x0000001fu, 0x3ec8b439u,
|
||||||
0x0004002bu, 0x00000006u, 0x00000020u, 0x3e4ccccdu, 0x0004002bu, 0x00000006u, 0x00000022u, 0x40c90fd0u,
|
0x0004002bu, 0x00000006u, 0x00000020u, 0x3e48b439u, 0x0004002bu, 0x00000006u, 0x00000022u, 0x40c90fd0u,
|
||||||
0x0004002bu, 0x00000006u, 0x00000028u, 0x3f170a3du, 0x0004002bu, 0x00000006u, 0x0000002bu, 0x3f860419u,
|
0x0004002bu, 0x00000006u, 0x00000028u, 0x3f16872bu, 0x0004002bu, 0x00000006u, 0x0000002bu, 0x3f860419u,
|
||||||
0x0004002bu, 0x00000006u, 0x00000031u, 0x3f47ae14u, 0x0004002bu, 0x00000006u, 0x00000032u, 0x3e6147aeu,
|
0x0004002bu, 0x00000006u, 0x00000031u, 0x3f48b439u, 0x0004002bu, 0x00000006u, 0x00000032u, 0x3e5d2f1bu,
|
||||||
0x0004002bu, 0x00000006u, 0x00000035u, 0x40060419u, 0x00040017u, 0x0000003au, 0x00000006u, 0x00000003u,
|
0x0004002bu, 0x00000006u, 0x00000035u, 0x40060419u, 0x00040017u, 0x0000003au, 0x00000006u, 0x00000003u,
|
||||||
0x00040020u, 0x0000003bu, 0x00000007u, 0x0000003au, 0x0004002bu, 0x00000006u, 0x00000042u, 0x3df5c28fu,
|
0x00040020u, 0x0000003bu, 0x00000007u, 0x0000003au, 0x0004002bu, 0x00000006u, 0x00000042u, 0x3df1a9fcu,
|
||||||
0x0004002bu, 0x00000006u, 0x00000043u, 0x3e75c28fu, 0x0006002cu, 0x0000003au, 0x00000044u, 0x00000042u,
|
0x0004002bu, 0x00000006u, 0x00000043u, 0x3e70a3d7u, 0x0006002cu, 0x0000003au, 0x00000044u, 0x00000042u,
|
||||||
0x00000042u, 0x00000043u, 0x00040015u, 0x00000046u, 0x00000020u, 0x00000000u, 0x0004002bu, 0x00000046u,
|
0x00000042u, 0x00000043u, 0x00040015u, 0x00000046u, 0x00000020u, 0x00000000u, 0x0004002bu, 0x00000046u,
|
||||||
0x00000047u, 0x00000000u, 0x0004002bu, 0x00000046u, 0x0000004bu, 0x00000001u, 0x00040017u, 0x00000056u,
|
0x00000047u, 0x00000000u, 0x0004002bu, 0x00000046u, 0x0000004bu, 0x00000001u, 0x00040017u, 0x00000056u,
|
||||||
0x00000006u, 0x00000004u, 0x00040020u, 0x00000057u, 0x00000003u, 0x00000056u, 0x0004003bu, 0x00000057u,
|
0x00000006u, 0x00000004u, 0x00040020u, 0x00000057u, 0x00000003u, 0x00000056u, 0x0004003bu, 0x00000057u,
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,60 +1,67 @@
|
||||||
// Auto-generated from text.vert.spv
|
// Auto-generated from text.vert.spv
|
||||||
// Size: 1840 bytes (460 words)
|
// Size: 2080 bytes (520 words)
|
||||||
0x07230203u, 0x00010000u, 0x0008000bu, 0x00000039u, 0x00000000u, 0x00020011u, 0x00000001u, 0x0006000bu,
|
0x07230203u, 0x00010000u, 0x0008000bu, 0x0000003eu, 0x00000000u, 0x00020011u, 0x00000001u, 0x0006000bu,
|
||||||
0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u,
|
0x00000001u, 0x4c534c47u, 0x6474732eu, 0x3035342eu, 0x00000000u, 0x0003000eu, 0x00000000u, 0x00000001u,
|
||||||
0x000b000fu, 0x00000000u, 0x00000004u, 0x6e69616du, 0x00000000u, 0x0000000bu, 0x00000028u, 0x00000031u,
|
0x000b000fu, 0x00000000u, 0x00000004u, 0x6e69616du, 0x00000000u, 0x0000000bu, 0x0000002eu, 0x00000036u,
|
||||||
0x00000033u, 0x00000036u, 0x00000037u, 0x00030003u, 0x00000002u, 0x000001c2u, 0x00040005u, 0x00000004u,
|
0x00000038u, 0x0000003bu, 0x0000003cu, 0x00030003u, 0x00000002u, 0x000001c2u, 0x00040005u, 0x00000004u,
|
||||||
0x6e69616du, 0x00000000u, 0x00030005u, 0x00000009u, 0x00736f70u, 0x00050005u, 0x0000000bu, 0x6f506e69u,
|
0x6e69616du, 0x00000000u, 0x00030005u, 0x00000009u, 0x00736f70u, 0x00050005u, 0x0000000bu, 0x6f506e69u,
|
||||||
0x69746973u, 0x00006e6fu, 0x00030005u, 0x0000000du, 0x0063646eu, 0x00070005u, 0x0000000fu, 0x66696e55u,
|
0x69746973u, 0x00006e6fu, 0x00040005u, 0x0000000eu, 0x5863646eu, 0x00000000u, 0x00070005u, 0x00000013u,
|
||||||
0x426d726fu, 0x65666675u, 0x6a624f72u, 0x00746365u, 0x00050006u, 0x0000000fu, 0x00000000u, 0x656d6974u,
|
0x66696e55u, 0x426d726fu, 0x65666675u, 0x6a624f72u, 0x00746365u, 0x00050006u, 0x00000013u, 0x00000000u,
|
||||||
0x00000000u, 0x00060006u, 0x0000000fu, 0x00000001u, 0x6f736572u, 0x6974756cu, 0x00006e6fu, 0x00060006u,
|
0x656d6974u, 0x00000000u, 0x00050006u, 0x00000013u, 0x00000001u, 0x58736572u, 0x00000000u, 0x00050006u,
|
||||||
0x0000000fu, 0x00000002u, 0x61746f72u, 0x6e6f6974u, 0x00000000u, 0x00060006u, 0x0000000fu, 0x00000003u,
|
0x00000013u, 0x00000002u, 0x59736572u, 0x00000000u, 0x00060006u, 0x00000013u, 0x00000003u, 0x61746f72u,
|
||||||
0x65766177u, 0x73616850u, 0x00000065u, 0x00030005u, 0x00000011u, 0x006f6275u, 0x00060005u, 0x00000026u,
|
0x6e6f6974u, 0x00000000u, 0x00060006u, 0x00000013u, 0x00000004u, 0x65766177u, 0x73616850u, 0x00000065u,
|
||||||
0x505f6c67u, 0x65567265u, 0x78657472u, 0x00000000u, 0x00060006u, 0x00000026u, 0x00000000u, 0x505f6c67u,
|
0x00060006u, 0x00000013u, 0x00000005u, 0x64646170u, 0x31676e69u, 0x00000000u, 0x00060006u, 0x00000013u,
|
||||||
0x7469736fu, 0x006e6f69u, 0x00070006u, 0x00000026u, 0x00000001u, 0x505f6c67u, 0x746e696fu, 0x657a6953u,
|
0x00000006u, 0x64646170u, 0x32676e69u, 0x00000000u, 0x00030005u, 0x00000015u, 0x006f6275u, 0x00040005u,
|
||||||
0x00000000u, 0x00070006u, 0x00000026u, 0x00000002u, 0x435f6c67u, 0x4470696cu, 0x61747369u, 0x0065636eu,
|
0x00000020u, 0x5963646eu, 0x00000000u, 0x00060005u, 0x0000002cu, 0x505f6c67u, 0x65567265u, 0x78657472u,
|
||||||
0x00070006u, 0x00000026u, 0x00000003u, 0x435f6c67u, 0x446c6c75u, 0x61747369u, 0x0065636eu, 0x00030005u,
|
0x00000000u, 0x00060006u, 0x0000002cu, 0x00000000u, 0x505f6c67u, 0x7469736fu, 0x006e6f69u, 0x00070006u,
|
||||||
0x00000028u, 0x00000000u, 0x00050005u, 0x00000031u, 0x67617266u, 0x6f6c6f43u, 0x00000072u, 0x00040005u,
|
0x0000002cu, 0x00000001u, 0x505f6c67u, 0x746e696fu, 0x657a6953u, 0x00000000u, 0x00070006u, 0x0000002cu,
|
||||||
0x00000033u, 0x6f436e69u, 0x00726f6cu, 0x00060005u, 0x00000036u, 0x67617266u, 0x43786554u, 0x64726f6fu,
|
0x00000002u, 0x435f6c67u, 0x4470696cu, 0x61747369u, 0x0065636eu, 0x00070006u, 0x0000002cu, 0x00000003u,
|
||||||
0x00000000u, 0x00050005u, 0x00000037u, 0x65546e69u, 0x6f6f4378u, 0x00006472u, 0x00040047u, 0x0000000bu,
|
0x435f6c67u, 0x446c6c75u, 0x61747369u, 0x0065636eu, 0x00030005u, 0x0000002eu, 0x00000000u, 0x00050005u,
|
||||||
0x0000001eu, 0x00000000u, 0x00050048u, 0x0000000fu, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u,
|
0x00000036u, 0x67617266u, 0x6f6c6f43u, 0x00000072u, 0x00040005u, 0x00000038u, 0x6f436e69u, 0x00726f6cu,
|
||||||
0x0000000fu, 0x00000001u, 0x00000023u, 0x00000008u, 0x00050048u, 0x0000000fu, 0x00000002u, 0x00000023u,
|
0x00060005u, 0x0000003bu, 0x67617266u, 0x43786554u, 0x64726f6fu, 0x00000000u, 0x00050005u, 0x0000003cu,
|
||||||
0x00000010u, 0x00050048u, 0x0000000fu, 0x00000003u, 0x00000023u, 0x00000014u, 0x00030047u, 0x0000000fu,
|
0x65546e69u, 0x6f6f4378u, 0x00006472u, 0x00040047u, 0x0000000bu, 0x0000001eu, 0x00000000u, 0x00050048u,
|
||||||
0x00000002u, 0x00040047u, 0x00000011u, 0x00000022u, 0x00000000u, 0x00040047u, 0x00000011u, 0x00000021u,
|
0x00000013u, 0x00000000u, 0x00000023u, 0x00000000u, 0x00050048u, 0x00000013u, 0x00000001u, 0x00000023u,
|
||||||
0x00000000u, 0x00050048u, 0x00000026u, 0x00000000u, 0x0000000bu, 0x00000000u, 0x00050048u, 0x00000026u,
|
0x00000004u, 0x00050048u, 0x00000013u, 0x00000002u, 0x00000023u, 0x00000008u, 0x00050048u, 0x00000013u,
|
||||||
0x00000001u, 0x0000000bu, 0x00000001u, 0x00050048u, 0x00000026u, 0x00000002u, 0x0000000bu, 0x00000003u,
|
0x00000003u, 0x00000023u, 0x0000000cu, 0x00050048u, 0x00000013u, 0x00000004u, 0x00000023u, 0x00000010u,
|
||||||
0x00050048u, 0x00000026u, 0x00000003u, 0x0000000bu, 0x00000004u, 0x00030047u, 0x00000026u, 0x00000002u,
|
0x00050048u, 0x00000013u, 0x00000005u, 0x00000023u, 0x00000014u, 0x00050048u, 0x00000013u, 0x00000006u,
|
||||||
0x00040047u, 0x00000031u, 0x0000001eu, 0x00000000u, 0x00040047u, 0x00000033u, 0x0000001eu, 0x00000001u,
|
0x00000023u, 0x00000018u, 0x00030047u, 0x00000013u, 0x00000002u, 0x00040047u, 0x00000015u, 0x00000022u,
|
||||||
0x00040047u, 0x00000036u, 0x0000001eu, 0x00000001u, 0x00040047u, 0x00000037u, 0x0000001eu, 0x00000002u,
|
0x00000000u, 0x00040047u, 0x00000015u, 0x00000021u, 0x00000000u, 0x00050048u, 0x0000002cu, 0x00000000u,
|
||||||
0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u, 0x00000002u, 0x00030016u, 0x00000006u, 0x00000020u,
|
0x0000000bu, 0x00000000u, 0x00050048u, 0x0000002cu, 0x00000001u, 0x0000000bu, 0x00000001u, 0x00050048u,
|
||||||
0x00040017u, 0x00000007u, 0x00000006u, 0x00000002u, 0x00040020u, 0x00000008u, 0x00000007u, 0x00000007u,
|
0x0000002cu, 0x00000002u, 0x0000000bu, 0x00000003u, 0x00050048u, 0x0000002cu, 0x00000003u, 0x0000000bu,
|
||||||
0x00040020u, 0x0000000au, 0x00000001u, 0x00000007u, 0x0004003bu, 0x0000000au, 0x0000000bu, 0x00000001u,
|
0x00000004u, 0x00030047u, 0x0000002cu, 0x00000002u, 0x00040047u, 0x00000036u, 0x0000001eu, 0x00000000u,
|
||||||
0x0006001eu, 0x0000000fu, 0x00000006u, 0x00000007u, 0x00000006u, 0x00000006u, 0x00040020u, 0x00000010u,
|
0x00040047u, 0x00000038u, 0x0000001eu, 0x00000001u, 0x00040047u, 0x0000003bu, 0x0000001eu, 0x00000001u,
|
||||||
0x00000002u, 0x0000000fu, 0x0004003bu, 0x00000010u, 0x00000011u, 0x00000002u, 0x00040015u, 0x00000012u,
|
0x00040047u, 0x0000003cu, 0x0000001eu, 0x00000002u, 0x00020013u, 0x00000002u, 0x00030021u, 0x00000003u,
|
||||||
0x00000020u, 0x00000001u, 0x0004002bu, 0x00000012u, 0x00000013u, 0x00000001u, 0x00040020u, 0x00000014u,
|
0x00000002u, 0x00030016u, 0x00000006u, 0x00000020u, 0x00040017u, 0x00000007u, 0x00000006u, 0x00000002u,
|
||||||
0x00000002u, 0x00000007u, 0x0004002bu, 0x00000006u, 0x00000018u, 0x40000000u, 0x0004002bu, 0x00000006u,
|
0x00040020u, 0x00000008u, 0x00000007u, 0x00000007u, 0x00040020u, 0x0000000au, 0x00000001u, 0x00000007u,
|
||||||
0x0000001au, 0x3f800000u, 0x00040015u, 0x0000001du, 0x00000020u, 0x00000000u, 0x0004002bu, 0x0000001du,
|
0x0004003bu, 0x0000000au, 0x0000000bu, 0x00000001u, 0x00040020u, 0x0000000du, 0x00000007u, 0x00000006u,
|
||||||
0x0000001eu, 0x00000001u, 0x00040020u, 0x0000001fu, 0x00000007u, 0x00000006u, 0x00040017u, 0x00000024u,
|
0x00040015u, 0x0000000fu, 0x00000020u, 0x00000000u, 0x0004002bu, 0x0000000fu, 0x00000010u, 0x00000000u,
|
||||||
0x00000006u, 0x00000004u, 0x0004001cu, 0x00000025u, 0x00000006u, 0x0000001eu, 0x0006001eu, 0x00000026u,
|
0x0009001eu, 0x00000013u, 0x00000006u, 0x00000006u, 0x00000006u, 0x00000006u, 0x00000006u, 0x00000006u,
|
||||||
0x00000024u, 0x00000006u, 0x00000025u, 0x00000025u, 0x00040020u, 0x00000027u, 0x00000003u, 0x00000026u,
|
0x00000006u, 0x00040020u, 0x00000014u, 0x00000002u, 0x00000013u, 0x0004003bu, 0x00000014u, 0x00000015u,
|
||||||
0x0004003bu, 0x00000027u, 0x00000028u, 0x00000003u, 0x0004002bu, 0x00000012u, 0x00000029u, 0x00000000u,
|
0x00000002u, 0x00040015u, 0x00000016u, 0x00000020u, 0x00000001u, 0x0004002bu, 0x00000016u, 0x00000017u,
|
||||||
0x0004002bu, 0x00000006u, 0x0000002bu, 0x00000000u, 0x00040020u, 0x0000002fu, 0x00000003u, 0x00000024u,
|
0x00000001u, 0x00040020u, 0x00000018u, 0x00000002u, 0x00000006u, 0x0004002bu, 0x00000006u, 0x0000001cu,
|
||||||
0x0004003bu, 0x0000002fu, 0x00000031u, 0x00000003u, 0x00040020u, 0x00000032u, 0x00000001u, 0x00000024u,
|
0x40000000u, 0x0004002bu, 0x00000006u, 0x0000001eu, 0x3f800000u, 0x0004002bu, 0x0000000fu, 0x00000021u,
|
||||||
0x0004003bu, 0x00000032u, 0x00000033u, 0x00000001u, 0x00040020u, 0x00000035u, 0x00000003u, 0x00000007u,
|
0x00000001u, 0x0004002bu, 0x00000016u, 0x00000024u, 0x00000002u, 0x00040017u, 0x0000002au, 0x00000006u,
|
||||||
0x0004003bu, 0x00000035u, 0x00000036u, 0x00000003u, 0x0004003bu, 0x0000000au, 0x00000037u, 0x00000001u,
|
0x00000004u, 0x0004001cu, 0x0000002bu, 0x00000006u, 0x00000021u, 0x0006001eu, 0x0000002cu, 0x0000002au,
|
||||||
0x00050036u, 0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu,
|
0x00000006u, 0x0000002bu, 0x0000002bu, 0x00040020u, 0x0000002du, 0x00000003u, 0x0000002cu, 0x0004003bu,
|
||||||
0x00000008u, 0x00000009u, 0x00000007u, 0x0004003bu, 0x00000008u, 0x0000000du, 0x00000007u, 0x0004003du,
|
0x0000002du, 0x0000002eu, 0x00000003u, 0x0004002bu, 0x00000016u, 0x0000002fu, 0x00000000u, 0x0004002bu,
|
||||||
0x00000007u, 0x0000000cu, 0x0000000bu, 0x0003003eu, 0x00000009u, 0x0000000cu, 0x0004003du, 0x00000007u,
|
0x00000006u, 0x00000032u, 0x00000000u, 0x00040020u, 0x00000034u, 0x00000003u, 0x0000002au, 0x0004003bu,
|
||||||
0x0000000eu, 0x00000009u, 0x00050041u, 0x00000014u, 0x00000015u, 0x00000011u, 0x00000013u, 0x0004003du,
|
0x00000034u, 0x00000036u, 0x00000003u, 0x00040020u, 0x00000037u, 0x00000001u, 0x0000002au, 0x0004003bu,
|
||||||
0x00000007u, 0x00000016u, 0x00000015u, 0x00050088u, 0x00000007u, 0x00000017u, 0x0000000eu, 0x00000016u,
|
0x00000037u, 0x00000038u, 0x00000001u, 0x00040020u, 0x0000003au, 0x00000003u, 0x00000007u, 0x0004003bu,
|
||||||
0x0005008eu, 0x00000007u, 0x00000019u, 0x00000017u, 0x00000018u, 0x00050050u, 0x00000007u, 0x0000001bu,
|
0x0000003au, 0x0000003bu, 0x00000003u, 0x0004003bu, 0x0000000au, 0x0000003cu, 0x00000001u, 0x00050036u,
|
||||||
0x0000001au, 0x0000001au, 0x00050083u, 0x00000007u, 0x0000001cu, 0x00000019u, 0x0000001bu, 0x0003003eu,
|
0x00000002u, 0x00000004u, 0x00000000u, 0x00000003u, 0x000200f8u, 0x00000005u, 0x0004003bu, 0x00000008u,
|
||||||
0x0000000du, 0x0000001cu, 0x00050041u, 0x0000001fu, 0x00000020u, 0x0000000du, 0x0000001eu, 0x0004003du,
|
0x00000009u, 0x00000007u, 0x0004003bu, 0x0000000du, 0x0000000eu, 0x00000007u, 0x0004003bu, 0x0000000du,
|
||||||
0x00000006u, 0x00000021u, 0x00000020u, 0x0004007fu, 0x00000006u, 0x00000022u, 0x00000021u, 0x00050041u,
|
0x00000020u, 0x00000007u, 0x0004003du, 0x00000007u, 0x0000000cu, 0x0000000bu, 0x0003003eu, 0x00000009u,
|
||||||
0x0000001fu, 0x00000023u, 0x0000000du, 0x0000001eu, 0x0003003eu, 0x00000023u, 0x00000022u, 0x0004003du,
|
0x0000000cu, 0x00050041u, 0x0000000du, 0x00000011u, 0x00000009u, 0x00000010u, 0x0004003du, 0x00000006u,
|
||||||
0x00000007u, 0x0000002au, 0x0000000du, 0x00050051u, 0x00000006u, 0x0000002cu, 0x0000002au, 0x00000000u,
|
0x00000012u, 0x00000011u, 0x00050041u, 0x00000018u, 0x00000019u, 0x00000015u, 0x00000017u, 0x0004003du,
|
||||||
0x00050051u, 0x00000006u, 0x0000002du, 0x0000002au, 0x00000001u, 0x00070050u, 0x00000024u, 0x0000002eu,
|
0x00000006u, 0x0000001au, 0x00000019u, 0x00050088u, 0x00000006u, 0x0000001bu, 0x00000012u, 0x0000001au,
|
||||||
0x0000002cu, 0x0000002du, 0x0000002bu, 0x0000001au, 0x00050041u, 0x0000002fu, 0x00000030u, 0x00000028u,
|
0x00050085u, 0x00000006u, 0x0000001du, 0x0000001bu, 0x0000001cu, 0x00050083u, 0x00000006u, 0x0000001fu,
|
||||||
0x00000029u, 0x0003003eu, 0x00000030u, 0x0000002eu, 0x0004003du, 0x00000024u, 0x00000034u, 0x00000033u,
|
0x0000001du, 0x0000001eu, 0x0003003eu, 0x0000000eu, 0x0000001fu, 0x00050041u, 0x0000000du, 0x00000022u,
|
||||||
0x0003003eu, 0x00000031u, 0x00000034u, 0x0004003du, 0x00000007u, 0x00000038u, 0x00000037u, 0x0003003eu,
|
0x00000009u, 0x00000021u, 0x0004003du, 0x00000006u, 0x00000023u, 0x00000022u, 0x00050041u, 0x00000018u,
|
||||||
0x00000036u, 0x00000038u, 0x000100fdu, 0x00010038u
|
0x00000025u, 0x00000015u, 0x00000024u, 0x0004003du, 0x00000006u, 0x00000026u, 0x00000025u, 0x00050088u,
|
||||||
|
0x00000006u, 0x00000027u, 0x00000023u, 0x00000026u, 0x00050085u, 0x00000006u, 0x00000028u, 0x00000027u,
|
||||||
|
0x0000001cu, 0x00050083u, 0x00000006u, 0x00000029u, 0x00000028u, 0x0000001eu, 0x0003003eu, 0x00000020u,
|
||||||
|
0x00000029u, 0x0004003du, 0x00000006u, 0x00000030u, 0x0000000eu, 0x0004003du, 0x00000006u, 0x00000031u,
|
||||||
|
0x00000020u, 0x00070050u, 0x0000002au, 0x00000033u, 0x00000030u, 0x00000031u, 0x00000032u, 0x0000001eu,
|
||||||
|
0x00050041u, 0x00000034u, 0x00000035u, 0x0000002eu, 0x0000002fu, 0x0003003eu, 0x00000035u, 0x00000033u,
|
||||||
|
0x0004003du, 0x0000002au, 0x00000039u, 0x00000038u, 0x0003003eu, 0x00000036u, 0x00000039u, 0x0004003du,
|
||||||
|
0x00000007u, 0x0000003du, 0x0000003cu, 0x0003003eu, 0x0000003bu, 0x0000003du, 0x000100fdu, 0x00010038u
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -263,6 +263,11 @@ private:
|
||||||
std::vector<uint16_t>& indices,
|
std::vector<uint16_t>& indices,
|
||||||
double wavePhase);
|
double wavePhase);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 计算文本宽度(像素)
|
||||||
|
*/
|
||||||
|
float calculateTextWidth(const std::string& text, float scale);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 生成文本四边形顶点
|
* @brief 生成文本四边形顶点
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -56,95 +56,95 @@ VulkanWidget::VulkanWidget(QWidget *parent)
|
||||||
setAttribute(Qt::WA_NativeWindow);
|
setAttribute(Qt::WA_NativeWindow);
|
||||||
setAttribute(Qt::WA_PaintOnScreen);
|
setAttribute(Qt::WA_PaintOnScreen);
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
||||||
// Create render timer
|
// Create render timer
|
||||||
m_renderTimer = new QTimer(this);
|
m_renderTimer = new QTimer(this);
|
||||||
connect(m_renderTimer, &QTimer::timeout, this, &VulkanWidget::onRenderTimer);
|
connect(m_renderTimer, &QTimer::timeout, this, &VulkanWidget::onRenderTimer);
|
||||||
|
|
||||||
qDebug() << "VulkanWidget created";
|
qDebug() << "VulkanWidget created";
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanWidget::~VulkanWidget()
|
VulkanWidget::~VulkanWidget()
|
||||||
{
|
{
|
||||||
qDebug() << "VulkanWidget destroying...";
|
qDebug() << "VulkanWidget destroying...";
|
||||||
|
|
||||||
if (m_renderTimer) {
|
if (m_renderTimer) {
|
||||||
m_renderTimer->stop();
|
m_renderTimer->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up renderer first
|
// Clean up renderer first
|
||||||
if (m_renderer) {
|
if (m_renderer) {
|
||||||
m_renderer->cleanup();
|
m_renderer->cleanup();
|
||||||
delete m_renderer;
|
delete m_renderer;
|
||||||
m_renderer = nullptr;
|
m_renderer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanupVulkan();
|
cleanupVulkan();
|
||||||
|
|
||||||
qDebug() << "VulkanWidget destroyed";
|
qDebug() << "VulkanWidget destroyed";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanWidget::initializeVulkan()
|
bool VulkanWidget::initializeVulkan()
|
||||||
{
|
{
|
||||||
qDebug() << "Initializing Vulkan...";
|
qDebug() << "Initializing Vulkan...";
|
||||||
|
|
||||||
if (m_initialized) {
|
if (m_initialized) {
|
||||||
qDebug() << "Vulkan already initialized";
|
qDebug() << "Vulkan already initialized";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 1: Initialize volk
|
// Step 1: Initialize volk
|
||||||
if (!initializeVolk()) {
|
if (!initializeVolk()) {
|
||||||
setError("Failed to initialize volk");
|
setError("Failed to initialize volk");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: Create Vulkan instance
|
// Step 2: Create Vulkan instance
|
||||||
if (!createInstance()) {
|
if (!createInstance()) {
|
||||||
setError("Failed to create Vulkan instance");
|
setError("Failed to create Vulkan instance");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Create surface from native window
|
// Step 3: Create surface from native window
|
||||||
if (!createSurface()) {
|
if (!createSurface()) {
|
||||||
setError("Failed to create Vulkan surface");
|
setError("Failed to create Vulkan surface");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: Select physical device
|
// Step 4: Select physical device
|
||||||
if (!selectPhysicalDevice()) {
|
if (!selectPhysicalDevice()) {
|
||||||
setError("Failed to select physical device");
|
setError("Failed to select physical device");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5: Create logical device
|
// Step 5: Create logical device
|
||||||
if (!createDevice()) {
|
if (!createDevice()) {
|
||||||
setError("Failed to create logical device");
|
setError("Failed to create logical device");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6: Create swapchain
|
// Step 6: Create swapchain
|
||||||
if (!createSwapchain()) {
|
if (!createSwapchain()) {
|
||||||
setError("Failed to create swapchain");
|
setError("Failed to create swapchain");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 7: Create command objects
|
// Step 7: Create command objects
|
||||||
if (!createCommandObjects()) {
|
if (!createCommandObjects()) {
|
||||||
setError("Failed to create command objects");
|
setError("Failed to create command objects");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 8: Create synchronization objects
|
// Step 8: Create synchronization objects
|
||||||
if (!createSyncObjects()) {
|
if (!createSyncObjects()) {
|
||||||
setError("Failed to create sync objects");
|
setError("Failed to create sync objects");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 9: Create VulkanRenderer - but only if we have reasonable dimensions
|
// Step 9: Create VulkanRenderer - but only if we have reasonable dimensions
|
||||||
if (m_surfaceWidth >= 100 && m_surfaceHeight >= 100) {
|
if (m_surfaceWidth >= 100 && m_surfaceHeight >= 100) {
|
||||||
m_renderer = new VulkanRenderer();
|
m_renderer = new VulkanRenderer();
|
||||||
|
|
||||||
// Get swapchain format
|
// Get swapchain format
|
||||||
VkSurfaceFormatKHR surfaceFormat;
|
VkSurfaceFormatKHR surfaceFormat;
|
||||||
uint32_t formatCount = 0;
|
uint32_t formatCount = 0;
|
||||||
|
|
@ -154,7 +154,7 @@ bool VulkanWidget::initializeVulkan()
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
|
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
|
||||||
surfaceFormat = formats[0];
|
surfaceFormat = formats[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize renderer
|
// Initialize renderer
|
||||||
if (!m_renderer->initialize(m_device, m_physicalDevice,
|
if (!m_renderer->initialize(m_device, m_physicalDevice,
|
||||||
m_queue, m_queueFamilyIndex,
|
m_queue, m_queueFamilyIndex,
|
||||||
|
|
@ -165,14 +165,14 @@ bool VulkanWidget::initializeVulkan()
|
||||||
m_renderer = nullptr;
|
m_renderer = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "VulkanRenderer initialized successfully!";
|
qDebug() << "VulkanRenderer initialized successfully!";
|
||||||
qDebug() << "Widget size:" << width() << "x" << height()
|
qDebug() << "Widget size:" << width() << "x" << height()
|
||||||
<< "| Surface size:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
<< "| Surface size:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "VulkanRenderer initialization deferred - window too small:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
qDebug() << "VulkanRenderer initialization deferred - window too small:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
qDebug() << "Vulkan initialization successful!";
|
qDebug() << "Vulkan initialization successful!";
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -181,13 +181,13 @@ bool VulkanWidget::initializeVulkan()
|
||||||
bool VulkanWidget::initializeVolk()
|
bool VulkanWidget::initializeVolk()
|
||||||
{
|
{
|
||||||
qDebug() << "Initializing volk...";
|
qDebug() << "Initializing volk...";
|
||||||
|
|
||||||
VkResult result = volkInitialize();
|
VkResult result = volkInitialize();
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
qDebug() << "Failed to initialize volk, error code:" << result;
|
qDebug() << "Failed to initialize volk, error code:" << result;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Volk initialized successfully";
|
qDebug() << "Volk initialized successfully";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +195,7 @@ bool VulkanWidget::initializeVolk()
|
||||||
bool VulkanWidget::createInstance()
|
bool VulkanWidget::createInstance()
|
||||||
{
|
{
|
||||||
qDebug() << "Creating Vulkan instance...";
|
qDebug() << "Creating Vulkan instance...";
|
||||||
|
|
||||||
VkApplicationInfo appInfo = {};
|
VkApplicationInfo appInfo = {};
|
||||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
appInfo.pApplicationName = "VulkanWidget";
|
appInfo.pApplicationName = "VulkanWidget";
|
||||||
|
|
@ -203,25 +203,25 @@ bool VulkanWidget::createInstance()
|
||||||
appInfo.pEngineName = "No Engine";
|
appInfo.pEngineName = "No Engine";
|
||||||
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||||
appInfo.apiVersion = VK_API_VERSION_1_0;
|
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||||||
|
|
||||||
std::vector<const char*> extensions = getRequiredInstanceExtensions();
|
std::vector<const char*> extensions = getRequiredInstanceExtensions();
|
||||||
|
|
||||||
VkInstanceCreateInfo createInfo = {};
|
VkInstanceCreateInfo createInfo = {};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
createInfo.pApplicationInfo = &appInfo;
|
createInfo.pApplicationInfo = &appInfo;
|
||||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
|
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
|
||||||
createInfo.ppEnabledExtensionNames = extensions.data();
|
createInfo.ppEnabledExtensionNames = extensions.data();
|
||||||
createInfo.enabledLayerCount = 0;
|
createInfo.enabledLayerCount = 0;
|
||||||
|
|
||||||
VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance);
|
VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
qDebug() << "Failed to create Vulkan instance, error code:" << result;
|
qDebug() << "Failed to create Vulkan instance, error code:" << result;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load instance-level functions
|
// Load instance-level functions
|
||||||
volkLoadInstance(m_instance);
|
volkLoadInstance(m_instance);
|
||||||
|
|
||||||
qDebug() << "Vulkan instance created successfully";
|
qDebug() << "Vulkan instance created successfully";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -229,7 +229,7 @@ bool VulkanWidget::createInstance()
|
||||||
bool VulkanWidget::createSurface()
|
bool VulkanWidget::createSurface()
|
||||||
{
|
{
|
||||||
qDebug() << "Creating Vulkan surface from native window...";
|
qDebug() << "Creating Vulkan surface from native window...";
|
||||||
|
|
||||||
if (!windowHandle()) {
|
if (!windowHandle()) {
|
||||||
qDebug() << "Window handle not available, creating window...";
|
qDebug() << "Window handle not available, creating window...";
|
||||||
create();
|
create();
|
||||||
|
|
@ -238,17 +238,17 @@ bool VulkanWidget::createSurface()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QWindow *window = windowHandle();
|
QWindow *window = windowHandle();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
VkWin32SurfaceCreateInfoKHR createInfo = {};
|
VkWin32SurfaceCreateInfoKHR createInfo = {};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||||
createInfo.hwnd = reinterpret_cast<HWND>(window->winId());
|
createInfo.hwnd = reinterpret_cast<HWND>(window->winId());
|
||||||
createInfo.hinstance = GetModuleHandle(nullptr);
|
createInfo.hinstance = GetModuleHandle(nullptr);
|
||||||
|
|
||||||
VkResult result = vkCreateWin32SurfaceKHR(m_instance, &createInfo, nullptr, &m_surface);
|
VkResult result = vkCreateWin32SurfaceKHR(m_instance, &createInfo, nullptr, &m_surface);
|
||||||
|
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
VkXlibSurfaceCreateInfoKHR createInfo = {};
|
VkXlibSurfaceCreateInfoKHR createInfo = {};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
|
||||||
|
|
@ -259,26 +259,26 @@ bool VulkanWidget::createSurface()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
createInfo.window = static_cast<Window>(window->winId());
|
createInfo.window = static_cast<Window>(window->winId());
|
||||||
|
|
||||||
VkResult result = vkCreateXlibSurfaceKHR(m_instance, &createInfo, nullptr, &m_surface);
|
VkResult result = vkCreateXlibSurfaceKHR(m_instance, &createInfo, nullptr, &m_surface);
|
||||||
|
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
// macOS requires MoltenVK and Metal
|
// macOS requires MoltenVK and Metal
|
||||||
VkMetalSurfaceCreateInfoEXT createInfo = {};
|
VkMetalSurfaceCreateInfoEXT createInfo = {};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
|
createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
|
||||||
createInfo.pLayer = nullptr; // This needs proper Metal layer setup
|
createInfo.pLayer = nullptr; // This needs proper Metal layer setup
|
||||||
|
|
||||||
VkResult result = vkCreateMetalSurfaceEXT(m_instance, &createInfo, nullptr, &m_surface);
|
VkResult result = vkCreateMetalSurfaceEXT(m_instance, &createInfo, nullptr, &m_surface);
|
||||||
#else
|
#else
|
||||||
qDebug() << "Unsupported platform for Vulkan surface creation";
|
qDebug() << "Unsupported platform for Vulkan surface creation";
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
qDebug() << "Failed to create Vulkan surface, error code:" << result;
|
qDebug() << "Failed to create Vulkan surface, error code:" << result;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Vulkan surface created successfully";
|
qDebug() << "Vulkan surface created successfully";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -286,28 +286,28 @@ bool VulkanWidget::createSurface()
|
||||||
bool VulkanWidget::selectPhysicalDevice()
|
bool VulkanWidget::selectPhysicalDevice()
|
||||||
{
|
{
|
||||||
qDebug() << "Selecting physical device...";
|
qDebug() << "Selecting physical device...";
|
||||||
|
|
||||||
uint32_t deviceCount = 0;
|
uint32_t deviceCount = 0;
|
||||||
vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr);
|
vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr);
|
||||||
|
|
||||||
if (deviceCount == 0) {
|
if (deviceCount == 0) {
|
||||||
qDebug() << "Failed to find GPUs with Vulkan support";
|
qDebug() << "Failed to find GPUs with Vulkan support";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<VkPhysicalDevice> devices(deviceCount);
|
std::vector<VkPhysicalDevice> devices(deviceCount);
|
||||||
vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
|
vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
|
||||||
|
|
||||||
// Select the first suitable device
|
// Select the first suitable device
|
||||||
for (const auto& device : devices) {
|
for (const auto& device : devices) {
|
||||||
VkPhysicalDeviceProperties properties;
|
VkPhysicalDeviceProperties properties;
|
||||||
vkGetPhysicalDeviceProperties(device, &properties);
|
vkGetPhysicalDeviceProperties(device, &properties);
|
||||||
|
|
||||||
qDebug() << "Found device:" << properties.deviceName;
|
qDebug() << "Found device:" << properties.deviceName;
|
||||||
|
|
||||||
// Temporarily set physical device to check queue families
|
// Temporarily set physical device to check queue families
|
||||||
m_physicalDevice = device;
|
m_physicalDevice = device;
|
||||||
|
|
||||||
// Check if device supports our queue family
|
// Check if device supports our queue family
|
||||||
uint32_t queueFamilyIndex;
|
uint32_t queueFamilyIndex;
|
||||||
if (findQueueFamily(queueFamilyIndex)) {
|
if (findQueueFamily(queueFamilyIndex)) {
|
||||||
|
|
@ -316,7 +316,7 @@ bool VulkanWidget::selectPhysicalDevice()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset if no suitable device found
|
// Reset if no suitable device found
|
||||||
m_physicalDevice = VK_NULL_HANDLE;
|
m_physicalDevice = VK_NULL_HANDLE;
|
||||||
qDebug() << "Failed to find suitable physical device";
|
qDebug() << "Failed to find suitable physical device";
|
||||||
|
|
@ -327,42 +327,42 @@ bool VulkanWidget::findQueueFamily(uint32_t &queueFamilyIndex)
|
||||||
{
|
{
|
||||||
uint32_t queueFamilyCount = 0;
|
uint32_t queueFamilyCount = 0;
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, nullptr);
|
vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, nullptr);
|
||||||
|
|
||||||
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, queueFamilies.data());
|
vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, queueFamilies.data());
|
||||||
|
|
||||||
for (uint32_t i = 0; i < queueFamilyCount; i++) {
|
for (uint32_t i = 0; i < queueFamilyCount; i++) {
|
||||||
// Check if queue family supports graphics
|
// Check if queue family supports graphics
|
||||||
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||||
// Check if queue family supports presentation
|
// Check if queue family supports presentation
|
||||||
VkBool32 presentSupport = false;
|
VkBool32 presentSupport = false;
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &presentSupport);
|
vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &presentSupport);
|
||||||
|
|
||||||
if (presentSupport) {
|
if (presentSupport) {
|
||||||
queueFamilyIndex = i;
|
queueFamilyIndex = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanWidget::createDevice()
|
bool VulkanWidget::createDevice()
|
||||||
{
|
{
|
||||||
qDebug() << "Creating logical device...";
|
qDebug() << "Creating logical device...";
|
||||||
|
|
||||||
float queuePriority = 1.0f;
|
float queuePriority = 1.0f;
|
||||||
VkDeviceQueueCreateInfo queueCreateInfo = {};
|
VkDeviceQueueCreateInfo queueCreateInfo = {};
|
||||||
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
queueCreateInfo.queueFamilyIndex = m_queueFamilyIndex;
|
queueCreateInfo.queueFamilyIndex = m_queueFamilyIndex;
|
||||||
queueCreateInfo.queueCount = 1;
|
queueCreateInfo.queueCount = 1;
|
||||||
queueCreateInfo.pQueuePriorities = &queuePriority;
|
queueCreateInfo.pQueuePriorities = &queuePriority;
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures deviceFeatures = {};
|
VkPhysicalDeviceFeatures deviceFeatures = {};
|
||||||
|
|
||||||
std::vector<const char*> deviceExtensions = getRequiredDeviceExtensions();
|
std::vector<const char*> deviceExtensions = getRequiredDeviceExtensions();
|
||||||
|
|
||||||
VkDeviceCreateInfo createInfo = {};
|
VkDeviceCreateInfo createInfo = {};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
createInfo.pQueueCreateInfos = &queueCreateInfo;
|
createInfo.pQueueCreateInfos = &queueCreateInfo;
|
||||||
|
|
@ -371,19 +371,19 @@ bool VulkanWidget::createDevice()
|
||||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
||||||
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
|
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
|
||||||
createInfo.enabledLayerCount = 0;
|
createInfo.enabledLayerCount = 0;
|
||||||
|
|
||||||
VkResult result = vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device);
|
VkResult result = vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
qDebug() << "Failed to create logical device, error code:" << result;
|
qDebug() << "Failed to create logical device, error code:" << result;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load device-level functions
|
// Load device-level functions
|
||||||
volkLoadDevice(m_device);
|
volkLoadDevice(m_device);
|
||||||
|
|
||||||
// Get queue handle
|
// Get queue handle
|
||||||
vkGetDeviceQueue(m_device, m_queueFamilyIndex, 0, &m_queue);
|
vkGetDeviceQueue(m_device, m_queueFamilyIndex, 0, &m_queue);
|
||||||
|
|
||||||
qDebug() << "Logical device created successfully";
|
qDebug() << "Logical device created successfully";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -393,40 +393,40 @@ bool VulkanWidget::createSwapchain()
|
||||||
qDebug() << "Creating swapchain...";
|
qDebug() << "Creating swapchain...";
|
||||||
qDebug() << "Widget size:" << width() << "x" << height();
|
qDebug() << "Widget size:" << width() << "x" << height();
|
||||||
qDebug() << "Device pixel ratio:" << devicePixelRatioF();
|
qDebug() << "Device pixel ratio:" << devicePixelRatioF();
|
||||||
|
|
||||||
// Query surface capabilities
|
// Query surface capabilities
|
||||||
VkSurfaceCapabilitiesKHR capabilities;
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities);
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities);
|
||||||
|
|
||||||
qDebug() << "Surface capabilities - current extent:"
|
qDebug() << "Surface capabilities - current extent:"
|
||||||
<< capabilities.currentExtent.width << "x" << capabilities.currentExtent.height;
|
<< capabilities.currentExtent.width << "x" << capabilities.currentExtent.height;
|
||||||
qDebug() << "Surface capabilities - min extent:"
|
qDebug() << "Surface capabilities - min extent:"
|
||||||
<< capabilities.minImageExtent.width << "x" << capabilities.minImageExtent.height;
|
<< capabilities.minImageExtent.width << "x" << capabilities.minImageExtent.height;
|
||||||
qDebug() << "Surface capabilities - max extent:"
|
qDebug() << "Surface capabilities - max extent:"
|
||||||
<< capabilities.maxImageExtent.width << "x" << capabilities.maxImageExtent.height;
|
<< capabilities.maxImageExtent.width << "x" << capabilities.maxImageExtent.height;
|
||||||
|
|
||||||
// Query surface formats
|
// Query surface formats
|
||||||
uint32_t formatCount;
|
uint32_t formatCount;
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr);
|
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr);
|
||||||
std::vector<VkSurfaceFormatKHR> formats(formatCount);
|
std::vector<VkSurfaceFormatKHR> formats(formatCount);
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
|
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
|
||||||
|
|
||||||
// Query present modes
|
// Query present modes
|
||||||
uint32_t presentModeCount;
|
uint32_t presentModeCount;
|
||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr);
|
vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr);
|
||||||
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, presentModes.data());
|
vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, presentModes.data());
|
||||||
|
|
||||||
// Select format
|
// Select format
|
||||||
VkSurfaceFormatKHR surfaceFormat = formats[0];
|
VkSurfaceFormatKHR surfaceFormat = formats[0];
|
||||||
for (const auto& format : formats) {
|
for (const auto& format : formats) {
|
||||||
if (format.format == VK_FORMAT_B8G8R8A8_SRGB &&
|
if (format.format == VK_FORMAT_B8G8R8A8_SRGB &&
|
||||||
format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||||
surfaceFormat = format;
|
surfaceFormat = format;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select present mode (prefer mailbox, fallback to FIFO)
|
// Select present mode (prefer mailbox, fallback to FIFO)
|
||||||
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
for (const auto& mode : presentModes) {
|
for (const auto& mode : presentModes) {
|
||||||
|
|
@ -435,7 +435,7 @@ bool VulkanWidget::createSwapchain()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine extent
|
// Determine extent
|
||||||
VkExtent2D extent;
|
VkExtent2D extent;
|
||||||
if (capabilities.currentExtent.width != UINT32_MAX) {
|
if (capabilities.currentExtent.width != UINT32_MAX) {
|
||||||
|
|
@ -445,27 +445,27 @@ bool VulkanWidget::createSwapchain()
|
||||||
// Calculate extent based on widget size with DPI scaling
|
// Calculate extent based on widget size with DPI scaling
|
||||||
uint32_t pixelWidth = static_cast<uint32_t>(width() * devicePixelRatioF());
|
uint32_t pixelWidth = static_cast<uint32_t>(width() * devicePixelRatioF());
|
||||||
uint32_t pixelHeight = static_cast<uint32_t>(height() * devicePixelRatioF());
|
uint32_t pixelHeight = static_cast<uint32_t>(height() * devicePixelRatioF());
|
||||||
|
|
||||||
extent.width = std::max(capabilities.minImageExtent.width,
|
extent.width = std::max(capabilities.minImageExtent.width,
|
||||||
std::min(capabilities.maxImageExtent.width, pixelWidth));
|
std::min(capabilities.maxImageExtent.width, pixelWidth));
|
||||||
extent.height = std::max(capabilities.minImageExtent.height,
|
extent.height = std::max(capabilities.minImageExtent.height,
|
||||||
std::min(capabilities.maxImageExtent.height, pixelHeight));
|
std::min(capabilities.maxImageExtent.height, pixelHeight));
|
||||||
qDebug() << "Calculated extent from widget:" << extent.width << "x" << extent.height
|
qDebug() << "Calculated extent from widget:" << extent.width << "x" << extent.height
|
||||||
<< "(widget:" << width() << "x" << height()
|
<< "(widget:" << width() << "x" << height()
|
||||||
<< "* DPR:" << devicePixelRatioF() << ")";
|
<< "* DPR:" << devicePixelRatioF() << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
m_surfaceWidth = extent.width;
|
m_surfaceWidth = extent.width;
|
||||||
m_surfaceHeight = extent.height;
|
m_surfaceHeight = extent.height;
|
||||||
|
|
||||||
qDebug() << "Final swapchain extent:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
qDebug() << "Final swapchain extent:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
||||||
|
|
||||||
// Determine image count
|
// Determine image count
|
||||||
uint32_t imageCount = capabilities.minImageCount + 1;
|
uint32_t imageCount = capabilities.minImageCount + 1;
|
||||||
if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) {
|
if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) {
|
||||||
imageCount = capabilities.maxImageCount;
|
imageCount = capabilities.maxImageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSwapchainCreateInfoKHR createInfo = {};
|
VkSwapchainCreateInfoKHR createInfo = {};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
createInfo.surface = m_surface;
|
createInfo.surface = m_surface;
|
||||||
|
|
@ -481,19 +481,19 @@ bool VulkanWidget::createSwapchain()
|
||||||
createInfo.presentMode = presentMode;
|
createInfo.presentMode = presentMode;
|
||||||
createInfo.clipped = VK_TRUE;
|
createInfo.clipped = VK_TRUE;
|
||||||
createInfo.oldSwapchain = VK_NULL_HANDLE;
|
createInfo.oldSwapchain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkResult result = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapchain);
|
VkResult result = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapchain);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
qDebug() << "Failed to create swapchain, error code:" << result;
|
qDebug() << "Failed to create swapchain, error code:" << result;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve swapchain images
|
// Retrieve swapchain images
|
||||||
vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, nullptr);
|
vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, nullptr);
|
||||||
m_swapchainImages.resize(imageCount);
|
m_swapchainImages.resize(imageCount);
|
||||||
vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount,
|
vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount,
|
||||||
reinterpret_cast<VkImage*>(m_swapchainImages.data()));
|
reinterpret_cast<VkImage*>(m_swapchainImages.data()));
|
||||||
|
|
||||||
// Create image views for swapchain images
|
// Create image views for swapchain images
|
||||||
m_swapchainImageViews.resize(imageCount);
|
m_swapchainImageViews.resize(imageCount);
|
||||||
for (uint32_t i = 0; i < imageCount; i++) {
|
for (uint32_t i = 0; i < imageCount; i++) {
|
||||||
|
|
@ -511,7 +511,7 @@ bool VulkanWidget::createSwapchain()
|
||||||
viewInfo.subresourceRange.levelCount = 1;
|
viewInfo.subresourceRange.levelCount = 1;
|
||||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||||
viewInfo.subresourceRange.layerCount = 1;
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
VkImageView imageView;
|
VkImageView imageView;
|
||||||
result = vkCreateImageView(m_device, &viewInfo, nullptr, &imageView);
|
result = vkCreateImageView(m_device, &viewInfo, nullptr, &imageView);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
|
|
@ -520,42 +520,42 @@ bool VulkanWidget::createSwapchain()
|
||||||
}
|
}
|
||||||
m_swapchainImageViews[i] = reinterpret_cast<void*>(imageView);
|
m_swapchainImageViews[i] = reinterpret_cast<void*>(imageView);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Swapchain created successfully with" << imageCount << "images, size:"
|
qDebug() << "Swapchain created successfully with" << imageCount << "images, size:"
|
||||||
<< m_surfaceWidth << "x" << m_surfaceHeight;
|
<< m_surfaceWidth << "x" << m_surfaceHeight;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanWidget::createCommandObjects()
|
bool VulkanWidget::createCommandObjects()
|
||||||
{
|
{
|
||||||
qDebug() << "Creating command objects...";
|
qDebug() << "Creating command objects...";
|
||||||
|
|
||||||
VkCommandPoolCreateInfo poolInfo = {};
|
VkCommandPoolCreateInfo poolInfo = {};
|
||||||
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
poolInfo.queueFamilyIndex = m_queueFamilyIndex;
|
poolInfo.queueFamilyIndex = m_queueFamilyIndex;
|
||||||
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||||
|
|
||||||
VkResult result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &m_commandPool);
|
VkResult result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &m_commandPool);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
qDebug() << "Failed to create command pool, error code:" << result;
|
qDebug() << "Failed to create command pool, error code:" << result;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
m_commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo allocInfo = {};
|
VkCommandBufferAllocateInfo allocInfo = {};
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
allocInfo.commandPool = m_commandPool;
|
allocInfo.commandPool = m_commandPool;
|
||||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
allocInfo.commandBufferCount = static_cast<uint32_t>(m_commandBuffers.size());
|
allocInfo.commandBufferCount = static_cast<uint32_t>(m_commandBuffers.size());
|
||||||
|
|
||||||
result = vkAllocateCommandBuffers(m_device, &allocInfo, m_commandBuffers.data());
|
result = vkAllocateCommandBuffers(m_device, &allocInfo, m_commandBuffers.data());
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
qDebug() << "Failed to allocate command buffers, error code:" << result;
|
qDebug() << "Failed to allocate command buffers, error code:" << result;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Command objects created successfully";
|
qDebug() << "Command objects created successfully";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -563,18 +563,18 @@ bool VulkanWidget::createCommandObjects()
|
||||||
bool VulkanWidget::createSyncObjects()
|
bool VulkanWidget::createSyncObjects()
|
||||||
{
|
{
|
||||||
qDebug() << "Creating synchronization objects...";
|
qDebug() << "Creating synchronization objects...";
|
||||||
|
|
||||||
m_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
|
m_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
m_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
|
m_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
|
m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
|
||||||
|
|
||||||
VkSemaphoreCreateInfo semaphoreInfo = {};
|
VkSemaphoreCreateInfo semaphoreInfo = {};
|
||||||
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
|
|
||||||
VkFenceCreateInfo fenceInfo = {};
|
VkFenceCreateInfo fenceInfo = {};
|
||||||
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
|
|
||||||
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
if (vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_imageAvailableSemaphores[i]) != VK_SUCCESS ||
|
if (vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_imageAvailableSemaphores[i]) != VK_SUCCESS ||
|
||||||
vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]) != VK_SUCCESS ||
|
vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]) != VK_SUCCESS ||
|
||||||
|
|
@ -583,7 +583,7 @@ bool VulkanWidget::createSyncObjects()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Synchronization objects created successfully";
|
qDebug() << "Synchronization objects created successfully";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -591,25 +591,25 @@ bool VulkanWidget::createSyncObjects()
|
||||||
bool VulkanWidget::recreateSwapchain()
|
bool VulkanWidget::recreateSwapchain()
|
||||||
{
|
{
|
||||||
qDebug() << "Recreating swapchain...";
|
qDebug() << "Recreating swapchain...";
|
||||||
|
|
||||||
// Wait for device to be idle
|
// Wait for device to be idle
|
||||||
vkDeviceWaitIdle(m_device);
|
vkDeviceWaitIdle(m_device);
|
||||||
|
|
||||||
// Cleanup old swapchain
|
// Cleanup old swapchain
|
||||||
cleanupSwapchain();
|
cleanupSwapchain();
|
||||||
|
|
||||||
// Create new swapchain
|
// Create new swapchain
|
||||||
if (!createSwapchain()) {
|
if (!createSwapchain()) {
|
||||||
qDebug() << "Failed to recreate swapchain";
|
qDebug() << "Failed to recreate swapchain";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update renderer with new surface dimensions
|
// Update renderer with new surface dimensions
|
||||||
if (m_renderer) {
|
if (m_renderer) {
|
||||||
qDebug() << "Updating VulkanRenderer to surface size:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
qDebug() << "Updating VulkanRenderer to surface size:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
||||||
m_renderer->resize(m_surfaceWidth, m_surfaceHeight);
|
m_renderer->resize(m_surfaceWidth, m_surfaceHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Swapchain recreated successfully";
|
qDebug() << "Swapchain recreated successfully";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -619,16 +619,16 @@ void VulkanWidget::renderFrame()
|
||||||
if (!m_initialized || !m_renderingEnabled) {
|
if (!m_initialized || !m_renderingEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for previous frame
|
// Wait for previous frame
|
||||||
vkWaitForFences(m_device, 1, &m_inFlightFences[m_currentFrame], VK_TRUE, UINT64_MAX);
|
vkWaitForFences(m_device, 1, &m_inFlightFences[m_currentFrame], VK_TRUE, UINT64_MAX);
|
||||||
|
|
||||||
// Acquire next image
|
// Acquire next image
|
||||||
uint32_t imageIndex;
|
uint32_t imageIndex;
|
||||||
VkResult result = vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX,
|
VkResult result = vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX,
|
||||||
m_imageAvailableSemaphores[m_currentFrame],
|
m_imageAvailableSemaphores[m_currentFrame],
|
||||||
VK_NULL_HANDLE, &imageIndex);
|
VK_NULL_HANDLE, &imageIndex);
|
||||||
|
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
recreateSwapchain();
|
recreateSwapchain();
|
||||||
return;
|
return;
|
||||||
|
|
@ -636,18 +636,18 @@ void VulkanWidget::renderFrame()
|
||||||
qDebug() << "Failed to acquire swapchain image";
|
qDebug() << "Failed to acquire swapchain image";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset fence
|
// Reset fence
|
||||||
vkResetFences(m_device, 1, &m_inFlightFences[m_currentFrame]);
|
vkResetFences(m_device, 1, &m_inFlightFences[m_currentFrame]);
|
||||||
|
|
||||||
// Record command buffer
|
// Record command buffer
|
||||||
vkResetCommandBuffer(m_commandBuffers[m_currentFrame], 0);
|
vkResetCommandBuffer(m_commandBuffers[m_currentFrame], 0);
|
||||||
recordCommandBuffer(m_commandBuffers[m_currentFrame], imageIndex);
|
recordCommandBuffer(m_commandBuffers[m_currentFrame], imageIndex);
|
||||||
|
|
||||||
// Submit command buffer
|
// Submit command buffer
|
||||||
VkSubmitInfo submitInfo = {};
|
VkSubmitInfo submitInfo = {};
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
|
||||||
VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphores[m_currentFrame]};
|
VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphores[m_currentFrame]};
|
||||||
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||||
submitInfo.waitSemaphoreCount = 1;
|
submitInfo.waitSemaphoreCount = 1;
|
||||||
|
|
@ -655,37 +655,37 @@ void VulkanWidget::renderFrame()
|
||||||
submitInfo.pWaitDstStageMask = waitStages;
|
submitInfo.pWaitDstStageMask = waitStages;
|
||||||
submitInfo.commandBufferCount = 1;
|
submitInfo.commandBufferCount = 1;
|
||||||
submitInfo.pCommandBuffers = &m_commandBuffers[m_currentFrame];
|
submitInfo.pCommandBuffers = &m_commandBuffers[m_currentFrame];
|
||||||
|
|
||||||
VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphores[m_currentFrame]};
|
VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphores[m_currentFrame]};
|
||||||
submitInfo.signalSemaphoreCount = 1;
|
submitInfo.signalSemaphoreCount = 1;
|
||||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||||
|
|
||||||
result = vkQueueSubmit(m_queue, 1, &submitInfo, m_inFlightFences[m_currentFrame]);
|
result = vkQueueSubmit(m_queue, 1, &submitInfo, m_inFlightFences[m_currentFrame]);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
qDebug() << "Failed to submit draw command buffer";
|
qDebug() << "Failed to submit draw command buffer";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present
|
// Present
|
||||||
VkPresentInfoKHR presentInfo = {};
|
VkPresentInfoKHR presentInfo = {};
|
||||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
presentInfo.waitSemaphoreCount = 1;
|
presentInfo.waitSemaphoreCount = 1;
|
||||||
presentInfo.pWaitSemaphores = signalSemaphores;
|
presentInfo.pWaitSemaphores = signalSemaphores;
|
||||||
|
|
||||||
VkSwapchainKHR swapchains[] = {m_swapchain};
|
VkSwapchainKHR swapchains[] = {m_swapchain};
|
||||||
presentInfo.swapchainCount = 1;
|
presentInfo.swapchainCount = 1;
|
||||||
presentInfo.pSwapchains = swapchains;
|
presentInfo.pSwapchains = swapchains;
|
||||||
presentInfo.pImageIndices = &imageIndex;
|
presentInfo.pImageIndices = &imageIndex;
|
||||||
|
|
||||||
result = vkQueuePresentKHR(m_queue, &presentInfo);
|
result = vkQueuePresentKHR(m_queue, &presentInfo);
|
||||||
|
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || m_needsResize) {
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || m_needsResize) {
|
||||||
m_needsResize = false;
|
m_needsResize = false;
|
||||||
recreateSwapchain();
|
recreateSwapchain();
|
||||||
} else if (result != VK_SUCCESS) {
|
} else if (result != VK_SUCCESS) {
|
||||||
qDebug() << "Failed to present swapchain image";
|
qDebug() << "Failed to present swapchain image";
|
||||||
}
|
}
|
||||||
|
|
||||||
m_currentFrame = (m_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
m_currentFrame = (m_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||||
m_frameCount++;
|
m_frameCount++;
|
||||||
}
|
}
|
||||||
|
|
@ -696,7 +696,7 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
|
||||||
if (!m_renderer && m_surfaceWidth >= 100 && m_surfaceHeight >= 100) {
|
if (!m_renderer && m_surfaceWidth >= 100 && m_surfaceHeight >= 100) {
|
||||||
qDebug() << "Creating deferred VulkanRenderer with actual surface size:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
qDebug() << "Creating deferred VulkanRenderer with actual surface size:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
||||||
m_renderer = new VulkanRenderer();
|
m_renderer = new VulkanRenderer();
|
||||||
|
|
||||||
VkSurfaceFormatKHR surfaceFormat;
|
VkSurfaceFormatKHR surfaceFormat;
|
||||||
uint32_t formatCount = 0;
|
uint32_t formatCount = 0;
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr);
|
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr);
|
||||||
|
|
@ -705,7 +705,7 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
|
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
|
||||||
surfaceFormat = formats[0];
|
surfaceFormat = formats[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_renderer->initialize(m_device, m_physicalDevice,
|
if (!m_renderer->initialize(m_device, m_physicalDevice,
|
||||||
m_queue, m_queueFamilyIndex,
|
m_queue, m_queueFamilyIndex,
|
||||||
static_cast<uint32_t>(surfaceFormat.format),
|
static_cast<uint32_t>(surfaceFormat.format),
|
||||||
|
|
@ -714,48 +714,50 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
|
||||||
delete m_renderer;
|
delete m_renderer;
|
||||||
m_renderer = nullptr;
|
m_renderer = nullptr;
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Deferred VulkanRenderer initialized successfully with surface size:"
|
qDebug() << "Deferred VulkanRenderer initialized successfully with surface size:"
|
||||||
<< m_surfaceWidth << "x" << m_surfaceHeight;
|
<< m_surfaceWidth << "x" << m_surfaceHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use VulkanRenderer if available
|
// Use VulkanRenderer if available
|
||||||
if (m_renderer) {
|
if (m_renderer) {
|
||||||
if (imageIndex >= m_swapchainImageViews.size()) {
|
if (imageIndex >= m_swapchainImageViews.size()) {
|
||||||
qDebug() << "ERROR: imageIndex out of bounds!";
|
qDebug() << "ERROR: imageIndex out of bounds!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageView imageView = reinterpret_cast<VkImageView>(m_swapchainImageViews[imageIndex]);
|
VkImageView imageView = reinterpret_cast<VkImageView>(m_swapchainImageViews[imageIndex]);
|
||||||
|
|
||||||
// Build lock info string
|
// Build lock info string
|
||||||
QString lockInfo;
|
QString lockInfo;
|
||||||
if (m_lastLockTime.isValid()) {
|
if (m_lastLockTime.isValid()) {
|
||||||
lockInfo = QString("Last Lock: %1\nDuration: %2s\nLock Count: %3")
|
lockInfo = QString("Last Lock: %1\nDuration: %2s\nFrame Count at Lock: %3\nFrames During Lock: %4\nLock Count: %5")
|
||||||
.arg(m_lastLockTime.toString("hh:mm:ss"))
|
.arg(m_lastLockTime.toString("hh:mm:ss"))
|
||||||
.arg(m_lastLockDuration)
|
.arg(m_lastLockDuration)
|
||||||
|
.arg(m_lastLockFrameCount)
|
||||||
|
.arg(m_lockPaintFrameCount)
|
||||||
.arg(m_lockCount);
|
.arg(m_lockCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug: Print dimensions occasionally to check for mismatch
|
// Debug: Print dimensions occasionally to check for mismatch
|
||||||
static int debugCounter = 0;
|
static int debugCounter = 0;
|
||||||
if (debugCounter++ % 300 == 0) { // Every ~5 seconds at 60fps
|
if (debugCounter++ % 300 == 0) { // Every ~5 seconds at 60fps
|
||||||
qDebug() << "Rendering - Widget:" << width() << "x" << height()
|
qDebug() << "Rendering - Widget:" << width() << "x" << height()
|
||||||
<< "| Surface:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
<< "| Surface:" << m_surfaceWidth << "x" << m_surfaceHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_renderer->recordCommandBuffer(commandBuffer, imageIndex, imageView,
|
m_renderer->recordCommandBuffer(commandBuffer, imageIndex, imageView,
|
||||||
m_frameCount, m_rotationAngle, m_wavePhase,
|
m_frameCount, m_rotationAngle, m_wavePhase,
|
||||||
m_renderingEnabled, lockInfo.toStdString());
|
m_renderingEnabled, lockInfo.toStdString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: Simple clear color pass
|
// Fallback: Simple clear color pass
|
||||||
VkCommandBufferBeginInfo beginInfo = {};
|
VkCommandBufferBeginInfo beginInfo = {};
|
||||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
|
||||||
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
||||||
|
|
||||||
VkClearColorValue clearColor;
|
VkClearColorValue clearColor;
|
||||||
float hue = (m_frameCount % 360) / 360.0f;
|
float hue = (m_frameCount % 360) / 360.0f;
|
||||||
float r = std::abs(std::sin(hue * 6.28318f));
|
float r = std::abs(std::sin(hue * 6.28318f));
|
||||||
|
|
@ -765,16 +767,16 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
|
||||||
clearColor.float32[1] = g * 0.5f + 0.1f;
|
clearColor.float32[1] = g * 0.5f + 0.1f;
|
||||||
clearColor.float32[2] = b * 0.5f + 0.1f;
|
clearColor.float32[2] = b * 0.5f + 0.1f;
|
||||||
clearColor.float32[3] = 1.0f;
|
clearColor.float32[3] = 1.0f;
|
||||||
|
|
||||||
VkImageSubresourceRange range = {};
|
VkImageSubresourceRange range = {};
|
||||||
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
range.baseMipLevel = 0;
|
range.baseMipLevel = 0;
|
||||||
range.levelCount = 1;
|
range.levelCount = 1;
|
||||||
range.baseArrayLayer = 0;
|
range.baseArrayLayer = 0;
|
||||||
range.layerCount = 1;
|
range.layerCount = 1;
|
||||||
|
|
||||||
VkImage image = reinterpret_cast<VkImage>(m_swapchainImages[imageIndex]);
|
VkImage image = reinterpret_cast<VkImage>(m_swapchainImages[imageIndex]);
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier1 = {};
|
VkImageMemoryBarrier barrier1 = {};
|
||||||
barrier1.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
barrier1.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
barrier1.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
barrier1.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
@ -785,13 +787,13 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
|
||||||
barrier1.subresourceRange = range;
|
barrier1.subresourceRange = range;
|
||||||
barrier1.srcAccessMask = 0;
|
barrier1.srcAccessMask = 0;
|
||||||
barrier1.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
barrier1.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
|
||||||
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier1);
|
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier1);
|
||||||
|
|
||||||
vkCmdClearColorImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
vkCmdClearColorImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
&clearColor, 1, &range);
|
&clearColor, 1, &range);
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier2 = {};
|
VkImageMemoryBarrier barrier2 = {};
|
||||||
barrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
barrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
barrier2.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
barrier2.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
|
@ -802,10 +804,10 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
|
||||||
barrier2.subresourceRange = range;
|
barrier2.subresourceRange = range;
|
||||||
barrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
barrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
barrier2.dstAccessMask = 0;
|
barrier2.dstAccessMask = 0;
|
||||||
|
|
||||||
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier2);
|
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier2);
|
||||||
|
|
||||||
vkEndCommandBuffer(commandBuffer);
|
vkEndCommandBuffer(commandBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -818,12 +820,12 @@ void VulkanWidget::cleanupSwapchain()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_swapchainImageViews.clear();
|
m_swapchainImageViews.clear();
|
||||||
|
|
||||||
if (m_swapchain != VK_NULL_HANDLE) {
|
if (m_swapchain != VK_NULL_HANDLE) {
|
||||||
vkDestroySwapchainKHR(m_device, m_swapchain, nullptr);
|
vkDestroySwapchainKHR(m_device, m_swapchain, nullptr);
|
||||||
m_swapchain = VK_NULL_HANDLE;
|
m_swapchain = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_swapchainImages.clear();
|
m_swapchainImages.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -832,11 +834,11 @@ void VulkanWidget::cleanupVulkan()
|
||||||
if (!m_initialized) {
|
if (!m_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_device != VK_NULL_HANDLE) {
|
if (m_device != VK_NULL_HANDLE) {
|
||||||
vkDeviceWaitIdle(m_device);
|
vkDeviceWaitIdle(m_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup sync objects
|
// Cleanup sync objects
|
||||||
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
if (m_imageAvailableSemaphores[i] != VK_NULL_HANDLE) {
|
if (m_imageAvailableSemaphores[i] != VK_NULL_HANDLE) {
|
||||||
|
|
@ -849,30 +851,30 @@ void VulkanWidget::cleanupVulkan()
|
||||||
vkDestroyFence(m_device, m_inFlightFences[i], nullptr);
|
vkDestroyFence(m_device, m_inFlightFences[i], nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup command pool
|
// Cleanup command pool
|
||||||
if (m_commandPool != VK_NULL_HANDLE) {
|
if (m_commandPool != VK_NULL_HANDLE) {
|
||||||
vkDestroyCommandPool(m_device, m_commandPool, nullptr);
|
vkDestroyCommandPool(m_device, m_commandPool, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup swapchain
|
// Cleanup swapchain
|
||||||
cleanupSwapchain();
|
cleanupSwapchain();
|
||||||
|
|
||||||
// Cleanup device
|
// Cleanup device
|
||||||
if (m_device != VK_NULL_HANDLE) {
|
if (m_device != VK_NULL_HANDLE) {
|
||||||
vkDestroyDevice(m_device, nullptr);
|
vkDestroyDevice(m_device, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup surface
|
// Cleanup surface
|
||||||
if (m_surface != VK_NULL_HANDLE) {
|
if (m_surface != VK_NULL_HANDLE) {
|
||||||
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
|
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup instance
|
// Cleanup instance
|
||||||
if (m_instance != VK_NULL_HANDLE) {
|
if (m_instance != VK_NULL_HANDLE) {
|
||||||
vkDestroyInstance(m_instance, nullptr);
|
vkDestroyInstance(m_instance, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
qDebug() << "Vulkan cleanup complete";
|
qDebug() << "Vulkan cleanup complete";
|
||||||
}
|
}
|
||||||
|
|
@ -882,13 +884,13 @@ void VulkanWidget::setRenderingEnabled(bool enabled)
|
||||||
if (m_renderingEnabled == enabled) {
|
if (m_renderingEnabled == enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_renderingEnabled = enabled;
|
m_renderingEnabled = enabled;
|
||||||
|
|
||||||
if (m_renderingEnabled) {
|
if (m_renderingEnabled) {
|
||||||
qDebug() << "Vulkan rendering ENABLED - Resuming animations";
|
qDebug() << "Vulkan rendering ENABLED - Resuming animations";
|
||||||
m_renderTimer->start(16); // ~60 FPS
|
m_renderTimer->start(16); // ~60 FPS
|
||||||
|
|
||||||
// Unlocked: calculate lock duration
|
// Unlocked: calculate lock duration
|
||||||
if (m_lastLockTime.isValid()) {
|
if (m_lastLockTime.isValid()) {
|
||||||
QDateTime unlockTime = QDateTime::currentDateTime();
|
QDateTime unlockTime = QDateTime::currentDateTime();
|
||||||
|
|
@ -898,12 +900,12 @@ void VulkanWidget::setRenderingEnabled(bool enabled)
|
||||||
qDebug() << "Frames at lock:" << m_lastLockFrameCount
|
qDebug() << "Frames at lock:" << m_lastLockFrameCount
|
||||||
<< "- Frames painted during lock:" << m_lockPaintFrameCount;
|
<< "- Frames painted during lock:" << m_lockPaintFrameCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_startTime = QDateTime::currentDateTime();
|
m_startTime = QDateTime::currentDateTime();
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Vulkan rendering DISABLED - Stopping animations";
|
qDebug() << "Vulkan rendering DISABLED - Stopping animations";
|
||||||
m_renderTimer->stop();
|
m_renderTimer->stop();
|
||||||
|
|
||||||
// Locked: record lock time
|
// Locked: record lock time
|
||||||
m_pauseTime = QDateTime::currentDateTime();
|
m_pauseTime = QDateTime::currentDateTime();
|
||||||
m_lastLockTime = m_pauseTime;
|
m_lastLockTime = m_pauseTime;
|
||||||
|
|
@ -934,7 +936,7 @@ void VulkanWidget::resetFrameCount()
|
||||||
void VulkanWidget::showEvent(QShowEvent *event)
|
void VulkanWidget::showEvent(QShowEvent *event)
|
||||||
{
|
{
|
||||||
QWidget::showEvent(event);
|
QWidget::showEvent(event);
|
||||||
|
|
||||||
if (!m_initialized) {
|
if (!m_initialized) {
|
||||||
initializeVulkan();
|
initializeVulkan();
|
||||||
}
|
}
|
||||||
|
|
@ -949,12 +951,12 @@ void VulkanWidget::hideEvent(QHideEvent *event)
|
||||||
void VulkanWidget::resizeEvent(QResizeEvent *event)
|
void VulkanWidget::resizeEvent(QResizeEvent *event)
|
||||||
{
|
{
|
||||||
QWidget::resizeEvent(event);
|
QWidget::resizeEvent(event);
|
||||||
|
|
||||||
if (m_initialized) {
|
if (m_initialized) {
|
||||||
m_needsResize = true;
|
m_needsResize = true;
|
||||||
|
|
||||||
// Note: Don't update renderer size here - it will be updated after swapchain recreation
|
// Note: Don't update renderer size here - it will be updated after swapchain recreation
|
||||||
// The renderer must use the actual surface dimensions (m_surfaceWidth/Height),
|
// The renderer must use the actual surface dimensions (m_surfaceWidth/Height),
|
||||||
// not the widget dimensions, which may differ on high DPI displays
|
// not the widget dimensions, which may differ on high DPI displays
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -979,13 +981,13 @@ void VulkanWidget::onRenderTimer()
|
||||||
if (m_rotationAngle >= 360.0) {
|
if (m_rotationAngle >= 360.0) {
|
||||||
m_rotationAngle -= 360.0;
|
m_rotationAngle -= 360.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_wavePhase += 0.05;
|
m_wavePhase += 0.05;
|
||||||
if (m_wavePhase >= 2 * M_PI) {
|
if (m_wavePhase >= 2 * M_PI) {
|
||||||
m_wavePhase -= 2 * M_PI;
|
m_wavePhase -= 2 * M_PI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFrame();
|
renderFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -998,9 +1000,9 @@ void VulkanWidget::setError(const QString &error)
|
||||||
std::vector<const char*> VulkanWidget::getRequiredInstanceExtensions()
|
std::vector<const char*> VulkanWidget::getRequiredInstanceExtensions()
|
||||||
{
|
{
|
||||||
std::vector<const char*> extensions;
|
std::vector<const char*> extensions;
|
||||||
|
|
||||||
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
|
|
@ -1008,7 +1010,7 @@ std::vector<const char*> VulkanWidget::getRequiredInstanceExtensions()
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
|
extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1017,4 +1019,4 @@ std::vector<const char*> VulkanWidget::getRequiredDeviceExtensions()
|
||||||
std::vector<const char*> extensions;
|
std::vector<const char*> extensions;
|
||||||
extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ typedef VkFlags VkSurfaceTransformFlagsKHR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Vulkan渲染组件类
|
* @brief Vulkan渲染组件类
|
||||||
*
|
*
|
||||||
* 使用Qt的native window属性创建Vulkan Surface
|
* 使用Qt的native window属性创建Vulkan Surface
|
||||||
* 通过volk机制加载Vulkan函数
|
* 通过volk机制加载Vulkan函数
|
||||||
*/
|
*/
|
||||||
|
|
@ -249,7 +249,7 @@ private:
|
||||||
|
|
||||||
// VulkanRenderer
|
// VulkanRenderer
|
||||||
VulkanRenderer *m_renderer;
|
VulkanRenderer *m_renderer;
|
||||||
|
|
||||||
// 动画参数
|
// 动画参数
|
||||||
double m_rotationAngle;
|
double m_rotationAngle;
|
||||||
double m_wavePhase;
|
double m_wavePhase;
|
||||||
|
|
@ -265,4 +265,4 @@ private:
|
||||||
static const int MAX_FRAMES_IN_FLIGHT = 2;
|
static const int MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VULKANWIDGET_H
|
#endif // VULKANWIDGET_H
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue