From d82c33863f56ac9e6702a9352aeefae771745191 Mon Sep 17 00:00:00 2001
From: scamiv <6170744+scamiv@users.noreply.github.com>
Date: Sun, 18 Jan 2026 19:16:40 +0100
Subject: [PATCH] Add WebGPU Debug Overlay and Shader Management
- Introduced WebGPUComputeMetricsEvent to track compute timing.
- Added WebGPUDebugOverlay component for displaying WebGPU performance metrics.
- Refactored TerritoryLayer to utilize new shader management for territory rendering.
- Updated shaders to support new parameters for enhanced visual effects.
- Removed deprecated territory border mode settings from UserSettingModal and SettingsModal.
- Enhanced GroundTruthData to manage new textures for owner indices and relations.
- Improved shader parameter handling in TerritoryRenderer and related classes.
This commit enhances the WebGPU rendering pipeline, providing better performance insights and visual fidelity through improved shader management and debugging capabilities.
---
src/client/InputHandler.ts | 4 +
src/client/graphics/GameRenderer.ts | 15 +
src/client/graphics/layers/SettingsModal.ts | 66 ++--
src/client/graphics/layers/TerritoryLayer.ts | 46 ++-
.../graphics/layers/WebGPUDebugOverlay.ts | 286 ++++++++++++++
.../graphics/webgpu/TerritoryRenderer.ts | 40 +-
.../graphics/webgpu/core/GroundTruthData.ts | 200 ++++++++--
.../webgpu/render/TerritoryRenderPass.ts | 63 +++-
.../webgpu/render/TerritoryShaderRegistry.ts | 353 ++++++++++++++++++
.../graphics/webgpu/shaders/render/retro.wgsl | 303 +++++++++++++++
.../webgpu/shaders/render/territory.wgsl | 85 ++++-
src/core/game/UserSettings.ts | 12 +-
12 files changed, 1356 insertions(+), 117 deletions(-)
create mode 100644 src/client/graphics/layers/WebGPUDebugOverlay.ts
create mode 100644 src/client/graphics/webgpu/render/TerritoryShaderRegistry.ts
create mode 100644 src/client/graphics/webgpu/shaders/render/retro.wgsl
diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts
index 1c12cf61b..b24671d96 100644
--- a/src/client/InputHandler.ts
+++ b/src/client/InputHandler.ts
@@ -193,6 +193,10 @@ export class TickMetricsEvent implements GameEvent {
) {}
}
+export class WebGPUComputeMetricsEvent implements GameEvent {
+ constructor(public readonly computeMs: number) {}
+}
+
export class InputHandler {
private lastPointerX: number = 0;
private lastPointerY: number = 0;
diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts
index 28bc6789d..753fa2fb2 100644
--- a/src/client/graphics/GameRenderer.ts
+++ b/src/client/graphics/GameRenderer.ts
@@ -44,6 +44,7 @@ import { TerritoryLayer } from "./layers/TerritoryLayer";
import { UILayer } from "./layers/UILayer";
import { UnitDisplay } from "./layers/UnitDisplay";
import { UnitLayer } from "./layers/UnitLayer";
+import { WebGPUDebugOverlay } from "./layers/WebGPUDebugOverlay";
import { WinModal } from "./layers/WinModal";
export function createRenderer(
@@ -241,6 +242,16 @@ export function createRenderer(
performanceOverlay.eventBus = eventBus;
performanceOverlay.userSettings = userSettings;
+ const webgpuDebugOverlay = document.querySelector(
+ "webgpu-debug-overlay",
+ ) as WebGPUDebugOverlay;
+ if (!(webgpuDebugOverlay instanceof WebGPUDebugOverlay)) {
+ console.error("webgpu debug overlay not found");
+ }
+ webgpuDebugOverlay.eventBus = eventBus;
+ webgpuDebugOverlay.userSettings = userSettings;
+ webgpuDebugOverlay.requestUpdate();
+
const alertFrame = document.querySelector("alert-frame") as AlertFrame;
if (!(alertFrame instanceof AlertFrame)) {
console.error("alert frame not found");
@@ -318,6 +329,7 @@ export function createRenderer(
inGamePromo,
alertFrame,
performanceOverlay,
+ webgpuDebugOverlay,
];
return new GameRenderer(
@@ -328,6 +340,7 @@ export function createRenderer(
uiState,
layers,
performanceOverlay,
+ webgpuDebugOverlay,
);
}
@@ -345,6 +358,7 @@ export class GameRenderer {
public uiState: UIState,
private layers: Layer[],
private performanceOverlay: PerformanceOverlay,
+ private webgpuDebugOverlay: WebGPUDebugOverlay,
) {
// Keep the main canvas transparent; the WebGPU territory canvas renders the background.
const context = canvas.getContext("2d", { alpha: true });
@@ -451,6 +465,7 @@ export class GameRenderer {
}
this.performanceOverlay.updateFrameMetrics(duration, layerDurations);
}
+ this.webgpuDebugOverlay.updateFrameMetrics(duration);
if (duration > 50) {
console.warn(
diff --git a/src/client/graphics/layers/SettingsModal.ts b/src/client/graphics/layers/SettingsModal.ts
index a58d21462..658368279 100644
--- a/src/client/graphics/layers/SettingsModal.ts
+++ b/src/client/graphics/layers/SettingsModal.ts
@@ -149,16 +149,6 @@ export class SettingsModal extends LitElement implements Layer {
this.requestUpdate();
}
- private onTerritoryBorderModeChange(event: Event) {
- const value = (event.target as HTMLSelectElement).value;
- const mode = Number.parseInt(value, 10);
- if (!Number.isFinite(mode))
- throw new Error(`Invalid border mode: ${value}`);
-
- this.userSettings.setInt("settings.territoryBorderMode", mode);
- this.requestUpdate();
- }
-
private onToggleRandomNameModeButtonClick() {
this.userSettings.toggleRandomName();
this.requestUpdate();
@@ -184,6 +174,11 @@ export class SettingsModal extends LitElement implements Layer {
this.requestUpdate();
}
+ private onToggleWebgpuDebugOverlayButtonClick() {
+ this.userSettings.toggleWebgpuDebug();
+ this.requestUpdate();
+ }
+
private onExitButtonClick() {
// redirect to the home page
window.location.href = "/";
@@ -309,34 +304,6 @@ export class SettingsModal extends LitElement implements Layer {
-
-

-
-
- ${translateText("user_setting.territory_border_mode_label")}
-
-
- ${translateText("user_setting.territory_border_mode_desc")}
-
-
-
-
-
+
+