// Precalculated block hash components
uniform uint blockHash[8];
-// Threshold is 0xfffffff8 for send/change blocks and 0xfffffe00 for all else
-uniform uint threshold;
-// Defines canvas size
-uniform float workload;
+// threshold - 0xfffffff8 for send/change blocks, 0xfffffe00 for all else
+// workload - Defines canvas size
+layout(std140) uniform UBO {
+ uint threshold;
+ float workload;
+};
// Random work values
// First 2 bytes will be overwritten by texture pixel position
static #program: WebGLProgram | null
static #workLocation: WebGLUniformLocation | null
static #blockHashLocation: WebGLUniformLocation | null
- static #thresholdLocation: WebGLUniformLocation | null
- static #workloadLocation: WebGLUniformLocation | null
static #vertexShader: WebGLShader | null
static #fragmentShader: WebGLShader | null
static #positionBuffer: WebGLBuffer | null
static #uvBuffer: WebGLBuffer | null
+ static #uboBuffer: WebGLBuffer | null
static #query: WebGLQuery | null
static #pixels: Uint8Array
// Vertex Positions, 2 triangles
this.#gl.vertexAttribPointer(1, 2, this.#gl.FLOAT, false, 0, 0)
this.#gl.enableVertexAttribArray(1)
+ this.#uboBuffer = this.#gl.createBuffer()
+ this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer)
+ this.#gl.bufferData(this.#gl.UNIFORM_BUFFER, 16, this.#gl.DYNAMIC_DRAW)
+ this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null)
+ this.#gl.bindBufferBase(this.#gl.UNIFORM_BUFFER, 0, this.#uboBuffer)
+ this.#gl.uniformBlockBinding(this.#program, this.#gl.getUniformBlockIndex(this.#program, 'UBO'), 0)
+
this.#pixels = new Uint8Array(this.#gl.drawingBufferWidth * this.#gl.drawingBufferHeight * 4)
this.#query = this.#gl.createQuery()
this.#workLocation = this.#gl.getUniformLocation(this.#program, 'work')
this.#blockHashLocation = this.#gl.getUniformLocation(this.#program, "blockHash")
- this.#thresholdLocation = this.#gl.getUniformLocation(this.#program, "threshold")
- this.#workloadLocation = this.#gl.getUniformLocation(this.#program, "workload")
}
static #calculate (hashHex: string, callback: (nonce: string | PromiseLike<string>) => any, threshold: number): void {
}
const hashBytes = new Uint32Array(view.buffer)
Pow.#gl.uniform1uiv(Pow.#blockHashLocation, hashBytes)
- Pow.#gl.uniform1ui(Pow.#thresholdLocation, threshold)
- Pow.#gl.uniform1f(Pow.#workloadLocation, Pow.#WORKLOAD - 1)
- const work = new Uint8Array(8)
+
+ // Set up uniform buffer object
+ const uboView = new DataView(new ArrayBuffer(16))
+ uboView.setUint32(0, threshold, true)
+ uboView.setFloat32(4, Pow.#WORKLOAD - 1, true)
+ Pow.#gl.bindBuffer(Pow.#gl.UNIFORM_BUFFER, Pow.#uboBuffer)
+ Pow.#gl.bufferSubData(Pow.#gl.UNIFORM_BUFFER, 0, uboView)
+ Pow.#gl.bindBuffer(Pow.#gl.UNIFORM_BUFFER, null)
// Draw output until success or progressCallback says to stop
+ const work = new Uint8Array(8)
let n = 0
- const frameTimes: number[] = []
const draw = (): void => {
n++
if (Pow.#gl == null) throw new Error('WebGL 2 is required')
// Check the pixels for any success
for (let i = 0; i < Pow.#pixels.length; i += 4) {
if (Pow.#pixels[i] !== 0) {
- let sum = 0, reciprocals = 0, product = 1, count = frameTimes.length
- for (let i = 0; i < count; i++) {
- sum += frameTimes[i]
- reciprocals += 1 / frameTimes[i]
- product *= frameTimes[i]
- }
const hex = Pow.#hexify(work.subarray(4, 8)) + Pow.#hexify([
Pow.#pixels[i + 2],
Pow.#pixels[i + 3],