Enable GPU/WebGL and add persistent cache dirs

Enable hardware-accelerated rendering and persist GPU/cache data. Added a BrowserSettings() helper that enables WebGL and use it when creating Chrome/Content/MenuPopup browsers (src/app/nebula_controller.cpp). Configure CefSettings to use a persistent user data and cache directory (src/app/run.cpp) by calling nebula::ui::GetUserDataDirectory() and GetCacheDirectory(). Add command-line switches to initialize the GPU process and avoid sandbox/blocklist fallbacks (disable GPU sandbox, in-process-gpu, ignore-gpu-blocklist, enable-accelerated-video-decode, use ANGLE D3D11) to prevent GPU crashes and Chromium falling back to software rendering (src/cef/nebula_app.cpp). Implement GetUserDataDirectory() and GetCacheDirectory() (preferring %LOCALAPPDATA% with an executable-directory fallback) and expose them in the header (src/ui/paths.cpp, src/ui/paths.h). These changes ensure GPU shader caching, WebGL support, and smoother video/graphics behavior.
This commit is contained in:
2026-05-14 19:37:49 +12:00
parent 10180b7109
commit a32940a3f3
5 changed files with 82 additions and 3 deletions
+9 -3
View File
@@ -40,6 +40,12 @@ CefWindowInfo ChildWindowInfo(HWND parent, const RECT& rect) {
return info; return info;
} }
CefBrowserSettings BrowserSettings() {
CefBrowserSettings settings;
settings.webgl = STATE_ENABLED;
return settings;
}
int ParseTabId(const std::string& value) { int ParseTabId(const std::string& value) {
int tab_id = 0; int tab_id = 0;
const auto result = std::from_chars(value.data(), value.data() + value.size(), tab_id); const auto result = std::from_chars(value.data(), value.data() + value.size(), tab_id);
@@ -388,7 +394,7 @@ void NebulaController::CreateChromeBrowser() {
} }
const auto layout = window_->CurrentLayout(); const auto layout = window_->CurrentLayout();
CefBrowserSettings browser_settings; CefBrowserSettings browser_settings = BrowserSettings();
chrome_client_ = new nebula::cef::NebulaBrowserClient(nebula::cef::BrowserRole::Chrome, this); chrome_client_ = new nebula::cef::NebulaBrowserClient(nebula::cef::BrowserRole::Chrome, this);
CefWindowInfo window_info = ChildWindowInfo(window_->hwnd(), layout.chrome); CefWindowInfo window_info = ChildWindowInfo(window_->hwnd(), layout.chrome);
CefBrowserHost::CreateBrowser( CefBrowserHost::CreateBrowser(
@@ -403,7 +409,7 @@ void NebulaController::CreateContentBrowser() {
const auto* tab = tabs_.ActiveTab(); const auto* tab = tabs_.ActiveTab();
const std::string url = tab && !tab->url.empty() ? tab->url : nebula::ui::GetHomeUrl(); const std::string url = tab && !tab->url.empty() ? tab->url : nebula::ui::GetHomeUrl();
const auto layout = window_->CurrentLayout(); const auto layout = window_->CurrentLayout();
CefBrowserSettings browser_settings; CefBrowserSettings browser_settings = BrowserSettings();
content_client_ = new nebula::cef::NebulaBrowserClient(nebula::cef::BrowserRole::Content, this); content_client_ = new nebula::cef::NebulaBrowserClient(nebula::cef::BrowserRole::Content, this);
CefWindowInfo window_info = ChildWindowInfo(window_->hwnd(), layout.content); CefWindowInfo window_info = ChildWindowInfo(window_->hwnd(), layout.content);
CefBrowserHost::CreateBrowser( CefBrowserHost::CreateBrowser(
@@ -431,7 +437,7 @@ void NebulaController::CreateMenuPopupBrowser() {
} }
const auto layout = window_->CurrentLayout(); const auto layout = window_->CurrentLayout();
CefBrowserSettings browser_settings; CefBrowserSettings browser_settings = BrowserSettings();
menu_popup_client_ = new nebula::cef::NebulaBrowserClient(nebula::cef::BrowserRole::MenuPopup, this); menu_popup_client_ = new nebula::cef::NebulaBrowserClient(nebula::cef::BrowserRole::MenuPopup, this);
CefWindowInfo window_info = ChildWindowInfo(window_->hwnd(), MenuPopupRect(window_->hwnd(), layout)); CefWindowInfo window_info = ChildWindowInfo(window_->hwnd(), MenuPopupRect(window_->hwnd(), layout));
CefBrowserHost::CreateBrowser( CefBrowserHost::CreateBrowser(
+13
View File
@@ -29,6 +29,19 @@ int RunNebula(HINSTANCE instance, int show_command) {
CefSettings settings; CefSettings settings;
settings.no_sandbox = true; settings.no_sandbox = true;
// A persistent profile is required for the GPU shader cache and several
// hardware acceleration features. Without these Chromium silently falls
// back to software rendering, which causes choppy video and disables
// WebGL/WebGL2 in the GPU diagnostics page.
const std::wstring user_data_dir = nebula::ui::GetUserDataDirectory().wstring();
const std::wstring cache_dir = nebula::ui::GetCacheDirectory().wstring();
if (!user_data_dir.empty()) {
CefString(&settings.root_cache_path).FromWString(user_data_dir);
}
if (!cache_dir.empty()) {
CefString(&settings.cache_path).FromWString(cache_dir);
}
if (!CefInitialize(main_args, settings, app, nullptr)) { if (!CefInitialize(main_args, settings, app, nullptr)) {
return CefGetExitCode(); return CefGetExitCode();
} }
+20
View File
@@ -58,6 +58,26 @@ void NebulaApp::OnBeforeCommandLineProcessing(const CefString& process_type,
// The bundled UI is loaded from file:// and uses ES modules. // The bundled UI is loaded from file:// and uses ES modules.
command_line->AppendSwitch("allow-file-access-from-files"); command_line->AppendSwitch("allow-file-access-from-files");
// CefSettings.no_sandbox disables the browser-level sandbox, but Chromium
// still attempts to bring up a separate GPU sandbox inside the GPU process.
// Without the host-side sandbox plumbing this fails with STATUS_BREAKPOINT
// (-2147483645) immediately on startup, which is exactly what the GPU
// diagnostics page was showing - the GPU process crashed three times and
// Chromium then fell back to software rendering. Disabling the GPU sandbox
// matches the rest of our no_sandbox configuration and lets the GPU
// process initialize.
command_line->AppendSwitch("no-sandbox");
command_line->AppendSwitch("disable-gpu-sandbox");
command_line->AppendSwitch("in-process-gpu");
// Avoid Chromium's conservative GPU blocklist, but let Chromium choose the
// safest graphics backend for this machine. Forcing raster/zero-copy paths
// can prevent WebGL shared contexts from initializing on some drivers.
command_line->AppendSwitch("ignore-gpu-blocklist");
command_line->AppendSwitch("enable-accelerated-video-decode");
command_line->AppendSwitchWithValue("use-gl", "angle");
command_line->AppendSwitchWithValue("use-angle", "d3d11");
} }
void NebulaApp::OnContextCreated(CefRefPtr<CefBrowser> browser, void NebulaApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
+38
View File
@@ -136,6 +136,44 @@ std::filesystem::path GetExecutableDirectory() {
return std::filesystem::path(exe_path).parent_path(); return std::filesystem::path(exe_path).parent_path();
} }
std::filesystem::path GetUserDataDirectory() {
std::filesystem::path root;
wchar_t buffer[MAX_PATH] = {};
// Prefer %LOCALAPPDATA% so the profile follows Chromium conventions and
// survives executable relocation.
const DWORD length =
GetEnvironmentVariableW(L"LOCALAPPDATA", buffer, MAX_PATH);
if (length > 0 && length < MAX_PATH) {
root = std::filesystem::path(buffer);
} else {
// Fall back to a directory next to the executable so a portable
// install still gets a writable profile.
root = GetExecutableDirectory();
}
if (root.empty()) {
return {};
}
std::filesystem::path user_data = root / L"Nebula" / L"User Data";
std::error_code ec;
std::filesystem::create_directories(user_data, ec);
return user_data;
}
std::filesystem::path GetCacheDirectory() {
auto user_data = GetUserDataDirectory();
if (user_data.empty()) {
return {};
}
std::filesystem::path cache = user_data / L"Cache";
std::error_code ec;
std::filesystem::create_directories(cache, ec);
return cache;
}
std::filesystem::path GetUiPagePath(const std::wstring& page_name) { std::filesystem::path GetUiPagePath(const std::wstring& page_name) {
const auto exe_dir = GetExecutableDirectory(); const auto exe_dir = GetExecutableDirectory();
if (exe_dir.empty()) { if (exe_dir.empty()) {
+2
View File
@@ -6,6 +6,8 @@
namespace nebula::ui { namespace nebula::ui {
std::filesystem::path GetExecutableDirectory(); std::filesystem::path GetExecutableDirectory();
std::filesystem::path GetUserDataDirectory();
std::filesystem::path GetCacheDirectory();
std::filesystem::path GetUiPagePath(const std::wstring& page_name); std::filesystem::path GetUiPagePath(const std::wstring& page_name);
std::string FilePathToUrl(std::filesystem::path path); std::string FilePathToUrl(std::filesystem::path path);
std::string GetChromeUrl(); std::string GetChromeUrl();