Files
OpenFrontIO/src/client/graphics/webgpu/core/WebGPUDevice.ts
T
scamiv bcd1412f75 refactor: restructure WebGPU territory renderer into extensible pass-based architecture
Refactor the monolithic TerritoryWebGLRenderer into a modular, extensible
architecture that separates ground truth computation from rendering passes.
This change also includes related improvements to game state management and
hover information handling.

WebGPU Architecture Refactor:
- Extract all shaders to external .wgsl files (no inlined shaders)
- Separate ground truth data management (GroundTruthData) from rendering
- Create pass-based architecture with ComputePass and RenderPass interfaces
- Implement compute passes: StateUpdatePass, DefendedClearPass, DefendedUpdatePass
- Implement render pass: TerritoryRenderPass
- Add TerritoryRenderer orchestrator with dependency-based execution ordering
- Add WebGPUDevice for device initialization and management
- Add ShaderLoader utility for loading .wgsl files via Vite ?raw imports

Performance Optimizations:
- Dependency order computed once at init (topological sort)
- Early exit checks at orchestrator and pass levels
- Bind groups rebuilt when textures/buffers are recreated
- Zero per-frame allocations (reuse command encoders and staging buffers)

Architecture Benefits:
- Easy to extend with new compute/render passes (borders, temporal smoothing, etc.)
- Clear separation between tick-based compute and frame-based rendering
- All shaders in external files for better maintainability
- Ground truth data computed once and reused by all passes

Related Changes:
- Add defended tile state support to GameMap (isDefended/setDefended)
- Expose tileStateView() for direct GPU state access
- Extract hover info logic to HoverInfo utility
- Remove TerrainLayer (terrain now rendered by WebGPU territory pass)
- Update GameRenderer to use transparent overlay canvas
- Add viewOffset() method to TransformHandler

Files:
- Deleted: TerritoryWebGLRenderer.ts (1217 lines), TerrainLayer.ts (77 lines)
- Added: 17 new files in webgpu/ directory structure
- Updated: TerritoryLayer.ts, GameRenderer.ts, PlayerInfoOverlay.ts,
  GameMap.ts, GameView.ts, GameImpl.ts, TransformHandler.ts, vite-env.d.ts
2026-02-05 21:46:47 +01:00

67 lines
1.6 KiB
TypeScript

/**
* Manages WebGPU device initialization and canvas context configuration.
*/
export class WebGPUDevice {
public readonly device: GPUDevice;
public readonly context: GPUCanvasContext;
public readonly canvasFormat: GPUTextureFormat;
private constructor(
device: GPUDevice,
context: GPUCanvasContext,
canvasFormat: GPUTextureFormat,
) {
this.device = device;
this.context = context;
this.canvasFormat = canvasFormat;
}
/**
* Initialize WebGPU device and canvas context.
* @param canvas Canvas element to configure
* @returns WebGPUDevice instance or null if WebGPU is not available
*/
static async create(canvas: HTMLCanvasElement): Promise<WebGPUDevice | null> {
const nav = globalThis.navigator as any;
if (!nav?.gpu || typeof nav.gpu.requestAdapter !== "function") {
return null;
}
const adapter = await nav.gpu.requestAdapter();
if (!adapter) {
return null;
}
const device = await adapter.requestDevice();
const context = canvas.getContext("webgpu");
if (!context) {
return null;
}
const canvasFormat =
typeof nav.gpu.getPreferredCanvasFormat === "function"
? nav.gpu.getPreferredCanvasFormat()
: "bgra8unorm";
context.configure({
device,
format: canvasFormat,
alphaMode: "opaque",
});
return new WebGPUDevice(device, context, canvasFormat);
}
/**
* Reconfigure the canvas context (e.g., when canvas size changes).
*/
reconfigure(): void {
this.context.configure({
device: this.device,
format: this.canvasFormat,
alphaMode: "opaque",
});
}
}