if (!(device instanceof GPUDevice)) {
throw new Error("WebGPU device failed to load.");
}
- device.lost.then((loss) => {
- console.dir(loss);
- console.warn(`Device lost. Reinitializing...`);
- this.#cpuBuffer?.destroy();
- this.#gpuBuffer?.destroy();
- this.#uboBuffer?.destroy();
- this.init();
- });
+ device.lost.then(this.reset);
this.#device = device;
this.setup();
} catch (err) {
}
});
}
+ static reset(loss) {
+ console.dir(loss);
+ console.warn(`Device lost. Reinitializing...`);
+ this.#cpuBuffer?.destroy();
+ this.#gpuBuffer?.destroy();
+ this.#uboBuffer?.destroy();
+ this.#busy = false;
+ this.init();
+ }
/**
* Finds a nonce that satisfies the Nano proof-of-work requirements.
*
}
if (this.#device == null) throw new Error(`WebGPU device failed to load.`);
let nonce = 0n;
- let found = false;
- try {
- do {
- const uboView = new DataView(new ArrayBuffer(48));
- for (let i = 0; i < 64; i += 8) {
- const uint32 = hash2.slice(i, i + 8);
- uboView.setUint32(i / 2, parseInt(uint32, 16));
- }
- const random = Math.floor(Math.random() * 4294967295);
- uboView.setUint32(32, random, true);
- uboView.setUint32(36, threshold, true);
- this.#device.queue.writeBuffer(this.#uboBuffer, 0, uboView);
- this.#device.queue.writeBuffer(this.#gpuBuffer, 8, new Uint32Array([0]));
- const bindGroup = this.#device.createBindGroup({
- layout: this.#bindGroupLayout,
- entries: [
- {
- binding: 0,
- resource: {
- buffer: this.#uboBuffer
- }
- },
- {
- binding: 1,
- resource: {
- buffer: this.#gpuBuffer
- }
+ do {
+ const uboView = new DataView(new ArrayBuffer(48));
+ for (let i = 0; i < 64; i += 8) {
+ const uint32 = hash2.slice(i, i + 8);
+ uboView.setUint32(i / 2, parseInt(uint32, 16));
+ }
+ const random = Math.floor(Math.random() * 4294967295);
+ uboView.setUint32(32, random, true);
+ uboView.setUint32(36, threshold, true);
+ this.#device.queue.writeBuffer(this.#uboBuffer, 0, uboView);
+ this.#device.queue.writeBuffer(this.#gpuBuffer, 8, new Uint32Array([0]));
+ const bindGroup = this.#device.createBindGroup({
+ layout: this.#bindGroupLayout,
+ entries: [
+ {
+ binding: 0,
+ resource: {
+ buffer: this.#uboBuffer
}
- ]
- });
- const commandEncoder = this.#device.createCommandEncoder();
- const passEncoder = commandEncoder.beginComputePass();
- passEncoder.setPipeline(this.#pipeline);
- passEncoder.setBindGroup(0, bindGroup);
- passEncoder.dispatchWorkgroups(256, 256, 256);
- passEncoder.end();
- commandEncoder.copyBufferToBuffer(
- this.#gpuBuffer,
- 0,
- this.#cpuBuffer,
- 0,
- 12
- );
- this.#device.queue.submit([commandEncoder.finish()]);
+ },
+ {
+ binding: 1,
+ resource: {
+ buffer: this.#gpuBuffer
+ }
+ }
+ ]
+ });
+ const commandEncoder = this.#device.createCommandEncoder();
+ const passEncoder = commandEncoder.beginComputePass();
+ passEncoder.setPipeline(this.#pipeline);
+ passEncoder.setBindGroup(0, bindGroup);
+ passEncoder.dispatchWorkgroups(256, 256, 256);
+ passEncoder.end();
+ commandEncoder.copyBufferToBuffer(this.#gpuBuffer, 0, this.#cpuBuffer, 0, 12);
+ this.#device.queue.submit([commandEncoder.finish()]);
+ let data = null;
+ try {
await this.#cpuBuffer.mapAsync(GPUMapMode.READ);
await this.#device.queue.onSubmittedWorkDone();
- const dataBuffer = this.#cpuBuffer.getMappedRange().slice(0);
+ data = new DataView(this.#cpuBuffer.getMappedRange().slice(0));
+ } catch (err) {
+ console.warn(`Error getting data from GPU. ${err}`);
+ this.reset();
+ } finally {
this.#cpuBuffer.unmap();
- if (dataBuffer == null) throw new Error(`Failed to get data from buffer.`);
- const dataView = new DataView(dataBuffer);
- nonce = dataView.getBigUint64(0, true);
- found = !!dataView.getUint32(8);
- } while (!found);
- } catch (err) {
- console.warn(`Error getting data from GPU. ${err}`);
- } finally {
- this.#busy = false;
- return nonce.toString(16).padStart(16, "0");
- }
+ }
+ if (data == null) throw new Error(`Failed to get data from buffer.`);
+ nonce = data.getBigUint64(0, true);
+ this.#busy = !data.getUint32(8);
+ } while (this.#busy);
+ return nonce.toString(16).padStart(16, "0");
}
};
}