From e969b3d38d1f4ffb89382ca513390b4ea33d96fc Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Sat, 11 Jan 2025 23:16:55 -0800 Subject: [PATCH] Extract common functionality into separate function call. --- src/classes/gpu.ts | 130 ++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/src/classes/gpu.ts b/src/classes/gpu.ts index 6873ac5..42659cc 100644 --- a/src/classes/gpu.ts +++ b/src/classes/gpu.ts @@ -294,69 +294,69 @@ export class NanoPowGpu { return found } - // static async dispatch (hash: string, seed: bigint, threshold: number, passes: number): Promise { - // if (this.#device == null) throw new Error(`WebGPU device failed to load.`) - // // Set up uniform buffer object - // // Note: u32 size is 4, but total alignment must be multiple of 16 - // const uboView = new DataView(new ArrayBuffer(48)) - // for (let i = 0; i < 64; i += 8) { - // const uint32 = hash.slice(i, i + 8) - // uboView.setUint32(i / 2, parseInt(uint32, 16)) - // } - // uboView.setBigUint64(32, seed, true) - // uboView.setUint32(40, threshold, true) - // this.#device.queue.writeBuffer(this.#uboBuffer, 0, uboView) - - // // Reset `nonce` and `found` to 0u in WORK before each calculation - // this.#device.queue.writeBuffer(this.#gpuBuffer, 0, new Uint32Array([0, 0, 0])) - - // // Bind UBO read and GPU write buffers - // const bindGroup = this.#device.createBindGroup({ - // layout: this.#bindGroupLayout, - // entries: [ - // { - // binding: 0, - // resource: { - // buffer: this.#uboBuffer - // }, - // }, - // { - // binding: 1, - // resource: { - // buffer: this.#gpuBuffer - // }, - // }, - // ], - // }) - - // // Create command encoder to issue commands to GPU and initiate computation - // const commandEncoder = this.#device.createCommandEncoder() - // const passEncoder = commandEncoder.beginComputePass() - - // // Issue commands and end compute pass structure - // passEncoder.setPipeline(this.#pipeline) - // passEncoder.setBindGroup(0, bindGroup) - // passEncoder.dispatchWorkgroups(passes, passes) - // passEncoder.end() - - // // Copy 8-byte nonce and 4-byte found flag from GPU to CPU for reading - // commandEncoder.copyBufferToBuffer(this.#gpuBuffer, 0, this.#cpuBuffer, 0, 12) - - // // End computation by passing array of command buffers to command queue for execution - // this.#device.queue.submit([commandEncoder.finish()]) - - // // Read results back to Javascript and then unmap buffer after reading - // let data = null - // try { - // await this.#cpuBuffer.mapAsync(GPUMapMode.READ) - // await this.#device.queue.onSubmittedWorkDone() - // data = new DataView(this.#cpuBuffer.getMappedRange().slice(0)) - // this.#cpuBuffer.unmap() - // } catch (err) { - // console.warn(`Error getting data from GPU. ${err}`) - // return this.search(hash, threshold) - // } - // if (data == null) throw new Error(`Failed to get data from buffer.`) - // return data - // } + static async #dispatch (seed: bigint, hash: string, threshold: number, passes: number): Promise { + if (this.#device == null) throw new Error(`WebGPU device failed to load.`) + // Set up uniform buffer object + // Note: u32 size is 4, but total alignment must be multiple of 16 + const uboView = new DataView(new ArrayBuffer(48)) + for (let i = 0; i < 64; i += 8) { + const uint32 = hash.slice(i, i + 8) + uboView.setUint32(i / 2, parseInt(uint32, 16)) + } + uboView.setBigUint64(32, seed, true) + uboView.setUint32(40, threshold, true) + this.#device.queue.writeBuffer(this.#uboBuffer, 0, uboView) + + // Reset `nonce` and `found` to 0u in WORK before each calculation + this.#device.queue.writeBuffer(this.#gpuBuffer, 0, new Uint32Array([0, 0, 0])) + + // Bind UBO read and GPU write buffers + const bindGroup = this.#device.createBindGroup({ + layout: this.#bindGroupLayout, + entries: [ + { + binding: 0, + resource: { + buffer: this.#uboBuffer + }, + }, + { + binding: 1, + resource: { + buffer: this.#gpuBuffer + }, + }, + ], + }) + + // Create command encoder to issue commands to GPU and initiate computation + const commandEncoder = this.#device.createCommandEncoder() + const passEncoder = commandEncoder.beginComputePass() + + // Issue commands and end compute pass structure + passEncoder.setPipeline(this.#pipeline) + passEncoder.setBindGroup(0, bindGroup) + passEncoder.dispatchWorkgroups(passes, passes) + passEncoder.end() + + // Copy 8-byte nonce and 4-byte found flag from GPU to CPU for reading + commandEncoder.copyBufferToBuffer(this.#gpuBuffer, 0, this.#cpuBuffer, 0, 12) + + // End computation by passing array of command buffers to command queue for execution + this.#device.queue.submit([commandEncoder.finish()]) + + // Read results back to Javascript and then unmap buffer after reading + let data = null + try { + await this.#cpuBuffer.mapAsync(GPUMapMode.READ) + await this.#device.queue.onSubmittedWorkDone() + data = new DataView(this.#cpuBuffer.getMappedRange().slice(0)) + this.#cpuBuffer.unmap() + } catch (err) { + console.warn(`Error getting data from GPU. ${err}`) + return this.#dispatch(seed, hash, threshold, passes) + } + if (data == null) throw new Error(`Failed to get data from buffer.`) + return data + } } -- 2.34.1