Files
WebGPU-Framework/demos/sort/demo.js

171 lines
3.2 KiB
JavaScript
Raw Normal View History

2025-11-17 15:06:39 +01:00
import Shader from "../../framework/WebGpu.js"
import Measure from "../../framework/Measure.js"
const adapter = await navigator.gpu.requestAdapter();
if (!adapter ) {
throw new Error("Failed to get GPU adapter");
}
const particleCount = 131072;
const workgroupSize = 256;
const numWorkgroups = Math.ceil( particleCount / workgroupSize );
const device = await adapter.requestDevice();
var passIndex = 0;
var jArray = new Array();
var kArray = new Array();
for ( let k = 512; k <= particleCount; k <<= 1 ) {
for ( let j = k >> 1; j > 0; j >>= 1 ) {
jArray.push( j );
kArray.push( k );
}
}
const indices = new Uint32Array( particleCount );
const threadPassIndices = new Uint32Array( particleCount );
for (var i = 0; i < particleCount; i++) {
indices[particleCount-i-1] = i;
threadPassIndices[0] = 0;
}
const localSortShader = new Shader( device, "./shaders/localSort.wgsl");
await localSortShader.addStage("main", GPUShaderStage.COMPUTE );
localSortShader.setVariable( "compare", indices );
localSortShader.setVariable( "totalCount", particleCount );
const bitonicSortGridHashShader = new Shader( device, "./shaders/bitonicSortUIntMultiPass.wgsl");
await bitonicSortGridHashShader.addStage("main", GPUShaderStage.COMPUTE );
bitonicSortGridHashShader.setVariable( "totalCount", particleCount );
bitonicSortGridHashShader.setBuffer( "compare", localSortShader.getBuffer("compare") );
bitonicSortGridHashShader.setVariable( "jArray", jArray );
bitonicSortGridHashShader.setVariable( "kArray", kArray );
const measure = new Measure();
measure.writeToPage = true;
measure.element = document.querySelector(".result");
for (var i = 3; i < 59; i++) {
bitonicSortGridHashShader.setVariable("threadPassIndices", threadPassIndices);
measure.start( "sort"+i );
//await localSortShader.execute( numWorkgroups );
const commandEncoder = device.createCommandEncoder();
// === Local sort ===
{
const passEncoder = commandEncoder.beginComputePass();
passEncoder.setPipeline( localSortShader.pipeline );
for ( const [ index, bindGroup ] of localSortShader.bindGroups.entries() ) {
passEncoder.setBindGroup( index, bindGroup );
}
passEncoder.dispatchWorkgroups( numWorkgroups );
passEncoder.end();
}
// === Bitonic global merge ===
{
const passEncoder = commandEncoder.beginComputePass();
passEncoder.setPipeline( bitonicSortGridHashShader.pipeline );
for ( const [ index, bindGroup ] of bitonicSortGridHashShader.bindGroups.entries() ) {
passEncoder.setBindGroup( index, bindGroup );
}
var numberOfPasses = 0;
for ( let k = 512; k <= particleCount; k <<= 1 ) {
for ( let j = k >> 1; j > 0; j >>= 1 ) {
numberOfPasses++;
passEncoder.dispatchWorkgroups( numWorkgroups );
}
}
passEncoder.end();
}
const commandBuffer = commandEncoder.finish();
device.queue.submit( [ commandBuffer ] );
await device.queue.onSubmittedWorkDone();
measure.end( "sort"+i );
}
var result = await bitonicSortGridHashShader.debugBuffer("compare");
await bitonicSortGridHashShader.debugBuffer("threadPassIndices");
var error = false;
for (var i = 0; i < particleCount; i++ ) {
if( result[i] != i ) {
error = true;
}
}
console.log("There is error?", error, particleCount);