-
Notifications
You must be signed in to change notification settings - Fork 1
/
webgpu.js
2 lines (2 loc) · 5.95 KB
/
webgpu.js
1
2
// https://github.com/lijialiang/lut-filter v1.0.1
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).lutFilter=t()}(this,(function(){"use strict";function e(e,t,r,n){return new(r||(r=Promise))((function(o,a){function i(e){try{l(n.next(e))}catch(e){a(e)}}function u(e){try{l(n.throw(e))}catch(e){a(e)}}function l(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,u)}l((n=n.apply(e,t||[])).next())}))}function t(e,t){var r,n,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(a){return function(u){return function(a){if(r)throw new TypeError("Generator is already executing.");for(;i;)try{if(r=1,n&&(o=2&a[0]?n.return:a[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,a[1])).done)return o;switch(n=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return i.label++,{value:a[1],done:!1};case 5:i.label++,n=a[1],a=[0];continue;case 7:a=i.ops.pop(),i.trys.pop();continue;default:if(!(o=i.trys,(o=o.length>0&&o[o.length-1])||6!==a[0]&&2!==a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){i.label=a[1];break}if(6===a[0]&&i.label<o[1]){i.label=o[1],o=a;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(a);break}o[2]&&i.ops.pop(),i.trys.pop();continue}a=t.call(e,i)}catch(e){a=[6,e],n=0}finally{r=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,u])}}}return function(r){var n=r.canvas,o=r.image,a=r.filterImage;return e(void 0,void 0,void 0,(function(){var e,r,i,u,l,s,c,d,f,p,g,x,m,b,v,h,y,w,T,C,P,U,G,E,S,q,B;return t(this,(function(t){switch(t.label){case 0:return n.width=o.width,n.height=o.height,[4,window.navigator.gpu.requestAdapter()];case 1:if(null===(e=t.sent()))throw new Error("Browser does not support WebGPU.");return[4,e.requestDevice()];case 2:if(r=t.sent(),null===(i=n.getContext("webgpu")))throw new Error("Browser does not support WebGPU.");return i.configure({device:r,format:"bgra8unorm"}),u=new Float32Array([-1,1,0,1,0,1,-1,-1,0,1,0,0,1,-1,0,1,1,0,1,-1,0,1,1,0,1,1,0,1,1,1,-1,1,0,1,0,1]),l=r.createBuffer({size:u.byteLength,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:!0}),new Float32Array(l.getMappedRange()).set(u),l.unmap(),[4,o.decode()];case 3:return t.sent(),s={width:o.width,height:o.height},c=r.createTexture({size:s,dimension:"2d",format:"rgba8unorm",usage:GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),f=(d=r.queue).copyExternalImageToTexture,q={},[4,createImageBitmap(o)];case 4:return f.apply(d,[(q.source=t.sent(),q),{texture:c,mipLevel:0},s]),[4,a.decode()];case 5:return t.sent(),p={width:a.width,height:a.height},g=r.createTexture({size:p,dimension:"2d",format:"rgba8unorm",usage:GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),m=(x=r.queue).copyExternalImageToTexture,B={},[4,createImageBitmap(a)];case 6:return m.apply(x,[(B.source=t.sent(),B),{texture:g,mipLevel:0},p]),b=r.createShaderModule({code:"\nstruct VertexOut {\n [[builtin(position)]] position : vec4<f32>;\n [[location(0)]] texCoords : vec2<f32>;\n};\n\n[[group(0), binding(0)]] var linearSampler: sampler;\n[[group(0), binding(1)]] var imageTexture: texture_2d<f32>;\n[[group(0), binding(2)]] var filterImageTexture: texture_2d<f32>;\n\n[[stage(vertex)]]\nfn vertex_main(\n [[location(0)]] position: vec4<f32>,\n [[location(1)]] texCoords: vec2<f32>\n) -> VertexOut\n{\n var output: VertexOut;\n output.position = position;\n output.texCoords = texCoords;\n output.texCoords.y = 1. - output.texCoords.y;\n return output;\n}\n\n[[stage(fragment)]]\nfn fragment_main(fragData: VertexOut) -> [[location(0)]] vec4<f32>\n{\n var textureColor = textureSample(imageTexture, linearSampler, fragData.texCoords).rgba;\n var blueColor = textureColor.b * 63.0;\n\n var quad1: vec2<f32>;\n quad1.y = floor(floor(blueColor) * 0.125);\n quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\n var quad2: vec2<f32>;\n quad2.y = floor(ceil(blueColor) * 0.125);\n quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\n var texPos1: vec2<f32>;\n texPos1.x = ((quad1.x * 64.0) + textureColor.r * 63.0 + 0.5)/512.0;\n texPos1.y = ((quad1.y * 64.0) + textureColor.g * 63.0 + 0.5)/512.0;\n\n var texPos2: vec2<f32>;\n texPos2.x = ((quad2.x * 64.0) + textureColor.r * 63.0 + 0.5)/512.0;\n texPos2.y = ((quad2.y * 64.0) + textureColor.g * 63.0 + 0.5)/512.0;\n\n var newColor1 = textureSample(filterImageTexture, linearSampler, texPos1);\n var newColor2 = textureSample(filterImageTexture, linearSampler, texPos2);\n\n return mix(newColor1, newColor2, fract(blueColor));\n}\n "}),v=r.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{}}]}),h=r.createSampler({magFilter:"nearest",minFilter:"nearest",addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"}),y=r.createBindGroup({layout:v,entries:[{binding:0,resource:h},{binding:1,resource:c.createView()},{binding:2,resource:g.createView()}]}),w=r.createPipelineLayout({bindGroupLayouts:[v]}),T=[{attributes:[{format:"float32x4",offset:0,shaderLocation:0},{format:"float32x2",offset:16,shaderLocation:1}],arrayStride:24,stepMode:"vertex"}],C={format:"bgra8unorm"},P=r.createRenderPipeline({layout:w,vertex:{module:b,entryPoint:"vertex_main",buffers:T},fragment:{module:b,entryPoint:"fragment_main",targets:[C]},primitive:{topology:"triangle-list",frontFace:"ccw",cullMode:"back"}}),U=r.createCommandEncoder(),G={storeOp:"store",view:i.getCurrentTexture().createView(),loadValue:{r:0,g:0,b:0,a:1}},E={colorAttachments:[G]},(S=U.beginRenderPass(E)).setPipeline(P),S.setVertexBuffer(0,l),S.setBindGroup(0,y),S.draw(6,2,0,0),S.endPass(),r.queue.submit([U.finish()]),[2]}}))}))}}));