diff --git a/apps/typegpu-docs/src/examples/algorithms/probability/constants.ts b/apps/typegpu-docs/src/examples/algorithms/probability/constants.ts index cf8aa2522..52f56e657 100644 --- a/apps/typegpu-docs/src/examples/algorithms/probability/constants.ts +++ b/apps/typegpu-docs/src/examples/algorithms/probability/constants.ts @@ -1,4 +1,4 @@ -import { Distribution } from './types.ts'; +import { Distribution, Generator } from './types.ts'; export const popupCooldown = 100000; export const cameraPositionGeo = [0, 0, 0.5]; @@ -6,5 +6,7 @@ export const cameraPositionHist = [0, 0, 0.2]; export const initialCameraAngle = 15; export const numSamplesOptions = [100, 1000, 2000, 5000, 10000, 50000]; export const initialNumSamples = numSamplesOptions[2]; +export const initialGenerator: Generator = Generator.BPETER; +export const generators: Generator[] = Object.values(Generator); export const initialDistribution: Distribution = Distribution.NORMAL; export const distributions: Distribution[] = Object.values(Distribution); diff --git a/apps/typegpu-docs/src/examples/algorithms/probability/executor.ts b/apps/typegpu-docs/src/examples/algorithms/probability/executor.ts index 8429acc1c..9440e3037 100644 --- a/apps/typegpu-docs/src/examples/algorithms/probability/executor.ts +++ b/apps/typegpu-docs/src/examples/algorithms/probability/executor.ts @@ -11,7 +11,11 @@ import type { TgpuSlot, } from 'typegpu'; import * as d from 'typegpu/data'; -import { randf } from '@typegpu/noise'; +import { + randf, + randomGeneratorSlot, + type StatefulGenerator, +} from '@typegpu/noise'; export class Executor { // don't exceed max workgroup grid X dimension size @@ -36,7 +40,10 @@ export class Executor { & StorageFlag, ] >; - readonly #pipelineCache: Map; + readonly #pipelineCache: WeakMap< + TgpuFn, + WeakMap + >; constructor(root: TgpuRoot) { this.#root = root; @@ -93,34 +100,54 @@ export class Executor { }); } - cachedPipeline(distribution: TgpuFn<() => d.Vec3f>) { - if (!import.meta.env.DEV) { - throw new Error('Function only for testing purposes'); + #pipelineCacheHas( + distribution: TgpuFn<() => d.Vec3f>, + generator: StatefulGenerator, + ): boolean { + const generatorMap = this.#pipelineCache.get(distribution); + if (!generatorMap) { + return false; } + return generatorMap.has(generator); + } + + #pipelineCacheSet( + distribution: TgpuFn<() => d.Vec3f>, + generator: StatefulGenerator, + pipeline: TgpuComputePipeline, + ) { if (!this.#pipelineCache.has(distribution)) { + this.#pipelineCache.set(distribution, new Map([[generator, pipeline]])); + return; + } + + // biome-ignore lint/style/noNonNullAssertion: just checked it above + this.#pipelineCache.get(distribution)!.set(generator, pipeline); + } + + pipelineCacheGet( + distribution: TgpuFn<() => d.Vec3f>, + generator: StatefulGenerator, + ): TgpuComputePipeline { + if (!this.#pipelineCacheHas(distribution, generator)) { const pipeline = this.#root['~unstable'] + .with(randomGeneratorSlot, generator) .with(this.#distributionSlot, distribution) - .withCompute(this.#dataMoreWorkersFunc) + .withCompute(this.#dataMoreWorkersFunc as TgpuComputeFn) .createPipeline(); - this.#pipelineCache.set(distribution, pipeline); + this.#pipelineCacheSet(distribution, generator, pipeline); } // biome-ignore lint/style/noNonNullAssertion: just checked it above - return this.#pipelineCache.get(distribution)!; + return this.#pipelineCache.get(distribution)!.get(generator)!; } async executeMoreWorkers( distribution: TgpuFn<() => d.Vec3f>, + generator: StatefulGenerator, ): Promise { - let pipeline = this.#pipelineCache.get(distribution); - if (!pipeline) { - pipeline = this.#root['~unstable'] - .with(this.#distributionSlot, distribution) - .withCompute(this.#dataMoreWorkersFunc as TgpuComputeFn) - .createPipeline(); - this.#pipelineCache.set(distribution, pipeline); - } + const pipeline = this.pipelineCacheGet(distribution, generator); pipeline .with(this.#bindGroupLayout, this.#bindGroup) diff --git a/apps/typegpu-docs/src/examples/algorithms/probability/helpers.ts b/apps/typegpu-docs/src/examples/algorithms/probability/helpers.ts index d9e3f9a2f..3929c8e1b 100644 --- a/apps/typegpu-docs/src/examples/algorithms/probability/helpers.ts +++ b/apps/typegpu-docs/src/examples/algorithms/probability/helpers.ts @@ -1,8 +1,8 @@ import tgpu from 'typegpu'; -import { randf } from '@typegpu/noise'; +import { BPETER, LCG, randf, type StatefulGenerator } from '@typegpu/noise'; import * as d from 'typegpu/data'; -import { Distribution, PlotType, type PRNG } from './types.ts'; +import { Distribution, Generator, PlotType, type PRNG } from './types.ts'; import * as c from './constants.ts'; const normal = d.vec3f(1.41, 1.41, 0); @@ -96,3 +96,11 @@ const distributionCameras = { export function getCameraPosition(distribution: Distribution): number[] { return distributionCameras[distribution]; } + +const GENERATOR_MAP = { + [Generator.BPETER]: BPETER, + [Generator.LCG]: LCG, +}; + +export const getGenerator = (gen: Generator): StatefulGenerator => + GENERATOR_MAP[gen]; diff --git a/apps/typegpu-docs/src/examples/algorithms/probability/index.ts b/apps/typegpu-docs/src/examples/algorithms/probability/index.ts index ebb78ee5e..82ed61f9f 100644 --- a/apps/typegpu-docs/src/examples/algorithms/probability/index.ts +++ b/apps/typegpu-docs/src/examples/algorithms/probability/index.ts @@ -2,9 +2,9 @@ import tgpu from 'typegpu'; import { Plotter } from './plotter.ts'; import { Executor } from './executor.ts'; -import type { Distribution } from './types.ts'; +import type { Distribution, Generator } from './types.ts'; import * as c from './constants.ts'; -import { getCameraPosition, getPRNG } from './helpers.ts'; +import { getCameraPosition, getGenerator, getPRNG } from './helpers.ts'; const root = await tgpu.init(); @@ -12,15 +12,18 @@ const executor = new Executor(root); const plotter = new Plotter(); let currentDistribution = c.initialDistribution; +let currentGenerator = c.initialGenerator; const replot = async ( currentDistribution: Distribution, + currentGenerator: Generator, animate = false, ) => { let samples = undefined; const prng = getPRNG(currentDistribution); + const gen = getGenerator(currentGenerator); - samples = await executor.executeMoreWorkers(prng.prng); + samples = await executor.executeMoreWorkers(prng.prng, gen); await plotter.plot(samples, prng, animate); }; @@ -63,7 +66,27 @@ export const controls = { 'Reseed': { async onButtonClick() { executor.reseed(); - await replot(currentDistribution, true); + await replot( + currentDistribution, + currentGenerator, + true, + ); + plotter.resetView(getCameraPosition(currentDistribution)); + }, + }, + 'Generator': { + initial: c.initialGenerator, + options: c.generators, + onSelectChange: async (value: Generator) => { + if (currentGenerator === value) { + return; + } + currentGenerator = value; + await replot( + currentDistribution, + currentGenerator, + true, + ); plotter.resetView(getCameraPosition(currentDistribution)); }, }, @@ -78,6 +101,7 @@ export const controls = { currentDistribution = value; await replot( currentDistribution, + currentGenerator, true, ); plotter.resetView(getCameraPosition(currentDistribution)); @@ -90,20 +114,25 @@ export const controls = { executor.count = value; await replot( currentDistribution, + currentGenerator, ); }, }, 'Test Resolution': import.meta.env.DEV && { onButtonClick() { - c.distributions - .map((dist) => - tgpu.resolve({ + for (const dist of c.distributions) { + for (const gen of c.generators) { + const code = tgpu.resolve({ externals: { - f: executor.cachedPipeline(getPRNG(dist).prng), + p: executor.pipelineCacheGet( + getPRNG(dist).prng, + getGenerator(gen), + ), }, - }) - ) - .map((r) => root.device.createShaderModule({ code: r })); + }); + root.device.createShaderModule({ code }); + } + } }, }, }; diff --git a/apps/typegpu-docs/src/examples/algorithms/probability/types.ts b/apps/typegpu-docs/src/examples/algorithms/probability/types.ts index f1577162f..d8611a989 100644 --- a/apps/typegpu-docs/src/examples/algorithms/probability/types.ts +++ b/apps/typegpu-docs/src/examples/algorithms/probability/types.ts @@ -69,3 +69,10 @@ export interface SimplePRNG { plotType: PlotType; prng: TgpuFn<() => d.Vec3f>; } + +export const Generator = { + BPETER: 'bpeter (default)', + LCG: 'lcg', +} as const; + +export type Generator = typeof Generator[keyof typeof Generator]; diff --git a/apps/typegpu-docs/src/examples/tests/uniformity/lcg.ts b/apps/typegpu-docs/src/examples/tests/uniformity/lcg.ts deleted file mode 100644 index 32641daf1..000000000 --- a/apps/typegpu-docs/src/examples/tests/uniformity/lcg.ts +++ /dev/null @@ -1,31 +0,0 @@ -import tgpu from 'typegpu'; -import * as d from 'typegpu/data'; -import * as std from 'typegpu/std'; -import type { StatefulGenerator } from '@typegpu/noise'; - -export const LCG: StatefulGenerator = (() => { - const seed = tgpu.privateVar(d.u32); - - const u32To01Float = tgpu.fn([d.u32], d.f32)`(val){ - let exponent: u32 = 0x3f800000; - let mantissa: u32 = 0x007fffff & val; - var ufloat: u32 = (exponent | mantissa); - return bitcast(ufloat) - 1f; - }`; - - return { - seed: (value: number) => { - 'kernel'; - seed.$ = d.u32(value * std.pow(32, 3)); - }, - seed2: (value: d.v2f) => { - 'kernel'; - seed.$ = d.u32(value.x * std.pow(32, 3) + value.y * std.pow(32, 2)); - }, - sample: () => { - 'kernel'; - seed.$ = seed.$ * 1664525 + 1013904223; // % 2 ^ 32 - return u32To01Float(seed.$); - }, - }; -})(); diff --git a/apps/typegpu-docs/src/examples/tests/uniformity/prngs.ts b/apps/typegpu-docs/src/examples/tests/uniformity/prngs.ts index 9d2033742..aa8358484 100644 --- a/apps/typegpu-docs/src/examples/tests/uniformity/prngs.ts +++ b/apps/typegpu-docs/src/examples/tests/uniformity/prngs.ts @@ -1,6 +1,4 @@ -import { BPETER, type StatefulGenerator } from '@typegpu/noise'; - -import { LCG } from './lcg.ts'; +import { BPETER, LCG, type StatefulGenerator } from '@typegpu/noise'; export const PRNG = { BPETER: 'bpeter (default)', diff --git a/packages/typegpu-noise/src/generator.ts b/packages/typegpu-noise/src/generator.ts index da76accfa..1448c6492 100644 --- a/packages/typegpu-noise/src/generator.ts +++ b/packages/typegpu-noise/src/generator.ts @@ -1,6 +1,6 @@ import tgpu, { type TgpuFn, type TgpuFnShell, type TgpuSlot } from 'typegpu'; import * as d from 'typegpu/data'; -import { add, cos, dot, fract } from 'typegpu/std'; +import { add, cos, dot, fract, pow } from 'typegpu/std'; export interface StatefulGenerator { seed: TgpuFn<(seed: d.F32) => d.Void> | ((seed: number) => void); @@ -47,6 +47,50 @@ export const BPETER: StatefulGenerator = (() => { }; })(); +/** + * Naive Linear Congruential Generator (LCG) + */ +export const LCG: StatefulGenerator = (() => { + const seed = tgpu.privateVar(d.u32); + + const u32To01Float = tgpu.fn([d.u32], d.f32)`(val){ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + }`; + + return { + seed: (value: number) => { + 'kernel'; + seed.$ = d.u32(value * pow(32, 3)); + }, + seed2: (value: d.v2f) => { + 'kernel'; + seed.$ = d.u32(value.x * pow(32, 3) + value.y * pow(32, 2)); + }, + seed3: (value: d.v3f) => { + 'kernel'; + seed.$ = d.u32( + value.x * pow(32, 3) + value.y * pow(32, 2) + + value.z * pow(32, 1), + ); + }, + seed4: (value: d.v4f) => { + 'kernel'; + seed.$ = d.u32( + value.x * pow(32, 3) + value.y * pow(32, 2) + + value.z * pow(32, 1) + value.w * pow(32, 0), + ); + }, + sample: () => { + 'kernel'; + seed.$ = seed.$ * 1664525 + 1013904223; // % 2 ^ 32 + return u32To01Float(seed.$); + }, + }; +})(); + // The default (Can change between releases to improve uniformity). export const DefaultGenerator: StatefulGenerator = BPETER; diff --git a/packages/typegpu-noise/src/index.ts b/packages/typegpu-noise/src/index.ts index 97dc584cf..d628c7c85 100644 --- a/packages/typegpu-noise/src/index.ts +++ b/packages/typegpu-noise/src/index.ts @@ -145,6 +145,7 @@ export { BPETER, // The default (Can change between releases to improve uniformity). DefaultGenerator, + LCG, // --- randomGeneratorShell, randomGeneratorSlot, diff --git a/packages/typegpu/tests/examples/individual/probability.test.ts b/packages/typegpu/tests/examples/individual/probability.test.ts index 7d74ae3f8..bd9bee249 100644 --- a/packages/typegpu/tests/examples/individual/probability.test.ts +++ b/packages/typegpu/tests/examples/individual/probability.test.ts @@ -14,7 +14,7 @@ describe('probability distribution plot example', () => { category: 'algorithms', name: 'probability', controlTriggers: ['Test Resolution'], - expectedCalls: 13, + expectedCalls: 39, }, device); expect(shaderCodes).toMatchInlineSnapshot(` @@ -74,6 +74,62 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_8(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_7() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_8(seed_5); + } + + fn randUniformExclusive_10() -> f32 { + return ((item_7() * 0.9999998) + 1e-7); + } + + fn randNormal_9(mu: f32, sigma: f32) -> f32 { + var theta = (6.283185307179586 * randUniformExclusive_10()); + var R = sqrt((-2 * log(randUniformExclusive_10()))); + return (((R * sin(theta)) * sigma) + mu); + } + + fn randInUnitSphere_6() -> vec3f { + var u = item_7(); + var v = vec3f(randNormal_9(0, 1), randNormal_9(0, 1), randNormal_9(0, 1)); + var vNorm = normalize(v); + return (vNorm * pow(u, 0.33)); + } + + struct item_11 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_11) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = randInUnitSphere_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -118,6 +174,54 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_8(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_7() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_8(seed_5); + } + + fn randOnUnitSphere_6() -> vec3f { + var z = ((2 * item_7()) - 1); + var oneMinusZSq = sqrt((1 - (z * z))); + var theta = (6.283185307179586 * item_7()); + var x = (cos(theta) * oneMinusZSq); + var y = (sin(theta) * oneMinusZSq); + return vec3f(x, y, z); + } + + struct item_9 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_9) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = randOnUnitSphere_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -163,6 +267,55 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_9(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_8() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_9(seed_5); + } + + fn randInUnitCircle_7() -> vec2f { + var radius = sqrt(item_8()); + var angle = (item_8() * 6.283185307179586); + return vec2f((cos(angle) * radius), (sin(angle) * radius)); + } + + fn prng_6() -> vec3f { + return vec3f(randInUnitCircle_7(), 0.5); + } + + struct item_10 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_10) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = prng_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -207,6 +360,54 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_9(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_8() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_9(seed_5); + } + + fn randOnUnitCircle_7() -> vec2f { + var angle = (item_8() * 6.283185307179586); + return vec2f(cos(angle), sin(angle)); + } + + fn prng_6() -> vec3f { + return vec3f(randOnUnitCircle_7(), 0.5); + } + + struct item_10 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_10) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = prng_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -246,6 +447,49 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_8(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_7() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_8(seed_5); + } + + fn randInUnitCube_6() -> vec3f { + return vec3f(item_7(), item_7(), item_7()); + } + + struct item_9 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_9) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = randInUnitCube_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -291,6 +535,55 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_8(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_7() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_8(seed_5); + } + + fn randOnUnitCube_6() -> vec3f { + var face = u32((item_7() * 6)); + var axis = (face % 3); + var result = vec3f(); + result[axis] = f32(select(0, 1, (face > 2))); + result[((axis + 1) % 3)] = item_7(); + result[((axis + 2) % 3)] = item_7(); + return result; + } + + struct item_9 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_9) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = randOnUnitCube_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -353,6 +646,72 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_10(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_9() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_10(seed_5); + } + + fn randUniformExclusive_12() -> f32 { + return ((item_9() * 0.9999998) + 1e-7); + } + + fn randNormal_11(mu: f32, sigma: f32) -> f32 { + var theta = (6.283185307179586 * randUniformExclusive_12()); + var R = sqrt((-2 * log(randUniformExclusive_12()))); + return (((R * sin(theta)) * sigma) + mu); + } + + fn randInUnitSphere_8() -> vec3f { + var u = item_9(); + var v = vec3f(randNormal_11(0, 1), randNormal_11(0, 1), randNormal_11(0, 1)); + var vNorm = normalize(v); + return (vNorm * pow(u, 0.33)); + } + + fn randInUnitHemisphere_7(normal: vec3f) -> vec3f { + var value = randInUnitSphere_8(); + var alignment = dot(normal, value); + return (sign(alignment) * value); + } + + fn prng_6() -> vec3f { + return randInUnitHemisphere_7(vec3f(1.409999966621399, 1.409999966621399, 0)); + } + + struct item_13 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_13) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = prng_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -407,6 +766,64 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_10(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_9() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_10(seed_5); + } + + fn randOnUnitSphere_8() -> vec3f { + var z = ((2 * item_9()) - 1); + var oneMinusZSq = sqrt((1 - (z * z))); + var theta = (6.283185307179586 * item_9()); + var x = (cos(theta) * oneMinusZSq); + var y = (sin(theta) * oneMinusZSq); + return vec3f(x, y, z); + } + + fn randOnUnitHemisphere_7(normal: vec3f) -> vec3f { + var value = randOnUnitSphere_8(); + var alignment = dot(normal, value); + return (sign(alignment) * value); + } + + fn prng_6() -> vec3f { + return randOnUnitHemisphere_7(vec3f(1.409999966621399, 1.409999966621399, 0)); + } + + struct item_11 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_11) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = prng_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -451,6 +868,54 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_9(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_8() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_9(seed_5); + } + + fn randBernoulli_7(p: f32) -> f32 { + var u = item_8(); + return step(u, p); + } + + fn prng_6() -> vec3f { + return vec3f(randBernoulli_7(0.7)); + } + + struct item_10 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_10) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = prng_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -494,6 +959,53 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_9(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_8() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_9(seed_5); + } + + fn randFloat01_7() -> f32 { + return item_8(); + } + + fn prng_6() -> vec3f { + return vec3f(randFloat01_7()); + } + + struct item_10 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_10) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = prng_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -542,6 +1054,58 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_10(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_9() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_10(seed_5); + } + + fn randUniformExclusive_8() -> f32 { + return ((item_9() * 0.9999998) + 1e-7); + } + + fn randExponential_7(rate: f32) -> f32 { + var u = randUniformExclusive_8(); + return ((-1 / rate) * log(u)); + } + + fn prng_6() -> vec3f { + return vec3f(randExponential_7(1)); + } + + struct item_11 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_11) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = prng_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -591,6 +1155,59 @@ describe('probability distribution plot example', () => { @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_10(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_9() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_10(seed_5); + } + + fn randUniformExclusive_8() -> f32 { + return ((item_9() * 0.9999998) + 1e-7); + } + + fn randNormal_7(mu: f32, sigma: f32) -> f32 { + var theta = (6.283185307179586 * randUniformExclusive_8()); + var R = sqrt((-2 * log(randUniformExclusive_8()))); + return (((R * sin(theta)) * sigma) + mu); + } + + fn prng_6() -> vec3f { + return vec3f(randNormal_7(0, 1)); + } + + struct item_11 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_11) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = prng_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + var seed_5: vec2f; fn seed_4(value: f32) { @@ -633,6 +1250,58 @@ describe('probability distribution plot example', () => { } randSeed_3(seedBuffer_2[id]); samplesBuffer_1[id] = prng_6(); + } + + @group(0) @binding(1) var samplesBuffer_1: array; + + @group(0) @binding(0) var seedBuffer_2: array; + + var seed_5: u32; + + fn item_4(value: f32) { + seed_5 = u32((value * 32768)); + } + + fn randSeed_3(seed: f32) { + item_4(seed); + } + + fn u32To01Float_10(val: u32) -> f32{ + let exponent: u32 = 0x3f800000; + let mantissa: u32 = 0x007fffff & val; + var ufloat: u32 = (exponent | mantissa); + return bitcast(ufloat) - 1f; + } + + fn item_9() -> f32 { + seed_5 = ((seed_5 * 1664525) + 1013904223); + return u32To01Float_10(seed_5); + } + + fn randUniformExclusive_8() -> f32 { + return ((item_9() * 0.9999998) + 1e-7); + } + + fn randCauchy_7(x0: f32, gamma: f32) -> f32 { + var u = randUniformExclusive_8(); + return (x0 + (gamma * tan((3.141592653589793 * (u - 0.5))))); + } + + fn prng_6() -> vec3f { + return vec3f(randCauchy_7(0, 1)); + } + + struct item_11 { + @builtin(global_invocation_id) gid: vec3u, + } + + @compute @workgroup_size(64) fn item_0(input: item_11) { + var id = input.gid.x; + if ((id >= arrayLength(&samplesBuffer_1))) { + return; + } + randSeed_3(seedBuffer_2[id]); + samplesBuffer_1[id] = prng_6(); }" `); });