GitHub Repository Guide: Developer Resources and Documentation
Navigate the open-source benchmarking ecosystem, contribute to development, and leverage GPU testing tools for your projects.
Contributing to Open Source Benchmarking
This developer guide covers everything you need to contribute to browser-based GPU benchmarking projects. Whether you're fixing bugs, adding features, or creating new tests, this guide provides the technical foundation for meaningful contributions.
Development Environment Setup
Prerequisites
Required Software:
- Node.js 18+ and npm 9+
- Git 2.30+
- Modern IDE (VS Code recommended)
- GPU with WebGL 2.0 support
Recommended Tools:
- Chrome DevTools or Firefox Developer Tools
- WebGL Inspector extension
- Spector.js (WebGL debugging)
- GPU monitoring (MSI Afterburner, nvidia-smi)
Repository Setup
# Fork and clone repository
git clone https://github.com/YOUR_USERNAME/gpu-benchmark
cd gpu-benchmark
# Install dependencies
npm install
# Start development server
npm run dev
# Server should start at http://localhost:3000
# Hot reload enabled for instant feedback
Project Architecture
Directory Structure
gpu-benchmark/
├── src/
│ ├── benchmarks/ # Individual benchmark tests
│ │ ├── rendering/ # Graphics rendering tests
│ │ ├── compute/ # Compute shader tests
│ │ ├── memory/ # Memory bandwidth tests
│ │ └── stress/ # Sustained load tests
│ ├── core/ # Core engine
│ │ ├── webgl/ # WebGL abstraction
│ │ ├── metrics/ # Performance measurement
│ │ ├── scoring/ # Score calculation
│ │ └── analytics/ # Result aggregation
│ ├── ui/ # User interface
│ │ ├── components/ # React components
│ │ └── styles/ # CSS/styling
│ └── utils/ # Utility functions
├── tests/ # Unit and integration tests
├── docs/ # Documentation
└── public/ # Static assets
Core Technologies
| Technology | Purpose | Version |
|---|---|---|
| TypeScript | Type-safe development | 5.0+ |
| React | UI framework | 18.0+ |
| WebGL 2.0 | GPU access | OpenGL ES 3.0 |
| Jest | Testing framework | 29.0+ |
| Webpack | Build tooling | 5.0+ |
Creating a New Benchmark Test
Benchmark Class Template
// src/benchmarks/custom-test.ts
import { BaseBenchmark } from '../core/base-benchmark';
import type { BenchmarkConfig, PerformanceMetrics } from '../types';
export class CustomBenchmark extends BaseBenchmark {
name = 'Custom Rendering Test';
description = 'Tests specific GPU capability';
category = 'rendering'; // or 'compute', 'memory', 'stress'
// Shader source code
private vertexShaderSource = `
#version 300 es
in vec4 aPosition;
in vec2 aTexCoord;
out vec2 vTexCoord;
void main() {
gl_Position = aPosition;
vTexCoord = aTexCoord;
}
`;
private fragmentShaderSource = `
#version 300 es
precision highp float;
in vec2 vTexCoord;
out vec4 fragColor;
uniform float uTime;
void main() {
// Custom shader logic
vec3 color = vec3(
sin(vTexCoord.x * 10.0 + uTime),
cos(vTexCoord.y * 10.0 + uTime),
sin(uTime)
) * 0.5 + 0.5;
fragColor = vec4(color, 1.0);
}
`;
async setup(gl: WebGL2RenderingContext): Promise {
// Compile shaders
this.program = this.createShaderProgram(
gl,
this.vertexShaderSource,
this.fragmentShaderSource
);
// Create geometry
this.createGeometry(gl);
// Set up uniforms
this.setupUniforms(gl);
}
render(gl: WebGL2RenderingContext, frameNumber: number): void {
const time = frameNumber / 60.0; // Assuming 60 FPS target
// Clear framebuffer
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Use shader program
gl.useProgram(this.program);
// Update uniforms
const timeLocation = gl.getUniformLocation(this.program, 'uTime');
gl.uniform1f(timeLocation, time);
// Draw geometry
gl.bindVertexArray(this.vao);
gl.drawArrays(gl.TRIANGLES, 0, this.vertexCount);
}
calculateScore(metrics: PerformanceMetrics): number {
// Custom scoring logic
const { avgFPS, minFPS, percentile99 } = metrics;
// Weighted score calculation
const baseScore = avgFPS * 100;
const consistencyBonus = (1 - (avgFPS - minFPS) / avgFPS) * 500;
const percentilePenalty = (avgFPS - percentile99) * 10;
return Math.round(baseScore + consistencyBonus - percentilePenalty);
}
cleanup(gl: WebGL2RenderingContext): void {
// Free GPU resources
gl.deleteProgram(this.program);
gl.deleteVertexArray(this.vao);
gl.deleteBuffer(this.vertexBuffer);
}
}
Registering Your Benchmark
// src/benchmarks/index.ts
import { CustomBenchmark } from './custom-test';
export const benchmarkRegistry = [
// Existing benchmarks
new VolumeShaderBenchmark(),
new ComputeShaderBenchmark(),
// Your new benchmark
new CustomBenchmark(),
];
Testing Your Contribution
Unit Tests
// tests/benchmarks/custom-test.spec.ts
import { CustomBenchmark } from '../../src/benchmarks/custom-test';
import { createMockWebGL2Context } from '../helpers/webgl-mock';
describe('CustomBenchmark', () => {
let benchmark: CustomBenchmark;
let gl: WebGL2RenderingContext;
beforeEach(() => {
benchmark = new CustomBenchmark();
gl = createMockWebGL2Context();
});
test('should initialize without errors', async () => {
await expect(benchmark.setup(gl)).resolves.not.toThrow();
});
test('should render frames correctly', () => {
benchmark.setup(gl);
expect(() => benchmark.render(gl, 0)).not.toThrow();
expect(() => benchmark.render(gl, 100)).not.toThrow();
});
test('should calculate score correctly', () => {
const metrics = {
avgFPS: 60,
minFPS: 55,
maxFPS: 65,
percentile99: 58,
frameCount: 1000,
duration: 16666,
};
const score = benchmark.calculateScore(metrics);
expect(score).toBeGreaterThan(0);
expect(score).toBeLessThan(10000);
});
test('should clean up resources', () => {
benchmark.setup(gl);
expect(() => benchmark.cleanup(gl)).not.toThrow();
});
});
Running Tests
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
# Run specific test file
npm test -- custom-test.spec.ts
Performance Best Practices
Optimization Guidelines
| Technique | Impact | When to Use |
|---|---|---|
| Vertex Array Objects (VAO) | High | Always for geometry |
| Uniform Buffer Objects (UBO) | Medium | Many shared uniforms |
| Instanced Rendering | Very High | Many identical objects |
| Texture Atlasing | Medium | Many small textures |
| Depth Pre-pass | Medium | Complex pixel shaders |
Common Pitfalls to Avoid
// ❌ BAD: Creating shaders every frame
render(gl, frame) {
const program = createProgram(gl, vs, fs); // SLOW!
gl.useProgram(program);
gl.drawArrays(...);
}
// ✓ GOOD: Create shaders once in setup
setup(gl) {
this.program = createProgram(gl, vs, fs);
}
render(gl, frame) {
gl.useProgram(this.program);
gl.drawArrays(...);
}
// ❌ BAD: Reading back from GPU every frame
render(gl, frame) {
gl.readPixels(...); // Causes GPU stall!
}
// ✓ GOOD: Only read when necessary
finish() {
gl.readPixels(...); // Only at end of test
}
// ❌ BAD: Synchronous resource loading
setup(gl) {
const texture = loadTexture('image.png'); // Blocks!
return texture;
}
// ✓ GOOD: Async loading with Promise
async setup(gl) {
this.texture = await loadTextureAsync('image.png');
}
Submitting Pull Requests
PR Checklist
Before Submitting:
☑ Code follows project style guide (ESLint passing)
☑ All tests pass (npm test)
☑ New features have tests
☑ Documentation updated
☑ No console.log() or debug code
☑ Git commit messages are descriptive
☑ Branch is up to date with main
PR Template:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Performance improvement
- [ ] Documentation update
## Testing
How has this been tested?
- [ ] Unit tests added/updated
- [ ] Manual testing on:
- [ ] Chrome
- [ ] Firefox
- [ ] Safari
## Screenshots
(if applicable)
## Checklist
- [ ] Code follows style guidelines
- [ ] Tests pass
- [ ] Documentation updated
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Community and Resources
Contributing to open source benchmarking projects helps the entire community:
- ✓ Start small: Fix typos, improve documentation
- ✓ Ask questions: Use GitHub Discussions or Discord
- ✓ Follow conventions: Match existing code style
- ✓ Test thoroughly: On multiple browsers and GPUs
- ✓ Be patient: Code review takes time
Learning Resources:
- WebGL Fundamentals - webglfundamentals.org
- GPU Gems (free online) - developer.nvidia.com/gpugems
- Khronos WebGL Reference - khronos.org/webgl
- OpenGL ES 3.0 Specification - official reference for WebGL 2.0
- Project Discord/Slack - for real-time help
Every contribution, from fixing a typo to implementing a major feature, makes browser-based benchmarking better for everyone. Welcome to the community!