// 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];
+layout(std140) uniform WORK {
+ 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
static #gl: WebGL2RenderingContext | null
static #program: WebGLProgram | null
- static #workLocation: WebGLUniformLocation | null
static #vertexShader: WebGLShader | null
static #fragmentShader: WebGLShader | null
static #positionBuffer: WebGLBuffer | null
static #uvBuffer: WebGLBuffer | null
static #uboBuffer: WebGLBuffer | null
+ static #workBuffer: WebGLBuffer | null
static #query: WebGLQuery | null
static #pixels: Uint8Array
// Vertex Positions, 2 triangles
this.#gl.bindBufferBase(this.#gl.UNIFORM_BUFFER, 0, this.#uboBuffer)
this.#gl.uniformBlockBinding(this.#program, this.#gl.getUniformBlockIndex(this.#program, 'UBO'), 0)
+ this.#workBuffer = this.#gl.createBuffer()
+ this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#workBuffer)
+ this.#gl.bufferData(this.#gl.UNIFORM_BUFFER, 32, this.#gl.STREAM_DRAW)
+ this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null)
+ this.#gl.bindBufferBase(this.#gl.UNIFORM_BUFFER, 1, this.#workBuffer)
+ this.#gl.uniformBlockBinding(this.#program, this.#gl.getUniformBlockIndex(this.#program, 'WORK'), 1)
+
this.#pixels = new Uint8Array(this.#gl.drawingBufferWidth * this.#gl.drawingBufferHeight * 4)
this.#query = this.#gl.createQuery()
- this.#workLocation = this.#gl.getUniformLocation(this.#program, 'work')
}
static #calculate (hashHex: string, callback: (nonce: string | PromiseLike<string>) => any, threshold: number): void {
// Draw output until success or progressCallback says to stop
const work = new Uint8Array(8)
- let n = 0
const draw = (): void => {
- n++
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')
- crypto.getRandomValues(work)
Pow.#gl.clear(Pow.#gl.COLOR_BUFFER_BIT)
- Pow.#gl.uniform4uiv(Pow.#workLocation, work)
+ // Upload work buffer
+ crypto.getRandomValues(work)
+ Pow.#gl.bindBuffer(Pow.#gl.UNIFORM_BUFFER, Pow.#workBuffer)
+ Pow.#gl.bufferSubData(Pow.#gl.UNIFORM_BUFFER, 0, Uint32Array.from(work))
+ Pow.#gl.bindBuffer(Pow.#gl.UNIFORM_BUFFER, null)
Pow.#gl.beginQuery(Pow.#gl.ANY_SAMPLES_PASSED_CONSERVATIVE, Pow.#query)
Pow.#gl.drawArrays(Pow.#gl.TRIANGLES, 0, 6)