npm package: @flux-gpu/core
Description: TypeScript-first WebGPU library - Core package
Latest version: 0.2.0

# @flux-gpu/core

[![npm version](https://img.shields.io/npm/v/@flux-gpu/core.svg)](https://www.npmjs.com/package/@flux-gpu/core)
[![bundle size](https://img.shields.io/bundlephobia/minzip/@flux-gpu/core)](https://bundlephobia.com/package/@flux-gpu/core)
[![TypeScript](https://img.shields.io/badge/TypeScript-first-blue.svg)](https://www.typescriptlang.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**A TypeScript-first WebGPU library that makes GPU programming accessible without hiding its power.**

```typescript
import { createFlux } from '@flux-gpu/core';

const flux = await createFlux(canvas);

const vertices = flux.vertexBuffer({
  data: new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]),
  attributes: [{ format: 'float32x2', shaderLocation: 0 }],
});

const pipeline = flux.renderPipeline()
  .vertex({ shader: vertexCode, buffers: [vertices] })
  .fragment({ shader: fragCode, targets: [flux.preferredFormat] })
  .build();

flux.frame((pass) => {
  pass.pipeline(pipeline).vertices(vertices).draw(3);
});
```

## Why Flux?

Flux occupies the sweet spot between raw WebGPU verbosity and high-level engine abstraction:

| Aspect | Raw WebGPU | **Flux** | Three.js/Babylon |
|--------|------------|----------|------------------|
| Lines for Triangle | ~120 | **~25** | ~15 |
| Learning Curve | Steep | **Low** | Low |
| GPU Control | Complete | **Full** | Abstracted |
| TypeScript | Optional | **First-class** | Optional |
| Bundle Size | 0KB | **~15KB** | 600KB+ |
| Mental Model | WebGPU | **WebGPU** | Scene Graph |
| Hidden Costs | None | **None** | Many |

## Features

- **TypeScript-First** — Strong typing catches GPU errors at compile time
- **Progressive Abstraction** — Simple API for basics, full control when needed
- **Zero Hidden Costs** — Every GPU operation is explicit and traceable
- **Escape Hatches** — Access raw WebGPU objects (`flux.device`, `buffer.native`) anytime
- **Framework Bindings** — First-class React, Vue, and Svelte support
- **Compute Ready** — GPU compute shaders are first-class citizens
- **Debug Tools** — Built-in performance monitoring and resource inspection

## Installation

```bash
npm install @flux-gpu/core

# Framework bindings (optional)
npm install @flux-gpu/react   # React hooks
npm install @flux-gpu/vue     # Vue composables
npm install @flux-gpu/svelte  # Svelte stores
```

## Quick Start

### Hello Triangle

```typescript
import { createFlux } from '@flux-gpu/core';

const canvas = document.querySelector('canvas')!;
const flux = await createFlux(canvas);

// Create vertex buffer with automatic layout inference
const vertices = flux.vertexBuffer({
  data: new Float32Array([
     0.0,  0.5,  1, 0, 0,  // top (red)
    -0.5, -0.5,  0, 1, 0,  // bottom-left (green)
     0.5, -0.5,  0, 0, 1,  // bottom-right (blue)
  ]),
  attributes: [
    { format: 'float32x2', shaderLocation: 0 },  // position
    { format: 'float32x3', shaderLocation: 1 },  // color
  ],
});

// Create shader
const shader = flux.shader(`
  struct VertexOutput {
    @builtin(position) pos: vec4f,
    @location(0) color: vec3f,
  }

  @vertex
  fn vs(@location(0) pos: vec2f, @location(1) color: vec3f) -> VertexOutput {
    return VertexOutput(vec4f(pos, 0.0, 1.0), color);
  }

  @fragment
  fn fs(@location(0) color: vec3f) -> @location(0) vec4f {
    return vec4f(color, 1.0);
  }
`);

// Build pipeline with fluent API
const pipeline = flux.renderPipeline()
  .vertex({ shader, entryPoint: 'vs', buffers: [vertices] })
  .fragment({ shader, entryPoint: 'fs', targets: [flux.preferredFormat] })
  .build();

// Render
function render() {
  flux.frame((pass) => {
    pass.pipeline(pipeline).vertices(vertices).draw(3);
  });
  requestAnimationFrame(render);
}
render();
```

### GPU Compute

```typescript
import { createFlux } from '@flux-gpu/core';

const flux = await createFlux(); // Headless mode for compute-only

// Create storage buffers
const input = flux.storageBuffer({ data: new Float32Array([1, 2, 3, 4]) });
const output = flux.storageBuffer({ data: 16, readBack: true });

// Compute shader
const shader = flux.shader(`
  @group(0) @binding(0) var<storage, read> input: array<f32>;
  @group(0) @binding(1) var<storage, read_write> output: array<f32>;

  @compute @workgroup_size(64)
  fn main(@builtin(global_invocation_id) id: vec3u) {
    output[id.x] = input[id.x] * 2.0;
  }
`);

// Build compute pipeline
const pipeline = flux.computePipeline()
  .shader(shader, 'main')
  .workgroupSize(64)
  .build();

// Execute
const batch = flux.batch();
const computePass = batch.computePass();
computePass.setPipeline(pipeline.native);
computePass.setBindGroup(0, flux.createBindGroupFromPipeline(pipeline.native, 0, {
  0: input,
  1: output,
}));
computePass.dispatchWorkgroups(1);
computePass.end();
batch.submit();

// Read results
const result = await output.readBack();
console.log(result); // Float32Array [2, 4, 6, 8]
```

## Core API

### Initialization

```typescript
// With canvas
const flux = await createFlux(canvas);
const flux = await createFlux('#my-canvas');

// Headless (compute only)
const flux = await createFlux();

// With options
const flux = await createFlux({
  canvas,
  powerPreference: 'high-performance',
});
```

### Buffers

```typescript
// Vertex buffer with automatic stride calculation
const positions = flux.vertexBuffer({
  data: new Float32Array([...]),
  attributes: [
    { format: 'float32x3', shaderLocation: 0 },
    { format: 'float32x2', shaderLocation: 1 },
  ],
});

// Index buffer (auto-detects uint16/uint32)
const indices = flux.indexBuffer({
  data: new Uint16Array([0, 1, 2]),
});

// Uniform buffer
const uniforms = flux.uniformBuffer({ size: 64 });
uniforms.write(new Float32Array([...]));

// Storage buffer for compute
const storage = flux.storageBuffer({
  data: new Float32Array(1024),
  readBack: true,
});
```

### Pipelines

```typescript
// Render pipeline (fluent builder)
const renderPipeline = flux.renderPipeline()
  .label('my-pipeline')
  .vertex({ shader, entryPoint: 'vs', buffers: [vertices] })
  .fragment({ shader, entryPoint: 'fs', targets: [flux.preferredFormat] })
  .primitive({ topology: 'triangle-list', cullMode: 'back' })
  .depthStencil({ format: 'depth24plus', depthWriteEnabled: true })
  .build();

// Compute pipeline
const computePipeline = flux.computePipeline()
  .shader(computeShader, 'main')
  .workgroupSize(256)
  .build();
```

### Rendering

```typescript
// Simple frame helper
flux.frame((pass) => {
  pass
    .pipeline(pipeline)
    .bindGroup(0, bindGroup)
    .vertices(vertices)
    .indices(indices)
    .drawIndexed(indexCount);
});

// Manual batching for complex scenarios
const batch = flux.batch('frame');

const renderPass = batch.renderPass({
  view: flux.getCurrentTextureView(),
  clearColor: { r: 0, g: 0, b: 0, a: 1 },
  depthView: depthTexture.createView(),
});

renderPass
  .pipeline(pipeline)
  .bindGroup(0, sceneBindGroup)
  .draw(vertexCount);
renderPass.end();

batch.submit();
```

### Escape Hatches

Flux never hides WebGPU. Access native objects anytime:

```typescript
// Access raw GPUDevice
const device = flux.device;

// Access native buffer
const gpuBuffer = myBuffer.native;

// Mix Flux and raw WebGPU
const encoder = device.createCommandEncoder();
encoder.copyBufferToBuffer(srcBuffer.native, 0, dstBuffer.native, 0, size);
device.queue.submit([encoder.finish()]);
```

## Framework Integration

### React

```tsx
import { useFlux, useFluxFrame, FluxCanvas } from '@flux-gpu/react';

function Scene() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const { flux, loading, error } = useFlux(canvasRef);

  useFluxFrame(flux, (flux, pass) => {
    pass.pipeline(pipeline).draw(3);
  });

  return <canvas ref={canvasRef} />;
}
```

### Vue

```vue
<script setup>
import { useFlux, useFluxFrame } from '@flux-gpu/vue';

const { flux, canvasRef, loading } = useFlux();

useFluxFrame(flux, (flux, pass) => {
  pass.pipeline(pipeline).draw(3);
});
</script>

<template>
  <canvas ref="canvasRef" />
</template>
```

### Svelte

```svelte
<script>
  import { createFluxStore, useFluxFrame } from '@flux-gpu/svelte';

  let canvas;
  const fluxStore = createFluxStore();

  $: if (canvas) fluxStore.init(canvas);

  useFluxFrame(fluxStore, (flux, pass) => {
    pass.pipeline(pipeline).draw(3);
  });
</script>

<canvas bind:this={canvas} />
```

## Debug Tools

```typescript
// Enable debug logging
flux.debug.enable({
  resources: true,  // Log resource creation
  commands: true,   // Log GPU commands
  timing: true,     // Performance timing
});

// Inspect resources
flux.debug.inspect(myBuffer);

// Read buffer contents (for debugging)
await flux.debug.inspectBufferContents(flux.device, myBuffer);

// Performance monitoring
const monitor = flux.debug.createPerformanceMonitor();

function render() {
  monitor.beginFrame();
  // ... render ...
  monitor.endFrame();
  
  const stats = monitor.getStats();
  console.log(`FPS: ${stats.fps.toFixed(0)}`);
}
```

## Browser Support

WebGPU is supported in:
- Chrome 113+ ✅
- Edge 113+ ✅
- Firefox Nightly (with flags) ⚠️
- Safari Technology Preview ⚠️

## Examples

- **[Hello Triangle](https://github.com/user/flux-gpu/tree/main/examples/hello-triangle)** — Basic rendering
- **[Compute Particles](https://github.com/user/flux-gpu/tree/main/examples/compute-particles)** — GPU compute with 100k particles
- **[Starling Murmuration](https://github.com/user/flux-gpu/tree/main/examples/starling-murmuration)** — 50k boids with compute shaders
- **[Deferred Rendering](https://github.com/user/flux-gpu/tree/main/examples/deferred-rendering)** — Multi-pass rendering

## Documentation

- [Getting Started](https://flux-gpu.dev/getting-started)
- [API Reference](https://flux-gpu.dev/api)
- [Concepts Guide](https://flux-gpu.dev/concepts)
- [Examples Gallery](https://flux-gpu.dev/examples)

## License

MIT © Flux GPU Contributors