diff --git a/404.html b/404.html index b430cf8b..662209f3 100644 --- a/404.html +++ b/404.html @@ -1,4 +1,4 @@ -404: This page could not be found

404

This page could not be found.

\ No newline at end of file + }

404

This page could not be found.

\ No newline at end of file diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/A-buffer.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/A-buffer.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/A-buffer.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/A-buffer.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/animometer.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/animometer.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/animometer.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/animometer.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/bitonicSort.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/bitonicSort.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/bitonicSort.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/bitonicSort.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/cameras.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/cameras.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/cameras.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/cameras.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/computeBoids.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/computeBoids.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/computeBoids.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/computeBoids.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/cornell.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/cornell.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/cornell.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/cornell.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/cubemap.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/cubemap.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/cubemap.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/cubemap.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/deferredRendering.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/deferredRendering.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/deferredRendering.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/deferredRendering.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/fractalCube.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/fractalCube.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/fractalCube.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/fractalCube.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/gameOfLife.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/gameOfLife.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/gameOfLife.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/gameOfLife.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/helloTriangle.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/helloTriangle.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/helloTriangle.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/helloTriangle.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/helloTriangleMSAA.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/helloTriangleMSAA.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/helloTriangleMSAA.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/helloTriangleMSAA.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/imageBlur.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/imageBlur.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/imageBlur.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/imageBlur.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/instancedCube.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/instancedCube.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/instancedCube.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/instancedCube.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/normalMap.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/normalMap.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/normalMap.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/normalMap.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/particles.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/particles.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/particles.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/particles.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/renderBundles.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/renderBundles.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/renderBundles.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/renderBundles.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/resizeCanvas.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/resizeCanvas.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/resizeCanvas.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/resizeCanvas.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/reversedZ.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/reversedZ.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/reversedZ.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/reversedZ.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/rotatingCube.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/rotatingCube.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/rotatingCube.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/rotatingCube.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/samplerParameters.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/samplerParameters.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/samplerParameters.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/samplerParameters.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/shadowMapping.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/shadowMapping.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/shadowMapping.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/shadowMapping.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/texturedCube.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/texturedCube.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/texturedCube.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/texturedCube.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/twoCubes.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/twoCubes.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/twoCubes.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/twoCubes.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/videoUploading.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/videoUploading.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/videoUploading.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/videoUploading.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/videoUploadingWebCodecs.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/videoUploadingWebCodecs.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/videoUploadingWebCodecs.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/videoUploadingWebCodecs.json diff --git a/_next/data/zFybhN_sEJJ4DmMVojx9G/samples/worker.json b/_next/data/JLmkatBKfvhCEo0dhqfFV/samples/worker.json similarity index 100% rename from _next/data/zFybhN_sEJJ4DmMVojx9G/samples/worker.json rename to _next/data/JLmkatBKfvhCEo0dhqfFV/samples/worker.json diff --git a/_next/static/zFybhN_sEJJ4DmMVojx9G/_buildManifest.js b/_next/static/JLmkatBKfvhCEo0dhqfFV/_buildManifest.js similarity index 100% rename from _next/static/zFybhN_sEJJ4DmMVojx9G/_buildManifest.js rename to _next/static/JLmkatBKfvhCEo0dhqfFV/_buildManifest.js diff --git a/_next/static/zFybhN_sEJJ4DmMVojx9G/_ssgManifest.js b/_next/static/JLmkatBKfvhCEo0dhqfFV/_ssgManifest.js similarity index 100% rename from _next/static/zFybhN_sEJJ4DmMVojx9G/_ssgManifest.js rename to _next/static/JLmkatBKfvhCEo0dhqfFV/_ssgManifest.js diff --git a/_next/static/chunks/112.be7dd3c74cc1b516.js b/_next/static/chunks/112.be7dd3c74cc1b516.js deleted file mode 100644 index 283da887..00000000 --- a/_next/static/chunks/112.be7dd3c74cc1b516.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[112],{5671:function(e,n,t){"use strict";t.d(n,{Tl:function(){return c},hu:function(){return p}});var r=t(5893),i=t(9008),o=t.n(i),a=t(1163),s=t(7294),l=t(9147),u=t.n(l);t(7319);let d=e=>{let n=(0,s.useRef)(null),i=(0,s.useMemo)(()=>e.sources.map(e=>{let{name:n,contents:i}=e;return{name:n,...function(e){let n;let i=null;{i=document.createElement("div");let o=t(4631);n=o(i,{lineNumbers:!0,lineWrapping:!0,theme:"monokai",readOnly:!0})}return{Container:function(t){return(0,r.jsx)("div",{...t,children:(0,r.jsx)("div",{ref(t){i&&t&&(t.appendChild(i),n.setOption("value",e))}})})}}}(i)}}),e.sources),l=(0,s.useRef)(null),d=(0,s.useMemo)(()=>{if(e.gui){let n=t(4376);return new n.GUI({autoPlace:!1})}},[]),c=(0,s.useRef)(null),p=(0,s.useMemo)(()=>{if(e.stats){let n=t(2792);return new n}},[]),m=(0,a.useRouter)(),h=m.asPath.match(/#([a-zA-Z0-9\.\/]+)/),[f,g]=(0,s.useState)(null),[E,v]=(0,s.useState)(null);return(0,s.useEffect)(()=>{if(h?v(h[1]):v(i[0].name),d&&l.current)for(l.current.appendChild(d.domElement);d.__controllers.length>0;)d.__controllers[0].remove();p&&c.current&&(p.dom.style.position="absolute",p.showPanel(1),c.current.appendChild(p.dom));let t={active:!0},r=()=>{t.active=!1};try{let o=n.current;if(!o)throw Error("The canvas is not available");let a=e.init({canvas:o,pageState:t,gui:d,stats:p});a instanceof Promise&&a.catch(e=>{console.error(e),g(e)})}catch(s){console.error(s),g(s)}return r},[]),(0,r.jsxs)("main",{children:[(0,r.jsxs)(o(),{children:[(0,r.jsx)("style",{dangerouslySetInnerHTML:{__html:"\n .CodeMirror {\n height: auto !important;\n margin: 1em 0;\n }\n\n .CodeMirror-scroll {\n height: auto !important;\n overflow: visible !important;\n }\n "}}),(0,r.jsx)("title",{children:"".concat(e.name," - WebGPU Samples")}),(0,r.jsx)("meta",{name:"description",content:e.description}),(0,r.jsx)("meta",{httpEquiv:"origin-trial",content:e.originTrial})]}),(0,r.jsxs)("div",{children:[(0,r.jsx)("h1",{children:e.name}),(0,r.jsx)("a",{target:"_blank",rel:"noreferrer",href:"https://github.com/".concat("webgpu/webgpu-samples","/tree/main/").concat(e.filename),children:"See it on Github!"}),(0,r.jsx)("p",{children:e.description}),f?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("p",{children:"Something went wrong. Do your browser and device support WebGPU?"}),(0,r.jsx)("p",{children:"".concat(f)})]}):null]}),(0,r.jsxs)("div",{className:u().canvasContainer,children:[(0,r.jsx)("div",{style:{position:"absolute",left:10},ref:c}),(0,r.jsx)("div",{style:{position:"absolute",right:10},ref:l}),(0,r.jsx)("canvas",{ref:n})]}),(0,r.jsxs)("div",{children:[(0,r.jsx)("nav",{className:u().sourceFileNav,children:(0,r.jsx)("ul",{children:i.map((e,n)=>(0,r.jsx)("li",{children:(0,r.jsx)("a",{href:"#".concat(e.name),"data-active":E==e.name,onClick(){v(e.name)},children:e.name})},n))})}),i.map((e,n)=>(0,r.jsx)(e.Container,{className:u().sourceFileContainer,"data-active":E==e.name},n))]})]})},c=e=>(0,r.jsx)(d,{...e});function p(e,n){if(!e)throw Error(n)}},8112:function(e,n,t){"use strict";let r;t.r(n),t.d(n,{default:function(){return g}});var i,o,a=t(5671),s=t(134);let l=(e,n,t,r,i,o,a)=>{let s=[];for(let l=0;l{let n=async n=>{let{canvas:t,pageState:r,gui:i,stats:o}=n,a=await navigator.gpu.requestAdapter(),s=await a.requestDevice();if(!r.active)return;let l=t.getContext("webgpu"),u=window.devicePixelRatio;t.width=t.clientWidth*u,t.height=t.clientHeight*u;let d=navigator.gpu.getPreferredCanvasFormat();l.configure({device:s,format:d,alphaMode:"premultiplied"}),e({canvas:t,pageState:r,gui:i,device:s,context:l,presentationFormat:d,stats:o})};return n};class d{executeRun(e,n,t,r){let i=e.beginRenderPass(n);i.setPipeline(t);for(let o=0;o{this.bindGroupMap[r[n]]=e}),this.pipeline=super.create2DRenderPipeline(e,o,[s.bindGroupLayout,this.computeBGDescript.bindGroupLayout],c,n),this.switchBindGroup=e=>{this.currentBindGroup=this.bindGroupMap[e],this.currentBindGroupName=e},this.setArguments=n=>{super.setUniformArguments(e,a,n,["width","height"])}}}p.sourceInfo={name:"src/sample/bitonicSort/bitonicDisplay.ts".substring(23),contents:"import {\n BindGroupsObjectsAndLayout,\n createBindGroupDescriptor,\n Base2DRendererClass,\n} from './utils';\n\nimport bitonicDisplay from './bitonicDisplay.frag.wgsl';\n\ninterface BitonicDisplayRenderArgs {\n width: number;\n height: number;\n}\n\nexport default class BitonicDisplayRenderer extends Base2DRendererClass {\n static sourceInfo = {\n name: __filename.substring(__dirname.length + 1),\n contents: __SOURCE__,\n };\n\n switchBindGroup: (name: string) => void;\n setArguments: (args: BitonicDisplayRenderArgs) => void;\n computeBGDescript: BindGroupsObjectsAndLayout;\n\n constructor(\n device: GPUDevice,\n presentationFormat: GPUTextureFormat,\n renderPassDescriptor: GPURenderPassDescriptor,\n bindGroupNames: string[],\n computeBGDescript: BindGroupsObjectsAndLayout,\n label: string\n ) {\n super();\n this.renderPassDescriptor = renderPassDescriptor;\n this.computeBGDescript = computeBGDescript;\n\n const uniformBuffer = device.createBuffer({\n size: Float32Array.BYTES_PER_ELEMENT * 2,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n\n const bgDescript = createBindGroupDescriptor(\n [0],\n [GPUShaderStage.FRAGMENT],\n ['buffer'],\n [{ type: 'uniform' }],\n [[{ buffer: uniformBuffer }]],\n label,\n device\n );\n\n this.currentBindGroup = bgDescript.bindGroups[0];\n this.currentBindGroupName = bindGroupNames[0];\n\n this.bindGroupMap = {};\n\n bgDescript.bindGroups.forEach((bg, idx) => {\n this.bindGroupMap[bindGroupNames[idx]] = bg;\n });\n\n this.pipeline = super.create2DRenderPipeline(\n device,\n label,\n [bgDescript.bindGroupLayout, this.computeBGDescript.bindGroupLayout],\n bitonicDisplay,\n presentationFormat\n );\n\n this.switchBindGroup = (name: string) => {\n this.currentBindGroup = this.bindGroupMap[name];\n this.currentBindGroupName = name;\n };\n\n this.setArguments = (args: BitonicDisplayRenderArgs) => {\n super.setUniformArguments(device, uniformBuffer, args, [\n 'width',\n 'height',\n ]);\n };\n }\n\n startRun(commandEncoder: GPUCommandEncoder, args: BitonicDisplayRenderArgs) {\n this.setArguments(args);\n super.executeRun(commandEncoder, this.renderPassDescriptor, this.pipeline, [\n this.currentBindGroup,\n this.computeBGDescript.bindGroups[0],\n ]);\n }\n}\n"};let m=e=>((e%2!=0||e>256)&&(e=256),"\n\nstruct Uniforms {\n width: f32,\n height: f32,\n algo: u32,\n blockHeight: u32,\n}\n\n// Create local workgroup data that can contain all elements\n\nvar local_data: array;\n\n//Compare and swap values in local_data\nfn compare_and_swap(idx_before: u32, idx_after: u32) {\n //idx_before should always be < idx_after\n if (local_data[idx_after] < local_data[idx_before]) {\n var temp: u32 = local_data[idx_before];\n local_data[idx_before] = local_data[idx_after];\n local_data[idx_after] = temp;\n }\n return;\n}\n\n// thread_id goes from 0 to threadsPerWorkgroup\nfn prepare_flip(thread_id: u32, block_height: u32) {\n let q: u32 = ((2 * thread_id) / block_height) * block_height;\n let half_height = block_height / 2;\n var idx: vec2 = vec2(\n thread_id % half_height, block_height - (thread_id % half_height) - 1,\n );\n idx.x += q;\n idx.y += q;\n compare_and_swap(idx.x, idx.y);\n}\n\nfn prepare_disperse(thread_id: u32, block_height: u32) {\n var q: u32 = ((2 * thread_id) / block_height) * block_height;\n let half_height = block_height / 2;\n var idx: vec2 = vec2(\n thread_id % half_height, (thread_id % half_height) + half_height\n );\n idx.x += q;\n idx.y += q;\n compare_and_swap(idx.x, idx.y);\n}\n\n@group(0) @binding(0) var input_data: array;\n@group(0) @binding(1) var output_data: array;\n@group(0) @binding(2) var uniforms: Uniforms;\n\n// Our compute shader will execute specified # of threads or elements / 2 threads\n@compute @workgroup_size(").concat(e,", 1, 1)\nfn computeMain(\n @builtin(global_invocation_id) global_id: vec3,\n @builtin(local_invocation_id) local_id: vec3,\n) {\n //Each thread will populate the workgroup data... (1 thread for every 2 elements)\n local_data[local_id.x * 2] = input_data[local_id.x * 2];\n local_data[local_id.x * 2 + 1] = input_data[local_id.x * 2 + 1];\n\n //...and wait for each other to finish their own bit of data population.\n workgroupBarrier();\n\n var num_elements = uniforms.width * uniforms.height;\n\n switch uniforms.algo {\n case 1: { //Local Flip\n prepare_flip(local_id.x, uniforms.blockHeight);\n }\n case 2: { //Local Disperse\n prepare_disperse(local_id.x, uniforms.blockHeight);\n }\n default: { \n \n }\n }\n\n //Ensure that all threads have swapped their own regions of data\n workgroupBarrier();\n\n //Repopulate global data with local data\n output_data[local_id.x * 2] = local_data[local_id.x * 2];\n output_data[local_id.x * 2 + 1] = local_data[local_id.x * 2 + 1];\n\n}"));var h="src/sample/bitonicSort/main.ts";(i=o||(o={}))[i.NONE=0]="NONE",i[i.FLIP_LOCAL=1]="FLIP_LOCAL",i[i.DISPERSE_LOCAL=2]="DISPERSE_LOCAL",i[i.FLIP_DISPERSE_LOCAL=3]="FLIP_DISPERSE_LOCAL",u(async e=>{let{pageState:n,device:t,gui:r,presentationFormat:i,context:a,canvas:s}=e,u=t.limits.maxComputeWorkgroupSizeX,d=[];for(let c=2*u;c>=4;c/=2)d.push(c);let h={"Total Elements":16,"Grid Width":4,"Grid Height":4,"Total Threads":8,hoveredElement:0,swappedElement:1,"Prev Step":"NONE","Next Step":"FLIP_LOCAL","Prev Swap Span":0,"Next Swap Span":2,workLoads:1,executeStep:!1,"Randomize Values"(){},"Execute Sort Step"(){},"Log Elements"(){},"Complete Sort"(){},sortSpeed:200},f=new Uint32Array(Array.from({length:h["Total Elements"]},(e,n)=>n)),g=512*Float32Array.BYTES_PER_ELEMENT,E=t.createBuffer({size:g,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),v=t.createBuffer({size:g,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),S=t.createBuffer({size:g,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),x=t.createBuffer({size:4*Float32Array.BYTES_PER_ELEMENT,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),b=l([0,1,2],[GPUShaderStage.COMPUTE|GPUShaderStage.FRAGMENT,GPUShaderStage.COMPUTE,GPUShaderStage.COMPUTE],["buffer","buffer","buffer"],[{type:"read-only-storage"},{type:"storage"},{type:"uniform"}],[[{buffer:E},{buffer:v},{buffer:x}]],"NaiveBitonicSort",t),y=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[b.bindGroupLayout]}),compute:{module:t.createShaderModule({code:m(h["Total Threads"])}),entryPoint:"computeMain"}}),_={colorAttachments:[{view:void 0,clearValue:{r:.1,g:.4,b:.5,a:1},loadOp:"clear",storeOp:"store"}]},w=new p(t,i,_,["default"],b,"BitonicDisplay"),P=()=>{U.setValue(h["Total Elements"]/2);let e=Math.sqrt(h["Total Elements"])%2==0?Math.floor(Math.sqrt(h["Total Elements"])):Math.floor(Math.sqrt(h["Total Elements"]/2)),n=h["Total Elements"]/e;V.setValue(e),z.setValue(n),F.setValue("NONE"),k.setValue("FLIP_LOCAL"),M.setValue(0),H.setValue(2),q=2},B=()=>{let e=f.length;for(;0!==e;){let n=Math.floor(Math.random()*e);e-=1,[f[e],f[n]]=[f[n],f[e]]}},G=()=>{f=new Uint32Array(Array.from({length:h["Total Elements"]},(e,n)=>n)),P(),y=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[b.bindGroupLayout]}),compute:{module:t.createShaderModule({code:m(h["Total Elements"]/2)}),entryPoint:"computeMain"}}),B(),q=2};B();let C=()=>{let e;switch(h["Next Step"]){case"FLIP_LOCAL":{let n=h["Next Swap Span"],t=Math.floor(h.hoveredElement/n)+1,r=h.hoveredElement%n;e=n*t-r-1,R.setValue(e)}break;case"DISPERSE_LOCAL":{let i=h["Next Swap Span"],o=i/2;e=h.hoveredElement%i{null!==I&&(clearInterval(I),I=null)},T=()=>{I=setInterval(()=>{"NONE"===h["Next Step"]&&(clearInterval(I),I=null),h.executeStep=!0,C()},h.sortSpeed)};r.add(h,"Total Elements",d).onChange(()=>{L(),G()});let U=r.add(h,"Total Threads"),D=r.addFolder("Sort Controls");D.add(h,"Execute Sort Step").onChange(()=>{L(),h.executeStep=!0}),D.add(h,"Randomize Values").onChange(()=>{L(),B(),P()}),D.add(h,"Log Elements").onChange(()=>console.log(f)),D.add(h,"Complete Sort").onChange(T),D.open();let A=r.addFolder("Hover Information"),N=A.add(h,"hoveredElement").onChange(C),R=A.add(h,"swappedElement"),O=r.addFolder("Execution Information"),F=O.add(h,"Prev Step"),k=O.add(h,"Next Step"),M=O.add(h,"Prev Swap Span"),H=O.add(h,"Next Swap Span"),V=O.add(h,"Grid Width"),z=O.add(h,"Grid Height"),W=document.getElementsByClassName("cr function");for(let j=0;j{let n=s.getBoundingClientRect().width,t=s.getBoundingClientRect().height,r=[n/h["Grid Width"],t/h["Grid Height"]],i=Math.floor(e.offsetX/r[0]),o=h["Grid Height"]-1-Math.floor(e.offsetY/r[1]);N.setValue(o*h["Grid Width"]+i),h.hoveredElement=o*h["Grid Width"]+i}),F.domElement.style.pointerEvents="none",M.domElement.style.pointerEvents="none",k.domElement.style.pointerEvents="none",H.domElement.style.pointerEvents="none",U.domElement.style.pointerEvents="none",V.domElement.style.pointerEvents="none",z.domElement.style.pointerEvents="none";let q=2;async function Y(){if(!n.active)return;t.queue.writeBuffer(E,0,f.buffer,f.byteOffset,f.byteLength);let e=new Float32Array([h["Grid Width"],h["Grid Height"]]),r=new Uint32Array([o[h["Next Step"]],h["Next Swap Span"]]);t.queue.writeBuffer(x,0,e.buffer,e.byteOffset,e.byteLength),t.queue.writeBuffer(x,8,r),_.colorAttachments[0].view=a.getCurrentTexture().createView();let i=t.createCommandEncoder();if(w.startRun(i,{width:h["Grid Width"],height:h["Grid Height"]}),h.executeStep&&q!==2*h["Total Elements"]){let s=i.beginComputePass();s.setPipeline(y),s.setBindGroup(0,b.bindGroups[0]),s.dispatchWorkgroups(1),s.end(),F.setValue(h["Next Step"]),M.setValue(h["Next Swap Span"]),H.setValue(h["Next Swap Span"]/2),1===h["Next Swap Span"]?(q*=2,k.setValue(q===2*h["Total Elements"]?"NONE":"FLIP_LOCAL"),H.setValue(q===2*h["Total Elements"]?0:q)):k.setValue("DISPERSE_LOCAL"),i.copyBufferToBuffer(v,0,S,0,g)}if(t.queue.submit([i.finish()]),h.executeStep){await S.mapAsync(GPUMapMode.READ,0,g);let l=S.getMappedRange(0,g),u=l.slice(0,Uint32Array.BYTES_PER_ELEMENT*h["Total Elements"]),d=new Uint32Array(u);S.unmap(),f=d,C()}h.executeStep=!1,requestAnimationFrame(Y)}requestAnimationFrame(Y)}).then(e=>r=e);let f=()=>(0,a.Tl)({name:"Bitonic Sort",description:"A naive bitonic sort algorithm executed on the GPU, based on tgfrerer's implementation at poniesandlight.co.uk/reflect/bitonic_merge_sort/. Each invocation of the bitonic sort shader dispatches a workgroup containing elements/2 threads. The GUI's Execution Information folder contains information about the sort's current state. The visualizer displays the sort's results as colored cells sorted from brightest to darkest.",init:r,gui:!0,sources:[{name:h.substring(23),contents:"import { makeSample, SampleInit } from '../../components/SampleLayout';\nimport { SampleInitFactoryWebGPU } from './utils';\nimport { createBindGroupDescriptor } from './utils';\nimport BitonicDisplayRenderer from './bitonicDisplay';\nimport bitonicDisplay from './bitonicDisplay.frag.wgsl';\nimport { NaiveBitonicCompute } from './computeShader';\nimport fullscreenTexturedQuad from '../../shaders/fullscreenTexturedQuad.wgsl';\n\n// Type of step that will be executed in our shader\nenum StepEnum {\n NONE = 0,\n FLIP_LOCAL = 1,\n DISPERSE_LOCAL = 2,\n FLIP_DISPERSE_LOCAL = 3,\n}\n\n// String access to StepEnum\ntype StepType =\n | 'NONE'\n | 'FLIP_LOCAL'\n | 'DISPERSE_LOCAL'\n | 'FLIP_DISPERSE_LOCAL';\n\n// Gui settings object\ninterface SettingsInterface {\n 'Total Elements': number;\n 'Grid Width': number;\n 'Grid Height': number;\n 'Total Threads': number;\n hoveredElement: number;\n swappedElement: number;\n 'Prev Step': StepType;\n 'Next Step': StepType;\n 'Prev Swap Span': number;\n 'Next Swap Span': number;\n workLoads: number;\n executeStep: boolean;\n 'Randomize Values': () => void;\n 'Execute Sort Step': () => void;\n 'Log Elements': () => void;\n 'Complete Sort': () => void;\n sortSpeed: number;\n}\n\nlet init: SampleInit;\nSampleInitFactoryWebGPU(\n async ({ pageState, device, gui, presentationFormat, context, canvas }) => {\n const maxWorkgroupsX = device.limits.maxComputeWorkgroupSizeX;\n\n const totalElementLengths = [];\n for (let i = maxWorkgroupsX * 2; i >= 4; i /= 2) {\n totalElementLengths.push(i);\n }\n\n const settings: SettingsInterface = {\n // number of cellElements. Must equal gridWidth * gridHeight and 'Total Threads' * 2\n 'Total Elements': 16,\n // width of screen in cells.\n 'Grid Width': 4,\n // height of screen in cells\n 'Grid Height': 4,\n // number of threads to execute in a workgroup ('Total Threads', 1, 1)\n 'Total Threads': 16 / 2,\n // currently highlighted element\n hoveredElement: 0,\n // element the hoveredElement just swapped with,\n swappedElement: 1,\n // Previously executed step\n 'Prev Step': 'NONE',\n // Next step to execute\n 'Next Step': 'FLIP_LOCAL',\n // Max thread span of previous block\n 'Prev Swap Span': 0,\n // Max thread span of next block\n 'Next Swap Span': 2,\n // workloads to dispatch per frame,\n workLoads: 1,\n // Whether we will dispatch a workload this frame\n executeStep: false,\n 'Randomize Values': () => {\n return;\n },\n 'Execute Sort Step': () => {\n return;\n },\n 'Log Elements': () => {\n return;\n },\n 'Complete Sort': () => {\n return;\n },\n sortSpeed: 200,\n };\n\n // Initialize initial elements array\n let elements = new Uint32Array(\n Array.from({ length: settings['Total Elements'] }, (_, i) => i)\n );\n\n // Initialize elementsBuffer and elementsStagingBuffer\n const elementsBufferSize = Float32Array.BYTES_PER_ELEMENT * 512;\n // Initialize input, output, staging buffers\n const elementsInputBuffer = device.createBuffer({\n size: elementsBufferSize,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n });\n const elementsOutputBuffer = device.createBuffer({\n size: elementsBufferSize,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n const elementsStagingBuffer = device.createBuffer({\n size: elementsBufferSize,\n usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,\n });\n\n // Create uniform buffer for compute shader\n const computeUniformsBuffer = device.createBuffer({\n // width, height, blockHeight, algo\n size: Float32Array.BYTES_PER_ELEMENT * 4,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n\n const computeBGDescript = createBindGroupDescriptor(\n [0, 1, 2],\n [\n GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,\n GPUShaderStage.COMPUTE,\n GPUShaderStage.COMPUTE,\n ],\n ['buffer', 'buffer', 'buffer'],\n [{ type: 'read-only-storage' }, { type: 'storage' }, { type: 'uniform' }],\n [\n [\n { buffer: elementsInputBuffer },\n { buffer: elementsOutputBuffer },\n { buffer: computeUniformsBuffer },\n ],\n ],\n 'NaiveBitonicSort',\n device\n );\n\n let computePipeline = device.createComputePipeline({\n layout: device.createPipelineLayout({\n bindGroupLayouts: [computeBGDescript.bindGroupLayout],\n }),\n compute: {\n module: device.createShaderModule({\n code: NaiveBitonicCompute(settings['Total Threads']),\n }),\n entryPoint: 'computeMain',\n },\n });\n\n // Create bitonic debug renderer\n const renderPassDescriptor: GPURenderPassDescriptor = {\n colorAttachments: [\n {\n view: undefined, // Assigned later\n\n clearValue: { r: 0.1, g: 0.4, b: 0.5, a: 1.0 },\n loadOp: 'clear',\n storeOp: 'store',\n },\n ],\n };\n\n const bitonicDisplayRenderer = new BitonicDisplayRenderer(\n device,\n presentationFormat,\n renderPassDescriptor,\n ['default'],\n computeBGDescript,\n 'BitonicDisplay'\n );\n\n const resetExecutionInformation = () => {\n totalThreadsCell.setValue(settings['Total Elements'] / 2);\n\n // Get new width and height of screen display in cells\n const newCellWidth =\n Math.sqrt(settings['Total Elements']) % 2 === 0\n ? Math.floor(Math.sqrt(settings['Total Elements']))\n : Math.floor(Math.sqrt(settings['Total Elements'] / 2));\n const newCellHeight = settings['Total Elements'] / newCellWidth;\n gridWidthCell.setValue(newCellWidth);\n gridHeightCell.setValue(newCellHeight);\n\n // Set prevStep to None (restart) and next step to FLIP\n prevStepCell.setValue('NONE');\n nextStepCell.setValue('FLIP_LOCAL');\n\n // Reset block heights\n prevBlockHeightCell.setValue(0);\n nextBlockHeightCell.setValue(2);\n highestBlockHeight = 2;\n };\n\n const randomizeElementArray = () => {\n let currentIndex = elements.length;\n // While there are elements to shuffle\n while (currentIndex !== 0) {\n // Pick a remaining element\n const randomIndex = Math.floor(Math.random() * currentIndex);\n currentIndex -= 1;\n [elements[currentIndex], elements[randomIndex]] = [\n elements[randomIndex],\n elements[currentIndex],\n ];\n }\n };\n\n const resizeElementArray = () => {\n // Recreate elements array with new length\n elements = new Uint32Array(\n Array.from({ length: settings['Total Elements'] }, (_, i) => i)\n );\n\n resetExecutionInformation();\n\n // Create new shader invocation with workgroupSize that reflects number of threads\n computePipeline = device.createComputePipeline({\n layout: device.createPipelineLayout({\n bindGroupLayouts: [computeBGDescript.bindGroupLayout],\n }),\n compute: {\n module: device.createShaderModule({\n code: NaiveBitonicCompute(settings['Total Elements'] / 2),\n }),\n entryPoint: 'computeMain',\n },\n });\n // Randomize array elements\n randomizeElementArray();\n highestBlockHeight = 2;\n };\n\n randomizeElementArray();\n\n const setSwappedElement = () => {\n let swappedIndex: number;\n switch (settings['Next Step']) {\n case 'FLIP_LOCAL':\n {\n const blockHeight = settings['Next Swap Span'];\n const p2 = Math.floor(settings.hoveredElement / blockHeight) + 1;\n const p3 = settings.hoveredElement % blockHeight;\n swappedIndex = blockHeight * p2 - p3 - 1;\n swappedElementCell.setValue(swappedIndex);\n }\n break;\n case 'DISPERSE_LOCAL':\n {\n const blockHeight = settings['Next Swap Span'];\n const halfHeight = blockHeight / 2;\n swappedIndex =\n settings.hoveredElement % blockHeight < halfHeight\n ? settings.hoveredElement + halfHeight\n : settings.hoveredElement - halfHeight;\n swappedElementCell.setValue(swappedIndex);\n }\n break;\n case 'NONE': {\n swappedIndex = settings.hoveredElement;\n swappedElementCell.setValue(swappedIndex);\n }\n default:\n {\n swappedIndex = settings.hoveredElement;\n swappedElementCell.setValue(swappedIndex);\n }\n break;\n }\n };\n\n let completeSortIntervalID: ReturnType | null = null;\n const endSortInterval = () => {\n if (completeSortIntervalID !== null) {\n clearInterval(completeSortIntervalID);\n completeSortIntervalID = null;\n }\n };\n const startSortInterval = () => {\n completeSortIntervalID = setInterval(() => {\n if (settings['Next Step'] === 'NONE') {\n clearInterval(completeSortIntervalID);\n completeSortIntervalID = null;\n }\n settings.executeStep = true;\n setSwappedElement();\n }, settings.sortSpeed);\n };\n\n // At top level, basic information about the number of elements sorted and the number of threads\n // deployed per workgroup.\n gui.add(settings, 'Total Elements', totalElementLengths).onChange(() => {\n endSortInterval();\n resizeElementArray();\n });\n const totalThreadsCell = gui.add(settings, 'Total Threads');\n\n // Folder with functions that control the execution of the sort\n const controlFolder = gui.addFolder('Sort Controls');\n controlFolder.add(settings, 'Execute Sort Step').onChange(() => {\n endSortInterval();\n settings.executeStep = true;\n });\n controlFolder.add(settings, 'Randomize Values').onChange(() => {\n endSortInterval();\n randomizeElementArray();\n resetExecutionInformation();\n });\n controlFolder\n .add(settings, 'Log Elements')\n .onChange(() => console.log(elements));\n controlFolder.add(settings, 'Complete Sort').onChange(startSortInterval);\n controlFolder.open();\n\n // Folder with indexes of the hovered element\n const hoverFolder = gui.addFolder('Hover Information');\n const hoveredElementCell = hoverFolder\n .add(settings, 'hoveredElement')\n .onChange(setSwappedElement);\n const swappedElementCell = hoverFolder.add(settings, 'swappedElement');\n\n // Additional Information about the execution state of the sort\n const executionInformationFolder = gui.addFolder('Execution Information');\n const prevStepCell = executionInformationFolder.add(settings, 'Prev Step');\n const nextStepCell = executionInformationFolder.add(settings, 'Next Step');\n const prevBlockHeightCell = executionInformationFolder.add(\n settings,\n 'Prev Swap Span'\n );\n const nextBlockHeightCell = executionInformationFolder.add(\n settings,\n 'Next Swap Span'\n );\n const gridWidthCell = executionInformationFolder.add(\n settings,\n 'Grid Width'\n );\n const gridHeightCell = executionInformationFolder.add(\n settings,\n 'Grid Height'\n );\n\n // Adjust styles of Function List Elements within GUI\n const liFunctionElements = document.getElementsByClassName('cr function');\n for (let i = 0; i < liFunctionElements.length; i++) {\n (liFunctionElements[i].children[0] as HTMLElement).style.display = 'flex';\n (liFunctionElements[i].children[0] as HTMLElement).style.justifyContent =\n 'center';\n (\n liFunctionElements[i].children[0].children[1] as HTMLElement\n ).style.position = 'absolute';\n }\n\n canvas.addEventListener('mousemove', (event) => {\n const currWidth = canvas.getBoundingClientRect().width;\n const currHeight = canvas.getBoundingClientRect().height;\n const cellSize: [number, number] = [\n currWidth / settings['Grid Width'],\n currHeight / settings['Grid Height'],\n ];\n const xIndex = Math.floor(event.offsetX / cellSize[0]);\n const yIndex =\n settings['Grid Height'] - 1 - Math.floor(event.offsetY / cellSize[1]);\n hoveredElementCell.setValue(yIndex * settings['Grid Width'] + xIndex);\n settings.hoveredElement = yIndex * settings['Grid Width'] + xIndex;\n });\n\n // Deactivate interaction with select GUI elements\n prevStepCell.domElement.style.pointerEvents = 'none';\n prevBlockHeightCell.domElement.style.pointerEvents = 'none';\n nextStepCell.domElement.style.pointerEvents = 'none';\n nextBlockHeightCell.domElement.style.pointerEvents = 'none';\n totalThreadsCell.domElement.style.pointerEvents = 'none';\n gridWidthCell.domElement.style.pointerEvents = 'none';\n gridHeightCell.domElement.style.pointerEvents = 'none';\n\n let highestBlockHeight = 2;\n\n async function frame() {\n if (!pageState.active) return;\n\n // Write elements buffer\n device.queue.writeBuffer(\n elementsInputBuffer,\n 0,\n elements.buffer,\n elements.byteOffset,\n elements.byteLength\n );\n\n const dims = new Float32Array([\n settings['Grid Width'],\n settings['Grid Height'],\n ]);\n const stepDetails = new Uint32Array([\n StepEnum[settings['Next Step']],\n settings['Next Swap Span'],\n ]);\n device.queue.writeBuffer(\n computeUniformsBuffer,\n 0,\n dims.buffer,\n dims.byteOffset,\n dims.byteLength\n );\n\n device.queue.writeBuffer(computeUniformsBuffer, 8, stepDetails);\n\n renderPassDescriptor.colorAttachments[0].view = context\n .getCurrentTexture()\n .createView();\n\n const commandEncoder = device.createCommandEncoder();\n bitonicDisplayRenderer.startRun(commandEncoder, {\n width: settings['Grid Width'],\n height: settings['Grid Height'],\n });\n if (\n settings.executeStep &&\n highestBlockHeight !== settings['Total Elements'] * 2\n ) {\n const computePassEncoder = commandEncoder.beginComputePass();\n computePassEncoder.setPipeline(computePipeline);\n computePassEncoder.setBindGroup(0, computeBGDescript.bindGroups[0]);\n computePassEncoder.dispatchWorkgroups(1);\n computePassEncoder.end();\n\n prevStepCell.setValue(settings['Next Step']);\n prevBlockHeightCell.setValue(settings['Next Swap Span']);\n nextBlockHeightCell.setValue(settings['Next Swap Span'] / 2);\n if (settings['Next Swap Span'] === 1) {\n highestBlockHeight *= 2;\n nextStepCell.setValue(\n highestBlockHeight === settings['Total Elements'] * 2\n ? 'NONE'\n : 'FLIP_LOCAL'\n );\n nextBlockHeightCell.setValue(\n highestBlockHeight === settings['Total Elements'] * 2\n ? 0\n : highestBlockHeight\n );\n } else {\n nextStepCell.setValue('DISPERSE_LOCAL');\n }\n commandEncoder.copyBufferToBuffer(\n elementsOutputBuffer,\n 0,\n elementsStagingBuffer,\n 0,\n elementsBufferSize\n );\n }\n device.queue.submit([commandEncoder.finish()]);\n\n if (settings.executeStep) {\n // Copy GPU element data to CPU\n await elementsStagingBuffer.mapAsync(\n GPUMapMode.READ,\n 0,\n elementsBufferSize\n );\n const copyElementsBuffer = elementsStagingBuffer.getMappedRange(\n 0,\n elementsBufferSize\n );\n // Get correct range of data from CPU copy of GPU Data\n const elementsData = copyElementsBuffer.slice(\n 0,\n Uint32Array.BYTES_PER_ELEMENT * settings['Total Elements']\n );\n // Extract data\n const elementsOutput = new Uint32Array(elementsData);\n elementsStagingBuffer.unmap();\n elements = elementsOutput;\n setSwappedElement();\n }\n settings.executeStep = false;\n requestAnimationFrame(frame);\n }\n requestAnimationFrame(frame);\n }\n).then((resultInit) => (init = resultInit));\n\nconst bitonicSortExample: () => JSX.Element = () =>\n makeSample({\n name: 'Bitonic Sort',\n description:\n \"A naive bitonic sort algorithm executed on the GPU, based on tgfrerer's implementation at poniesandlight.co.uk/reflect/bitonic_merge_sort/. Each invocation of the bitonic sort shader dispatches a workgroup containing elements/2 threads. The GUI's Execution Information folder contains information about the sort's current state. The visualizer displays the sort's results as colored cells sorted from brightest to darkest.\",\n init,\n gui: true,\n sources: [\n {\n name: __filename.substring(__dirname.length + 1),\n contents: __SOURCE__,\n },\n BitonicDisplayRenderer.sourceInfo,\n {\n name: '../../../shaders/fullscreenTexturedQuad.vert.wgsl',\n contents: fullscreenTexturedQuad,\n },\n {\n name: './bitonicDisplay.frag.wgsl',\n contents: bitonicDisplay,\n },\n {\n name: './bitonicCompute.frag.wgsl',\n contents: NaiveBitonicCompute(16),\n },\n ],\n filename: __filename,\n });\n\nexport default bitonicSortExample;\n"},p.sourceInfo,{name:"../../../shaders/fullscreenTexturedQuad.vert.wgsl",contents:s.Z},{name:"./bitonicDisplay.frag.wgsl",contents:c},{name:"./bitonicCompute.frag.wgsl",contents:m(16)}],filename:h});var g=f},9147:function(e){e.exports={canvasContainer:"SampleLayout_canvasContainer__zRR_l",sourceFileNav:"SampleLayout_sourceFileNav__ml48P",sourceFileContainer:"SampleLayout_sourceFileContainer__3s84x"}},134:function(e,n){"use strict";n.Z="@group(0) @binding(0) var mySampler : sampler;\n@group(0) @binding(1) var myTexture : texture_2d;\n\nstruct VertexOutput {\n @builtin(position) Position : vec4,\n @location(0) fragUV : vec2,\n}\n\n@vertex\nfn vert_main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {\n const pos = array(\n vec2( 1.0, 1.0),\n vec2( 1.0, -1.0),\n vec2(-1.0, -1.0),\n vec2( 1.0, 1.0),\n vec2(-1.0, -1.0),\n vec2(-1.0, 1.0),\n );\n\n const uv = array(\n vec2(1.0, 0.0),\n vec2(1.0, 1.0),\n vec2(0.0, 1.0),\n vec2(1.0, 0.0),\n vec2(0.0, 1.0),\n vec2(0.0, 0.0),\n );\n\n var output : VertexOutput;\n output.Position = vec4(pos[VertexIndex], 0.0, 1.0);\n output.fragUV = uv[VertexIndex];\n return output;\n}\n\n@fragment\nfn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 {\n return textureSample(myTexture, mySampler, fragUV);\n}\n"}}]); \ No newline at end of file diff --git a/_next/static/chunks/16.8197ee741050be41.js b/_next/static/chunks/16.8197ee741050be41.js new file mode 100644 index 00000000..ce6767bc --- /dev/null +++ b/_next/static/chunks/16.8197ee741050be41.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[16],{5671:function(e,n,t){"use strict";t.d(n,{Tl:function(){return c},hu:function(){return p}});var r=t(5893),o=t(9008),a=t.n(o),i=t(1163),s=t(7294),l=t(9147),u=t.n(l);t(7319);let d=e=>{let n=(0,s.useRef)(null),o=(0,s.useMemo)(()=>e.sources.map(e=>{let{name:n,contents:o}=e;return{name:n,...function(e){let n;let o=null;{o=document.createElement("div");let a=t(4631);n=a(o,{lineNumbers:!0,lineWrapping:!0,theme:"monokai",readOnly:!0})}return{Container:function(t){return(0,r.jsx)("div",{...t,children:(0,r.jsx)("div",{ref(t){o&&t&&(t.appendChild(o),n.setOption("value",e))}})})}}}(o)}}),e.sources),l=(0,s.useRef)(null),d=(0,s.useMemo)(()=>{if(e.gui){let n=t(4376);return new n.GUI({autoPlace:!1})}},[]),c=(0,s.useRef)(null),p=(0,s.useMemo)(()=>{if(e.stats){let n=t(2792);return new n}},[]),m=(0,i.useRouter)(),f=m.asPath.match(/#([a-zA-Z0-9\.\/]+)/),[g,h]=(0,s.useState)(null),[S,E]=(0,s.useState)(null);return(0,s.useEffect)(()=>{if(f?E(f[1]):E(o[0].name),d&&l.current)for(l.current.appendChild(d.domElement);d.__controllers.length>0;)d.__controllers[0].remove();p&&c.current&&(p.dom.style.position="absolute",p.showPanel(1),c.current.appendChild(p.dom));let t={active:!0},r=()=>{t.active=!1};try{let a=n.current;if(!a)throw Error("The canvas is not available");let i=e.init({canvas:a,pageState:t,gui:d,stats:p});i instanceof Promise&&i.catch(e=>{console.error(e),h(e)})}catch(s){console.error(s),h(s)}return r},[]),(0,r.jsxs)("main",{children:[(0,r.jsxs)(a(),{children:[(0,r.jsx)("style",{dangerouslySetInnerHTML:{__html:"\n .CodeMirror {\n height: auto !important;\n margin: 1em 0;\n }\n\n .CodeMirror-scroll {\n height: auto !important;\n overflow: visible !important;\n }\n "}}),(0,r.jsx)("title",{children:"".concat(e.name," - WebGPU Samples")}),(0,r.jsx)("meta",{name:"description",content:e.description}),(0,r.jsx)("meta",{httpEquiv:"origin-trial",content:e.originTrial})]}),(0,r.jsxs)("div",{children:[(0,r.jsx)("h1",{children:e.name}),(0,r.jsx)("a",{target:"_blank",rel:"noreferrer",href:"https://github.com/".concat("webgpu/webgpu-samples","/tree/main/").concat(e.filename),children:"See it on Github!"}),(0,r.jsx)("p",{children:e.description}),g?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("p",{children:"Something went wrong. Do your browser and device support WebGPU?"}),(0,r.jsx)("p",{children:"".concat(g)})]}):null]}),(0,r.jsxs)("div",{className:u().canvasContainer,children:[(0,r.jsx)("div",{style:{position:"absolute",left:10},ref:c}),(0,r.jsx)("div",{style:{position:"absolute",right:10},ref:l}),(0,r.jsx)("canvas",{ref:n})]}),(0,r.jsxs)("div",{children:[(0,r.jsx)("nav",{className:u().sourceFileNav,children:(0,r.jsx)("ul",{children:o.map((e,n)=>(0,r.jsx)("li",{children:(0,r.jsx)("a",{href:"#".concat(e.name),"data-active":S==e.name,onClick(){E(e.name)},children:e.name})},n))})}),o.map((e,n)=>(0,r.jsx)(e.Container,{className:u().sourceFileContainer,"data-active":S==e.name},n))]})]})},c=e=>(0,r.jsx)(d,{...e});function p(e,n){if(!e)throw Error(n)}},5016:function(e,n,t){"use strict";let r;t.r(n),t.d(n,{default:function(){return E}});var o,a,i=t(5671),s=t(134);let l=(e,n,t,r,o,a,i)=>{let s=[];for(let l=0;l{let n=async n=>{let{canvas:t,pageState:r,gui:o,stats:a}=n,i=await navigator.gpu.requestAdapter(),s=await i.requestDevice();if(!r.active)return;let l=t.getContext("webgpu"),u=window.devicePixelRatio;t.width=t.clientWidth*u,t.height=t.clientHeight*u;let d=navigator.gpu.getPreferredCanvasFormat();l.configure({device:s,format:d,alphaMode:"premultiplied"}),e({canvas:t,pageState:r,gui:o,device:s,context:l,presentationFormat:d,stats:a})};return n};class d{executeRun(e,n,t,r){let o=e.beginRenderPass(n);o.setPipeline(t);for(let a=0;a{e.queue.writeBuffer(a,0,new Uint32Array([n.highlight]))}}}p.sourceInfo={name:"src/sample/bitonicSort/bitonicDisplay.ts".substring(23),contents:"import {\n BindGroupCluster,\n Base2DRendererClass,\n createBindGroupCluster,\n} from './utils';\n\nimport bitonicDisplay from './bitonicDisplay.frag.wgsl';\n\ninterface BitonicDisplayRenderArgs {\n highlight: number;\n}\n\nexport default class BitonicDisplayRenderer extends Base2DRendererClass {\n static sourceInfo = {\n name: __filename.substring(__dirname.length + 1),\n contents: __SOURCE__,\n };\n\n switchBindGroup: (name: string) => void;\n setArguments: (args: BitonicDisplayRenderArgs) => void;\n computeBGDescript: BindGroupCluster;\n\n constructor(\n device: GPUDevice,\n presentationFormat: GPUTextureFormat,\n renderPassDescriptor: GPURenderPassDescriptor,\n computeBGDescript: BindGroupCluster,\n label: string\n ) {\n super();\n this.renderPassDescriptor = renderPassDescriptor;\n this.computeBGDescript = computeBGDescript;\n\n const uniformBuffer = device.createBuffer({\n size: Uint32Array.BYTES_PER_ELEMENT,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n\n const bgCluster = createBindGroupCluster(\n [0],\n [GPUShaderStage.FRAGMENT],\n ['buffer'],\n [{ type: 'uniform' }],\n [[{ buffer: uniformBuffer }]],\n label,\n device\n );\n\n this.currentBindGroup = bgCluster.bindGroups[0];\n\n this.pipeline = super.create2DRenderPipeline(\n device,\n label,\n [this.computeBGDescript.bindGroupLayout, bgCluster.bindGroupLayout],\n bitonicDisplay,\n presentationFormat\n );\n\n this.setArguments = (args: BitonicDisplayRenderArgs) => {\n device.queue.writeBuffer(\n uniformBuffer,\n 0,\n new Uint32Array([args.highlight])\n );\n };\n }\n\n startRun(commandEncoder: GPUCommandEncoder, args: BitonicDisplayRenderArgs) {\n this.setArguments(args);\n super.executeRun(commandEncoder, this.renderPassDescriptor, this.pipeline, [\n this.computeBGDescript.bindGroups[0],\n this.currentBindGroup,\n ]);\n }\n}\n"};let m=e=>((e%2!=0||e>256)&&(e=256),"\n\nstruct Uniforms {\n width: f32,\n height: f32,\n algo: u32,\n blockHeight: u32,\n}\n\n// Create local workgroup data that can contain all elements\nvar local_data: array;\n\n// Define groups (functions refer to this data)\n@group(0) @binding(0) var input_data: array;\n@group(0) @binding(1) var output_data: array;\n@group(0) @binding(2) var uniforms: Uniforms;\n@group(0) @binding(3) var counter: atomic;\n\n// Compare and swap values in local_data\nfn local_compare_and_swap(idx_before: u32, idx_after: u32) {\n //idx_before should always be < idx_after\n if (local_data[idx_after] < local_data[idx_before]) {\n atomicAdd(&counter, 1);\n var temp: u32 = local_data[idx_before];\n local_data[idx_before] = local_data[idx_after];\n local_data[idx_after] = temp;\n }\n return;\n}\n\n// thread_id goes from 0 to threadsPerWorkgroup\nfn get_flip_indices(thread_id: u32, block_height: u32) -> vec2 {\n // Caculate index offset (i.e move indices into correct block)\n let block_offset: u32 = ((2 * thread_id) / block_height) * block_height;\n let half_height = block_height / 2;\n // Calculate index spacing\n var idx: vec2 = vec2(\n thread_id % half_height, block_height - (thread_id % half_height) - 1,\n );\n idx.x += block_offset;\n idx.y += block_offset;\n return idx;\n}\n\nfn get_disperse_indices(thread_id: u32, block_height: u32) -> vec2 {\n var block_offset: u32 = ((2 * thread_id) / block_height) * block_height;\n let half_height = block_height / 2;\n var idx: vec2 = vec2(\n thread_id % half_height, (thread_id % half_height) + half_height\n );\n idx.x += block_offset;\n idx.y += block_offset;\n return idx;\n}\n\nfn global_compare_and_swap(idx_before: u32, idx_after: u32) {\n if (input_data[idx_after] < input_data[idx_before]) {\n output_data[idx_before] = input_data[idx_after];\n output_data[idx_after] = input_data[idx_before];\n } \n}\n\n// Constants/enum\nconst ALGO_NONE = 0;\nconst ALGO_LOCAL_FLIP = 1;\nconst ALGO_LOCAL_DISPERSE = 2;\nconst ALGO_GLOBAL_FLIP = 3;\n\n// Our compute shader will execute specified # of threads or elements / 2 threads\n@compute @workgroup_size(").concat(e,", 1, 1)\nfn computeMain(\n @builtin(global_invocation_id) global_id: vec3,\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3,\n) {\n\n let offset = ").concat(e," * 2 * workgroup_id.x;\n // If we will perform a local swap, then populate the local data\n if (uniforms.algo <= 2) {\n // Assign range of input_data to local_data.\n // Range cannot exceed maxWorkgroupsX * 2\n // Each thread will populate the workgroup data... (1 thread for every 2 elements)\n local_data[local_id.x * 2] = input_data[offset + local_id.x * 2];\n local_data[local_id.x * 2 + 1] = input_data[offset + local_id.x * 2 + 1];\n }\n\n //...and wait for each other to finish their own bit of data population.\n workgroupBarrier();\n\n switch uniforms.algo {\n case 1: { // Local Flip\n let idx = get_flip_indices(local_id.x, uniforms.blockHeight);\n local_compare_and_swap(idx.x, idx.y);\n } \n case 2: { // Local Disperse\n let idx = get_disperse_indices(local_id.x, uniforms.blockHeight);\n local_compare_and_swap(idx.x, idx.y);\n } \n case 3: { // Global Flip\n let idx = get_flip_indices(global_id.x, uniforms.blockHeight);\n global_compare_and_swap(idx.x, idx.y);\n }\n case 4: { \n let idx = get_disperse_indices(global_id.x, uniforms.blockHeight);\n global_compare_and_swap(idx.x, idx.y);\n }\n default: { \n \n }\n }\n\n // Ensure that all threads have swapped their own regions of data\n workgroupBarrier();\n\n if (uniforms.algo <= ALGO_LOCAL_DISPERSE) {\n //Repopulate global data with local data\n output_data[offset + local_id.x * 2] = local_data[local_id.x * 2];\n output_data[offset + local_id.x * 2 + 1] = local_data[local_id.x * 2 + 1];\n }\n\n}"));var f="@group(0) @binding(3) var counter: atomic;\n\n@compute @workgroup_size(1, 1, 1)\nfn atomicToZero() {\n let counterValue = atomicLoad(&counter);\n atomicSub(&counter, counterValue);\n}",g="src/sample/bitonicSort/main.ts";(o=a||(a={}))[o.NONE=0]="NONE",o[o.FLIP_LOCAL=1]="FLIP_LOCAL",o[o.DISPERSE_LOCAL=2]="DISPERSE_LOCAL",o[o.FLIP_GLOBAL=3]="FLIP_GLOBAL",o[o.DISPERSE_GLOBAL=4]="DISPERSE_GLOBAL";let h=e=>{let n=Math.log2(e);return n*(n+1)/2};u(async e=>{let{pageState:n,device:t,gui:r,presentationFormat:o,context:i,canvas:s}=e,u=t.limits.maxComputeWorkgroupSizeX,d=[],c=32*u;for(let g=c;g>=4;g/=2)d.push(g);let S=Math.sqrt(c)%2==0?Math.floor(Math.sqrt(c)):Math.floor(Math.sqrt(c/2)),E={"Total Elements":c,"Grid Width":S,"Grid Height":c/S,"Total Threads":u,"Hovered Cell":0,"Swapped Cell":1,"Step Index":0,"Total Steps":h(c),"Prev Step":"NONE","Next Step":"FLIP_LOCAL","Prev Swap Span":0,"Next Swap Span":2,"Total Workgroups":c/(2*u),"Total Swaps":0,executeStep:!1,"Display Mode":"Elements","Randomize Values"(){},"Execute Sort Step"(){},"Log Elements"(){},"Complete Sort"(){},"Sort Speed":50},v=new Uint32Array(Array.from({length:E["Total Elements"]},(e,n)=>n)),x=Float32Array.BYTES_PER_ELEMENT*d[0],_=t.createBuffer({size:x,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),b=t.createBuffer({size:x,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),C=t.createBuffer({size:x,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),y=t.createBuffer({size:Uint32Array.BYTES_PER_ELEMENT,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),P=t.createBuffer({size:Uint32Array.BYTES_PER_ELEMENT,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),w=t.createBuffer({size:4*Float32Array.BYTES_PER_ELEMENT,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),B=l([0,1,2,3],[GPUShaderStage.COMPUTE|GPUShaderStage.FRAGMENT,GPUShaderStage.COMPUTE,GPUShaderStage.COMPUTE|GPUShaderStage.FRAGMENT,GPUShaderStage.COMPUTE],["buffer","buffer","buffer","buffer"],[{type:"read-only-storage"},{type:"storage"},{type:"uniform"},{type:"storage"}],[[{buffer:_},{buffer:b},{buffer:w},{buffer:y}]],"BitonicSort",t),T=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[B.bindGroupLayout]}),compute:{module:t.createShaderModule({code:m(E["Total Threads"])}),entryPoint:"computeMain"}}),G=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[B.bindGroupLayout]}),compute:{module:t.createShaderModule({code:f}),entryPoint:"atomicToZero"}}),L={colorAttachments:[{view:void 0,clearValue:{r:.1,g:.4,b:.5,a:1},loadOp:"clear",storeOp:"store"}]},I=new p(t,o,L,B,"BitonicDisplay"),U=()=>{F.setValue(Math.min(E["Total Elements"]/2,u));let e=(E["Total Elements"]-1)/(2*u);H.setValue(Math.ceil(e)),X.setValue(0),Q.setValue(h(E["Total Elements"]));let n=Math.sqrt(E["Total Elements"])%2==0?Math.floor(Math.sqrt(E["Total Elements"])):Math.floor(Math.sqrt(E["Total Elements"]/2)),r=E["Total Elements"]/n;z.setValue(n),Y.setValue(r),J.setValue("NONE"),K.setValue("FLIP_LOCAL"),ee.setValue(0),en.setValue(2);let o=t.createCommandEncoder(),a=o.beginComputePass();a.setPipeline(G),a.setBindGroup(0,B.bindGroups[0]),a.dispatchWorkgroups(1),a.end(),t.queue.submit([o.finish()]),$.setValue(0),eo=2},A=()=>{let e=v.length;for(;0!==e;){let n=Math.floor(Math.random()*e);e-=1,[v[e],v[n]]=[v[n],v[e]]}},R=()=>{v=new Uint32Array(Array.from({length:E["Total Elements"]},(e,n)=>n)),U(),T=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[B.bindGroupLayout]}),compute:{module:t.createShaderModule({code:m(E["Total Elements"]/2)}),entryPoint:"computeMain"}}),A(),eo=2};A();let M=()=>{let e;switch(E["Next Step"]){case"FLIP_LOCAL":case"FLIP_GLOBAL":{let n=E["Next Swap Span"],t=Math.floor(E["Hovered Cell"]/n)+1,r=E["Hovered Cell"]%n;e=n*t-r-1,j.setValue(e)}break;case"DISPERSE_LOCAL":{let o=E["Next Swap Span"],a=o/2;e=E["Hovered Cell"]%o{null!==O&&(clearInterval(O),O=null)},D=()=>{let e=E["Sort Speed"];O=setInterval(()=>{"NONE"===E["Next Step"]&&(clearInterval(O),O=null),E["Sort Speed"]!==e&&(clearInterval(O),O=null,D()),E.executeStep=!0,M()},E["Sort Speed"])},N=r.addFolder("Compute Resources");N.add(E,"Total Elements",d).onChange(()=>{k(),R()});let F=N.add(E,"Total Threads"),H=N.add(E,"Total Workgroups");N.open();let V=r.addFolder("Sort Controls");V.add(E,"Sort Speed",50,1e3).step(50),V.add(E,"Execute Sort Step").onChange(()=>{k(),E.executeStep=!0}),V.add(E,"Randomize Values").onChange(()=>{k(),A(),U()}),V.add(E,"Log Elements").onChange(()=>console.log(v)),V.add(E,"Complete Sort").onChange(D),V.open();let W=r.addFolder("Grid Information");W.add(E,"Display Mode",["Elements","Swap Highlight"]);let z=W.add(E,"Grid Width"),Y=W.add(E,"Grid Height"),q=W.add(E,"Hovered Cell").onChange(M),j=W.add(E,"Swapped Cell"),Z=r.addFolder("Execution Information"),X=Z.add(E,"Step Index"),Q=Z.add(E,"Total Steps"),J=Z.add(E,"Prev Step"),K=Z.add(E,"Next Step"),$=Z.add(E,"Total Swaps"),ee=Z.add(E,"Prev Swap Span"),en=Z.add(E,"Next Swap Span"),et=document.getElementsByClassName("cr function");for(let er=0;er{let n=s.getBoundingClientRect().width,t=s.getBoundingClientRect().height,r=[n/E["Grid Width"],t/E["Grid Height"]],o=Math.floor(e.offsetX/r[0]),a=E["Grid Height"]-1-Math.floor(e.offsetY/r[1]);q.setValue(a*E["Grid Width"]+o),E["Hovered Cell"]=a*E["Grid Width"]+o}),H.domElement.style.pointerEvents="none",q.domElement.style.pointerEvents="none",j.domElement.style.pointerEvents="none",X.domElement.style.pointerEvents="none",Q.domElement.style.pointerEvents="none",J.domElement.style.pointerEvents="none",ee.domElement.style.pointerEvents="none",K.domElement.style.pointerEvents="none",en.domElement.style.pointerEvents="none",F.domElement.style.pointerEvents="none",z.domElement.style.pointerEvents="none",Y.domElement.style.pointerEvents="none",$.domElement.style.pointerEvents="none";let eo=2;async function ea(){if(!n.active)return;t.queue.writeBuffer(_,0,v.buffer,v.byteOffset,v.byteLength);let e=new Float32Array([E["Grid Width"],E["Grid Height"]]),r=new Uint32Array([a[E["Next Step"]],E["Next Swap Span"]]);t.queue.writeBuffer(w,0,e.buffer,e.byteOffset,e.byteLength),t.queue.writeBuffer(w,8,r),L.colorAttachments[0].view=i.getCurrentTexture().createView();let o=t.createCommandEncoder();if(I.startRun(o,{highlight:"Elements"===E["Display Mode"]?0:1}),E.executeStep&&eo!==2*E["Total Elements"]){let s=o.beginComputePass();s.setPipeline(T),s.setBindGroup(0,B.bindGroups[0]),s.dispatchWorkgroups(E["Total Workgroups"]),s.end(),X.setValue(E["Step Index"]+1),J.setValue(E["Next Step"]),ee.setValue(E["Next Swap Span"]),en.setValue(E["Next Swap Span"]/2),1===E["Next Swap Span"]?(eo*=2)==2*E["Total Elements"]?(K.setValue("NONE"),en.setValue(0)):eo>2*E["Total Threads"]?(K.setValue("FLIP_GLOBAL"),en.setValue(eo)):(K.setValue("FLIP_LOCAL"),en.setValue(eo)):E["Next Swap Span"]>2*E["Total Threads"]?K.setValue("DISPERSE_GLOBAL"):K.setValue("DISPERSE_LOCAL"),o.copyBufferToBuffer(b,0,C,0,x),o.copyBufferToBuffer(y,0,P,0,Uint32Array.BYTES_PER_ELEMENT)}if(t.queue.submit([o.finish()]),E.executeStep){await C.mapAsync(GPUMapMode.READ,0,x);let l=C.getMappedRange(0,x);await P.mapAsync(GPUMapMode.READ,0,Uint32Array.BYTES_PER_ELEMENT);let u=P.getMappedRange(0,Uint32Array.BYTES_PER_ELEMENT),d=l.slice(0,Uint32Array.BYTES_PER_ELEMENT*E["Total Elements"]),c=u.slice(0,Uint32Array.BYTES_PER_ELEMENT),p=new Uint32Array(d);$.setValue(new Uint32Array(c)[0]),C.unmap(),P.unmap(),v=p,M()}E.executeStep=!1,requestAnimationFrame(ea)}D(),requestAnimationFrame(ea)}).then(e=>r=e);let S=()=>(0,i.Tl)({name:"Bitonic Sort",description:"A naive bitonic sort algorithm executed on the GPU, based on tgfrerer's implementation at poniesandlight.co.uk/reflect/bitonic_merge_sort/. Each invocation of the bitonic sort shader dispatches a workgroup containing elements/2 threads. The GUI's Execution Information folder contains information about the sort's current state. The visualizer displays the sort's results as colored cells sorted from brightest to darkest.",init:r,gui:!0,sources:[{name:g.substring(23),contents:"import { makeSample, SampleInit } from '../../components/SampleLayout';\nimport { createBindGroupCluster, SampleInitFactoryWebGPU } from './utils';\nimport BitonicDisplayRenderer from './bitonicDisplay';\nimport bitonicDisplay from './bitonicDisplay.frag.wgsl';\nimport { NaiveBitonicCompute } from './computeShader';\nimport fullscreenTexturedQuad from '../../shaders/fullscreenTexturedQuad.wgsl';\nimport atomicToZero from './atomicToZero.wgsl';\n\n// Type of step that will be executed in our shader\nenum StepEnum {\n NONE,\n FLIP_LOCAL,\n DISPERSE_LOCAL,\n FLIP_GLOBAL,\n DISPERSE_GLOBAL,\n}\n\n// String access to StepEnum\ntype StepType =\n | 'NONE'\n | 'FLIP_LOCAL'\n | 'DISPERSE_LOCAL'\n | 'FLIP_GLOBAL'\n | 'DISPERSE_GLOBAL';\n\ntype DisplayType = 'Elements' | 'Swap Highlight';\n\n// Gui settings object\ninterface SettingsInterface {\n 'Total Elements': number;\n 'Grid Width': number;\n 'Grid Height': number;\n 'Total Threads': number;\n 'Hovered Cell': number;\n 'Swapped Cell': number;\n 'Step Index': number;\n 'Total Steps': number;\n 'Prev Step': StepType;\n 'Next Step': StepType;\n 'Prev Swap Span': number;\n 'Next Swap Span': number;\n 'Total Workgroups': number;\n 'Display Mode': DisplayType;\n 'Total Swaps': number;\n executeStep: boolean;\n 'Randomize Values': () => void;\n 'Execute Sort Step': () => void;\n 'Log Elements': () => void;\n 'Complete Sort': () => void;\n 'Sort Speed': number;\n}\n\nconst getNumSteps = (numElements: number) => {\n const n = Math.log2(numElements);\n return (n * (n + 1)) / 2;\n};\n\nlet init: SampleInit;\nSampleInitFactoryWebGPU(\n async ({ pageState, device, gui, presentationFormat, context, canvas }) => {\n const maxThreadsX = device.limits.maxComputeWorkgroupSizeX;\n\n const totalElementLengths = [];\n const maxElements = maxThreadsX * 32;\n for (let i = maxElements; i >= 4; i /= 2) {\n totalElementLengths.push(i);\n }\n\n const defaultGridWidth =\n Math.sqrt(maxElements) % 2 === 0\n ? Math.floor(Math.sqrt(maxElements))\n : Math.floor(Math.sqrt(maxElements / 2));\n\n const defaultGridHeight = maxElements / defaultGridWidth;\n\n const settings: SettingsInterface = {\n // number of cellElements. Must equal gridWidth * gridHeight and 'Total Threads' * 2\n 'Total Elements': maxElements,\n // width of screen in cells.\n 'Grid Width': defaultGridWidth,\n // height of screen in cells\n 'Grid Height': defaultGridHeight,\n // number of threads to execute in a workgroup ('Total Threads', 1, 1)\n 'Total Threads': maxThreadsX,\n // Cell in element grid mouse element is hovering over\n 'Hovered Cell': 0,\n // element the hovered cell just swapped with,\n 'Swapped Cell': 1,\n // Index of current step\n 'Step Index': 0,\n // Total steps to sort current number of elements\n 'Total Steps': getNumSteps(maxElements),\n // Previously executed step\n 'Prev Step': 'NONE',\n // Next step to execute\n 'Next Step': 'FLIP_LOCAL',\n // Max thread span of previous block\n 'Prev Swap Span': 0,\n // Max thread span of next block\n 'Next Swap Span': 2,\n // Workgroups to dispatch per frame,\n 'Total Workgroups': maxElements / (maxThreadsX * 2),\n // The number of swap operations executed over time\n 'Total Swaps': 0,\n // Whether we will dispatch a workload this frame\n executeStep: false,\n 'Display Mode': 'Elements',\n 'Randomize Values': () => {\n return;\n },\n 'Execute Sort Step': () => {\n return;\n },\n 'Log Elements': () => {\n return;\n },\n 'Complete Sort': () => {\n return;\n },\n 'Sort Speed': 50,\n };\n\n // Initialize initial elements array\n let elements = new Uint32Array(\n Array.from({ length: settings['Total Elements'] }, (_, i) => i)\n );\n\n // Initialize elementsBuffer and elementsStagingBuffer\n const elementsBufferSize =\n Float32Array.BYTES_PER_ELEMENT * totalElementLengths[0];\n // Initialize input, output, staging buffers\n const elementsInputBuffer = device.createBuffer({\n size: elementsBufferSize,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n });\n const elementsOutputBuffer = device.createBuffer({\n size: elementsBufferSize,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n const elementsStagingBuffer = device.createBuffer({\n size: elementsBufferSize,\n usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,\n });\n\n // Initialize atomic swap buffer on GPU and CPU. Counts number of swaps actually performed by\n // compute shader (when value at index x is greater than value at index y)\n const atomicSwapsOutputBuffer = device.createBuffer({\n size: Uint32Array.BYTES_PER_ELEMENT,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n const atomicSwapsStagingBuffer = device.createBuffer({\n size: Uint32Array.BYTES_PER_ELEMENT,\n usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,\n });\n\n // Create uniform buffer for compute shader\n const computeUniformsBuffer = device.createBuffer({\n // width, height, blockHeight, algo\n size: Float32Array.BYTES_PER_ELEMENT * 4,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n\n const computeBGCluster = createBindGroupCluster(\n [0, 1, 2, 3],\n [\n GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,\n GPUShaderStage.COMPUTE,\n GPUShaderStage.COMPUTE | GPUShaderStage.FRAGMENT,\n GPUShaderStage.COMPUTE,\n ],\n ['buffer', 'buffer', 'buffer', 'buffer'],\n [\n { type: 'read-only-storage' },\n { type: 'storage' },\n { type: 'uniform' },\n { type: 'storage' },\n ],\n [\n [\n { buffer: elementsInputBuffer },\n { buffer: elementsOutputBuffer },\n { buffer: computeUniformsBuffer },\n { buffer: atomicSwapsOutputBuffer },\n ],\n ],\n 'BitonicSort',\n device\n );\n\n let computePipeline = device.createComputePipeline({\n layout: device.createPipelineLayout({\n bindGroupLayouts: [computeBGCluster.bindGroupLayout],\n }),\n compute: {\n module: device.createShaderModule({\n code: NaiveBitonicCompute(settings['Total Threads']),\n }),\n entryPoint: 'computeMain',\n },\n });\n\n // Simple pipeline that zeros out an atomic value at group 0 binding 3\n const atomicToZeroComputePipeline = device.createComputePipeline({\n layout: device.createPipelineLayout({\n bindGroupLayouts: [computeBGCluster.bindGroupLayout],\n }),\n compute: {\n module: device.createShaderModule({\n code: atomicToZero,\n }),\n entryPoint: 'atomicToZero',\n },\n });\n\n // Create bitonic debug renderer\n const renderPassDescriptor: GPURenderPassDescriptor = {\n colorAttachments: [\n {\n view: undefined, // Assigned later\n\n clearValue: { r: 0.1, g: 0.4, b: 0.5, a: 1.0 },\n loadOp: 'clear',\n storeOp: 'store',\n },\n ],\n };\n\n const bitonicDisplayRenderer = new BitonicDisplayRenderer(\n device,\n presentationFormat,\n renderPassDescriptor,\n computeBGCluster,\n 'BitonicDisplay'\n );\n\n const resetExecutionInformation = () => {\n // Total threads are either elements / 2 or maxWorkgroupsSizeX\n totalThreadsController.setValue(\n Math.min(settings['Total Elements'] / 2, maxThreadsX)\n );\n\n // Dispatch a workgroup for every (Max threads * 2) elements\n const workgroupsPerStep =\n (settings['Total Elements'] - 1) / (maxThreadsX * 2);\n\n totalWorkgroupsController.setValue(Math.ceil(workgroupsPerStep));\n\n // Reset step Index and number of steps based on elements size\n stepIndexController.setValue(0);\n totalStepsController.setValue(getNumSteps(settings['Total Elements']));\n\n // Get new width and height of screen display in cells\n const newCellWidth =\n Math.sqrt(settings['Total Elements']) % 2 === 0\n ? Math.floor(Math.sqrt(settings['Total Elements']))\n : Math.floor(Math.sqrt(settings['Total Elements'] / 2));\n const newCellHeight = settings['Total Elements'] / newCellWidth;\n gridWidthController.setValue(newCellWidth);\n gridHeightController.setValue(newCellHeight);\n\n // Set prevStep to None (restart) and next step to FLIP\n prevStepController.setValue('NONE');\n nextStepController.setValue('FLIP_LOCAL');\n\n // Reset block heights\n prevBlockHeightController.setValue(0);\n nextBlockHeightController.setValue(2);\n\n // Reset Total Swaps by setting atomic value to 0\n const commandEncoder = device.createCommandEncoder();\n const computePassEncoder = commandEncoder.beginComputePass();\n computePassEncoder.setPipeline(atomicToZeroComputePipeline);\n computePassEncoder.setBindGroup(0, computeBGCluster.bindGroups[0]);\n computePassEncoder.dispatchWorkgroups(1);\n computePassEncoder.end();\n device.queue.submit([commandEncoder.finish()]);\n totalSwapsController.setValue(0);\n\n highestBlockHeight = 2;\n };\n\n const randomizeElementArray = () => {\n let currentIndex = elements.length;\n // While there are elements to shuffle\n while (currentIndex !== 0) {\n // Pick a remaining element\n const randomIndex = Math.floor(Math.random() * currentIndex);\n currentIndex -= 1;\n [elements[currentIndex], elements[randomIndex]] = [\n elements[randomIndex],\n elements[currentIndex],\n ];\n }\n };\n\n const resizeElementArray = () => {\n // Recreate elements array with new length\n elements = new Uint32Array(\n Array.from({ length: settings['Total Elements'] }, (_, i) => i)\n );\n\n resetExecutionInformation();\n\n // Create new shader invocation with workgroupSize that reflects number of threads\n computePipeline = device.createComputePipeline({\n layout: device.createPipelineLayout({\n bindGroupLayouts: [computeBGCluster.bindGroupLayout],\n }),\n compute: {\n module: device.createShaderModule({\n code: NaiveBitonicCompute(settings['Total Elements'] / 2),\n }),\n entryPoint: 'computeMain',\n },\n });\n // Randomize array elements\n randomizeElementArray();\n highestBlockHeight = 2;\n };\n\n randomizeElementArray();\n\n const setSwappedCell = () => {\n let swappedIndex: number;\n switch (settings['Next Step']) {\n case 'FLIP_LOCAL':\n case 'FLIP_GLOBAL':\n {\n const blockHeight = settings['Next Swap Span'];\n const p2 = Math.floor(settings['Hovered Cell'] / blockHeight) + 1;\n const p3 = settings['Hovered Cell'] % blockHeight;\n swappedIndex = blockHeight * p2 - p3 - 1;\n swappedCellController.setValue(swappedIndex);\n }\n break;\n case 'DISPERSE_LOCAL':\n {\n const blockHeight = settings['Next Swap Span'];\n const halfHeight = blockHeight / 2;\n swappedIndex =\n settings['Hovered Cell'] % blockHeight < halfHeight\n ? settings['Hovered Cell'] + halfHeight\n : settings['Hovered Cell'] - halfHeight;\n swappedCellController.setValue(swappedIndex);\n }\n break;\n case 'NONE': {\n swappedIndex = settings['Hovered Cell'];\n swappedCellController.setValue(swappedIndex);\n }\n default:\n {\n swappedIndex = settings['Hovered Cell'];\n swappedCellController.setValue(swappedIndex);\n }\n break;\n }\n };\n\n let completeSortIntervalID: ReturnType | null = null;\n const endSortInterval = () => {\n if (completeSortIntervalID !== null) {\n clearInterval(completeSortIntervalID);\n completeSortIntervalID = null;\n }\n };\n const startSortInterval = () => {\n const currentIntervalSpeed = settings['Sort Speed'];\n completeSortIntervalID = setInterval(() => {\n if (settings['Next Step'] === 'NONE') {\n clearInterval(completeSortIntervalID);\n completeSortIntervalID = null;\n }\n if (settings['Sort Speed'] !== currentIntervalSpeed) {\n clearInterval(completeSortIntervalID);\n completeSortIntervalID = null;\n startSortInterval();\n }\n settings.executeStep = true;\n setSwappedCell();\n }, settings['Sort Speed']);\n };\n\n // At top level, information about resources used to execute the compute shader\n // i.e elements sorted, threads/invocations per workgroup, and workgroups dispatched\n const computeResourcesFolder = gui.addFolder('Compute Resources');\n computeResourcesFolder\n .add(settings, 'Total Elements', totalElementLengths)\n .onChange(() => {\n endSortInterval();\n resizeElementArray();\n });\n const totalThreadsController = computeResourcesFolder.add(\n settings,\n 'Total Threads'\n );\n const totalWorkgroupsController = computeResourcesFolder.add(\n settings,\n 'Total Workgroups'\n );\n computeResourcesFolder.open();\n\n // Folder with functions that control the execution of the sort\n const controlFolder = gui.addFolder('Sort Controls');\n controlFolder.add(settings, 'Sort Speed', 50, 1000).step(50);\n controlFolder.add(settings, 'Execute Sort Step').onChange(() => {\n endSortInterval();\n settings.executeStep = true;\n });\n controlFolder.add(settings, 'Randomize Values').onChange(() => {\n endSortInterval();\n randomizeElementArray();\n resetExecutionInformation();\n });\n controlFolder\n .add(settings, 'Log Elements')\n .onChange(() => console.log(elements));\n controlFolder.add(settings, 'Complete Sort').onChange(startSortInterval);\n controlFolder.open();\n\n // Information about grid display\n const gridFolder = gui.addFolder('Grid Information');\n gridFolder.add(settings, 'Display Mode', ['Elements', 'Swap Highlight']);\n const gridWidthController = gridFolder.add(settings, 'Grid Width');\n const gridHeightController = gridFolder.add(settings, 'Grid Height');\n const hoveredCellController = gridFolder\n .add(settings, 'Hovered Cell')\n .onChange(setSwappedCell);\n const swappedCellController = gridFolder.add(settings, 'Swapped Cell');\n\n // Additional Information about the execution state of the sort\n const executionInformationFolder = gui.addFolder('Execution Information');\n const stepIndexController = executionInformationFolder.add(\n settings,\n 'Step Index'\n );\n const totalStepsController = executionInformationFolder.add(\n settings,\n 'Total Steps'\n );\n const prevStepController = executionInformationFolder.add(\n settings,\n 'Prev Step'\n );\n const nextStepController = executionInformationFolder.add(\n settings,\n 'Next Step'\n );\n const totalSwapsController = executionInformationFolder.add(\n settings,\n 'Total Swaps'\n );\n const prevBlockHeightController = executionInformationFolder.add(\n settings,\n 'Prev Swap Span'\n );\n const nextBlockHeightController = executionInformationFolder.add(\n settings,\n 'Next Swap Span'\n );\n\n // Adjust styles of Function List Elements within GUI\n const liFunctionElements = document.getElementsByClassName('cr function');\n for (let i = 0; i < liFunctionElements.length; i++) {\n (liFunctionElements[i].children[0] as HTMLElement).style.display = 'flex';\n (liFunctionElements[i].children[0] as HTMLElement).style.justifyContent =\n 'center';\n (\n liFunctionElements[i].children[0].children[1] as HTMLElement\n ).style.position = 'absolute';\n }\n\n canvas.addEventListener('mousemove', (event) => {\n const currWidth = canvas.getBoundingClientRect().width;\n const currHeight = canvas.getBoundingClientRect().height;\n const cellSize: [number, number] = [\n currWidth / settings['Grid Width'],\n currHeight / settings['Grid Height'],\n ];\n const xIndex = Math.floor(event.offsetX / cellSize[0]);\n const yIndex =\n settings['Grid Height'] - 1 - Math.floor(event.offsetY / cellSize[1]);\n hoveredCellController.setValue(yIndex * settings['Grid Width'] + xIndex);\n settings['Hovered Cell'] = yIndex * settings['Grid Width'] + xIndex;\n });\n\n // Deactivate interaction with select GUI elements\n totalWorkgroupsController.domElement.style.pointerEvents = 'none';\n hoveredCellController.domElement.style.pointerEvents = 'none';\n swappedCellController.domElement.style.pointerEvents = 'none';\n stepIndexController.domElement.style.pointerEvents = 'none';\n totalStepsController.domElement.style.pointerEvents = 'none';\n prevStepController.domElement.style.pointerEvents = 'none';\n prevBlockHeightController.domElement.style.pointerEvents = 'none';\n nextStepController.domElement.style.pointerEvents = 'none';\n nextBlockHeightController.domElement.style.pointerEvents = 'none';\n totalThreadsController.domElement.style.pointerEvents = 'none';\n gridWidthController.domElement.style.pointerEvents = 'none';\n gridHeightController.domElement.style.pointerEvents = 'none';\n totalSwapsController.domElement.style.pointerEvents = 'none';\n\n let highestBlockHeight = 2;\n\n startSortInterval();\n\n async function frame() {\n if (!pageState.active) return;\n\n // Write elements buffer\n device.queue.writeBuffer(\n elementsInputBuffer,\n 0,\n elements.buffer,\n elements.byteOffset,\n elements.byteLength\n );\n\n const dims = new Float32Array([\n settings['Grid Width'],\n settings['Grid Height'],\n ]);\n const stepDetails = new Uint32Array([\n StepEnum[settings['Next Step']],\n settings['Next Swap Span'],\n ]);\n device.queue.writeBuffer(\n computeUniformsBuffer,\n 0,\n dims.buffer,\n dims.byteOffset,\n dims.byteLength\n );\n\n device.queue.writeBuffer(computeUniformsBuffer, 8, stepDetails);\n\n renderPassDescriptor.colorAttachments[0].view = context\n .getCurrentTexture()\n .createView();\n\n const commandEncoder = device.createCommandEncoder();\n bitonicDisplayRenderer.startRun(commandEncoder, {\n highlight: settings['Display Mode'] === 'Elements' ? 0 : 1,\n });\n if (\n settings.executeStep &&\n highestBlockHeight !== settings['Total Elements'] * 2\n ) {\n const computePassEncoder = commandEncoder.beginComputePass();\n computePassEncoder.setPipeline(computePipeline);\n computePassEncoder.setBindGroup(0, computeBGCluster.bindGroups[0]);\n computePassEncoder.dispatchWorkgroups(settings['Total Workgroups']);\n computePassEncoder.end();\n stepIndexController.setValue(settings['Step Index'] + 1);\n prevStepController.setValue(settings['Next Step']);\n prevBlockHeightController.setValue(settings['Next Swap Span']);\n nextBlockHeightController.setValue(settings['Next Swap Span'] / 2);\n if (settings['Next Swap Span'] === 1) {\n highestBlockHeight *= 2;\n if (highestBlockHeight === settings['Total Elements'] * 2) {\n nextStepController.setValue('NONE');\n nextBlockHeightController.setValue(0);\n } else if (highestBlockHeight > settings['Total Threads'] * 2) {\n nextStepController.setValue('FLIP_GLOBAL');\n nextBlockHeightController.setValue(highestBlockHeight);\n } else {\n nextStepController.setValue('FLIP_LOCAL');\n nextBlockHeightController.setValue(highestBlockHeight);\n }\n } else {\n settings['Next Swap Span'] > settings['Total Threads'] * 2\n ? nextStepController.setValue('DISPERSE_GLOBAL')\n : nextStepController.setValue('DISPERSE_LOCAL');\n }\n\n // Copy GPU accessible buffers to CPU accessible buffers\n commandEncoder.copyBufferToBuffer(\n elementsOutputBuffer,\n 0,\n elementsStagingBuffer,\n 0,\n elementsBufferSize\n );\n\n commandEncoder.copyBufferToBuffer(\n atomicSwapsOutputBuffer,\n 0,\n atomicSwapsStagingBuffer,\n 0,\n Uint32Array.BYTES_PER_ELEMENT\n );\n }\n device.queue.submit([commandEncoder.finish()]);\n\n if (settings.executeStep) {\n // Copy GPU element data to CPU\n await elementsStagingBuffer.mapAsync(\n GPUMapMode.READ,\n 0,\n elementsBufferSize\n );\n const copyElementsBuffer = elementsStagingBuffer.getMappedRange(\n 0,\n elementsBufferSize\n );\n // Copy atomic swaps data to CPU\n await atomicSwapsStagingBuffer.mapAsync(\n GPUMapMode.READ,\n 0,\n Uint32Array.BYTES_PER_ELEMENT\n );\n const copySwapsBuffer = atomicSwapsStagingBuffer.getMappedRange(\n 0,\n Uint32Array.BYTES_PER_ELEMENT\n );\n // Get correct range of data from CPU copy of GPU Data\n const elementsData = copyElementsBuffer.slice(\n 0,\n Uint32Array.BYTES_PER_ELEMENT * settings['Total Elements']\n );\n const swapsData = copySwapsBuffer.slice(\n 0,\n Uint32Array.BYTES_PER_ELEMENT\n );\n // Extract data\n const elementsOutput = new Uint32Array(elementsData);\n totalSwapsController.setValue(new Uint32Array(swapsData)[0]);\n elementsStagingBuffer.unmap();\n atomicSwapsStagingBuffer.unmap();\n // Elements output becomes elements input, swap accumulate\n elements = elementsOutput;\n setSwappedCell();\n }\n settings.executeStep = false;\n requestAnimationFrame(frame);\n }\n requestAnimationFrame(frame);\n }\n).then((resultInit) => (init = resultInit));\n\nconst bitonicSortExample: () => JSX.Element = () =>\n makeSample({\n name: 'Bitonic Sort',\n description:\n \"A naive bitonic sort algorithm executed on the GPU, based on tgfrerer's implementation at poniesandlight.co.uk/reflect/bitonic_merge_sort/. Each invocation of the bitonic sort shader dispatches a workgroup containing elements/2 threads. The GUI's Execution Information folder contains information about the sort's current state. The visualizer displays the sort's results as colored cells sorted from brightest to darkest.\",\n init,\n gui: true,\n sources: [\n {\n name: __filename.substring(__dirname.length + 1),\n contents: __SOURCE__,\n },\n BitonicDisplayRenderer.sourceInfo,\n {\n name: '../../../shaders/fullscreenTexturedQuad.vert.wgsl',\n contents: fullscreenTexturedQuad,\n },\n {\n name: './bitonicDisplay.frag.wgsl',\n contents: bitonicDisplay,\n },\n {\n name: './bitonicCompute.frag.wgsl',\n contents: NaiveBitonicCompute(64),\n },\n {\n name: './atomicToZero.wgsl',\n contents: atomicToZero,\n },\n ],\n filename: __filename,\n });\n\nexport default bitonicSortExample;\n"},p.sourceInfo,{name:"../../../shaders/fullscreenTexturedQuad.vert.wgsl",contents:s.Z},{name:"./bitonicDisplay.frag.wgsl",contents:c},{name:"./bitonicCompute.frag.wgsl",contents:m(64)},{name:"./atomicToZero.wgsl",contents:f}],filename:g});var E=S},9147:function(e){e.exports={canvasContainer:"SampleLayout_canvasContainer__zRR_l",sourceFileNav:"SampleLayout_sourceFileNav__ml48P",sourceFileContainer:"SampleLayout_sourceFileContainer__3s84x"}},134:function(e,n){"use strict";n.Z="@group(0) @binding(0) var mySampler : sampler;\n@group(0) @binding(1) var myTexture : texture_2d;\n\nstruct VertexOutput {\n @builtin(position) Position : vec4,\n @location(0) fragUV : vec2,\n}\n\n@vertex\nfn vert_main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {\n const pos = array(\n vec2( 1.0, 1.0),\n vec2( 1.0, -1.0),\n vec2(-1.0, -1.0),\n vec2( 1.0, 1.0),\n vec2(-1.0, -1.0),\n vec2(-1.0, 1.0),\n );\n\n const uv = array(\n vec2(1.0, 0.0),\n vec2(1.0, 1.0),\n vec2(0.0, 1.0),\n vec2(1.0, 0.0),\n vec2(0.0, 1.0),\n vec2(0.0, 0.0),\n );\n\n var output : VertexOutput;\n output.Position = vec4(pos[VertexIndex], 0.0, 1.0);\n output.fragUV = uv[VertexIndex];\n return output;\n}\n\n@fragment\nfn frag_main(@location(0) fragUV : vec2) -> @location(0) vec4 {\n return textureSample(myTexture, mySampler, fragUV);\n}\n"}}]); \ No newline at end of file diff --git a/_next/static/chunks/pages/_app-67c697283af90eb7.js b/_next/static/chunks/pages/_app-029e0c7dcec9c745.js similarity index 83% rename from _next/static/chunks/pages/_app-67c697283af90eb7.js rename to _next/static/chunks/pages/_app-029e0c7dcec9c745.js index 26a77a71..43e2cf46 100644 --- a/_next/static/chunks/pages/_app-67c697283af90eb7.js +++ b/_next/static/chunks/pages/_app-029e0c7dcec9c745.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[888],{3454:function(e,t,n){"use strict";var a,r;e.exports=(null==(a=n.g.process)?void 0:a.env)&&"object"==typeof(null==(r=n.g.process)?void 0:r.env)?n.g.process:n(7663)},6840:function(e,t,n){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_app",function(){return n(6505)}])},227:function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getDomainLocale=function(e,t,n,a){return!1},("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},1551:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=n(2648).Z,r=n(7273).Z,l=a(n(7294)),o=n(1003),i=n(4465),s=n(2692),u=n(8245),d=n(9246),c=n(227),f=n(3468);let p={};function h(e,t,n,a){if(!e||!o.isLocalURL(t))return;Promise.resolve(e.prefetch(t,n,a)).catch(e=>{});let r=a&&void 0!==a.locale?a.locale:e&&e.locale;p[t+"%"+n+(r?"%"+r:"")]=!0}let b=l.default.forwardRef(function(e,t){let n,a;let{href:b,as:m,children:_,prefetch:y,passHref:v,replace:g,shallow:x,scroll:w,locale:k,onClick:P,onMouseEnter:j,onTouchStart:C,legacyBehavior:L=!0!==Boolean(!0)}=e,T=r(e,["href","as","children","prefetch","passHref","replace","shallow","scroll","locale","onClick","onMouseEnter","onTouchStart","legacyBehavior"]);n=_,L&&("string"==typeof n||"number"==typeof n)&&(n=l.default.createElement("a",null,n));let G=!1!==y,M=l.default.useContext(s.RouterContext),O=l.default.useContext(u.AppRouterContext);O&&(M=O);let{href:E,as:R}=l.default.useMemo(()=>{let[e,t]=o.resolveHref(M,b,!0);return{href:e,as:m?o.resolveHref(M,m):t||e}},[M,b,m]),S=l.default.useRef(E),A=l.default.useRef(R);L&&(a=l.default.Children.only(n));let N=L?a&&"object"==typeof a&&a.ref:t,[D,I,U]=d.useIntersection({rootMargin:"200px"}),B=l.default.useCallback(e=>{(A.current!==R||S.current!==E)&&(U(),A.current=R,S.current=E),D(e),N&&("function"==typeof N?N(e):"object"==typeof N&&(N.current=e))},[R,N,E,U,D]);l.default.useEffect(()=>{let e=I&&G&&o.isLocalURL(E),t=void 0!==k?k:M&&M.locale,n=p[E+"%"+R+(t?"%"+t:"")];e&&!n&&h(M,E,R,{locale:t})},[R,E,I,k,G,M]);let W={ref:B,onClick(e){L||"function"!=typeof P||P(e),L&&a.props&&"function"==typeof a.props.onClick&&a.props.onClick(e),e.defaultPrevented||function(e,t,n,a,r,i,s,u,d,c){let{nodeName:f}=e.currentTarget,p="A"===f.toUpperCase();if(p&&(function(e){let{target:t}=e.currentTarget;return t&&"_self"!==t||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||e.nativeEvent&&2===e.nativeEvent.which}(e)||!o.isLocalURL(n)))return;e.preventDefault();let h=()=>{"beforePopState"in t?t[r?"replace":"push"](n,a,{shallow:i,locale:u,scroll:s}):t[r?"replace":"push"](a||n,{forceOptimisticNavigation:!c})};d?l.default.startTransition(h):h()}(e,M,E,R,g,x,w,k,Boolean(O),G)},onMouseEnter(e){L||"function"!=typeof j||j(e),L&&a.props&&"function"==typeof a.props.onMouseEnter&&a.props.onMouseEnter(e),!(!G&&O)&&o.isLocalURL(E)&&h(M,E,R,{priority:!0})},onTouchStart(e){L||"function"!=typeof C||C(e),L&&a.props&&"function"==typeof a.props.onTouchStart&&a.props.onTouchStart(e),!(!G&&O)&&o.isLocalURL(E)&&h(M,E,R,{priority:!0})}};if(!L||v||"a"===a.type&&!("href"in a.props)){let Z=void 0!==k?k:M&&M.locale,H=M&&M.isLocaleDomain&&c.getDomainLocale(R,Z,M.locales,M.domainLocales);W.href=H||f.addBasePath(i.addLocale(R,Z,M&&M.defaultLocale))}return L?l.default.cloneElement(a,W):l.default.createElement("a",Object.assign({},T,W),n)});t.default=b,("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},9246:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.useIntersection=function(e){let{rootRef:t,rootMargin:n,disabled:s}=e,u=s||!l,[d,c]=a.useState(!1),[f,p]=a.useState(null);a.useEffect(()=>{if(l){if(!u&&!d&&f&&f.tagName){let e=function(e,t,n){let{id:a,observer:r,elements:l}=function(e){let t;let n={root:e.root||null,margin:e.rootMargin||""},a=i.find(e=>e.root===n.root&&e.margin===n.margin);if(a&&(t=o.get(a)))return t;let r=new Map,l=new IntersectionObserver(e=>{e.forEach(e=>{let t=r.get(e.target),n=e.isIntersecting||e.intersectionRatio>0;t&&n&&t(n)})},e);return t={id:n,observer:l,elements:r},i.push(n),o.set(n,t),t}(n);return l.set(e,t),r.observe(e),function(){if(l.delete(e),r.unobserve(e),0===l.size){r.disconnect(),o.delete(a);let t=i.findIndex(e=>e.root===a.root&&e.margin===a.margin);t>-1&&i.splice(t,1)}}}(f,e=>e&&c(e),{root:null==t?void 0:t.current,rootMargin:n});return e}}else if(!d){let a=r.requestIdleCallback(()=>c(!0));return()=>r.cancelIdleCallback(a)}},[f,u,n,t,d]);let h=a.useCallback(()=>{c(!1)},[]);return[p,d,h]};var a=n(7294),r=n(4686);let l="function"==typeof IntersectionObserver,o=new Map,i=[];("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},8245:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TemplateContext=t.GlobalLayoutRouterContext=t.LayoutRouterContext=t.AppRouterContext=void 0;var a=(0,n(2648).Z)(n(7294));let r=a.default.createContext(null);t.AppRouterContext=r;let l=a.default.createContext(null);t.LayoutRouterContext=l;let o=a.default.createContext(null);t.GlobalLayoutRouterContext=o;let i=a.default.createContext(null);t.TemplateContext=i},7645:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){let n=l.default,r=(null==t?void 0:t.suspense)?{}:{loading(e){let{error:t,isLoading:n,pastDelay:a}=e;return null}};if(e instanceof Promise?r.loader=()=>e:"function"==typeof e?r.loader=e:"object"==typeof e&&(r=a({},r,e)),(r=a({},r,t)).suspense&&(delete r.ssr,delete r.loading),r.loadableGenerated&&delete(r=a({},r,r.loadableGenerated)).loadableGenerated,"boolean"==typeof r.ssr&&!r.suspense){if(!r.ssr)return delete r.ssr,o(n,r);delete r.ssr}return n(r)},t.noSSR=o;var a=n(6495).Z,r=n(2648).Z,l=(r(n(7294)),r(n(4588)));function o(e,t){return delete t.webpack,delete t.modules,e(t)}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},3644:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.LoadableContext=void 0;var a=(0,n(2648).Z)(n(7294));let r=a.default.createContext(null);t.LoadableContext=r},4588:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=n(6495).Z,r=(0,n(2648).Z)(n(7294)),l=n(3644);let{useSyncExternalStore:o}=n(7294),i=[],s=[],u=!1;function d(e){let t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then(e=>(n.loading=!1,n.loaded=e,e)).catch(e=>{throw n.loading=!1,n.error=e,e}),n}class c{promise(){return this._res.promise}retry(){this._clearTimeouts(),this._res=this._loadFn(this._opts.loader),this._state={pastDelay:!1,timedOut:!1};let{_res:e,_opts:t}=this;e.loading&&("number"==typeof t.delay&&(0===t.delay?this._state.pastDelay=!0:this._delay=setTimeout(()=>{this._update({pastDelay:!0})},t.delay)),"number"==typeof t.timeout&&(this._timeout=setTimeout(()=>{this._update({timedOut:!0})},t.timeout))),this._res.promise.then(()=>{this._update({}),this._clearTimeouts()}).catch(e=>{this._update({}),this._clearTimeouts()}),this._update({})}_update(e){this._state=a({},this._state,{error:this._res.error,loaded:this._res.loaded,loading:this._res.loading},e),this._callbacks.forEach(e=>e())}_clearTimeouts(){clearTimeout(this._delay),clearTimeout(this._timeout)}getCurrentValue(){return this._state}subscribe(e){return this._callbacks.add(e),()=>{this._callbacks.delete(e)}}constructor(e,t){this._loadFn=e,this._opts=t,this._callbacks=new Set,this._delay=null,this._timeout=null,this.retry()}}function f(e){return function(e,t){let n=Object.assign({loader:null,loading:null,delay:200,timeout:null,webpack:null,modules:null,suspense:!1},t);n.suspense&&(n.lazy=r.default.lazy(n.loader));let i=null;function d(){if(!i){let t=new c(e,n);i={getCurrentValue:t.getCurrentValue.bind(t),subscribe:t.subscribe.bind(t),retry:t.retry.bind(t),promise:t.promise.bind(t)}}return i.promise()}if(!u){let f=n.webpack?n.webpack():n.modules;f&&s.push(e=>{for(let t of f)if(-1!==e.indexOf(t))return d()})}function p(){d();let e=r.default.useContext(l.LoadableContext);e&&Array.isArray(n.modules)&&n.modules.forEach(t=>{e(t)})}let h=n.suspense?function(e,t){return p(),r.default.createElement(n.lazy,a({},e,{ref:t}))}:function(e,t){p();let a=o(i.subscribe,i.getCurrentValue,i.getCurrentValue);return r.default.useImperativeHandle(t,()=>({retry:i.retry}),[]),r.default.useMemo(()=>{var t;return a.loading||a.error?r.default.createElement(n.loading,{isLoading:a.loading,pastDelay:a.pastDelay,timedOut:a.timedOut,error:a.error,retry:i.retry}):a.loaded?r.default.createElement((t=a.loaded)&&t.__esModule?t.default:t,e):null},[e,a])};return h.preload=()=>d(),h.displayName="LoadableComponent",r.default.forwardRef(h)}(d,e)}function p(e,t){let n=[];for(;e.length;){let a=e.pop();n.push(a(t))}return Promise.all(n).then(()=>{if(e.length)return p(e,t)})}f.preloadAll=()=>new Promise((e,t)=>{p(i).then(e,t)}),f.preloadReady=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return new Promise(t=>{let n=()=>(u=!0,t());p(s,e).then(n,n)})},window.__NEXT_PRELOADREADY=f.preloadReady,t.default=f},6505:function(e,t,n){"use strict";n.r(t);var a=n(5893),r=n(9008),l=n.n(r),o=n(1664),i=n.n(o),s=n(1163),u=n(7294);n(4112);var d=n(6988),c=n.n(d),f=n(1958),p=n(3454);let h="WebGPU Samples",b=e=>{let{Component:t,pageProps:n}=e,r=(0,s.useRouter)(),o=Object.keys(f.pages),[d,b]=(0,u.useState)(!1),m=r.asPath.match(/(\?wgsl=[01])#(\S+)/);if(m){let _=m[2];return r.replace("/samples/".concat(_)),(0,a.jsx)(a.Fragment,{})}return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(l(),{children:[(0,a.jsx)("title",{children:h}),(0,a.jsx)("meta",{name:"description",content:"The WebGPU Samples are a set of samples demonstrating the use of the WebGPU API."}),(0,a.jsx)("meta",{name:"viewport",content:"width=device-width, initial-scale=1, shrink-to-fit=no"})]}),(0,a.jsxs)("div",{className:c().wrapper,children:[(0,a.jsxs)("nav",{className:"".concat(c().panel," ").concat(c().container),"data-expanded":d,children:[(0,a.jsxs)("h1",{children:[(0,a.jsx)(i(),{href:"/",children:h}),(0,a.jsx)("div",{className:c().expand,onClick(){b(!d)}})]}),(0,a.jsxs)("div",{className:c().panelContents,children:[(0,a.jsx)("a",{href:"https://github.com/".concat("webgpu/webgpu-samples"),children:"Github"}),(0,a.jsx)("hr",{}),(0,a.jsx)("ul",{className:c().exampleList,children:o.map(e=>{let t="/samples/[slug]"===r.pathname&&r.query.slug===e?c().selected:void 0;return(0,a.jsx)("li",{className:t,onMouseOver(){f.pages[e].render.preload()},children:(0,a.jsx)(i(),{href:"/samples/".concat(e),onClick(){b(!1)},children:e})},e)})}),(0,a.jsx)("hr",{}),(0,a.jsx)("h3",{children:"Other Pages"}),(0,a.jsx)("ul",{className:c().exampleList,children:(0,a.jsx)("li",{children:(0,a.jsx)("a",{rel:"noreferrer",target:"_blank",href:"".concat(p.env.BASE_PATH||"","/workload-simulator.html"),children:"Workload Simulator ↗️"})})})]})]}),(0,a.jsx)(t,{...n})]})]})};t.default=b},1958:function(e,t,n){"use strict";n.r(t),n.d(t,{__N_SSG:function(){return o},pages:function(){return i}});var a=n(5893),r=n(5152),l=n.n(r),o=!0;let i={helloTriangle:l()(()=>Promise.all([n.e(126),n.e(82),n.e(607)]).then(n.bind(n,6607)),{loadableGenerated:{webpack:()=>[6607]}}),helloTriangleMSAA:l()(()=>Promise.all([n.e(126),n.e(82),n.e(198)]).then(n.bind(n,1198)),{loadableGenerated:{webpack:()=>[1198]}}),resizeCanvas:l()(()=>Promise.all([n.e(126),n.e(82),n.e(565)]).then(n.bind(n,8565)),{loadableGenerated:{webpack:()=>[8565]}}),rotatingCube:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(15)]).then(n.bind(n,9015)),{loadableGenerated:{webpack:()=>[9015]}}),twoCubes:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(710)]).then(n.bind(n,5710)),{loadableGenerated:{webpack:()=>[5710]}}),texturedCube:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(613)]).then(n.bind(n,613)),{loadableGenerated:{webpack:()=>[613]}}),instancedCube:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(621)]).then(n.bind(n,8621)),{loadableGenerated:{webpack:()=>[8621]}}),fractalCube:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(103)]).then(n.bind(n,5103)),{loadableGenerated:{webpack:()=>[5103]}}),cameras:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(878)]).then(n.bind(n,3878)),{loadableGenerated:{webpack:()=>[3878]}}),cubemap:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(432)]).then(n.bind(n,1432)),{loadableGenerated:{webpack:()=>[1432]}}),computeBoids:l()(()=>Promise.all([n.e(126),n.e(82),n.e(752)]).then(n.bind(n,2752)),{loadableGenerated:{webpack:()=>[2752]}}),animometer:l()(()=>Promise.all([n.e(126),n.e(82),n.e(841)]).then(n.bind(n,841)),{loadableGenerated:{webpack:()=>[841]}}),videoUploading:l()(()=>Promise.all([n.e(126),n.e(82),n.e(677)]).then(n.bind(n,6677)),{loadableGenerated:{webpack:()=>[6677]}}),videoUploadingWebCodecs:l()(()=>Promise.all([n.e(126),n.e(82),n.e(31)]).then(n.bind(n,7031)),{loadableGenerated:{webpack:()=>[7031]}}),samplerParameters:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(624)]).then(n.bind(n,8624)),{loadableGenerated:{webpack:()=>[8624]}}),imageBlur:l()(()=>Promise.all([n.e(126),n.e(82),n.e(770)]).then(n.bind(n,1770)),{loadableGenerated:{webpack:()=>[1770]}}),shadowMapping:l()(()=>Promise.all([n.e(126),n.e(746),n.e(667),n.e(82),n.e(342)]).then(n.bind(n,2342)),{loadableGenerated:{webpack:()=>[2342]}}),reversedZ:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(588)]).then(n.bind(n,7502)),{loadableGenerated:{webpack:()=>[7502]}}),deferredRendering:l()(()=>Promise.all([n.e(126),n.e(746),n.e(667),n.e(82),n.e(704)]).then(n.bind(n,9704)),{loadableGenerated:{webpack:()=>[9704]}}),particles:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(167)]).then(n.bind(n,6167)),{loadableGenerated:{webpack:()=>[6167]}}),cornell:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(874)]).then(n.bind(n,6874)),{loadableGenerated:{webpack:()=>[6874]}}),gameOfLife:l()(()=>Promise.all([n.e(126),n.e(82),n.e(391)]).then(n.bind(n,7391)),{loadableGenerated:{webpack:()=>[7391]}}),renderBundles:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(428)]).then(n.bind(n,3428)),{loadableGenerated:{webpack:()=>[3428]}}),worker:l()(()=>Promise.all([n.e(126),n.e(82),n.e(78)]).then(n.bind(n,6078)),{loadableGenerated:{webpack:()=>[6078]}}),"A-buffer":l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(73)]).then(n.bind(n,3073)),{loadableGenerated:{webpack:()=>[3073]}}),bitonicSort:l()(()=>Promise.all([n.e(126),n.e(82),n.e(112)]).then(n.bind(n,8112)),{loadableGenerated:{webpack:()=>[8112]}}),normalMap:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(118)]).then(n.bind(n,7118)),{loadableGenerated:{webpack:()=>[7118]}})};t.default=function(e){let{slug:t}=e,n=i[t];return(0,a.jsx)(n,{})}},6988:function(e){e.exports={container:"MainLayout_container__l_Vkn",wrapper:"MainLayout_wrapper__eI_HE",panel:"MainLayout_panel__GdjKj",exampleList:"MainLayout_exampleList__FHCmd",selected:"MainLayout_selected__Yjoh0",expand:"MainLayout_expand__FEWWW",exampleLink:"MainLayout_exampleLink__qX1DA",panelContents:"MainLayout_panelContents__w1BWs"}},4112:function(){},7663:function(e){!function(){var t={229:function(e){var t,n,a,r=e.exports={};function l(){throw Error("setTimeout has not been defined")}function o(){throw Error("clearTimeout has not been defined")}function i(e){if(t===setTimeout)return setTimeout(e,0);if((t===l||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(a){try{return t.call(null,e,0)}catch(n){return t.call(this,e,0)}}}!function(){try{t="function"==typeof setTimeout?setTimeout:l}catch(e){t=l}try{n="function"==typeof clearTimeout?clearTimeout:o}catch(a){n=o}}();var s=[],u=!1,d=-1;function c(){u&&a&&(u=!1,a.length?s=a.concat(s):d=-1,s.length&&f())}function f(){if(!u){var e=i(c);u=!0;for(var t=s.length;t;){for(a=s,s=[];++d1)for(var n=1;n{});let r=a&&void 0!==a.locale?a.locale:e&&e.locale;p[t+"%"+n+(r?"%"+r:"")]=!0}let b=l.default.forwardRef(function(e,t){let n,a;let{href:b,as:m,children:_,prefetch:y,passHref:v,replace:g,shallow:x,scroll:w,locale:k,onClick:P,onMouseEnter:j,onTouchStart:C,legacyBehavior:L=!0!==Boolean(!0)}=e,T=r(e,["href","as","children","prefetch","passHref","replace","shallow","scroll","locale","onClick","onMouseEnter","onTouchStart","legacyBehavior"]);n=_,L&&("string"==typeof n||"number"==typeof n)&&(n=l.default.createElement("a",null,n));let G=!1!==y,M=l.default.useContext(s.RouterContext),O=l.default.useContext(u.AppRouterContext);O&&(M=O);let{href:E,as:R}=l.default.useMemo(()=>{let[e,t]=o.resolveHref(M,b,!0);return{href:e,as:m?o.resolveHref(M,m):t||e}},[M,b,m]),S=l.default.useRef(E),A=l.default.useRef(R);L&&(a=l.default.Children.only(n));let N=L?a&&"object"==typeof a&&a.ref:t,[D,I,U]=d.useIntersection({rootMargin:"200px"}),B=l.default.useCallback(e=>{(A.current!==R||S.current!==E)&&(U(),A.current=R,S.current=E),D(e),N&&("function"==typeof N?N(e):"object"==typeof N&&(N.current=e))},[R,N,E,U,D]);l.default.useEffect(()=>{let e=I&&G&&o.isLocalURL(E),t=void 0!==k?k:M&&M.locale,n=p[E+"%"+R+(t?"%"+t:"")];e&&!n&&h(M,E,R,{locale:t})},[R,E,I,k,G,M]);let W={ref:B,onClick(e){L||"function"!=typeof P||P(e),L&&a.props&&"function"==typeof a.props.onClick&&a.props.onClick(e),e.defaultPrevented||function(e,t,n,a,r,i,s,u,d,c){let{nodeName:f}=e.currentTarget,p="A"===f.toUpperCase();if(p&&(function(e){let{target:t}=e.currentTarget;return t&&"_self"!==t||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||e.nativeEvent&&2===e.nativeEvent.which}(e)||!o.isLocalURL(n)))return;e.preventDefault();let h=()=>{"beforePopState"in t?t[r?"replace":"push"](n,a,{shallow:i,locale:u,scroll:s}):t[r?"replace":"push"](a||n,{forceOptimisticNavigation:!c})};d?l.default.startTransition(h):h()}(e,M,E,R,g,x,w,k,Boolean(O),G)},onMouseEnter(e){L||"function"!=typeof j||j(e),L&&a.props&&"function"==typeof a.props.onMouseEnter&&a.props.onMouseEnter(e),!(!G&&O)&&o.isLocalURL(E)&&h(M,E,R,{priority:!0})},onTouchStart(e){L||"function"!=typeof C||C(e),L&&a.props&&"function"==typeof a.props.onTouchStart&&a.props.onTouchStart(e),!(!G&&O)&&o.isLocalURL(E)&&h(M,E,R,{priority:!0})}};if(!L||v||"a"===a.type&&!("href"in a.props)){let Z=void 0!==k?k:M&&M.locale,H=M&&M.isLocaleDomain&&c.getDomainLocale(R,Z,M.locales,M.domainLocales);W.href=H||f.addBasePath(i.addLocale(R,Z,M&&M.defaultLocale))}return L?l.default.cloneElement(a,W):l.default.createElement("a",Object.assign({},T,W),n)});t.default=b,("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},9246:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.useIntersection=function(e){let{rootRef:t,rootMargin:n,disabled:s}=e,u=s||!l,[d,c]=a.useState(!1),[f,p]=a.useState(null);a.useEffect(()=>{if(l){if(!u&&!d&&f&&f.tagName){let e=function(e,t,n){let{id:a,observer:r,elements:l}=function(e){let t;let n={root:e.root||null,margin:e.rootMargin||""},a=i.find(e=>e.root===n.root&&e.margin===n.margin);if(a&&(t=o.get(a)))return t;let r=new Map,l=new IntersectionObserver(e=>{e.forEach(e=>{let t=r.get(e.target),n=e.isIntersecting||e.intersectionRatio>0;t&&n&&t(n)})},e);return t={id:n,observer:l,elements:r},i.push(n),o.set(n,t),t}(n);return l.set(e,t),r.observe(e),function(){if(l.delete(e),r.unobserve(e),0===l.size){r.disconnect(),o.delete(a);let t=i.findIndex(e=>e.root===a.root&&e.margin===a.margin);t>-1&&i.splice(t,1)}}}(f,e=>e&&c(e),{root:null==t?void 0:t.current,rootMargin:n});return e}}else if(!d){let a=r.requestIdleCallback(()=>c(!0));return()=>r.cancelIdleCallback(a)}},[f,u,n,t,d]);let h=a.useCallback(()=>{c(!1)},[]);return[p,d,h]};var a=n(7294),r=n(4686);let l="function"==typeof IntersectionObserver,o=new Map,i=[];("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},8245:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.TemplateContext=t.GlobalLayoutRouterContext=t.LayoutRouterContext=t.AppRouterContext=void 0;var a=(0,n(2648).Z)(n(7294));let r=a.default.createContext(null);t.AppRouterContext=r;let l=a.default.createContext(null);t.LayoutRouterContext=l;let o=a.default.createContext(null);t.GlobalLayoutRouterContext=o;let i=a.default.createContext(null);t.TemplateContext=i},7645:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){let n=l.default,r=(null==t?void 0:t.suspense)?{}:{loading(e){let{error:t,isLoading:n,pastDelay:a}=e;return null}};if(e instanceof Promise?r.loader=()=>e:"function"==typeof e?r.loader=e:"object"==typeof e&&(r=a({},r,e)),(r=a({},r,t)).suspense&&(delete r.ssr,delete r.loading),r.loadableGenerated&&delete(r=a({},r,r.loadableGenerated)).loadableGenerated,"boolean"==typeof r.ssr&&!r.suspense){if(!r.ssr)return delete r.ssr,o(n,r);delete r.ssr}return n(r)},t.noSSR=o;var a=n(6495).Z,r=n(2648).Z,l=(r(n(7294)),r(n(4588)));function o(e,t){return delete t.webpack,delete t.modules,e(t)}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},3644:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.LoadableContext=void 0;var a=(0,n(2648).Z)(n(7294));let r=a.default.createContext(null);t.LoadableContext=r},4588:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=n(6495).Z,r=(0,n(2648).Z)(n(7294)),l=n(3644);let{useSyncExternalStore:o}=n(7294),i=[],s=[],u=!1;function d(e){let t=e(),n={loading:!0,loaded:null,error:null};return n.promise=t.then(e=>(n.loading=!1,n.loaded=e,e)).catch(e=>{throw n.loading=!1,n.error=e,e}),n}class c{promise(){return this._res.promise}retry(){this._clearTimeouts(),this._res=this._loadFn(this._opts.loader),this._state={pastDelay:!1,timedOut:!1};let{_res:e,_opts:t}=this;e.loading&&("number"==typeof t.delay&&(0===t.delay?this._state.pastDelay=!0:this._delay=setTimeout(()=>{this._update({pastDelay:!0})},t.delay)),"number"==typeof t.timeout&&(this._timeout=setTimeout(()=>{this._update({timedOut:!0})},t.timeout))),this._res.promise.then(()=>{this._update({}),this._clearTimeouts()}).catch(e=>{this._update({}),this._clearTimeouts()}),this._update({})}_update(e){this._state=a({},this._state,{error:this._res.error,loaded:this._res.loaded,loading:this._res.loading},e),this._callbacks.forEach(e=>e())}_clearTimeouts(){clearTimeout(this._delay),clearTimeout(this._timeout)}getCurrentValue(){return this._state}subscribe(e){return this._callbacks.add(e),()=>{this._callbacks.delete(e)}}constructor(e,t){this._loadFn=e,this._opts=t,this._callbacks=new Set,this._delay=null,this._timeout=null,this.retry()}}function f(e){return function(e,t){let n=Object.assign({loader:null,loading:null,delay:200,timeout:null,webpack:null,modules:null,suspense:!1},t);n.suspense&&(n.lazy=r.default.lazy(n.loader));let i=null;function d(){if(!i){let t=new c(e,n);i={getCurrentValue:t.getCurrentValue.bind(t),subscribe:t.subscribe.bind(t),retry:t.retry.bind(t),promise:t.promise.bind(t)}}return i.promise()}if(!u){let f=n.webpack?n.webpack():n.modules;f&&s.push(e=>{for(let t of f)if(-1!==e.indexOf(t))return d()})}function p(){d();let e=r.default.useContext(l.LoadableContext);e&&Array.isArray(n.modules)&&n.modules.forEach(t=>{e(t)})}let h=n.suspense?function(e,t){return p(),r.default.createElement(n.lazy,a({},e,{ref:t}))}:function(e,t){p();let a=o(i.subscribe,i.getCurrentValue,i.getCurrentValue);return r.default.useImperativeHandle(t,()=>({retry:i.retry}),[]),r.default.useMemo(()=>{var t;return a.loading||a.error?r.default.createElement(n.loading,{isLoading:a.loading,pastDelay:a.pastDelay,timedOut:a.timedOut,error:a.error,retry:i.retry}):a.loaded?r.default.createElement((t=a.loaded)&&t.__esModule?t.default:t,e):null},[e,a])};return h.preload=()=>d(),h.displayName="LoadableComponent",r.default.forwardRef(h)}(d,e)}function p(e,t){let n=[];for(;e.length;){let a=e.pop();n.push(a(t))}return Promise.all(n).then(()=>{if(e.length)return p(e,t)})}f.preloadAll=()=>new Promise((e,t)=>{p(i).then(e,t)}),f.preloadReady=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return new Promise(t=>{let n=()=>(u=!0,t());p(s,e).then(n,n)})},window.__NEXT_PRELOADREADY=f.preloadReady,t.default=f},6505:function(e,t,n){"use strict";n.r(t);var a=n(5893),r=n(9008),l=n.n(r),o=n(1664),i=n.n(o),s=n(1163),u=n(7294);n(4112);var d=n(6988),c=n.n(d),f=n(1958),p=n(3454);let h="WebGPU Samples",b=e=>{let{Component:t,pageProps:n}=e,r=(0,s.useRouter)(),o=Object.keys(f.pages),[d,b]=(0,u.useState)(!1),m=r.asPath.match(/(\?wgsl=[01])#(\S+)/);if(m){let _=m[2];return r.replace("/samples/".concat(_)),(0,a.jsx)(a.Fragment,{})}return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(l(),{children:[(0,a.jsx)("title",{children:h}),(0,a.jsx)("meta",{name:"description",content:"The WebGPU Samples are a set of samples demonstrating the use of the WebGPU API."}),(0,a.jsx)("meta",{name:"viewport",content:"width=device-width, initial-scale=1, shrink-to-fit=no"})]}),(0,a.jsxs)("div",{className:c().wrapper,children:[(0,a.jsxs)("nav",{className:"".concat(c().panel," ").concat(c().container),"data-expanded":d,children:[(0,a.jsxs)("h1",{children:[(0,a.jsx)(i(),{href:"/",children:h}),(0,a.jsx)("div",{className:c().expand,onClick(){b(!d)}})]}),(0,a.jsxs)("div",{className:c().panelContents,children:[(0,a.jsx)("a",{href:"https://github.com/".concat("webgpu/webgpu-samples"),children:"Github"}),(0,a.jsx)("hr",{}),(0,a.jsx)("ul",{className:c().exampleList,children:o.map(e=>{let t="/samples/[slug]"===r.pathname&&r.query.slug===e?c().selected:void 0;return(0,a.jsx)("li",{className:t,onMouseOver(){f.pages[e].render.preload()},children:(0,a.jsx)(i(),{href:"/samples/".concat(e),onClick(){b(!1)},children:e})},e)})}),(0,a.jsx)("hr",{}),(0,a.jsx)("h3",{children:"Other Pages"}),(0,a.jsx)("ul",{className:c().exampleList,children:(0,a.jsx)("li",{children:(0,a.jsx)("a",{rel:"noreferrer",target:"_blank",href:"".concat(p.env.BASE_PATH||"","/workload-simulator.html"),children:"Workload Simulator ↗️"})})})]})]}),(0,a.jsx)(t,{...n})]})]})};t.default=b},1958:function(e,t,n){"use strict";n.r(t),n.d(t,{__N_SSG:function(){return o},pages:function(){return i}});var a=n(5893),r=n(5152),l=n.n(r),o=!0;let i={helloTriangle:l()(()=>Promise.all([n.e(126),n.e(82),n.e(607)]).then(n.bind(n,6607)),{loadableGenerated:{webpack:()=>[6607]}}),helloTriangleMSAA:l()(()=>Promise.all([n.e(126),n.e(82),n.e(198)]).then(n.bind(n,1198)),{loadableGenerated:{webpack:()=>[1198]}}),resizeCanvas:l()(()=>Promise.all([n.e(126),n.e(82),n.e(565)]).then(n.bind(n,8565)),{loadableGenerated:{webpack:()=>[8565]}}),rotatingCube:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(15)]).then(n.bind(n,9015)),{loadableGenerated:{webpack:()=>[9015]}}),twoCubes:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(710)]).then(n.bind(n,5710)),{loadableGenerated:{webpack:()=>[5710]}}),texturedCube:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(613)]).then(n.bind(n,613)),{loadableGenerated:{webpack:()=>[613]}}),instancedCube:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(621)]).then(n.bind(n,8621)),{loadableGenerated:{webpack:()=>[8621]}}),fractalCube:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(103)]).then(n.bind(n,5103)),{loadableGenerated:{webpack:()=>[5103]}}),cameras:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(878)]).then(n.bind(n,3878)),{loadableGenerated:{webpack:()=>[3878]}}),cubemap:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(432)]).then(n.bind(n,1432)),{loadableGenerated:{webpack:()=>[1432]}}),computeBoids:l()(()=>Promise.all([n.e(126),n.e(82),n.e(752)]).then(n.bind(n,2752)),{loadableGenerated:{webpack:()=>[2752]}}),animometer:l()(()=>Promise.all([n.e(126),n.e(82),n.e(841)]).then(n.bind(n,841)),{loadableGenerated:{webpack:()=>[841]}}),videoUploading:l()(()=>Promise.all([n.e(126),n.e(82),n.e(677)]).then(n.bind(n,6677)),{loadableGenerated:{webpack:()=>[6677]}}),videoUploadingWebCodecs:l()(()=>Promise.all([n.e(126),n.e(82),n.e(31)]).then(n.bind(n,7031)),{loadableGenerated:{webpack:()=>[7031]}}),samplerParameters:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(624)]).then(n.bind(n,8624)),{loadableGenerated:{webpack:()=>[8624]}}),imageBlur:l()(()=>Promise.all([n.e(126),n.e(82),n.e(770)]).then(n.bind(n,1770)),{loadableGenerated:{webpack:()=>[1770]}}),shadowMapping:l()(()=>Promise.all([n.e(126),n.e(746),n.e(667),n.e(82),n.e(342)]).then(n.bind(n,2342)),{loadableGenerated:{webpack:()=>[2342]}}),reversedZ:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(588)]).then(n.bind(n,7502)),{loadableGenerated:{webpack:()=>[7502]}}),deferredRendering:l()(()=>Promise.all([n.e(126),n.e(746),n.e(667),n.e(82),n.e(704)]).then(n.bind(n,9704)),{loadableGenerated:{webpack:()=>[9704]}}),particles:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(167)]).then(n.bind(n,6167)),{loadableGenerated:{webpack:()=>[6167]}}),cornell:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(874)]).then(n.bind(n,6874)),{loadableGenerated:{webpack:()=>[6874]}}),gameOfLife:l()(()=>Promise.all([n.e(126),n.e(82),n.e(391)]).then(n.bind(n,7391)),{loadableGenerated:{webpack:()=>[7391]}}),renderBundles:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(428)]).then(n.bind(n,3428)),{loadableGenerated:{webpack:()=>[3428]}}),worker:l()(()=>Promise.all([n.e(126),n.e(82),n.e(78)]).then(n.bind(n,6078)),{loadableGenerated:{webpack:()=>[6078]}}),"A-buffer":l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(73)]).then(n.bind(n,3073)),{loadableGenerated:{webpack:()=>[3073]}}),bitonicSort:l()(()=>Promise.all([n.e(126),n.e(82),n.e(16)]).then(n.bind(n,5016)),{loadableGenerated:{webpack:()=>[5016]}}),normalMap:l()(()=>Promise.all([n.e(126),n.e(746),n.e(82),n.e(118)]).then(n.bind(n,7118)),{loadableGenerated:{webpack:()=>[7118]}})};t.default=function(e){let{slug:t}=e,n=i[t];return(0,a.jsx)(n,{})}},6988:function(e){e.exports={container:"MainLayout_container__l_Vkn",wrapper:"MainLayout_wrapper__eI_HE",panel:"MainLayout_panel__GdjKj",exampleList:"MainLayout_exampleList__FHCmd",selected:"MainLayout_selected__Yjoh0",expand:"MainLayout_expand__FEWWW",exampleLink:"MainLayout_exampleLink__qX1DA",panelContents:"MainLayout_panelContents__w1BWs"}},4112:function(){},7663:function(e){!function(){var t={229:function(e){var t,n,a,r=e.exports={};function l(){throw Error("setTimeout has not been defined")}function o(){throw Error("clearTimeout has not been defined")}function i(e){if(t===setTimeout)return setTimeout(e,0);if((t===l||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(a){try{return t.call(null,e,0)}catch(n){return t.call(this,e,0)}}}!function(){try{t="function"==typeof setTimeout?setTimeout:l}catch(e){t=l}try{n="function"==typeof clearTimeout?clearTimeout:o}catch(a){n=o}}();var s=[],u=!1,d=-1;function c(){u&&a&&(u=!1,a.length?s=a.concat(s):d=-1,s.length&&f())}function f(){if(!u){var e=i(c);u=!0;for(var t=s.length;t;){for(a=s,s=[];++d1)for(var n=1;n0&&e[a-1][2]>f;a--)e[a]=e[a-1];e[a]=[r,n,f];return}for(var o=1/0,a=0;a=f&&Object.keys(l.O).every(function(e){return l.O[e](r[i])})?r.splice(i--,1):(c=!1,f0&&e[f-1][2]>a;f--)e[f]=e[f-1];e[f]=[r,n,a];return}for(var o=1/0,f=0;f=a&&Object.keys(l.O).every(function(e){return l.O[e](r[i])})?r.splice(i--,1):(c=!1,aWebGPU Samples \ No newline at end of file +WebGPU Samples \ No newline at end of file diff --git a/samples/A-buffer.html b/samples/A-buffer.html index 214c9f41..574985f9 100644 --- a/samples/A-buffer.html +++ b/samples/A-buffer.html @@ -10,6 +10,6 @@ } A-Buffer - WebGPU Samples

A-Buffer

See it on Github!

Demonstrates order independent transparency using a per-pixel + limiting memory usage (when required)."/>

\ No newline at end of file + limiting memory usage (when required).

\ No newline at end of file diff --git a/samples/animometer.html b/samples/animometer.html index 54565e7f..be721ff7 100644 --- a/samples/animometer.html +++ b/samples/animometer.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Animometer - WebGPU Samples \ No newline at end of file + Animometer - WebGPU Samples \ No newline at end of file diff --git a/samples/bitonicSort.html b/samples/bitonicSort.html index 99cb63d2..6b3a5618 100644 --- a/samples/bitonicSort.html +++ b/samples/bitonicSort.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Bitonic Sort - WebGPU Samples

Bitonic Sort

See it on Github!

A naive bitonic sort algorithm executed on the GPU, based on tgfrerer's implementation at poniesandlight.co.uk/reflect/bitonic_merge_sort/. Each invocation of the bitonic sort shader dispatches a workgroup containing elements/2 threads. The GUI's Execution Information folder contains information about the sort's current state. The visualizer displays the sort's results as colored cells sorted from brightest to darkest.

\ No newline at end of file + Bitonic Sort - WebGPU Samples

Bitonic Sort

See it on Github!

A naive bitonic sort algorithm executed on the GPU, based on tgfrerer's implementation at poniesandlight.co.uk/reflect/bitonic_merge_sort/. Each invocation of the bitonic sort shader dispatches a workgroup containing elements/2 threads. The GUI's Execution Information folder contains information about the sort's current state. The visualizer displays the sort's results as colored cells sorted from brightest to darkest.

\ No newline at end of file diff --git a/samples/cameras.html b/samples/cameras.html index 6615f1dc..03ff5a47 100644 --- a/samples/cameras.html +++ b/samples/cameras.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Cameras - WebGPU Samples \ No newline at end of file + Cameras - WebGPU Samples \ No newline at end of file diff --git a/samples/computeBoids.html b/samples/computeBoids.html index 5cc3d7e1..f66813b3 100644 --- a/samples/computeBoids.html +++ b/samples/computeBoids.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Compute Boids - WebGPU Samples \ No newline at end of file + Compute Boids - WebGPU Samples \ No newline at end of file diff --git a/samples/cornell.html b/samples/cornell.html index 421e9e04..a3592d21 100644 --- a/samples/cornell.html +++ b/samples/cornell.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Cornell box - WebGPU Samples \ No newline at end of file + Cornell box - WebGPU Samples \ No newline at end of file diff --git a/samples/cubemap.html b/samples/cubemap.html index ecd59df6..6a3a7413 100644 --- a/samples/cubemap.html +++ b/samples/cubemap.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Cubemap - WebGPU Samples \ No newline at end of file + Cubemap - WebGPU Samples \ No newline at end of file diff --git a/samples/deferredRendering.html b/samples/deferredRendering.html index 8d83f7b4..33aea27f 100644 --- a/samples/deferredRendering.html +++ b/samples/deferredRendering.html @@ -16,7 +16,7 @@ We also update light position in a compute shader, where further operations like tile/cluster culling could happen. The debug view shows the depth buffer on the left (flipped and scaled a bit to make it more visible), the normal G buffer in the middle, and the albedo G-buffer on the right side of the screen. - "/>

Deferred Rendering

See it on Github!

This example shows how to do deferred rendering with webgpu. + "/>

Deferred Rendering

See it on Github!

This example shows how to do deferred rendering with webgpu. Render geometry info to multiple targets in the gBuffers in the first pass. In this sample we have 2 gBuffers for normals and albedo, along with a depth texture. And then do the lighting in a second pass with per fragment data read from gBuffers so it's independent of scene complexity. @@ -24,4 +24,4 @@ We also update light position in a compute shader, where further operations like tile/cluster culling could happen. The debug view shows the depth buffer on the left (flipped and scaled a bit to make it more visible), the normal G buffer in the middle, and the albedo G-buffer on the right side of the screen. -

\ No newline at end of file +

\ No newline at end of file diff --git a/samples/fractalCube.html b/samples/fractalCube.html index ced8075e..8c5928a3 100644 --- a/samples/fractalCube.html +++ b/samples/fractalCube.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Fractal Cube - WebGPU Samples \ No newline at end of file + Fractal Cube - WebGPU Samples \ No newline at end of file diff --git a/samples/gameOfLife.html b/samples/gameOfLife.html index 34605d3e..d6ae5fcb 100644 --- a/samples/gameOfLife.html +++ b/samples/gameOfLife.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Conway's Game of Life - WebGPU Samples \ No newline at end of file + Conway's Game of Life - WebGPU Samples \ No newline at end of file diff --git a/samples/helloTriangle.html b/samples/helloTriangle.html index 12179778..f614d6b5 100644 --- a/samples/helloTriangle.html +++ b/samples/helloTriangle.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Hello Triangle - WebGPU Samples \ No newline at end of file + Hello Triangle - WebGPU Samples \ No newline at end of file diff --git a/samples/helloTriangleMSAA.html b/samples/helloTriangleMSAA.html index a26e17e4..c1e4aaa9 100644 --- a/samples/helloTriangleMSAA.html +++ b/samples/helloTriangleMSAA.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Hello Triangle MSAA - WebGPU Samples \ No newline at end of file + Hello Triangle MSAA - WebGPU Samples \ No newline at end of file diff --git a/samples/imageBlur.html b/samples/imageBlur.html index 163df691..6c11ad72 100644 --- a/samples/imageBlur.html +++ b/samples/imageBlur.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Image Blur - WebGPU Samples \ No newline at end of file + Image Blur - WebGPU Samples \ No newline at end of file diff --git a/samples/instancedCube.html b/samples/instancedCube.html index 15fa21df..150c0bfb 100644 --- a/samples/instancedCube.html +++ b/samples/instancedCube.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Instanced Cube - WebGPU Samples \ No newline at end of file + Instanced Cube - WebGPU Samples \ No newline at end of file diff --git a/samples/normalMap.html b/samples/normalMap.html index c08ccb66..11efad89 100644 --- a/samples/normalMap.html +++ b/samples/normalMap.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Normal Mapping - WebGPU Samples \ No newline at end of file + Normal Mapping - WebGPU Samples \ No newline at end of file diff --git a/samples/particles.html b/samples/particles.html index bcabe989..43e3ddc7 100644 --- a/samples/particles.html +++ b/samples/particles.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Particles - WebGPU Samples \ No newline at end of file + Particles - WebGPU Samples \ No newline at end of file diff --git a/samples/renderBundles.html b/samples/renderBundles.html index e6fc2b9a..d1bff006 100644 --- a/samples/renderBundles.html +++ b/samples/renderBundles.html @@ -11,7 +11,7 @@ Render Bundles - WebGPU Samples

Render Bundles

See it on Github!

This example shows how to use render bundles. It renders a large number of + of instancing to reduce draw overhead.)"/>

Render Bundles

See it on Github!

This example shows how to use render bundles. It renders a large number of meshes individually as a proxy for a more complex scene in order to demonstrate the reduction in JavaScript time spent to issue render commands. (Typically a scene like this would make use - of instancing to reduce draw overhead.)

\ No newline at end of file + of instancing to reduce draw overhead.)

\ No newline at end of file diff --git a/samples/resizeCanvas.html b/samples/resizeCanvas.html index 302bb5a6..070389c4 100644 --- a/samples/resizeCanvas.html +++ b/samples/resizeCanvas.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Resize Canvas - WebGPU Samples \ No newline at end of file + Resize Canvas - WebGPU Samples \ No newline at end of file diff --git a/samples/reversedZ.html b/samples/reversedZ.html index 613d0c8a..0e824021 100644 --- a/samples/reversedZ.html +++ b/samples/reversedZ.html @@ -17,7 +17,7 @@ Related reading: https://developer.nvidia.com/content/depth-precision-visualized https://thxforthefish.com/posts/reverse_z/ - "/>

Reversed Z

See it on Github!

This example shows the use of reversed z technique for better utilization of depth buffer precision. + "/>

Reversed Z

See it on Github!

This example shows the use of reversed z technique for better utilization of depth buffer precision. The left column uses regular method, while the right one uses reversed z technique. Both are using depth32float as their depth buffer format. A set of red and green planes are positioned very close to each other. Higher sets are placed further from camera (and are scaled for better visual purpose). @@ -26,4 +26,4 @@ Related reading: https://developer.nvidia.com/content/depth-precision-visualized https://thxforthefish.com/posts/reverse_z/ -

\ No newline at end of file +

\ No newline at end of file diff --git a/samples/rotatingCube.html b/samples/rotatingCube.html index b6942c99..77e22589 100644 --- a/samples/rotatingCube.html +++ b/samples/rotatingCube.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Rotating Cube - WebGPU Samples \ No newline at end of file + Rotating Cube - WebGPU Samples \ No newline at end of file diff --git a/samples/samplerParameters.html b/samples/samplerParameters.html index 98724344..b63015eb 100644 --- a/samples/samplerParameters.html +++ b/samples/samplerParameters.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Sampler Parameters - WebGPU Samples

Sampler Parameters

See it on Github!

Visualizes what all the sampler parameters do. Shows a textured plane at various scales (rotated, head-on, in perspective, and in vanishing perspective). The bottom-right view shows the raw contents of the 4 mipmap levels of the test texture (16x16, 8x8, 4x4, and 2x2).

\ No newline at end of file + Sampler Parameters - WebGPU Samples

Sampler Parameters

See it on Github!

Visualizes what all the sampler parameters do. Shows a textured plane at various scales (rotated, head-on, in perspective, and in vanishing perspective). The bottom-right view shows the raw contents of the 4 mipmap levels of the test texture (16x16, 8x8, 4x4, and 2x2).

\ No newline at end of file diff --git a/samples/shadowMapping.html b/samples/shadowMapping.html index 1df50fdf..a356ba0d 100644 --- a/samples/shadowMapping.html +++ b/samples/shadowMapping.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Shadow Mapping - WebGPU Samples \ No newline at end of file + Shadow Mapping - WebGPU Samples \ No newline at end of file diff --git a/samples/texturedCube.html b/samples/texturedCube.html index c29948bb..b3e9afb1 100644 --- a/samples/texturedCube.html +++ b/samples/texturedCube.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Textured Cube - WebGPU Samples \ No newline at end of file + Textured Cube - WebGPU Samples \ No newline at end of file diff --git a/samples/twoCubes.html b/samples/twoCubes.html index 36fe340f..3c806c18 100644 --- a/samples/twoCubes.html +++ b/samples/twoCubes.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Two Cubes - WebGPU Samples \ No newline at end of file + Two Cubes - WebGPU Samples \ No newline at end of file diff --git a/samples/videoUploading.html b/samples/videoUploading.html index f9992404..eab166f6 100644 --- a/samples/videoUploading.html +++ b/samples/videoUploading.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Video Uploading - WebGPU Samples \ No newline at end of file + Video Uploading - WebGPU Samples \ No newline at end of file diff --git a/samples/videoUploadingWebCodecs.html b/samples/videoUploadingWebCodecs.html index 2b29815d..63b2ba77 100644 --- a/samples/videoUploadingWebCodecs.html +++ b/samples/videoUploadingWebCodecs.html @@ -8,4 +8,4 @@ height: auto !important; overflow: visible !important; } - Video Uploading with WebCodecs - WebGPU Samples \ No newline at end of file + Video Uploading with WebCodecs - WebGPU Samples \ No newline at end of file diff --git a/samples/worker.html b/samples/worker.html index 1d76368b..6e34e6b5 100644 --- a/samples/worker.html +++ b/samples/worker.html @@ -10,6 +10,6 @@ } WebGPU in a Worker - WebGPU Samples

WebGPU in a Worker

See it on Github!

This example shows one method of using WebGPU in a web worker and presenting to + which is then transferred to the worker where all the WebGPU calls are made."/>

\ No newline at end of file + which is then transferred to the worker where all the WebGPU calls are made.

\ No newline at end of file