Add GPU error handling and performance optimizations

Introduces a comprehensive GPU configuration and fallback system to resolve GPU process launch failures (Error 18), including new modules for GPU management and performance monitoring. Adds a GPU diagnostics HTML page, optimized CSS for rendering, and a diagnostic startup script. Updates main and preload scripts for improved stability, async file operations, and enhanced API exposure. Site history and bookmarks handling are optimized for performance and reliability.
This commit is contained in:
2025-07-26 14:38:05 +12:00
parent 0b61f86dd4
commit fbd9ba8a1b
10 changed files with 1081 additions and 59 deletions
+215
View File
@@ -0,0 +1,215 @@
<!DOCTYPE html>
<html>
<head>
<title>GPU Diagnostics - Nebula Browser</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.status {
padding: 10px;
margin: 10px 0;
border-radius: 4px;
}
.status.good { background: #d4edda; color: #155724; }
.status.warning { background: #fff3cd; color: #856404; }
.status.error { background: #f8d7da; color: #721c24; }
button {
background: #007bff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
margin: 5px;
}
button:hover { background: #0056b3; }
pre {
background: #f8f9fa;
padding: 10px;
border-radius: 4px;
overflow-x: auto;
font-size: 12px;
}
.canvas-test {
border: 1px solid #ccc;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>GPU Diagnostics</h1>
<div id="gpu-status" class="status">
<h3>GPU Status</h3>
<p>Loading GPU information...</p>
</div>
<div class="status">
<h3>WebGL Test</h3>
<canvas id="webgl-canvas" class="canvas-test" width="300" height="150"></canvas>
<p id="webgl-status">Testing WebGL...</p>
</div>
<div class="status">
<h3>Canvas 2D Acceleration Test</h3>
<canvas id="canvas2d" class="canvas-test" width="300" height="150"></canvas>
<p id="canvas2d-status">Testing Canvas 2D...</p>
</div>
<div>
<h3>Actions</h3>
<button onclick="refreshGPUInfo()">Refresh GPU Info</button>
<button onclick="forceGC()">Force Garbage Collection</button>
<button onclick="applyFallback(1)">Apply GPU Fallback Level 1</button>
<button onclick="applyFallback(2)">Apply GPU Fallback Level 2</button>
</div>
<div>
<h3>Detailed GPU Information</h3>
<pre id="gpu-details">Loading...</pre>
</div>
</div>
<script>
async function refreshGPUInfo() {
try {
const gpuInfo = await window.electronAPI.invoke('get-gpu-info');
const statusDiv = document.getElementById('gpu-status');
const detailsDiv = document.getElementById('gpu-details');
if (gpuInfo.error) {
statusDiv.className = 'status error';
statusDiv.innerHTML = `<h3>GPU Status</h3><p>Error: ${gpuInfo.error}</p>`;
} else {
const isGPUWorking = checkGPUFeatures(gpuInfo.featureStatus);
statusDiv.className = `status ${isGPUWorking ? 'good' : 'warning'}`;
statusDiv.innerHTML = `
<h3>GPU Status</h3>
<p><strong>Hardware Acceleration:</strong> ${isGPUWorking ? 'Enabled' : 'Disabled/Limited'}</p>
<p><strong>Fallback Level:</strong> ${gpuInfo.fallbackStatus?.fallbackLevel || 0}</p>
<p><strong>GPU Enabled:</strong> ${gpuInfo.fallbackStatus?.gpuEnabled ? 'Yes' : 'No'}</p>
`;
}
detailsDiv.textContent = JSON.stringify(gpuInfo, null, 2);
} catch (err) {
console.error('Failed to get GPU info:', err);
document.getElementById('gpu-status').innerHTML = `<h3>GPU Status</h3><p>Error: ${err.message}</p>`;
}
}
function checkGPUFeatures(features) {
const criticalFeatures = ['gpu_compositing', 'webgl', 'webgl2'];
return criticalFeatures.some(feature =>
features[feature] && !features[feature].includes('disabled')
);
}
async function forceGC() {
try {
await window.electronAPI.invoke('force-gc');
alert('Garbage collection completed');
} catch (err) {
alert('Failed to force GC: ' + err.message);
}
}
async function applyFallback(level) {
try {
const result = await window.electronAPI.invoke('apply-gpu-fallback', level);
if (result.success) {
alert(`Applied GPU fallback level ${level}. App restart may be required.`);
} else {
alert('Failed to apply fallback: ' + result.error);
}
} catch (err) {
alert('Failed to apply fallback: ' + err.message);
}
}
// Test WebGL
function testWebGL() {
const canvas = document.getElementById('webgl-canvas');
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
const status = document.getElementById('webgl-status');
if (gl) {
// Draw a simple triangle
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, `
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
`);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, `
precision mediump float;
void main() {
gl_Color = vec4(0.0, 1.0, 0.0, 1.0);
}
`);
gl.compileShader(fragmentShader);
status.textContent = 'WebGL: Available ✓';
status.parentElement.className = 'status good';
// Clear with green color to show it's working
gl.clearColor(0.0, 0.8, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
} else {
status.textContent = 'WebGL: Not Available ✗';
status.parentElement.className = 'status error';
}
}
// Test Canvas 2D
function testCanvas2D() {
const canvas = document.getElementById('canvas2d');
const ctx = canvas.getContext('2d');
const status = document.getElementById('canvas2d-status');
try {
// Draw some graphics to test acceleration
const gradient = ctx.createLinearGradient(0, 0, 300, 0);
gradient.addColorStop(0, '#ff0000');
gradient.addColorStop(1, '#0000ff');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 300, 150);
ctx.fillStyle = 'white';
ctx.font = '20px Arial';
ctx.fillText('Canvas 2D Working!', 50, 80);
status.textContent = 'Canvas 2D: Working ✓';
status.parentElement.className = 'status good';
} catch (err) {
status.textContent = 'Canvas 2D: Error - ' + err.message;
status.parentElement.className = 'status error';
}
}
// Initialize tests
window.addEventListener('DOMContentLoaded', () => {
refreshGPUInfo();
testWebGL();
testCanvas2D();
});
</script>
</body>
</html>