171 lines
3.2 KiB
JavaScript
171 lines
3.2 KiB
JavaScript
|
|
|
||
|
|
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);
|
||
|
|
|