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);