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:
@@ -40,6 +40,12 @@ CefWindowInfo ChildWindowInfo(HWND parent, const RECT& rect) {
|
||||
return info;
|
||||
}
|
||||
|
||||
CefBrowserSettings BrowserSettings() {
|
||||
CefBrowserSettings settings;
|
||||
settings.webgl = STATE_ENABLED;
|
||||
return settings;
|
||||
}
|
||||
|
||||
int ParseTabId(const std::string& value) {
|
||||
int tab_id = 0;
|
||||
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();
|
||||
CefBrowserSettings browser_settings;
|
||||
CefBrowserSettings browser_settings = BrowserSettings();
|
||||
chrome_client_ = new nebula::cef::NebulaBrowserClient(nebula::cef::BrowserRole::Chrome, this);
|
||||
CefWindowInfo window_info = ChildWindowInfo(window_->hwnd(), layout.chrome);
|
||||
CefBrowserHost::CreateBrowser(
|
||||
@@ -403,7 +409,7 @@ void NebulaController::CreateContentBrowser() {
|
||||
const auto* tab = tabs_.ActiveTab();
|
||||
const std::string url = tab && !tab->url.empty() ? tab->url : nebula::ui::GetHomeUrl();
|
||||
const auto layout = window_->CurrentLayout();
|
||||
CefBrowserSettings browser_settings;
|
||||
CefBrowserSettings browser_settings = BrowserSettings();
|
||||
content_client_ = new nebula::cef::NebulaBrowserClient(nebula::cef::BrowserRole::Content, this);
|
||||
CefWindowInfo window_info = ChildWindowInfo(window_->hwnd(), layout.content);
|
||||
CefBrowserHost::CreateBrowser(
|
||||
@@ -431,7 +437,7 @@ void NebulaController::CreateMenuPopupBrowser() {
|
||||
}
|
||||
|
||||
const auto layout = window_->CurrentLayout();
|
||||
CefBrowserSettings browser_settings;
|
||||
CefBrowserSettings browser_settings = BrowserSettings();
|
||||
menu_popup_client_ = new nebula::cef::NebulaBrowserClient(nebula::cef::BrowserRole::MenuPopup, this);
|
||||
CefWindowInfo window_info = ChildWindowInfo(window_->hwnd(), MenuPopupRect(window_->hwnd(), layout));
|
||||
CefBrowserHost::CreateBrowser(
|
||||
|
||||
@@ -29,6 +29,19 @@ int RunNebula(HINSTANCE instance, int show_command) {
|
||||
CefSettings settings;
|
||||
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)) {
|
||||
return CefGetExitCode();
|
||||
}
|
||||
|
||||
@@ -58,6 +58,26 @@ void NebulaApp::OnBeforeCommandLineProcessing(const CefString& process_type,
|
||||
|
||||
// The bundled UI is loaded from file:// and uses ES modules.
|
||||
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,
|
||||
|
||||
@@ -136,6 +136,44 @@ std::filesystem::path GetExecutableDirectory() {
|
||||
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) {
|
||||
const auto exe_dir = GetExecutableDirectory();
|
||||
if (exe_dir.empty()) {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
namespace nebula::ui {
|
||||
|
||||
std::filesystem::path GetExecutableDirectory();
|
||||
std::filesystem::path GetUserDataDirectory();
|
||||
std::filesystem::path GetCacheDirectory();
|
||||
std::filesystem::path GetUiPagePath(const std::wstring& page_name);
|
||||
std::string FilePathToUrl(std::filesystem::path path);
|
||||
std::string GetChromeUrl();
|
||||
|
||||
Reference in New Issue
Block a user