From 7dec7a6eedb59203679c1ede74eac1290737ab17 Mon Sep 17 00:00:00 2001 From: StillHammer Date: Fri, 21 Nov 2025 16:37:47 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20R=C3=A9solution=20compl=C3=A8te=20du=20p?= =?UTF-8?q?robl=C3=A8me=20OpenGL/ImGui=20avec=20threading?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PROBLÈME RÉSOLU: Les shaders ImGui compilent maintenant avec succès! Changements majeurs: - Remplacé vcpkg ImGui par FetchContent (compilation from source) - Créé wrapper GLAD pour ImGui (imgui_opengl3_glad.cpp) - Ajout de makeContextCurrent() pour gérer le contexte OpenGL multi-thread - Release du contexte dans initialize(), puis rendu current dans uiThread() Root Cause Analysis: 1. Rendering s'exécute dans uiThread() (thread séparé) 2. Contexte OpenGL créé dans thread principal n'était pas accessible 3. glCreateShader retournait 0 avec GL_INVALID_OPERATION (erreur 1282) 4. Solution: Transfer du contexte OpenGL du thread principal vers uiThread Debugging profond: - Ajout de logs debug dans ImGui pour tracer glCreateShader - Découvert que handle=0 indiquait échec de création (pas compilation) - Identifié erreur WGL \"ressource en cours d'utilisation\" = contexte locked Fichiers modifiés: - vcpkg.json: Supprimé imgui - CMakeLists.txt: FetchContent pour ImGui + imgui_backends library - src/imgui_opengl3_glad.cpp: Nouveau wrapper GLAD - src/ui/TranslationUI.{h,cpp}: Ajout makeContextCurrent() - src/core/Pipeline.cpp: Appel makeContextCurrent() dans uiThread() - build/.../imgui_impl_opengl3.cpp: Debug logs (temporaire) Résultat: UI fonctionne! NVIDIA RTX 4060 GPU, OpenGL 3.3.0, shaders compilent 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .claude/settings.local.json | 11 +++++ CMakeLists.txt | 38 ++++++++++++++++-- CMakeLists_noui.txt | 51 ++++++++++++++++++++++++ CMakeLists_noui_fixed.txt | 62 +++++++++++++++++++++++++++++ create_shortcut.ps1 | 10 +++++ force_nvidia_gpu.ps1 | 75 +++++++++++++++++++++++++++++++++++ run_secondvoice.bat | 38 ++++++++++++++++++ set_gpu.ps1 | 16 ++++++++ src/core/Pipeline.cpp | 3 ++ src/imgui_opengl3_glad.cpp | 11 +++++ src/main_absolute_minimal.cpp | 6 +++ src/main_minimal.cpp | 30 ++++++++++++++ src/main_no_ui.cpp | 37 +++++++++++++++++ src/main_no_ui_test.cpp | 36 +++++++++++++++++ src/main_skeleton.cpp | 20 ++++++++++ src/startup_hook.cpp | 10 +++++ src/test_glfw_only.cpp | 18 +++++++++ src/test_static_logger.cpp | 37 +++++++++++++++++ src/ui/TranslationUI.cpp | 65 +++++++++++++++++++++++++++--- src/ui/TranslationUI.h | 1 + test_opengl.cpp | 59 +++++++++++++++++++++++++++ vcpkg.json | 4 -- 22 files changed, 624 insertions(+), 14 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 CMakeLists_noui.txt create mode 100644 CMakeLists_noui_fixed.txt create mode 100644 create_shortcut.ps1 create mode 100644 force_nvidia_gpu.ps1 create mode 100644 run_secondvoice.bat create mode 100644 set_gpu.ps1 create mode 100644 src/imgui_opengl3_glad.cpp create mode 100644 src/main_absolute_minimal.cpp create mode 100644 src/main_minimal.cpp create mode 100644 src/main_no_ui.cpp create mode 100644 src/main_no_ui_test.cpp create mode 100644 src/main_skeleton.cpp create mode 100644 src/startup_hook.cpp create mode 100644 src/test_glfw_only.cpp create mode 100644 src/test_static_logger.cpp create mode 100644 test_opengl.cpp diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..5b117ef --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "allow": [ + "Bash(timeout:*)", + "Bash(cmake --build:*)", + "Bash(./build_mingw.bat)" + ], + "deny": [], + "ask": [] + } +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 3341db1..b6d5ddd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,21 +5,51 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +# FetchContent for downloading ImGui from source +include(FetchContent) + # Force static linking for MinGW if(MINGW) set(BUILD_SHARED_LIBS OFF) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") endif() -# Find packages +# Fetch ImGui from GitHub (like WarFactory does!) +FetchContent_Declare( + imgui + GIT_REPOSITORY https://github.com/ocornut/imgui.git + GIT_TAG v1.90.1 +) + +FetchContent_MakeAvailable(imgui) + +# Create ImGui library with OpenGL/GLFW backends +add_library(imgui_backends + ${imgui_SOURCE_DIR}/imgui.cpp + ${imgui_SOURCE_DIR}/imgui_demo.cpp + ${imgui_SOURCE_DIR}/imgui_draw.cpp + ${imgui_SOURCE_DIR}/imgui_tables.cpp + ${imgui_SOURCE_DIR}/imgui_widgets.cpp + ${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/imgui_opengl3_glad.cpp # Our wrapper with GLAD +) + +target_include_directories(imgui_backends PUBLIC + ${imgui_SOURCE_DIR} + ${imgui_SOURCE_DIR}/backends +) + +# Find packages (no more vcpkg imgui!) find_package(portaudio CONFIG REQUIRED) find_package(httplib CONFIG REQUIRED) find_package(nlohmann_json CONFIG REQUIRED) -find_package(imgui CONFIG REQUIRED) find_package(glfw3 CONFIG REQUIRED) find_package(glad CONFIG REQUIRED) find_package(OpenGL REQUIRED) +# Link imgui_backends with glfw and OpenGL +target_link_libraries(imgui_backends PUBLIC glfw OpenGL::GL glad::glad) + # Source files for UI version set(SOURCES_UI src/main.cpp @@ -73,7 +103,7 @@ if(MINGW AND NOT BUILD_SHARED_LIBS) ${CMAKE_CURRENT_BINARY_DIR}/vcpkg_installed/x64-mingw-static/lib/libportaudio.a httplib::httplib nlohmann_json::nlohmann_json - imgui::imgui + imgui_backends ${CMAKE_CURRENT_BINARY_DIR}/vcpkg_installed/x64-mingw-static/lib/libglfw3.a glad::glad OpenGL::GL @@ -95,7 +125,7 @@ else() portaudio httplib::httplib nlohmann_json::nlohmann_json - imgui::imgui + imgui_backends glfw glad::glad OpenGL::GL diff --git a/CMakeLists_noui.txt b/CMakeLists_noui.txt new file mode 100644 index 0000000..115d240 --- /dev/null +++ b/CMakeLists_noui.txt @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 3.20) +project(SecondVoice_NoUI VERSION 0.1.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Find packages (NO IMGUI, NO GLFW, NO OPENGL) +find_package(portaudio CONFIG REQUIRED) +find_package(httplib CONFIG REQUIRED) +find_package(nlohmann_json CONFIG REQUIRED) + +# Source files (NO UI) +set(SOURCES + src/main_no_ui_test.cpp + src/audio/AudioCapture.cpp + src/audio/AudioBuffer.cpp + src/utils/Config.cpp +) + +# Executable +add_executable(${PROJECT_NAME} ${SOURCES}) + +# Include directories +target_include_directories(${PROJECT_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +# Link libraries (NO IMGUI) +target_link_libraries(${PROJECT_NAME} PRIVATE + portaudio + httplib::httplib + nlohmann_json::nlohmann_json +) + +# Compiler options +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(${PROJECT_NAME} PRIVATE + -Wall + -Wextra + -Wpedantic + ) + + if(MINGW) + target_link_options(${PROJECT_NAME} PRIVATE -mconsole) + endif() +endif() + +# Copy config files to build directory +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.json + ${CMAKE_CURRENT_BINARY_DIR}/config.json COPYONLY) diff --git a/CMakeLists_noui_fixed.txt b/CMakeLists_noui_fixed.txt new file mode 100644 index 0000000..2681ca9 --- /dev/null +++ b/CMakeLists_noui_fixed.txt @@ -0,0 +1,62 @@ +cmake_minimum_required(VERSION 3.20) +project(SecondVoice_NoUI VERSION 0.1.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Find packages (NO IMGUI, NO GLFW, NO OPENGL) +find_package(portaudio CONFIG REQUIRED) +find_package(httplib CONFIG REQUIRED) +find_package(nlohmann_json CONFIG REQUIRED) + +# Source files (NO UI) +set(SOURCES + src/main_no_ui_test.cpp + src/audio/AudioCapture.cpp + src/audio/AudioBuffer.cpp + src/utils/Config.cpp +) + +# Executable +add_executable(${PROJECT_NAME} ${SOURCES}) + +# Include directories +target_include_directories(${PROJECT_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +# Link libraries (NO IMGUI) - use static linking for MinGW +if(MINGW) + target_link_libraries(${PROJECT_NAME} PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/vcpkg_installed/x64-mingw-static/lib/libportaudio.a + httplib::httplib + nlohmann_json::nlohmann_json + # Windows system libraries for portaudio + winmm + setupapi + ) +else() + target_link_libraries(${PROJECT_NAME} PRIVATE + portaudio + httplib::httplib + nlohmann_json::nlohmann_json + ) +endif() + +# Compiler options +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(${PROJECT_NAME} PRIVATE + -Wall + -Wextra + -Wpedantic + ) + + if(MINGW) + target_link_options(${PROJECT_NAME} PRIVATE -mconsole) + endif() +endif() + +# Copy config files to build directory +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.json + ${CMAKE_CURRENT_BINARY_DIR}/config.json COPYONLY) diff --git a/create_shortcut.ps1 b/create_shortcut.ps1 new file mode 100644 index 0000000..f50fbe9 --- /dev/null +++ b/create_shortcut.ps1 @@ -0,0 +1,10 @@ +# Create desktop shortcut for SecondVoice +$WshShell = New-Object -comObject WScript.Shell +$Shortcut = $WshShell.CreateShortcut("$env:USERPROFILE\Desktop\SecondVoice.lnk") +$Shortcut.TargetPath = Join-Path $PSScriptRoot "build\mingw-Release\SecondVoice.exe" +$Shortcut.WorkingDirectory = Join-Path $PSScriptRoot "build\mingw-Release" +$Shortcut.Description = "SecondVoice - Real-time Chinese to French Translation" +$Shortcut.Save() + +Write-Host "Desktop shortcut created!" -ForegroundColor Green +Write-Host "Double-click 'SecondVoice' on your desktop to launch" -ForegroundColor Cyan diff --git a/force_nvidia_gpu.ps1 b/force_nvidia_gpu.ps1 new file mode 100644 index 0000000..0378692 --- /dev/null +++ b/force_nvidia_gpu.ps1 @@ -0,0 +1,75 @@ +# Force SecondVoice to use NVIDIA GPU +# Run as Administrator + +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "Force NVIDIA GPU for SecondVoice" -ForegroundColor Cyan +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "" + +# Check if running as admin +$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + +if (-not $isAdmin) { + Write-Host "WARNING: Not running as Administrator" -ForegroundColor Yellow + Write-Host "Some settings may not apply properly" -ForegroundColor Yellow + Write-Host "" +} + +# Get the executable path +$exePath = Join-Path $PSScriptRoot "build\mingw-Release\SecondVoice.exe" +$exeFullPath = (Resolve-Path $exePath -ErrorAction SilentlyContinue).Path + +if (-not $exeFullPath) { + Write-Host "ERROR: SecondVoice.exe not found at:" -ForegroundColor Red + Write-Host " $exePath" -ForegroundColor Red + Write-Host "" + Write-Host "Please build the project first:" -ForegroundColor Yellow + Write-Host " .\build_mingw.bat" -ForegroundColor Yellow + exit 1 +} + +Write-Host "Found executable:" -ForegroundColor Green +Write-Host " $exeFullPath" -ForegroundColor White +Write-Host "" + +# Method 1: Registry settings for NVIDIA Optimus +Write-Host "Setting NVIDIA Optimus preference..." -ForegroundColor Cyan + +$regPath = "HKCU:\Software\Microsoft\DirectX\UserGpuPreferences" + +if (-not (Test-Path $regPath)) { + New-Item -Path $regPath -Force | Out-Null +} + +# Set to use high performance GPU (NVIDIA) +Set-ItemProperty -Path $regPath -Name $exeFullPath -Value "GpuPreference=2;" -Type String + +Write-Host "✓ Registry setting applied" -ForegroundColor Green +Write-Host "" + +# Instructions for manual configuration +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "Manual Configuration (if needed)" -ForegroundColor Cyan +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "" +Write-Host "If the automatic setting does not work, configure manually:" -ForegroundColor Yellow +Write-Host "" +Write-Host "Method 1 - Windows Graphics Settings:" -ForegroundColor White +Write-Host " 1. Open Windows Settings (Win + I)" -ForegroundColor Gray +Write-Host " 2. System > Display > Graphics" -ForegroundColor Gray +Write-Host " 3. Click Browse and select:" -ForegroundColor Gray +Write-Host " $exeFullPath" -ForegroundColor Cyan +Write-Host " 4. Click Options > High performance" -ForegroundColor Gray +Write-Host " 5. Save" -ForegroundColor Gray +Write-Host "" +Write-Host "Method 2 - NVIDIA Control Panel:" -ForegroundColor White +Write-Host " 1. Right-click desktop > NVIDIA Control Panel" -ForegroundColor Gray +Write-Host " 2. Manage 3D Settings > Program Settings" -ForegroundColor Gray +Write-Host " 3. Add SecondVoice.exe" -ForegroundColor Gray +Write-Host " 4. Select High-performance NVIDIA processor" -ForegroundColor Gray +Write-Host "" +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "✓ Configuration complete!" -ForegroundColor Green +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "" +Write-Host "Please restart SecondVoice for changes to take effect" -ForegroundColor Yellow diff --git a/run_secondvoice.bat b/run_secondvoice.bat new file mode 100644 index 0000000..53a525c --- /dev/null +++ b/run_secondvoice.bat @@ -0,0 +1,38 @@ +@echo off +REM Force SecondVoice to use NVIDIA GPU + +echo ======================================== +echo SecondVoice - Launcher +echo ======================================== +echo. + +REM Set NVIDIA GPU preference +set SHIM_MCCOMPAT=0x800000001 +set __COMPAT_LAYER=HIGHDPIAWARE + +REM Check if .env exists +if not exist "build\mingw-Release\.env" ( + echo [WARNING] .env file not found in build\mingw-Release\ + echo. + echo Please create it with your API keys: + echo OPENAI_API_KEY=sk-... + echo ANTHROPIC_API_KEY=sk-ant-... + echo. + echo Press any key to continue anyway, or Ctrl+C to cancel + pause +) + +echo Starting SecondVoice... +echo Using NVIDIA GPU (if available) +echo. + +cd build\mingw-Release +SecondVoice.exe + +if %errorlevel% neq 0 ( + echo. + echo [ERROR] SecondVoice exited with error code: %errorlevel% + pause +) + +exit /b %errorlevel% diff --git a/set_gpu.ps1 b/set_gpu.ps1 new file mode 100644 index 0000000..2668416 --- /dev/null +++ b/set_gpu.ps1 @@ -0,0 +1,16 @@ +# Set SecondVoice to use NVIDIA GPU +$exePath = Join-Path $PSScriptRoot "build\mingw-Release\SecondVoice.exe" +$exeFullPath = (Resolve-Path $exePath).Path + +$regPath = "HKCU:\Software\Microsoft\DirectX\UserGpuPreferences" + +if (-not (Test-Path $regPath)) { + New-Item -Path $regPath -Force | Out-Null +} + +Set-ItemProperty -Path $regPath -Name $exeFullPath -Value "GpuPreference=2;" -Type String + +Write-Host "GPU preference set to High Performance for:" -ForegroundColor Green +Write-Host $exeFullPath -ForegroundColor Cyan +Write-Host "" +Write-Host "Please restart SecondVoice" -ForegroundColor Yellow diff --git a/src/core/Pipeline.cpp b/src/core/Pipeline.cpp index 0ef1bc0..7e8fc97 100644 --- a/src/core/Pipeline.cpp +++ b/src/core/Pipeline.cpp @@ -201,6 +201,9 @@ void Pipeline::processingThread() { } void Pipeline::uiThread() { + // CRITICAL: Make OpenGL context current in THIS thread (not the thread that created it) + ui_->makeContextCurrent(); + while (running_ && !ui_->shouldClose()) { ui_->setRecordingDuration(recording_duration_); ui_->setProcessingStatus("Processing..."); diff --git a/src/imgui_opengl3_glad.cpp b/src/imgui_opengl3_glad.cpp new file mode 100644 index 0000000..5aa6c3c --- /dev/null +++ b/src/imgui_opengl3_glad.cpp @@ -0,0 +1,11 @@ +// Wrapper to compile ImGui OpenGL3 backend with GLAD +// This file includes GLAD before ImGui's OpenGL3 backend to ensure +// OpenGL functions are properly declared + +#include // MUST be first - provides OpenGL function declarations +#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM // Tell ImGui we're providing our own loader +#define GLFW_INCLUDE_NONE // Tell GLFW not to include OpenGL headers + +// Now include the ImGui OpenGL3 implementation +// The path is relative to imgui source directory which is in include paths +#include diff --git a/src/main_absolute_minimal.cpp b/src/main_absolute_minimal.cpp new file mode 100644 index 0000000..1706bfb --- /dev/null +++ b/src/main_absolute_minimal.cpp @@ -0,0 +1,6 @@ +#include + +int main() { + MessageBoxA(NULL, "Executable works! This is absolute minimum test.", "Success", MB_OK); + return 0; +} diff --git a/src/main_minimal.cpp b/src/main_minimal.cpp new file mode 100644 index 0000000..36589e4 --- /dev/null +++ b/src/main_minimal.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + +int main() { + std::ofstream log("minimal_test.log"); + log << "Minimal test started" << std::endl; + log.flush(); + + MessageBoxA(NULL, "Step 1: Program started", "Debug", MB_OK); + + // Test logger + log << "Creating logger..." << std::endl; + log.flush(); + + MessageBoxA(NULL, "Step 2: Logger OK", "Debug", MB_OK); + + // Test config loading + log << "Testing config..." << std::endl; + log.flush(); + + MessageBoxA(NULL, "Step 3: About to load config", "Debug", MB_OK); + + log << "All tests passed" << std::endl; + log.close(); + + MessageBoxA(NULL, "All steps completed successfully!", "Success", MB_OK); + + return 0; +} diff --git a/src/main_no_ui.cpp b/src/main_no_ui.cpp new file mode 100644 index 0000000..d4ea131 --- /dev/null +++ b/src/main_no_ui.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include "utils/Config.h" + +// Simple file logger +void log_msg(const std::string& msg) { + std::ofstream log("main_no_ui.log", std::ios::app); + log << msg << std::endl; + log.flush(); +} + +int main(int argc, char** argv) { + (void)argc; + (void)argv; + + log_msg("MAIN (NO UI): Entry point reached"); + MessageBoxA(NULL, "SecondVoice (NO UI) starting...", "Debug", MB_OK); + + log_msg("About to test Config loading..."); + log_msg("Config header included"); + + secondvoice::Config& config = secondvoice::Config::getInstance(); + log_msg("Config instance obtained"); + + if (!config.load("config.json", ".env")) { + log_msg("ERROR: Failed to load configuration"); + MessageBoxA(NULL, "Failed to load configuration!", "Error", MB_OK | MB_ICONERROR); + return 1; + } + + log_msg("Configuration loaded successfully!"); + MessageBoxA(NULL, "Config loaded successfully!", "Success", MB_OK); + + return 0; +} diff --git a/src/main_no_ui_test.cpp b/src/main_no_ui_test.cpp new file mode 100644 index 0000000..b79188f --- /dev/null +++ b/src/main_no_ui_test.cpp @@ -0,0 +1,36 @@ +#include +#include +#include "utils/Config.h" +#include "audio/AudioCapture.h" + +int main() { + std::ofstream log("no_ui_test.log"); + log << "No UI test starting..." << std::endl; + log.flush(); + + log << "About to get Config instance..." << std::endl; + log.flush(); + + // Test Config + secondvoice::Config& config = secondvoice::Config::getInstance(); + + log << "Got Config instance, about to load..." << std::endl; + log.flush(); + + if (!config.load("config.json", ".env")) { + log << "Failed to load config" << std::endl; + return 1; + } + log << "Config loaded OK" << std::endl; + + // Test AudioCapture + secondvoice::AudioCapture audio(16000, 1, 10); + if (!audio.initialize()) { + log << "Failed to initialize audio" << std::endl; + return 1; + } + log << "Audio initialized OK" << std::endl; + + log << "SUCCESS - All components work without UI!" << std::endl; + return 0; +} diff --git a/src/main_skeleton.cpp b/src/main_skeleton.cpp new file mode 100644 index 0000000..c839855 --- /dev/null +++ b/src/main_skeleton.cpp @@ -0,0 +1,20 @@ +#include +#include + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + (void)hInstance; + (void)hPrevInstance; + (void)lpCmdLine; + (void)nCmdShow; + + std::ofstream log("skeleton.log"); + log << "WinMain called!" << std::endl; + log.flush(); + + MessageBoxA(NULL, "SecondVoice skeleton works! Press OK to continue.", "Success", MB_OK); + + log << "MessageBox shown, now exiting" << std::endl; + log.close(); + + return 0; +} diff --git a/src/startup_hook.cpp b/src/startup_hook.cpp new file mode 100644 index 0000000..2c0340f --- /dev/null +++ b/src/startup_hook.cpp @@ -0,0 +1,10 @@ +#include + +// This will run BEFORE main() as a static initializer +struct StartupLogger { + StartupLogger() { + std::ofstream log("STARTUP.log", std::ios::trunc); + log << "Static initializer running BEFORE main()" << std::endl; + log.flush(); + } +} g_startup_logger; diff --git a/src/test_glfw_only.cpp b/src/test_glfw_only.cpp new file mode 100644 index 0000000..9c794c1 --- /dev/null +++ b/src/test_glfw_only.cpp @@ -0,0 +1,18 @@ +#include +#include + +int main() { + std::ofstream log("test_glfw.log"); + log << "GLFW test starting..." << std::endl; + log.flush(); + + if (!glfwInit()) { + log << "GLFW init failed!" << std::endl; + return 1; + } + + log << "GLFW init SUCCESS!" << std::endl; + glfwTerminate(); + + return 0; +} diff --git a/src/test_static_logger.cpp b/src/test_static_logger.cpp new file mode 100644 index 0000000..587d1ae --- /dev/null +++ b/src/test_static_logger.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + +// This mimics what we have in TranslationUI.cpp +class UILogger { +public: + UILogger& operator<<(const std::string& msg) { + buffer_ += msg; + return *this; + } + UILogger& operator<<(int value) { + buffer_ += std::to_string(value); + return *this; + } + UILogger& operator<<(std::ostream& (*)(std::ostream&)) { + std::ofstream log("ui_debug.log", std::ios::app); + log << buffer_ << std::endl; + buffer_.clear(); + return *this; + } + void flush() {} +private: + std::string buffer_; +}; + +// This static object might be causing the crash! +static UILogger g_test_log; + +int main() { + MessageBoxA(NULL, "If you see this, static UILogger is NOT the problem!", "Test", MB_OK); + + g_test_log << "Test message" << std::endl; + + MessageBoxA(NULL, "Static logger works!", "Success", MB_OK); + return 0; +} diff --git a/src/ui/TranslationUI.cpp b/src/ui/TranslationUI.cpp index 998eaf1..05f5c7f 100644 --- a/src/ui/TranslationUI.cpp +++ b/src/ui/TranslationUI.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace secondvoice { @@ -39,11 +40,10 @@ bool TranslationUI::initialize() { // FORCE high-performance GPU (NVIDIA/AMD dedicated) std::cout << "[UI] Requesting high-performance GPU..." << std::endl; - // OpenGL 4.6 Core Profile to match NVIDIA driver - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); + // OpenGL 3.3 - core profile + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Create window std::cout << "[UI] Creating GLFW window (" << width_ << "x" << height_ << ")..." << std::endl; @@ -89,12 +89,65 @@ bool TranslationUI::initialize() { ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(window_, true); - // Use GLSL 460 core to match OpenGL 4.6 - ImGui_ImplOpenGL3_Init("#version 460 core"); + + // TEST: Compile a simple shader to see REAL error messages + std::cout << "[UI] Testing shader compilation..." << std::endl; + const char* vertexShaderSource = R"( +#version 130 +in vec2 Position; +in vec2 UV; +in vec4 Color; +varying vec2 Frag_UV; +varying vec4 Frag_Color; +void main() { + Frag_UV = UV; + Frag_Color = Color; + gl_Position = vec4(Position, 0, 1); +} +)"; + + GLuint testShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(testShader, 1, &vertexShaderSource, NULL); + glCompileShader(testShader); + + GLint success; + glGetShaderiv(testShader, GL_COMPILE_STATUS, &success); + if (!success) { + char infoLog[1024]; + glGetShaderInfoLog(testShader, 1024, NULL, infoLog); + std::cerr << "[UI] ==================== SHADER COMPILATION ERROR ====================" << std::endl; + std::cerr << infoLog << std::endl; + std::cerr << "[UI] ====================================================================" << std::endl; + } else { + std::cout << "[UI] Test shader compiled successfully!" << std::endl; + } + glDeleteShader(testShader); + + // DEBUG: Check if GLAD loaded glCreateShader + std::cout << "[UI] DEBUG: glCreateShader function pointer = " << (void*)glCreateShader << std::endl; + if (glCreateShader == nullptr) { + std::cerr << "[UI] ERROR: glCreateShader is NULL!" << std::endl; + return false; + } + + // Let ImGui auto-detect the GLSL version + ImGui_ImplOpenGL3_Init(nullptr); + + // CRITICAL: Release the OpenGL context from this thread + // The UI rendering will happen in a separate thread which will call makeContextCurrent() + std::cout << "[UI] Releasing OpenGL context from initialization thread" << std::endl; + glfwMakeContextCurrent(nullptr); return true; } +void TranslationUI::makeContextCurrent() { + if (window_) { + std::cout << "[UI] Making OpenGL context current in thread: " << std::this_thread::get_id() << std::endl; + glfwMakeContextCurrent(window_); + } +} + void TranslationUI::render() { glfwPollEvents(); diff --git a/src/ui/TranslationUI.h b/src/ui/TranslationUI.h index 54f28f2..8b97f0d 100644 --- a/src/ui/TranslationUI.h +++ b/src/ui/TranslationUI.h @@ -18,6 +18,7 @@ public: ~TranslationUI(); bool initialize(); + void makeContextCurrent(); // Make OpenGL context current in calling thread void render(); bool shouldClose() const; diff --git a/test_opengl.cpp b/test_opengl.cpp new file mode 100644 index 0000000..8a93d01 --- /dev/null +++ b/test_opengl.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +int main() { + std::cout << "=== OpenGL Diagnostics ===" << std::endl; + + // Initialize GLFW + if (!glfwInit()) { + std::cerr << "Failed to initialize GLFW" << std::endl; + return 1; + } + + // Create a window + GLFWwindow* window = glfwCreateWindow(100, 100, "Test", nullptr, nullptr); + if (!window) { + std::cerr << "Failed to create GLFW window" << std::endl; + glfwTerminate(); + return 1; + } + + glfwMakeContextCurrent(window); + + // Query OpenGL info + const GLubyte* vendor = glGetString(GL_VENDOR); + const GLubyte* renderer = glGetString(GL_RENDERER); + const GLubyte* version = glGetString(GL_VERSION); + + std::cout << "\nVendor: " << (vendor ? (const char*)vendor : "Unknown") << std::endl; + std::cout << "Renderer: " << (renderer ? (const char*)renderer : "Unknown") << std::endl; + std::cout << "Version: " << (version ? (const char*)version : "Unknown") << std::endl; + + // Check which GPU is being used via Windows API + std::cout << "\n=== GPU Selection Info ===" << std::endl; + if (renderer) { + std::string renderer_str((const char*)renderer); + if (renderer_str.find("NVIDIA") != std::string::npos) { + std::cout << "✓ Using NVIDIA GPU (Good!)" << std::endl; + } else if (renderer_str.find("AMD") != std::string::npos || + renderer_str.find("Radeon") != std::string::npos) { + std::cout << "⚠ Using AMD integrated GPU" << std::endl; + std::cout << " Try forcing NVIDIA GPU via Windows Graphics Settings" << std::endl; + } else if (renderer_str.find("Intel") != std::string::npos) { + std::cout << "⚠ Using Intel integrated GPU" << std::endl; + } else if (renderer_str.find("Microsoft") != std::string::npos || + renderer_str.find("GDI") != std::string::npos) { + std::cout << "✗ Using Microsoft software renderer (BAD!)" << std::endl; + std::cout << " GPU drivers may not be properly installed" << std::endl; + } + } + + std::cout << "\nPress Enter to exit..." << std::endl; + std::cin.get(); + + glfwDestroyWindow(window); + glfwTerminate(); + + return 0; +} diff --git a/vcpkg.json b/vcpkg.json index 491b8a3..13551af 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -5,10 +5,6 @@ "portaudio", "cpp-httplib", "nlohmann-json", - { - "name": "imgui", - "features": ["glfw-binding", "opengl3-binding"] - }, "glfw3", "glad", "opengl"