+++ /dev/null
-// src/shaders/compute.wgsl
-var compute_default = "struct UBO{blockhash:array<vec4<u32>,2>,seed:vec2<u32>,threshold:u32};@group(0)@binding(0)var<uniform> ubo:UBO;struct WORK{nonce:vec2<u32>,found:atomic<u32>};@group(0)@binding(1)var<storage,read_write>work:WORK;const BLAKE2B_IV_0=vec2(0xF2BDC900u,0x6A09E667u);const Z=vec2(0u);const CARRY=vec4(1u,0u,1u,0u);const ROTATE_1=vec4(1u);const ROTATE_8=vec4(8u);const ROTATE_16=vec4(16u);const ROTATE_24=vec4(24u);const ROTATE_31=vec4(31u);var<workgroup> found:bool;@compute @workgroup_size(32)fn search(@builtin(global_invocation_id)global_id:vec3<u32>,@builtin(local_invocation_id)local_id:vec3<u32>){found=(local_id.x==0u&&atomicLoad(&work.found)!=0u);workgroupBarrier();if(found){return;}main(global_id);}@compute @workgroup_size(1)fn validate(@builtin(global_invocation_id)global_id:vec3<u32>){main(global_id);}fn main(id:vec3<u32>){let m0:vec2<u32>=ubo.seed ^ id.xy;let m1:vec2<u32>=ubo.blockhash[0u].xy;let m2:vec2<u32>=ubo.blockhash[0u].zw;let m3:vec2<u32>=ubo.blockhash[1u].xy;let m4:vec2<u32>=ubo.blockhash[1u].zw;var v01:vec4<u32>=vec4(BLAKE2B_IV_0,0x84CAA73Bu,0xBB67AE85u);var v23:vec4<u32>=vec4(0xFE94F82Bu,0x3C6EF372u,0x5F1D36F1u,0xA54FF53Au);var v45:vec4<u32>=vec4(0xADE682D1u,0x510E527Fu,0x2B3E6C1Fu,0x9B05688Cu);var v67:vec4<u32>=vec4(0xFB41BD6Bu,0x1F83D9ABu,0x137E2179u,0x5BE0CD19u);var v89:vec4<u32>=vec4(0xF3BCC908u,0x6A09E667u,0x84CAA73Bu,0xBB67AE85u);var vAB:vec4<u32>=vec4(0xFE94F82Bu,0x3C6EF372u,0x5F1D36F1u,0xA54FF53Au);var vCD:vec4<u32>=vec4(0xADE682F9u,0x510E527Fu,0x2B3E6C1Fu,0x9B05688Cu);var vEF:vec4<u32>=vec4(0x04BE4294u,0xE07C2654u,0x137E2179u,0x5BE0CD19u);var v56:vec4<u32>;var vFC:vec4<u32>;var v74:vec4<u32>;var vDE:vec4<u32>;var s0:vec4<u32>;var s1:vec4<u32>;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m0,m2);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;v23+=vec4(m4,Z);v23.y+=u32(v23.x<m4.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m1,m3);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m4);v01.w+=u32(v01.z<m4.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m1,m0);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m2);v01.w+=u32(v01.z<m2.x);v23+=vec4(Z,m3);v23.w+=u32(v23.z<m3.x);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(Z,m0);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+vec4(m2,Z);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01.z+=m3.x;v01.w+=m3.y+u32(v01.z<m3.x);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m1,m4)+vec4(0u,u32(v23.x+vec4(m1,m4).x<v23.x),0u,u32(v23.z+vec4(m1,m4).z<v23.z));vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m3)+vec4(Z,0u,u32(v01.z+vec4(Z,m3).z<v01.z));vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m1)+vec4(Z,0u,u32(v01.z+vec4(Z,m1).z<v01.z));vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m2,Z)+vec4(0u,u32(v01.x+vec4(m2,Z).x<v01.x),Z);v23+=vec4(m4,Z)+vec4(0u,u32(v23.x+vec4(m4,Z).x<v23.x),Z);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m0,Z)+vec4(0u,u32(v23.x+vec4(m0,Z).x<v23.x),Z);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s1=v23+vec4(m2,Z);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m0,Z)+vec4(0u,u32(v01.x+vec4(m0,Z).x<v01.x),Z);v23+=vec4(m4,Z)+vec4(0u,u32(v23.x+vec4(m4,Z).x<v23.x),Z);vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s1=v23+vec4(Z,m3);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m1,Z)+vec4(0u,u32(v01.x+vec4(m1,Z).x<v01.x),Z);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m2,Z)+vec4(0u,u32(v01.x+vec4(m2,Z).x<v01.x),Z);v23+=vec4(m0,Z)+vec4(0u,u32(v23.x+vec4(m0,Z).x<v23.x),Z);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s1=v23+vec4(Z,m3);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m4,Z)+vec4(0u,u32(v01.x+vec4(m4,Z).x<v01.x),Z);v23+=vec4(Z,m1)+vec4(Z,0u,u32(v23.z+vec4(Z,m1).z<v23.z));vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m1)+vec4(Z,0u,u32(v01.z+vec4(Z,m1).z<v01.z));v23+=vec4(Z,m4)+vec4(Z,0u,u32(v23.z+vec4(Z,m4).z<v23.z));vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m0,Z)+vec4(0u,u32(v01.x+vec4(m0,Z).x<v01.x),Z);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m3)+vec4(Z,0u,u32(v01.z+vec4(Z,m3).z<v01.z));s1=v23+vec4(m2,Z);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s1=v23+vec4(Z,m3);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m1,Z)+vec4(0u,u32(v23.x+vec4(m1,Z).x<v23.x),Z);vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(Z,m2)+vec4(Z,0u,u32(v23.z+vec4(Z,m2).z<v23.z));vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m0,m4)+vec4(0u,u32(v01.x+vec4(m0,m4).x<v01.x),0u,u32(v01.z+vec4(m0,m4).z<v01.z));vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(Z,m0);v23.w+=u32(v23.z<m0.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m3,Z)+vec4(0u,u32(v23.x+vec4(m3,Z).x<v23.x),Z);vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m1,Z)+vec4(0u,u32(v23.x+vec4(m1,Z).x<v23.x),Z);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m2,Z)+vec4(0u,u32(v01.x+vec4(m2,Z).x<v01.x),Z);v23+=vec4(m4,Z)+vec4(0u,u32(v23.x+vec4(m4,Z).x<v23.x),Z);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(Z,m1);v23.w+=u32(v23.z<m1.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m2,m4);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m3,Z);v23.y+=u32(v23.x<m3.x);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(Z,m0);v23.w+=u32(v23.z<m0.x);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m0,m2);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;v23+=vec4(m4,Z);v23.y+=u32(v23.x<m4.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m1,m3);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m4);v01.w+=u32(v01.z<m4.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m1,m0);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m2);v01.w+=u32(v01.z<m2.x);v23+=vec4(Z,m3);v23.w+=u32(v23.z<m3.x);vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89).yxwz&CARRY);if((BLAKE2B_IV_0.y ^ v01.y ^ v89.y)>ubo.threshold&&atomicLoad(&work.found)==0u){atomicStore(&work.found,1u);work.nonce=m0;}return;}";
-
-// src/shaders/gl-downsample.ts
-var NanoPowGlDownsampleShader = `#version 300 es
-#pragma vscode_glsllint_stage: frag
-#ifdef GL_FRAGMENT_PRECISION_HIGH
-precision highp float;
-#else
-precision mediump float;
-#endif
-precision highp int;
-
-out uvec4 nonce;
-
-// source texture to be downsampled
-uniform highp usampler2D src;
-
-void main() {
- nonce = uvec4(0u);
- vec2 inputSize = vec2(textureSize(src, 0));
- vec2 texel = vec2(1.0) / inputSize;
- vec2 blockCoord = (floor(gl_FragCoord.xy) * 2.0 + vec2(0.5)) / inputSize;
-
- uvec4 pixel = texture(src, blockCoord);
- nonce = pixel.x == 0u ? nonce : pixel;
-
- pixel = texture(src, blockCoord + vec2(texel.x, 0.0));
- nonce = pixel.x == 0u ? nonce : pixel;
-
- pixel = texture(src, blockCoord + vec2(0.0, texel.y));
- nonce = pixel.x == 0u ? nonce : pixel;
-
- pixel = texture(src, blockCoord + vec2(texel.x, texel.y));
- nonce = pixel.x == 0u ? nonce : pixel;
-}
-`;
-
-// src/shaders/gl-draw.ts
-var NanoPowGlDrawShader = `#version 300 es
-#pragma vscode_glsllint_stage: frag
-#ifdef GL_FRAGMENT_PRECISION_HIGH
-precision highp float;
-#else
-precision mediump float;
-#endif
-
-out uvec4 nonce;
-
-// blockhash - Array of precalculated block hash components
-// threshold - 0xfffffff8 for send/change blocks, 0xfffffe00 for all else
-// search - Checks all pixels if true, else only checks 1 pixel to validate
-layout(std140) uniform UBO {
- uint blockhash[8];
- uint threshold;
- bool search;
-};
-
-// Random work seed values
-layout(std140) uniform WORK {
- uvec2 seed;
-};
-
-// Defined separately from uint v[0].y below as the original value is required
-// to calculate the second uint32 of the digest for threshold comparison
-const uint BLAKE2B_IV32_1 = 0x6A09E667u;
-
-// Used during G for vector bit rotations
-const uvec4 ROTATE_1 = uvec4(1u);
-const uvec4 ROTATE_8 = uvec4(8u);
-const uvec4 ROTATE_16 = uvec4(16u);
-const uvec4 ROTATE_24 = uvec4(24u);
-const uvec4 ROTATE_31 = uvec4(31u);
-
-// Both buffers represent 16 uint64s as 32 uint32s
-// because that's what GLSL offers, just like Javascript
-
-// Compression buffer, intialized to 2 instances of the initialization vector
-// The following values have been modified from the BLAKE2B_IV:
-// OUTLEN is constant 8 bytes
-// v[0] ^= 0x01010000u ^ uint(OUTLEN);
-// INLEN is constant 40 bytes: work value (8) + block hash (32)
-// v[12] ^= uint(INLEN);
-// It's always the "last" compression at this INLEN
-// v[14] = ~v[14];
-const uvec2 blake2b_iv[16] = uvec2[16](
- uvec2(0xF2BDC900u, 0x6A09E667u),
- uvec2(0x84CAA73Bu, 0xBB67AE85u),
- uvec2(0xFE94F82Bu, 0x3C6EF372u),
- uvec2(0x5F1D36F1u, 0xA54FF53Au),
- uvec2(0xADE682D1u, 0x510E527Fu),
- uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
- uvec2(0xFB41BD6Bu, 0x1F83D9ABu),
- uvec2(0x137E2179u, 0x5BE0CD19u),
- uvec2(0xF3BCC908u, 0x6A09E667u),
- uvec2(0x84CAA73Bu, 0xBB67AE85u),
- uvec2(0xFE94F82Bu, 0x3C6EF372u),
- uvec2(0x5F1D36F1u, 0xA54FF53Au),
- uvec2(0xADE682F9u, 0x510E527Fu),
- uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
- uvec2(0x04BE4294u, 0xE07C2654u),
- uvec2(0x137E2179u, 0x5BE0CD19u)
-);
-
-// Iterated initialization vector
-uvec2 v[16];
-
-// Input data buffer
-uvec2 m[16];
-
-// G mixing function, compressing two subprocesses into one
-void G (
- uint a0, uint b0, uint c0, uint d0, uvec2 x0, uvec2 y0,
- uint a1, uint b1, uint c1, uint d1, uvec2 x1, uvec2 y1
-) {
- uvec4 a = uvec4(v[a0], v[a1]);
- uvec4 b = uvec4(v[b0], v[b1]);
- uvec4 c = uvec4(v[c0], v[c1]);
- uvec4 d = uvec4(v[d0], v[d1]);
- uvec4 mx = uvec4(x0, x1);
- uvec4 my = uvec4(y0, y1);
-
- a = a + b + uvec4(0u, uint(a.x + b.x < a.x), 0u, uint(a.z + b.z < a.z));
- a = a + mx + uvec4(0u, uint(a.x + mx.x < a.x), 0u, uint(a.z + mx.z < a.z));
- d = (d ^ a).yxwz;
- c = c + d + uvec4(0u, uint(c.x + d.x < c.x), 0u, uint(c.z + d.z < c.z));
- b = ((b ^ c) >> ROTATE_24) | ((b ^ c) << ROTATE_8).yxwz;
- a = a + b + uvec4(0u, uint(a.x + b.x < b.x), 0u, uint(a.z + b.z < b.z));
- a = a + my + uvec4(0u, uint(a.x + my.x < a.x), 0u, uint(a.z + my.z < a.z));
- d = ((d ^ a) >> ROTATE_16) | ((d ^ a) << ROTATE_16).yxwz;
- c = c + d + uvec4(0u, uint(c.x + d.x < c.x), 0u, uint(c.z + d.z < c.z));
- b = ((b ^ c) >> ROTATE_31).yxwz | ((b ^ c) << ROTATE_1);
-
- v[a0] = a.xy;
- v[b0] = b.xy;
- v[c0] = c.xy;
- v[d0] = d.xy;
- v[a1] = a.zw;
- v[b1] = b.zw;
- v[c1] = c.zw;
- v[d1] = d.zw;
-}
-
-void main() {
- // Initialize fragment output
- nonce = uvec4(0u);
-
- // Nonce uniquely differentiated by pixel location
- m[0u] = seed ^ uvec2(gl_FragCoord);
-
- // Block hash
- m[1u] = uvec2(blockhash[0u], blockhash[1u]);
- m[2u] = uvec2(blockhash[2u], blockhash[3u]);
- m[3u] = uvec2(blockhash[4u], blockhash[5u]);
- m[4u] = uvec2(blockhash[6u], blockhash[7u]);
-
- // Reset v
- v = blake2b_iv;
-
- // Twelve rounds of G mixing
-
- // Round 0
- G(0u, 4u, 8u, 12u, m[0u], m[1u], 1u, 5u, 9u, 13u, m[2u], m[3u]);
- G(2u, 6u, 10u, 14u, m[4u], m[5u], 3u, 7u, 11u, 15u, m[6u], m[7u]);
- G(0u, 5u, 10u, 15u, m[8u], m[9u], 1u, 6u, 11u, 12u, m[10u], m[11u]);
- G(2u, 7u, 8u, 13u, m[12u], m[13u], 3u, 4u, 9u, 14u, m[14u], m[15u]);
-
- // Round 1
- G(0u, 4u, 8u, 12u, m[14u], m[10u], 1u, 5u, 9u, 13u, m[4u], m[8u]);
- G(2u, 6u, 10u, 14u, m[9u], m[15u], 3u, 7u, 11u, 15u, m[13u], m[6u]);
- G(0u, 5u, 10u, 15u, m[1u], m[12u], 1u, 6u, 11u, 12u, m[0u], m[2u]);
- G(2u, 7u, 8u, 13u, m[11u], m[7u], 3u, 4u, 9u, 14u, m[5u], m[3u]);
-
- // Round 2
- G(0u, 4u, 8u, 12u, m[11u], m[8u], 1u, 5u, 9u, 13u, m[12u], m[0u]);
- G(2u, 6u, 10u, 14u, m[5u], m[2u], 3u, 7u, 11u, 15u, m[15u], m[13u]);
- G(0u, 5u, 10u, 15u, m[10u], m[14u], 1u, 6u, 11u, 12u, m[3u], m[6u]);
- G(2u, 7u, 8u, 13u, m[7u], m[1u], 3u, 4u, 9u, 14u, m[9u], m[4u]);
-
- // Round 3
- G(0u, 4u, 8u, 12u, m[7u], m[9u], 1u, 5u, 9u, 13u, m[3u], m[1u]);
- G(2u, 6u, 10u, 14u, m[13u], m[12u], 3u, 7u, 11u, 15u, m[11u], m[14u]);
- G(0u, 5u, 10u, 15u, m[2u], m[6u], 1u, 6u, 11u, 12u, m[5u], m[10u]);
- G(2u, 7u, 8u, 13u, m[4u], m[0u], 3u, 4u, 9u, 14u, m[15u], m[8u]);
-
- // Round 4
- G(0u, 4u, 8u, 12u, m[9u], m[0u], 1u, 5u, 9u, 13u, m[5u], m[7u]);
- G(2u, 6u, 10u, 14u, m[2u], m[4u], 3u, 7u, 11u, 15u, m[10u], m[15u]);
- G(0u, 5u, 10u, 15u, m[14u], m[1u], 1u, 6u, 11u, 12u, m[11u], m[12u]);
- G(2u, 7u, 8u, 13u, m[6u], m[8u], 3u, 4u, 9u, 14u, m[3u], m[13u]);
-
- // Round 5
- G(0u, 4u, 8u, 12u, m[2u], m[12u], 1u, 5u, 9u, 13u, m[6u], m[10u]);
- G(2u, 6u, 10u, 14u, m[0u], m[11u], 3u, 7u, 11u, 15u, m[8u], m[3u]);
- G(0u, 5u, 10u, 15u, m[4u], m[13u], 1u, 6u, 11u, 12u, m[7u], m[5u]);
- G(2u, 7u, 8u, 13u, m[15u], m[14u], 3u, 4u, 9u, 14u, m[1u], m[9u]);
-
- // Round 6
- G(0u, 4u, 8u, 12u, m[12u], m[5u], 1u, 5u, 9u, 13u, m[1u], m[15u]);
- G(2u, 6u, 10u, 14u, m[14u], m[13u], 3u, 7u, 11u, 15u, m[4u], m[10u]);
- G(0u, 5u, 10u, 15u, m[0u], m[7u], 1u, 6u, 11u, 12u, m[6u], m[3u]);
- G(2u, 7u, 8u, 13u, m[9u], m[2u], 3u, 4u, 9u, 14u, m[8u], m[11u]);
-
- // Round 7
- G(0u, 4u, 8u, 12u, m[13u], m[11u], 1u, 5u, 9u, 13u, m[7u], m[14u]);
- G(2u, 6u, 10u, 14u, m[12u], m[1u], 3u, 7u, 11u, 15u, m[3u], m[9u]);
- G(0u, 5u, 10u, 15u, m[5u], m[0u], 1u, 6u, 11u, 12u, m[15u], m[4u]);
- G(2u, 7u, 8u, 13u, m[8u], m[6u], 3u, 4u, 9u, 14u, m[2u], m[10u]);
-
- // Round 8
- G(0u, 4u, 8u, 12u, m[6u], m[15u], 1u, 5u, 9u, 13u, m[14u], m[9u]);
- G(2u, 6u, 10u, 14u, m[11u], m[3u], 3u, 7u, 11u, 15u, m[0u], m[8u]);
- G(0u, 5u, 10u, 15u, m[12u], m[2u], 1u, 6u, 11u, 12u, m[13u], m[7u]);
- G(2u, 7u, 8u, 13u, m[1u], m[4u], 3u, 4u, 9u, 14u, m[10u], m[5u]);
-
- // Round 9
- G(0u, 4u, 8u, 12u, m[10u], m[2u], 1u, 5u, 9u, 13u, m[8u], m[4u]);
- G(2u, 6u, 10u, 14u, m[7u], m[6u], 3u, 7u, 11u, 15u, m[1u], m[5u]);
- G(0u, 5u, 10u, 15u, m[15u], m[11u], 1u, 6u, 11u, 12u, m[9u], m[14u]);
- G(2u, 7u, 8u, 13u, m[3u], m[12u], 3u, 4u, 9u, 14u, m[13u], m[0u]);
-
- // Round 10
- G(0u, 4u, 8u, 12u, m[0u], m[1u], 1u, 5u, 9u, 13u, m[2u], m[3u]);
- G(2u, 6u, 10u, 14u, m[4u], m[5u], 3u, 7u, 11u, 15u, m[6u], m[7u]);
- G(0u, 5u, 10u, 15u, m[8u], m[9u], 1u, 6u, 11u, 12u, m[10u], m[11u]);
- G(2u, 7u, 8u, 13u, m[12u], m[13u], 3u, 4u, 9u, 14u, m[14u], m[15u]);
-
- // Round 11
- G(0u, 4u, 8u, 12u, m[14u], m[10u], 1u, 5u, 9u, 13u, m[4u], m[8u]);
- G(2u, 6u, 10u, 14u, m[9u], m[15u], 3u, 7u, 11u, 15u, m[13u], m[6u]);
- G(0u, 5u, 10u, 15u, m[1u], m[12u], 1u, 6u, 11u, 12u, m[0u], m[2u]);
- G(2u, 7u, 8u, 13u, m[11u], m[7u], 3u, 4u, 9u, 14u, m[5u], m[3u]);
-
- // Pixel data set from work seed values
- // Finalize digest from high bits, low bits can be safely ignored
- if ((BLAKE2B_IV32_1 ^ v[0u].y ^ v[8u].y) >= threshold && (search || uvec2(gl_FragCoord) == uvec2(0u))) {
- nonce = uvec4(1u, m[0u].y, m[0u].x, (uint(gl_FragCoord.x) << 16u) | uint(gl_FragCoord.y));
- }
-
- // Valid nonce not found
- if (nonce.x == 0u) {
- discard;
- }
-}
-`;
-
-// src/shaders/gl-vertex.ts
-var NanoPowGlVertexShader = `#version 300 es
-#pragma vscode_glsllint_stage: vert
-#ifdef GL_FRAGMENT_PRECISION_HIGH
-precision highp float;
-#else
-precision mediump float;
-#endif
-
-layout (location=0) in vec4 position;
-
-void main() {
- gl_Position = position;
-}
-`;
-
-// src/classes/gl.ts
-var NanoPowGl = class _NanoPowGl {
- static #busy = false;
- static #debug = false;
- static #raf = 0;
- /** Used to set canvas size. */
- static #cores = Math.max(1, Math.floor(navigator.hardwareConcurrency));
- static #WORKLOAD = 256 * this.#cores;
- static #canvas = new OffscreenCanvas(this.#WORKLOAD, this.#WORKLOAD);
- static get size() {
- return this.#gl?.drawingBufferWidth;
- }
- static #gl;
- static #drawProgram;
- static #downsampleProgram;
- static #vertexShader;
- static #drawShader;
- static #downsampleShader;
- static #positionBuffer;
- static #drawFbo;
- static #downsampleFbos = [];
- static #downsampleSrcLocation;
- static #uboBuffer;
- static #uboView = new DataView(new ArrayBuffer(144));
- static #seedBuffer;
- static #seed = new BigUint64Array(1);
- static #query;
- static #pixels;
- /**Vertex Positions, 2 triangles */
- static #positions = new Float32Array([
- -1,
- -1,
- 1,
- -1,
- 1,
- 1,
- -1,
- 1
- ]);
- /** Compile */
- static async init() {
- if (this.#busy) return;
- this.#busy = true;
- try {
- this.#canvas.addEventListener("webglcontextlost", (event) => {
- event.preventDefault();
- console.warn("WebGL context lost. Waiting for it to be restored...");
- cancelAnimationFrame(this.#raf);
- }, false);
- this.#canvas.addEventListener("webglcontextrestored", (event) => {
- console.warn("WebGL context restored. Reinitializing...");
- _NanoPowGl.init();
- }, false);
- this.#gl = this.#canvas.getContext("webgl2");
- if (this.#gl == null) throw new Error("WebGL 2 is required");
- this.#drawProgram = this.#gl.createProgram();
- if (this.#drawProgram == null) throw new Error("Failed to create shader program");
- this.#vertexShader = this.#gl.createShader(this.#gl.VERTEX_SHADER);
- if (this.#vertexShader == null) throw new Error("Failed to create vertex shader");
- this.#gl.shaderSource(this.#vertexShader, NanoPowGlVertexShader);
- this.#gl.compileShader(this.#vertexShader);
- if (!this.#gl.getShaderParameter(this.#vertexShader, this.#gl.COMPILE_STATUS))
- throw new Error(this.#gl.getShaderInfoLog(this.#vertexShader) ?? `Failed to compile vertex shader`);
- this.#drawShader = this.#gl.createShader(this.#gl.FRAGMENT_SHADER);
- if (this.#drawShader == null) throw new Error("Failed to create fragment shader");
- this.#gl.shaderSource(this.#drawShader, NanoPowGlDrawShader);
- this.#gl.compileShader(this.#drawShader);
- if (!this.#gl.getShaderParameter(this.#drawShader, this.#gl.COMPILE_STATUS))
- throw new Error(this.#gl.getShaderInfoLog(this.#drawShader) ?? `Failed to compile fragment shader`);
- this.#gl.attachShader(this.#drawProgram, this.#vertexShader);
- this.#gl.attachShader(this.#drawProgram, this.#drawShader);
- this.#gl.linkProgram(this.#drawProgram);
- if (!this.#gl.getProgramParameter(this.#drawProgram, this.#gl.LINK_STATUS))
- throw new Error(this.#gl.getProgramInfoLog(this.#drawProgram) ?? `Failed to link program`);
- this.#downsampleProgram = this.#gl.createProgram();
- if (this.#downsampleProgram == null) throw new Error("Failed to create downsample program");
- this.#downsampleShader = this.#gl.createShader(this.#gl.FRAGMENT_SHADER);
- if (this.#downsampleShader == null) throw new Error("Failed to create downsample shader");
- this.#gl.shaderSource(this.#downsampleShader, NanoPowGlDownsampleShader);
- this.#gl.compileShader(this.#downsampleShader);
- if (!this.#gl.getShaderParameter(this.#downsampleShader, this.#gl.COMPILE_STATUS))
- throw new Error(this.#gl.getShaderInfoLog(this.#downsampleShader) ?? `Failed to compile downsample shader`);
- this.#gl.attachShader(this.#downsampleProgram, this.#vertexShader);
- this.#gl.attachShader(this.#downsampleProgram, this.#downsampleShader);
- this.#gl.linkProgram(this.#downsampleProgram);
- if (!this.#gl.getProgramParameter(this.#downsampleProgram, this.#gl.LINK_STATUS))
- throw new Error(this.#gl.getProgramInfoLog(this.#downsampleProgram) ?? `Failed to link program`);
- this.#gl.useProgram(this.#drawProgram);
- const triangleArray = this.#gl.createVertexArray();
- this.#gl.bindVertexArray(triangleArray);
- this.#positionBuffer = this.#gl.createBuffer();
- this.#gl.bindBuffer(this.#gl.ARRAY_BUFFER, this.#positionBuffer);
- this.#gl.bufferData(this.#gl.ARRAY_BUFFER, this.#positions, this.#gl.STATIC_DRAW);
- this.#gl.vertexAttribPointer(0, 2, this.#gl.FLOAT, false, 0, 0);
- this.#gl.enableVertexAttribArray(0);
- this.#gl.bindBuffer(this.#gl.ARRAY_BUFFER, null);
- const texture = this.#gl.createTexture();
- this.#gl.bindTexture(this.#gl.TEXTURE_2D, texture);
- this.#gl.texImage2D(this.#gl.TEXTURE_2D, 0, this.#gl.RGBA32UI, this.#gl.drawingBufferWidth, this.#gl.drawingBufferHeight, 0, this.#gl.RGBA_INTEGER, this.#gl.UNSIGNED_INT, null);
- this.#gl.texParameteri(this.#gl.TEXTURE_2D, this.#gl.TEXTURE_MIN_FILTER, this.#gl.NEAREST);
- this.#gl.texParameteri(this.#gl.TEXTURE_2D, this.#gl.TEXTURE_MAG_FILTER, this.#gl.NEAREST);
- const framebuffer = this.#gl.createFramebuffer();
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, framebuffer);
- this.#gl.framebufferTexture2D(this.#gl.FRAMEBUFFER, this.#gl.COLOR_ATTACHMENT0, this.#gl.TEXTURE_2D, texture, 0);
- if (this.#gl.checkFramebufferStatus(this.#gl.FRAMEBUFFER) !== this.#gl.FRAMEBUFFER_COMPLETE)
- throw new Error(`Failed to create drawing framebuffer`);
- this.#drawFbo = { texture, framebuffer, size: { x: this.#gl.drawingBufferWidth, y: this.#gl.drawingBufferHeight } };
- for (let i = 1; i <= 4; i++) {
- const width = this.#gl.drawingBufferWidth / 2 ** i;
- const height = this.#gl.drawingBufferHeight / 2 ** i;
- const texture2 = this.#gl.createTexture();
- this.#gl.bindTexture(this.#gl.TEXTURE_2D, texture2);
- this.#gl.texImage2D(this.#gl.TEXTURE_2D, 0, this.#gl.RGBA32UI, width, height, 0, this.#gl.RGBA_INTEGER, this.#gl.UNSIGNED_INT, null);
- this.#gl.texParameteri(this.#gl.TEXTURE_2D, this.#gl.TEXTURE_MIN_FILTER, this.#gl.NEAREST);
- this.#gl.texParameteri(this.#gl.TEXTURE_2D, this.#gl.TEXTURE_MAG_FILTER, this.#gl.NEAREST);
- const framebuffer2 = this.#gl.createFramebuffer();
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, framebuffer2);
- this.#gl.framebufferTexture2D(this.#gl.FRAMEBUFFER, this.#gl.COLOR_ATTACHMENT0, this.#gl.TEXTURE_2D, texture2, 0);
- if (this.#gl.checkFramebufferStatus(this.#gl.FRAMEBUFFER) !== this.#gl.FRAMEBUFFER_COMPLETE)
- throw new Error(`Failed to create downsampling framebuffer ${i}`);
- this.#downsampleFbos.push({ texture: texture2, framebuffer: framebuffer2, size: { x: width, y: height } });
- }
- this.#downsampleSrcLocation = this.#gl.getUniformLocation(this.#downsampleProgram, "src");
- this.#gl.bindTexture(this.#gl.TEXTURE_2D, null);
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
- this.#uboBuffer = this.#gl.createBuffer();
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer);
- this.#gl.bufferData(this.#gl.UNIFORM_BUFFER, 144, 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.#drawProgram, this.#gl.getUniformBlockIndex(this.#drawProgram, "UBO"), 0);
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
- this.#seedBuffer = this.#gl.createBuffer();
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#seedBuffer);
- 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, 1, this.#seedBuffer);
- this.#gl.uniformBlockBinding(this.#drawProgram, this.#gl.getUniformBlockIndex(this.#drawProgram, "WORK"), 1);
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
- this.#query = this.#gl.createQuery();
- this.#pixels = new Uint32Array(this.#gl.drawingBufferWidth * this.#gl.drawingBufferHeight * 4);
- console.log(`NanoPow WebGL initialized at ${this.#gl.drawingBufferWidth}x${this.#gl.drawingBufferHeight}. Maximum nonces checked per frame: ${this.#gl.drawingBufferWidth * this.#gl.drawingBufferHeight}`);
- } catch (err) {
- throw new Error("WebGL initialization failed.", { cause: err });
- } finally {
- this.#busy = false;
- }
- }
- static reset() {
- cancelAnimationFrame(_NanoPowGl.#raf);
- _NanoPowGl.#gl?.deleteQuery(_NanoPowGl.#query);
- _NanoPowGl.#query = null;
- _NanoPowGl.#gl?.deleteBuffer(_NanoPowGl.#seedBuffer);
- _NanoPowGl.#seedBuffer = null;
- _NanoPowGl.#gl?.deleteBuffer(_NanoPowGl.#uboBuffer);
- _NanoPowGl.#uboBuffer = null;
- for (const fbo of _NanoPowGl.#downsampleFbos) {
- _NanoPowGl.#gl?.deleteFramebuffer(fbo.framebuffer);
- _NanoPowGl.#gl?.deleteTexture(fbo.texture);
- }
- _NanoPowGl.#downsampleFbos = [];
- _NanoPowGl.#gl?.deleteShader(_NanoPowGl.#downsampleShader);
- _NanoPowGl.#downsampleShader = null;
- _NanoPowGl.#gl?.deleteProgram(_NanoPowGl.#downsampleProgram);
- _NanoPowGl.#downsampleProgram = null;
- _NanoPowGl.#gl?.deleteFramebuffer(_NanoPowGl.#drawFbo?.framebuffer ?? null);
- _NanoPowGl.#drawFbo = null;
- _NanoPowGl.#gl?.deleteTexture(_NanoPowGl.#drawFbo);
- _NanoPowGl.#drawFbo = null;
- _NanoPowGl.#gl?.deleteBuffer(_NanoPowGl.#positionBuffer);
- _NanoPowGl.#positionBuffer = null;
- _NanoPowGl.#gl?.deleteShader(_NanoPowGl.#drawShader);
- _NanoPowGl.#drawShader = null;
- _NanoPowGl.#gl?.deleteShader(_NanoPowGl.#vertexShader);
- _NanoPowGl.#vertexShader = null;
- _NanoPowGl.#gl?.deleteProgram(_NanoPowGl.#drawProgram);
- _NanoPowGl.#drawProgram = null;
- _NanoPowGl.#gl = null;
- _NanoPowGl.#busy = false;
- _NanoPowGl.init();
- }
- static #logAverages(times) {
- let count = times.length, sum = 0, reciprocals = 0, logarithms = 0, truncated = 0, min = 65535, max = 0, rate = 0;
- times.sort();
- for (let i = 0; i < count; i++) {
- sum += times[i];
- reciprocals += 1 / times[i];
- logarithms += Math.log(times[i]);
- min = Math.min(min, times[i]);
- max = Math.max(max, times[i]);
- if (count < 3 || i > count * 0.1 && i < count * 0.9) truncated += times[i];
- }
- const averages = {
- "Count (frames)": count,
- "Total (ms)": sum,
- "Rate (f/s)": 1e3 * count * 0.8 / (truncated || sum),
- "Minimum (ms)": min,
- "Maximum (ms)": max,
- "Arithmetic Mean (ms)": sum / count,
- "Truncated Mean (ms)": truncated / count,
- "Harmonic Mean (ms)": count / reciprocals,
- "Geometric Mean (ms)": Math.exp(logarithms / count)
- };
- console.log(`Averages: ${JSON.stringify(averages)}`);
- console.table(averages);
- }
- static #draw(seed) {
- if (this.#gl == null || this.#query == null) throw new Error("WebGL 2 is required to draw and query pixels");
- if (this.#drawFbo == null) throw new Error("FBO is required to draw");
- if (this.#seed[0] == null || this.#seedBuffer == null) throw new Error("Seed is required to draw");
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#seedBuffer);
- this.#gl.bufferSubData(this.#gl.UNIFORM_BUFFER, 0, seed);
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
- this.#gl.useProgram(this.#drawProgram);
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, this.#drawFbo.framebuffer);
- this.#gl.activeTexture(this.#gl.TEXTURE0);
- this.#gl.bindTexture(this.#gl.TEXTURE_2D, this.#drawFbo.texture);
- this.#gl.beginQuery(this.#gl.ANY_SAMPLES_PASSED_CONSERVATIVE, this.#query);
- this.#gl.viewport(0, 0, this.#drawFbo.size.x, this.#drawFbo.size.y);
- this.#gl.drawArrays(this.#gl.TRIANGLES, 0, 4);
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
- this.#gl.endQuery(this.#gl.ANY_SAMPLES_PASSED_CONSERVATIVE);
- }
- static async #checkQueryResult() {
- return new Promise((resolve, reject) => {
- function check() {
- try {
- if (_NanoPowGl.#gl == null || _NanoPowGl.#query == null) throw new Error("WebGL 2 is required to check query results");
- if (_NanoPowGl.#gl.getQueryParameter(_NanoPowGl.#query, _NanoPowGl.#gl.QUERY_RESULT_AVAILABLE)) {
- resolve(!!_NanoPowGl.#gl.getQueryParameter(_NanoPowGl.#query, _NanoPowGl.#gl.QUERY_RESULT));
- } else {
- _NanoPowGl.#raf = requestAnimationFrame(check);
- }
- } catch (err) {
- reject(err);
- }
- }
- check();
- });
- }
- /**
- * Reads pixels into the work buffer, checks every 4th pixel for the 'found'
- * byte, converts the subsequent 3 pixels with the nonce byte values to a hex
- * string, and returns the result.
- *
- * @param workHex - Original nonce if provided for a validation call
- * @returns Nonce as an 8-byte (16-char) hexadecimal string
- */
- static #readResult(workHex) {
- if (this.#gl == null) throw new Error("WebGL 2 is required to read pixels");
- if (this.#drawFbo == null) throw new Error("Source FBO is required to downsample");
- let source = this.#drawFbo;
- let pixelCount;
- const start = performance.now();
- if (workHex != null) {
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, source.framebuffer);
- this.#gl.readPixels(0, 0, 1, 1, this.#gl.RGBA_INTEGER, this.#gl.UNSIGNED_INT, this.#pixels);
- pixelCount = 4;
- } else {
- this.#gl.useProgram(this.#downsampleProgram);
- for (const fbo of this.#downsampleFbos) {
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, fbo.framebuffer);
- this.#gl.activeTexture(this.#gl.TEXTURE0);
- this.#gl.bindTexture(this.#gl.TEXTURE_2D, source.texture);
- this.#gl.uniform1i(this.#downsampleSrcLocation, 0);
- this.#gl.viewport(0, 0, fbo.size.x, fbo.size.y);
- this.#gl.drawArrays(this.#gl.TRIANGLES, 0, 4);
- source = fbo;
- }
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, source.framebuffer);
- this.#gl.readPixels(0, 0, source.size.x, source.size.y, this.#gl.RGBA_INTEGER, this.#gl.UNSIGNED_INT, this.#pixels);
- pixelCount = source.size.x * source.size.y * 4;
- }
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
- for (let i = 0; i < pixelCount; i += 4) {
- if (this.#pixels[i] !== 0) {
- if (this.#debug) console.log(`readResults (${performance.now() - start} ms)`);
- if (this.#debug) console.log(`Pixel: rgba(${this.#pixels[i]}, ${this.#pixels[i + 1]}, ${this.#pixels[i + 2]}, ${this.#pixels[i + 3].toString(16).padStart(8, "0")})`);
- const hex = `${this.#pixels[i + 1].toString(16).padStart(8, "0")}${this.#pixels[i + 2].toString(16).padStart(8, "0")}`;
- if (workHex == null || workHex == hex) return hex;
- }
- }
- throw new Error("Query reported result but nonce value not found");
- }
- /**
- * Finds a nonce that satisfies the Nano proof-of-work requirements.
- *
- * @param {string} hash - Hexadecimal hash of previous block, or public key for new accounts
- * @param {number} [threshold=0xfffffff8] - Difficulty of proof-of-work calculation
- */
- static async search(hash, options) {
- if (this.#busy) {
- console.log("NanoPowGl is busy. Retrying search...");
- return new Promise((resolve) => {
- setTimeout(async () => {
- const result = this.search(hash, options);
- resolve(result);
- }, 100);
- });
- }
- this.#busy = true;
- if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new Error(`Invalid hash ${hash}`);
- const threshold = typeof options?.threshold !== "number" || options.threshold < 0 || options.threshold > 4294967295 ? 4294967288 : options.threshold;
- const effort = typeof options?.effort !== "number" || options.effort < 1 || options.effort > 32 ? this.#cores : options.effort;
- this.#debug = !!options?.debug;
- if (this.#WORKLOAD !== 256 * effort) {
- this.#WORKLOAD = 256 * effort;
- this.#canvas.height = this.#WORKLOAD;
- this.#canvas.width = this.#WORKLOAD;
- this.reset();
- }
- if (_NanoPowGl.#gl == null) throw new Error("WebGL 2 is required");
- if (this.#gl == null) throw new Error("WebGL 2 is required");
- if (this.#drawFbo == null) throw new Error("WebGL framebuffer is required");
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, this.#drawFbo.framebuffer);
- this.#gl.clearBufferuiv(this.#gl.COLOR, 0, [0, 0, 0, 0]);
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
- for (let i = 0; i < this.#uboView.byteLength; i++) this.#uboView.setUint8(i, 0);
- for (let i = 0; i < 64; i += 8) {
- const uint32 = hash.slice(i, i + 8);
- this.#uboView.setUint32(i * 2, parseInt(uint32, 16));
- }
- this.#uboView.setUint32(128, threshold, true);
- this.#uboView.setUint32(132, 1, true);
- if (this.#debug) console.log("UBO", this.#uboView.buffer.slice(0));
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer);
- this.#gl.bufferSubData(this.#gl.UNIFORM_BUFFER, 0, this.#uboView);
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
- let times = [];
- let start = performance.now();
- let nonce = null;
- if (this.#debug) console.groupCollapsed("Seeds (click to view)");
- while (nonce == null) {
- start = performance.now();
- const random0 = Math.floor(Math.random() * 4294967295);
- const random1 = Math.floor(Math.random() * 4294967295);
- this.#seed[0] = BigInt(random0) << 32n | BigInt(random1);
- if (this.#debug) console.log("Seed", this.#seed);
- this.#draw(this.#seed);
- const found = await this.#checkQueryResult();
- times.push(performance.now() - start);
- if (found) {
- if (this.#debug) console.groupEnd();
- nonce = this.#readResult();
- }
- }
- this.#busy = false;
- if (this.#debug) this.#logAverages(times);
- return nonce;
- }
- /**
- * Validates that a nonce satisfies Nano proof-of-work requirements.
- *
- * @param {string} work - Hexadecimal proof-of-work value to validate
- * @param {string} hash - Hexadecimal hash of previous block, or public key for new accounts
- * @param {number} [threshold=0xfffffff8] - Difficulty of proof-of-work calculation
- */
- static async validate(work, hash, options) {
- if (this.#busy) {
- console.log("NanoPowGl is busy. Retrying validate...");
- return new Promise((resolve) => {
- setTimeout(async () => {
- const result = this.validate(work, hash, options);
- resolve(result);
- }, 100);
- });
- }
- this.#busy = true;
- if (!/^[A-Fa-f0-9]{16}$/.test(work)) throw new Error(`Invalid work ${work}`);
- if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new Error(`Invalid hash ${hash}`);
- const threshold = typeof options?.threshold !== "number" || options.threshold < 0 || options.threshold > 4294967295 ? 4294967288 : options.threshold;
- this.#debug = !!options?.debug;
- if (_NanoPowGl.#gl == null) throw new Error("WebGL 2 is required");
- if (this.#gl == null) throw new Error("WebGL 2 is required");
- if (this.#drawFbo == null) throw new Error("WebGL framebuffer is required");
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, this.#drawFbo.framebuffer);
- this.#gl.clearBufferuiv(this.#gl.COLOR, 0, [0, 0, 0, 0]);
- this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
- for (let i = 0; i < this.#uboView.byteLength; i++) this.#uboView.setUint8(i, 0);
- for (let i = 0; i < 64; i += 8) {
- const uint32 = hash.slice(i, i + 8);
- this.#uboView.setUint32(i * 2, parseInt(uint32, 16));
- }
- this.#uboView.setUint32(128, threshold, true);
- this.#uboView.setUint32(132, 0, true);
- if (this.#debug) console.log("UBO", this.#uboView.buffer.slice(0));
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer);
- this.#gl.bufferSubData(this.#gl.UNIFORM_BUFFER, 0, this.#uboView);
- this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
- let nonce = null;
- this.#seed[0] = BigInt(`0x${work}`);
- if (this.#debug) console.log("Work", this.#seed);
- this.#draw(this.#seed);
- let found = await this.#checkQueryResult();
- if (found) {
- try {
- nonce = this.#readResult(work);
- } catch (err) {
- found = false;
- }
- }
- this.#busy = false;
- if (found && nonce !== work) throw new Error(`Nonce found but does not match work`);
- return found;
- }
-};
-
-// src/classes/gpu.ts
-var NanoPowGpu = class _NanoPowGpu {
- // Initialize WebGPU
- static #busy = false;
- static #debug = false;
- static #device = null;
- static #gpuBufferReset = new BigUint64Array([0n, 0n]);
- static #gpuBuffer;
- static #cpuBuffer;
- static #uboBuffer;
- static #uboView;
- static #bindGroupLayout;
- static #searchPipeline;
- static #validatePipeline;
- // Initialize WebGPU
- static async init() {
- if (this.#busy) return;
- this.#busy = true;
- try {
- if (navigator.gpu == null) throw new Error("WebGPU is not supported in this browser.");
- const adapter = await navigator.gpu.requestAdapter();
- if (adapter == null) throw new Error("WebGPU adapter refused by browser.");
- const device = await adapter.requestDevice();
- if (!(device instanceof GPUDevice)) throw new Error("WebGPU device failed to load.");
- device.lost.then(this.reset);
- this.#device = device;
- this.setup();
- } catch (err) {
- throw new Error("WebGPU initialization failed.", { cause: err });
- } finally {
- this.#busy = false;
- }
- }
- static setup() {
- if (this.#device == null) throw new Error(`WebGPU device failed to load.`);
- this.#gpuBuffer = this.#device.createBuffer({
- size: 16,
- usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
- });
- this.#cpuBuffer = this.#device.createBuffer({
- size: 16,
- usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
- });
- this.#uboBuffer = this.#device.createBuffer({
- size: 48,
- usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
- });
- this.#uboView = new DataView(new ArrayBuffer(48));
- this.#bindGroupLayout = this.#device.createBindGroupLayout({
- entries: [
- {
- binding: 0,
- visibility: GPUShaderStage.COMPUTE,
- buffer: { type: "uniform" }
- },
- {
- binding: 1,
- visibility: GPUShaderStage.COMPUTE,
- buffer: { type: "storage" }
- }
- ]
- });
- const shaderModule = this.#device.createShaderModule({
- code: compute_default
- });
- this.#searchPipeline = this.#device.createComputePipeline({
- layout: this.#device.createPipelineLayout({
- bindGroupLayouts: [this.#bindGroupLayout]
- }),
- compute: {
- entryPoint: "search",
- module: shaderModule
- }
- });
- this.#validatePipeline = this.#device.createComputePipeline({
- layout: this.#device.createPipelineLayout({
- bindGroupLayouts: [this.#bindGroupLayout]
- }),
- compute: {
- entryPoint: "validate",
- module: shaderModule
- }
- });
- console.log(`NanoPow WebGPU initialized. Recommended effort: ${Math.max(1, Math.floor(navigator.hardwareConcurrency / 2))}`);
- }
- static reset() {
- console.warn(`GPU device lost. Reinitializing...`);
- _NanoPowGpu.#cpuBuffer?.destroy();
- _NanoPowGpu.#gpuBuffer?.destroy();
- _NanoPowGpu.#uboBuffer?.destroy();
- _NanoPowGpu.#busy = false;
- _NanoPowGpu.init();
- }
- static #logAverages(times) {
- let count = times.length, truncatedCount = 0, truncated = 0, sum = 0, reciprocals = 0, logarithms = 0, min = Number.MAX_SAFE_INTEGER, max = 0, median = 0, rate = 0;
- times.sort();
- for (let i = 0; i < count; i++) {
- sum += times[i];
- reciprocals += 1 / times[i];
- logarithms += Math.log(times[i]);
- min = Math.min(min, times[i]);
- max = Math.max(max, times[i]);
- if (i === Math.ceil(count / 2)) {
- median = times[i];
- }
- if (count < 3 || i > 0.1 * count && i < 0.9 * (count - 1)) {
- truncated += times[i];
- truncatedCount++;
- }
- }
- const averages = {
- "Count (dispatches)": count,
- "Total (ms)": sum,
- "Rate (d/s)": 1e3 * truncatedCount / (truncated || sum),
- "Minimum (ms)": min,
- "Maximum (ms)": max,
- "Median (ms)": median,
- "Arithmetic Mean (ms)": sum / count,
- "Truncated Mean (ms)": truncated / truncatedCount,
- "Harmonic Mean (ms)": count / reciprocals,
- "Geometric Mean (ms)": Math.exp(logarithms / count)
- };
- console.table(averages);
- }
- static async #dispatch(pipeline, seed, hash, threshold, passes) {
- if (this.#device == null) throw new Error(`WebGPU device failed to load.`);
- for (let i = 0; i < this.#uboView.byteLength; i++) this.#uboView.setUint8(i, 0);
- for (let i = 0; i < 64; i += 16) {
- const u64 = hash.slice(i, i + 16);
- this.#uboView.setBigUint64(i / 2, BigInt(`0x${u64}`));
- }
- this.#uboView.setBigUint64(32, seed, true);
- this.#uboView.setUint32(40, threshold, true);
- if (this.#debug) console.log("UBO", this.#uboView);
- this.#device.queue.writeBuffer(this.#uboBuffer, 0, this.#uboView);
- this.#device.queue.writeBuffer(this.#gpuBuffer, 0, this.#gpuBufferReset);
- const bindGroup = this.#device.createBindGroup({
- layout: this.#bindGroupLayout,
- entries: [
- {
- binding: 0,
- resource: {
- buffer: this.#uboBuffer
- }
- },
- {
- binding: 1,
- resource: {
- buffer: this.#gpuBuffer
- }
- }
- ]
- });
- const commandEncoder = this.#device.createCommandEncoder();
- const passEncoder = commandEncoder.beginComputePass();
- passEncoder.setPipeline(pipeline);
- passEncoder.setBindGroup(0, bindGroup);
- passEncoder.dispatchWorkgroups(passes, passes);
- 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();
- data = new DataView(this.#cpuBuffer.getMappedRange().slice(0));
- this.#cpuBuffer.unmap();
- } catch (err) {
- console.warn(`Error getting data from GPU. ${err}`);
- return this.#dispatch(pipeline, seed, hash, threshold, passes);
- }
- if (this.#debug) console.log("gpuBuffer data", data);
- if (data == null) throw new Error(`Failed to get data from buffer.`);
- return data;
- }
- /**
- * Finds a nonce that satisfies the Nano proof-of-work requirements.
- *
- * @param {string} hash - Hexadecimal hash of previous block, or public key for new accounts
- * @param {NanoPowOptions} options - Used to configure search execution
- */
- static async search(hash, options) {
- if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new TypeError(`Invalid hash ${hash}`);
- if (this.#busy) {
- console.log("NanoPowGpu is busy. Retrying search...");
- return new Promise((resolve) => {
- setTimeout(async () => {
- const result = this.search(hash, options);
- resolve(result);
- }, 100);
- });
- }
- this.#busy = true;
- const threshold = typeof options?.threshold !== "number" || options.threshold < 0 || options.threshold > 4294967295 ? 4294967288 : options.threshold;
- const effort = typeof options?.effort !== "number" || options.effort < 1 || options.effort > 32 ? 2048 : options.effort * 256;
- this.#debug = !!options?.debug;
- let loads = 0;
- while (this.#device == null && loads < 20) {
- await new Promise((resolve) => {
- setTimeout(resolve, 500);
- });
- }
- if (this.#device == null) {
- this.#busy = false;
- throw new Error(`WebGPU device failed to load.`);
- }
- let times = [];
- let start = performance.now();
- let nonce = 0n;
- do {
- start = performance.now();
- const random0 = Math.floor(Math.random() * 4294967295);
- const random1 = Math.floor(Math.random() * 4294967295);
- const seed = BigInt(random0) << 32n | BigInt(random1);
- if (this.#debug) console.log(`seed: ${seed}`);
- const data = await this.#dispatch(this.#searchPipeline, seed, hash, threshold, effort);
- nonce = data.getBigUint64(0, true);
- this.#busy = !data.getUint32(8);
- times.push(performance.now() - start);
- } while (this.#busy);
- if (this.#debug) this.#logAverages(times);
- return nonce.toString(16).padStart(16, "0");
- }
- /**
- * Validates that a nonce satisfies Nano proof-of-work requirements.
- *
- * @param {string} work - Hexadecimal proof-of-work value to validate
- * @param {string} hash - Hexadecimal hash of previous block, or public key for new accounts
- * @param {NanoPowOptions} options - Options used to configure search execution
- */
- static async validate(work, hash, options) {
- if (!/^[A-Fa-f0-9]{16}$/.test(work)) throw new TypeError(`Invalid work ${work}`);
- if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new TypeError(`Invalid hash ${hash}`);
- if (this.#busy) {
- console.log("NanoPowGpu is busy. Retrying validate...");
- return new Promise((resolve) => {
- setTimeout(async () => {
- const result = this.validate(work, hash, options);
- resolve(result);
- }, 100);
- });
- }
- this.#busy = true;
- this.#debug = !!options?.debug;
- const threshold = typeof options?.threshold !== "number" || options.threshold < 0 || options.threshold > 4294967295 ? 4294967288 : options.threshold;
- let loads = 0;
- while (this.#device == null && loads < 20) {
- await new Promise((resolve) => {
- setTimeout(resolve, 500);
- });
- }
- if (this.#device == null) {
- this.#busy = false;
- throw new Error(`WebGPU device failed to load.`);
- }
- const seed = BigInt(`0x${work}`);
- if (this.#debug) console.log(`work: ${work}`);
- const data = await this.#dispatch(this.#validatePipeline, seed, hash, threshold, 1);
- const nonce = data.getBigUint64(0, true).toString(16).padStart(16, "0");
- if (this.#debug) console.log(`nonce: ${nonce}`);
- const found = !!data.getUint32(8);
- this.#busy = false;
- if (found && work !== nonce) throw new Error(`Nonce (${nonce}) found but does not match work (${work})`);
- return found;
- }
-};
-
-// src/classes/index.ts
-var isGlSupported;
-var isGpuSupported = false;
-try {
- await NanoPowGpu.init();
- isGpuSupported = true;
-} catch (err) {
- console.warn("WebGPU is not supported in this environment.\n", err);
- isGpuSupported = false;
-}
-try {
- await NanoPowGl.init();
- isGlSupported = true;
-} catch (err) {
- console.warn("WebGL is not supported in this environment.\n", err);
- isGlSupported = false;
-}
-var NanoPow = isGpuSupported ? NanoPowGpu : isGlSupported ? NanoPowGl : null;
-
-// src/main.ts
-var main_default = NanoPow;
-export {
- NanoPow,
- NanoPowGl,
- NanoPowGpu,
- main_default as default
-};