in vec2 uv_pos;
out vec4 fragColor;
-// Random work values
-// First 2 bytes will be overwritten by texture pixel position
-// Second 2 bytes will be modified if the canvas size is greater than 256x256
-uniform uvec4 u_work0;
-// Last 4 bytes remain as generated externally
-uniform uvec4 u_work1;
// Precalculated block hash components
uniform uint blockHash[8];
// Threshold is 0xfffffff8 for send/change blocks and 0xfffffe for all else
// Defines canvas size
uniform float workload;
+// Random work values
+// First 2 bytes will be overwritten by texture pixel position
+// Second 2 bytes will be modified if the canvas size is greater than 256x256
+// Last 4 bytes remain as generated externally
+uniform uvec4 work[2];
+
// Defined separately from uint v[32] below as the original value is required
// to calculate the second uint32 of the digest for threshold comparison
#define BLAKE2B_IV32_1 0x6A09E667u
void main() {
int i;
+ uvec4 u_work0 = work[0];
+ uvec4 u_work1 = work[1];
uint uv_x = uint(uv_pos.x * workload);
uint uv_y = uint(uv_pos.y * workload);
uint x_pos = uv_x % 256u;
}`
/** Used to set canvas size. Must be a multiple of 256. */
- static #WORKLOAD: number = 256 * Math.max(1, Math.floor(navigator.hardwareConcurrency) / 2)
+ static #WORKLOAD: number = 256 * Math.max(1, Math.floor(navigator.hardwareConcurrency))
static #hexify (arr: number[] | Uint8Array): string {
let out = ''
static #gl: WebGL2RenderingContext | null
static #program: WebGLProgram | null
- static #work0Location: WebGLUniformLocation | null
- static #work1Location: WebGLUniformLocation | null
+ static #workLocation: WebGLUniformLocation | null
static #blockHashLocation: WebGLUniformLocation | null
static #thresholdLocation: WebGLUniformLocation | null
static #workloadLocation: WebGLUniformLocation | null
this.#pixels = new Uint8Array(this.#gl.drawingBufferWidth * this.#gl.drawingBufferHeight * 4)
this.#query = this.#gl.createQuery()
- this.#work0Location = this.#gl.getUniformLocation(this.#program, 'u_work0')
- this.#work1Location = this.#gl.getUniformLocation(this.#program, 'u_work1')
+ 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")
Pow.#gl.uniform1uiv(Pow.#blockHashLocation, hashBytes)
Pow.#gl.uniform1ui(Pow.#thresholdLocation, threshold)
Pow.#gl.uniform1f(Pow.#workloadLocation, Pow.#WORKLOAD - 1)
- const work0 = new Uint8Array(4)
- const work1 = new Uint8Array(4)
+ const work = new Uint8Array(8)
// Draw output until success or progressCallback says to stop
let n = 0
if (Pow.#gl == null) throw new Error('WebGL 2 is required')
if (Pow.#query == null) throw new Error('WebGL 2 is required to run queries')
performance.mark('start')
- crypto.getRandomValues(work0)
- crypto.getRandomValues(work1)
+ crypto.getRandomValues(work)
Pow.#gl.clear(Pow.#gl.COLOR_BUFFER_BIT)
- Pow.#gl.uniform4uiv(Pow.#work0Location, work0)
- Pow.#gl.uniform4uiv(Pow.#work1Location, work1)
+ Pow.#gl.uniform4uiv(Pow.#workLocation, work)
Pow.#gl.beginQuery(Pow.#gl.ANY_SAMPLES_PASSED_CONSERVATIVE, Pow.#query)
Pow.#gl.drawArrays(Pow.#gl.TRIANGLES, 0, 6)
performance.mark('end')
frameTimes.push(performance.measure('draw', 'start', 'end').duration)
performance.clearMarks()
+ performance.clearMeasures()
// No valid nonce found, start the next draw call
requestAnimationFrame(draw)
}
console.log(`Average: ${sum / count} ms`)
console.log(`Harmonic: ${count / reciprocals} ms`)
console.log(`Geometric: ${Math.pow(product, 1 / count)} ms`)
- const hex = Pow.#hexify(work1) + Pow.#hexify([
+ const hex = Pow.#hexify(work.subarray(4, 8)) + Pow.#hexify([
Pow.#pixels[i + 2],
Pow.#pixels[i + 3],
- work0[2] ^ (Pow.#pixels[i] - 1),
- work0[3] ^ (Pow.#pixels[i + 1] - 1)
+ work[2] ^ (Pow.#pixels[i] - 1),
+ work[3] ^ (Pow.#pixels[i + 1] - 1)
])
// Return the work value with the custom bits
typeof callback === 'function' && callback(hex)