Fix blocky WebGPU sky: view inputs refresh when the camera moves (t91)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -57,6 +57,61 @@ with launch(viewport={'width':960,'height':600}) as (_,pg,url):
|
||||
}""")
|
||||
assert all(r['max']==0 for r in parity),parity
|
||||
print('PASS dirty and forced full uploads render identically in',len(parity),'look/light/lens/fog configurations')
|
||||
# Adjacent noise cells must use the same hash for their shared lattice corners.
|
||||
noise=pg.evaluate("""async()=>{
|
||||
const code=GPU_SMOOTH.slice(GPU_SMOOTH.indexOf('fn h21'),GPU_SMOOTH.indexOf('fn lin'))+`
|
||||
@vertex fn vs(@builtin(vertex_index) i:u32)->@builtin(position) vec4f {
|
||||
let p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3));return vec4f(p[i],0,1);
|
||||
}
|
||||
@fragment fn fs(@builtin(position) p:vec4f)->@location(0) vec4f {
|
||||
let edge=floor(p.x/2.);let along=floor(p.y)*0.1;
|
||||
let epsilon=select(-0.0001,0.0001,u32(p.x)%2u==1u);
|
||||
return vec4f(vn(vec2f(edge+epsilon,along)),vn(vec2f(along,edge+epsilon)),0,1);
|
||||
}`;
|
||||
const module=GPU.device.createShaderModule({code});
|
||||
const pipeline=await GPU.device.createRenderPipelineAsync({layout:'auto',
|
||||
vertex:{module,entryPoint:'vs'},fragment:{module,entryPoint:'fs',targets:[{format:'rgba8unorm'}]}});
|
||||
const texture=GPU.device.createTexture({size:[960,100],format:'rgba8unorm',
|
||||
usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC});
|
||||
const buffer=GPU.device.createBuffer({size:960*100*4,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});
|
||||
const encoder=GPU.device.createCommandEncoder();
|
||||
const pass=encoder.beginRenderPass({colorAttachments:[{
|
||||
view:texture.createView(),loadOp:'clear',storeOp:'store'}]});
|
||||
pass.setPipeline(pipeline);pass.draw(3);pass.end();
|
||||
encoder.copyTextureToBuffer({texture},{buffer,bytesPerRow:960*4},[960,100]);
|
||||
GPU.device.queue.submit([encoder.finish()]);await buffer.mapAsync(GPUMapMode.READ);
|
||||
const pixels=new Uint8Array(buffer.getMappedRange());let max=0;
|
||||
for(let y=0;y<100;y++)for(let x=0;x<960;x+=2)for(let c=0;c<2;c++) {
|
||||
const i=(y*960+x)*4+c;max=Math.max(max,Math.abs(pixels[i]-pixels[i+4]));
|
||||
}
|
||||
buffer.unmap();buffer.destroy();texture.destroy();return max;
|
||||
}""")
|
||||
assert noise<=1,noise
|
||||
print('PASS smooth noise is continuous across horizontal and vertical lattice boundaries',noise)
|
||||
motion=pg.evaluate("""async()=>{
|
||||
const results=[],now=performance.now.bind(performance);performance.now=()=>5000;
|
||||
try {
|
||||
SET.fog=false;SET.glow='low';SET.lightEvery=1;R.lens=false;
|
||||
for(const look of ['pixel','smooth'])for(const light of ['full','fast','off']) {
|
||||
SET.look=look;SET.lighting=light;
|
||||
for(let n=0;n<12;n++) {
|
||||
SET.zoom=6-n*0.37;resizeRender();R.camX=80.25+n*7.3;R.camY=5.5+n*0.43;
|
||||
R.rain=0;R.frame++;drawWorld();await GPU.device.queue.onSubmittedWorkDone();
|
||||
}
|
||||
const a=worldPixelContext().getImageData(0,0,960,600).data;
|
||||
const cleanCells=GPU.uploadCells;
|
||||
// Discard all view textures/light history as well as the resident-world cache.
|
||||
GPU.resident.fill(0);GPU.viewKey=null;GPU.lightFrame=undefined;
|
||||
R.rain=0;drawWorld();await GPU.device.queue.onSubmittedWorkDone();
|
||||
const b=worldPixelContext().getImageData(0,0,960,600).data;
|
||||
let max=0;for(let i=0;i<a.length;i++)max=Math.max(max,Math.abs(a[i]-b[i]));
|
||||
results.push({look,light,max,cleanCells});
|
||||
}
|
||||
SET.lighting='full';return results;
|
||||
} finally {performance.now=now;}
|
||||
}""")
|
||||
assert all(r['max']==0 for r in motion),motion
|
||||
print('PASS pan/zoom matches fresh full redraw in both looks and all light modes',motion)
|
||||
cadence=pg.evaluate("""()=>{
|
||||
SET.lightEvery=3;R.frame=1002;drawWorld();const old=GPU.lightFrame,origin=R.lx0;
|
||||
R.camX+=4;R.frame=1003;drawWorld();const held=GPU.lightFrame===old && R.lx0===origin;
|
||||
|
||||
Reference in New Issue
Block a user