shader-converter-wasm
Version:
WebAssembly-based shader language converter and validator. Convert between GLSL, WGSL, SPIR-V, Metal, and HLSL in the browser.
290 lines (217 loc) • 7.8 kB
Markdown
# Shader Converter WASM
[](https://www.npmjs.com/package/shader-converter-wasm)
[](https://github.com/yourusername/shader-converter-wasm/blob/main/LICENSE)
A WebAssembly-based shader language converter and validator for the browser. Convert between GLSL, WGSL, SPIR-V, Metal, and HLSL with zero native dependencies.
## ✨ Features
- 🔄 **15 Conversion Paths**: Convert between GLSL ↔ WGSL ↔ SPIR-V → Metal/HLSL
- ✅ **Validation**: Syntax and semantic validation with detailed error reporting
- 🔍 **Auto-Detection**: Intelligent shader language detection with confidence scoring
- 📦 **Resource Analysis**: Extract uniforms, textures, inputs, and outputs
- 🎯 **Entry Point Analysis**: Detailed entry point information
- 🧩 **SPIR-V Processing**: Binary and assembly manipulation
- 🚀 **Browser-Native**: Runs entirely in the browser via WebAssembly
- 📦 **Zero Dependencies**: No native toolchain required
## 📦 Installation
```bash
npm install shader-converter-wasm
```
## 🚀 Quick Start
```javascript
import init, { ShaderConverter } from 'shader-converter-wasm';
// Initialize WASM module
await init();
// Create converter instance
const converter = new ShaderConverter();
// Convert WGSL to GLSL
const wgsl = `
@vertex
fn main(@location(0) pos: vec3<f32>) -> @builtin(position) vec4<f32> {
return vec4<f32>(pos, 1.0);
}`;
const glsl = converter.convert(wgsl, 'wgsl', 'glsl', 'vertex');
console.log(glsl);
```
## 📚 Supported Conversions
| From / To | GLSL | WGSL | SPIR-V | Metal | HLSL |
|-----------|------|------|--------|-------|------|
| **GLSL** | - | ✓ | ✓ | ✓ | ✓ |
| **WGSL** | ✓ | - | ✓ | ✓ | ✓ |
| **SPIR-V**| ✓ | ✓ | - | ✓ | ✓ |
## 🎯 Core API
### Shader Conversion
```javascript
// Basic conversion
converter.convert(source, fromFormat, toFormat, stage);
// Example: WGSL to Metal
const metal = converter.convert(wgslCode, 'wgsl', 'metal', 'fragment');
```
### Shader Validation
```javascript
// Detailed validation
const result = converter.validate_detailed(source, 'wgsl', null);
const data = JSON.parse(result);
if (data.valid) {
console.log('Valid shader!', data.stats);
} else {
console.error('Validation errors:', data.errors);
}
```
### Auto-Detection
```javascript
// Detect shader language and stage
const result = converter.detect_shader(unknownCode);
const detection = JSON.parse(result);
console.log(detection.language); // 'wgsl'
console.log(detection.confidence); // 0.95
console.log(detection.stage); // 'vertex'
```
### Resource Analysis
```javascript
// Extract shader resources
const result = converter.analyze_resources(source, 'wgsl');
const resources = JSON.parse(result);
console.log(resources.uniforms); // ['modelMatrix', 'viewMatrix']
console.log(resources.textures); // ['colorTexture', 'normalTexture']
console.log(resources.inputs); // ['position', 'normal', 'uv']
console.log(resources.outputs); // ['fragColor']
```
### Entry Point Analysis
```javascript
// Get entry point information
const result = converter.analyze_entry_points(source, 'wgsl');
const data = JSON.parse(result);
data.entry_points.forEach(ep => {
console.log(`${ep.name} (${ep.stage})`);
console.log(`Workgroup size: ${ep.workgroup_size}`);
});
```
### Best Practices Check
```javascript
// Check for performance issues and best practices
const result = converter.check_shader(source, 'wgsl');
const check = JSON.parse(result);
console.log('Complexity:', check.complexity); // 'low' | 'medium' | 'high'
console.log('Warnings:', check.warnings);
console.log('Suggestions:', check.suggestions);
```
## 📖 Complete Example
```javascript
import init, { ShaderConverter } from 'shader-converter-wasm';
async function processShader(shaderCode) {
// Initialize
await init();
const converter = new ShaderConverter();
// 1. Auto-detect language
const detection = JSON.parse(converter.detect_shader(shaderCode));
console.log(`Detected: ${detection.language} (${detection.confidence * 100}%)`);
// 2. Validate shader
const validation = JSON.parse(
converter.validate_detailed(shaderCode, detection.language, null)
);
if (!validation.valid) {
console.error('Validation errors:', validation.errors);
return;
}
// 3. Analyze resources
const resources = JSON.parse(
converter.analyze_resources(shaderCode, detection.language)
);
console.log('Resources:', resources);
// 4. Convert to other formats
const glsl = converter.convert(shaderCode, detection.language, 'glsl', null);
const metal = converter.convert(shaderCode, detection.language, 'metal', null);
const hlsl = converter.convert(shaderCode, detection.language, 'hlsl', null);
return { glsl, metal, hlsl };
}
```
## 🔧 SPIR-V Processing
```javascript
import { SpirvProcessor } from 'shader-converter-wasm';
const processor = new SpirvProcessor();
// Binary to assembly
const assembly = processor.binary_to_assembly(spirvBytes);
// Assembly to binary
const binary = processor.assembly_to_binary(assemblyText);
// Validate SPIR-V binary
const isValid = processor.validate_binary(spirvBytes);
// Get module info
const info = processor.get_module_info(spirvBytes);
```
## 📊 API Response Formats
### Detection Result
```typescript
{
language: 'glsl' | 'wgsl' | 'spirv',
confidence: number, // 0.0 - 1.0
stage: 'vertex' | 'fragment' | 'compute' | 'unknown'
}
```
### Validation Result
```typescript
{
valid: boolean,
errors?: [{
type: 'syntax' | 'semantic',
message: string
}],
stats?: {
entryPoints: number,
functions: number,
globals: number,
types: number
}
}
```
### Resource Analysis
```typescript
{
uniforms: string[],
textures: string[],
inputs: string[],
outputs: string[]
}
```
## 🎨 Use Cases
- **WebGPU Applications**: Convert GLSL shaders to WGSL
- **Shader Playgrounds**: Build online shader editors with live conversion
- **Cross-Platform Tools**: Convert shaders for multiple graphics APIs
- **Shader Analysis**: Validate and analyze shader code in the browser
- **Educational Tools**: Teach shader programming with instant feedback
## 🌐 Browser Compatibility
- Chrome 57+
- Firefox 52+
- Safari 11+
- Edge 16+
Requires WebAssembly support.
## ⚡ Performance Tips
1. **Initialize once**: Call `await init()` only once at startup
2. **Reuse instances**: Create converter/processor instances once and reuse
3. **Batch operations**: Process multiple shaders without re-initializing
```javascript
// ✓ Good
await init();
const converter = new ShaderConverter();
const result1 = converter.convert(code1, 'wgsl', 'glsl', null);
const result2 = converter.convert(code2, 'wgsl', 'metal', null);
// ✗ Bad
await init();
const result1 = new ShaderConverter().convert(code1, 'wgsl', 'glsl', null);
await init();
const result2 = new ShaderConverter().convert(code2, 'wgsl', 'metal', null);
```
## 📄 License
MIT License - see LICENSE file for details
## 🔗 Links
- [Documentation](https://github.com/yourusername/shader-converter-wasm#readme)
- [API Reference](./API.md)
- [Examples](./examples)
- [Report Issues](https://github.com/yourusername/shader-converter-wasm/issues)
## 🙏 Acknowledgments
Built with:
- [naga](https://github.com/gfx-rs/naga) - Shader translation library
- [rspirv](https://github.com/gfx-rs/rspirv) - SPIR-V parser and builder
- [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) - Rust/WASM bindings
## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
---
Made with ❤️ using Rust and WebAssembly