From 403badad4ed661ca3dd5a16b3f2f84979ae830d8 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Wed, 26 Jul 2023 18:45:49 -0600 Subject: [PATCH 01/55] Update README.md - compute is actually last --- README.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 5e0913ed..fc0640e8 100644 --- a/README.md +++ b/README.md @@ -78,17 +78,16 @@ const points = new Points('gl-canvas'); // create your render pass with three shaders as follow const renderPasses = [ - new RenderPass( /*wgsl*/ ` - // add @vertex string - `, - /*wgsl*/ + new RenderPass( + /*wgsl*/ ` + // add @vertex string + `, + /*wgsl*/` + // add @fragment string + `, + /*wgsl*/` + // add @compute string ` - // add @compute string - `, - /*wgsl*/ - ` - // add @fragment string - ` ) ]; From 9d7da4c4e2439e40ac2f36bb478f78121f2ce6e3 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 25 Nov 2023 18:45:18 -0600 Subject: [PATCH 02/55] test demo for parameters - to figure out new parameters --- examples/main.js | 1 + examples/params_test/compute.js | 13 +++++++++++++ examples/params_test/frag.js | 24 ++++++++++++++++++++++++ examples/params_test/index.js | 23 +++++++++++++++++++++++ examples/params_test/vert.js | 15 +++++++++++++++ 5 files changed, 76 insertions(+) create mode 100644 examples/params_test/compute.js create mode 100644 examples/params_test/frag.js create mode 100644 examples/params_test/index.js create mode 100644 examples/params_test/vert.js diff --git a/examples/main.js b/examples/main.js index 30c95d3c..dade6576 100644 --- a/examples/main.js +++ b/examples/main.js @@ -92,6 +92,7 @@ const shaderProjects = [ { name: 'Spritesheet 1', path: './spritesheet1/index.js' }, { name: 'UVs 1', path: './uvs1/index.js' }, { name: 'Video Texture 1', path: './videotexture1/index.js' }, + { name: 'PARAMS TEST', path: './params_test/index.js' }, ] const shaderNames = {}; diff --git a/examples/params_test/compute.js b/examples/params_test/compute.js new file mode 100644 index 00000000..00dd5ed7 --- /dev/null +++ b/examples/params_test/compute.js @@ -0,0 +1,13 @@ +const compute = /*wgsl*/` + +@compute @workgroup_size(8,8,1) +fn main( + @builtin(global_invocation_id) GlobalId: vec3, + @builtin(workgroup_id) WorkGroupID: vec3, + @builtin(local_invocation_id) LocalInvocationID: vec3 +) { + let time = params.time; +} +`; + +export default compute; diff --git a/examples/params_test/frag.js b/examples/params_test/frag.js new file mode 100644 index 00000000..1c217c7d --- /dev/null +++ b/examples/params_test/frag.js @@ -0,0 +1,24 @@ +import { fnusin } from '../../src/core/animation.js'; + +const frag = /*wgsl*/` + +${fnusin} + +@fragment +fn main( + @location(0) color: vec4, + @location(1) uv: vec2, + @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(3) uvr: vec2, // uv with aspect ratio corrected + @location(4) mouse: vec2, + @builtin(position) position: vec4 +) -> @location(0) vec4 { + + + let finalColor:vec4 = test; + + return finalColor; +} +`; + +export default frag; diff --git a/examples/params_test/index.js b/examples/params_test/index.js new file mode 100644 index 00000000..cfdd9771 --- /dev/null +++ b/examples/params_test/index.js @@ -0,0 +1,23 @@ +import vert from './vert.js'; +import compute from './compute.js'; +import frag from './frag.js'; +import Points from '../../src/absulit.points.module.js'; + +const base = { + vert, + compute, + frag, + /** + * + * @param {Points} points + */ + init: async points => { + points.addStorageMap('test', [1,0,0,.5], 'vec4f'); + points.addStorage('test2', 1, 'vec4f', 4); + }, + update: points => { + + } +} + +export default base; \ No newline at end of file diff --git a/examples/params_test/vert.js b/examples/params_test/vert.js new file mode 100644 index 00000000..fdf316e3 --- /dev/null +++ b/examples/params_test/vert.js @@ -0,0 +1,15 @@ +const vert = /*wgsl*/` + +@vertex +fn main( + @location(0) position: vec4, + @location(1) color: vec4, + @location(2) uv: vec2, + @builtin(vertex_index) vertexIndex: u32 +) -> Fragment { + + return defaultVertexBody(position, color, uv); +} +`; + +export default vert; From 81bc2958da8dcb5573e498130f1d62158ed6cf96 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 25 Nov 2023 20:07:49 -0600 Subject: [PATCH 03/55] struct size is now manual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Because of this previous naïve approach, I was ignoring the paddings, and since calculate this is hard for me, it's now manual --- examples/params_test/compute.js | 4 ++++ examples/params_test/frag.js | 15 ++++++++++++++- examples/params_test/index.js | 3 ++- examples/params_test/structs.js | 11 +++++++++++ examples/params_test/vert.js | 4 ++++ src/absulit.points.module.js | 7 ++++--- 6 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 examples/params_test/structs.js diff --git a/examples/params_test/compute.js b/examples/params_test/compute.js index 00dd5ed7..74c37a05 100644 --- a/examples/params_test/compute.js +++ b/examples/params_test/compute.js @@ -1,5 +1,9 @@ +import { structs } from './structs.js'; + const compute = /*wgsl*/` +${structs} + @compute @workgroup_size(8,8,1) fn main( @builtin(global_invocation_id) GlobalId: vec3, diff --git a/examples/params_test/frag.js b/examples/params_test/frag.js index 1c217c7d..0ff363ae 100644 --- a/examples/params_test/frag.js +++ b/examples/params_test/frag.js @@ -1,8 +1,12 @@ import { fnusin } from '../../src/core/animation.js'; +import { structs } from './structs.js'; +import { rand } from '../../src/core/random.js'; const frag = /*wgsl*/` ${fnusin} +${structs} +${rand} @fragment fn main( @@ -14,8 +18,17 @@ fn main( @builtin(position) position: vec4 ) -> @location(0) vec4 { + var finalColor:vec4 = vec4(); + + if(variables.init == 0){ + rand_seed = uvr + params.time; + rand(); + finalColor = vec4(rand_seed, 0, 1); + variables.init = 1; + variables.color = finalColor; + } + finalColor = variables.color; - let finalColor:vec4 = test; return finalColor; } diff --git a/examples/params_test/index.js b/examples/params_test/index.js index cfdd9771..4c4daf7a 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -13,7 +13,8 @@ const base = { */ init: async points => { points.addStorageMap('test', [1,0,0,.5], 'vec4f'); - points.addStorage('test2', 1, 'vec4f', 4); + points.addStorage('variables', 1, 'Variable', 32); + points.addStorage('test2', 1, 'TestStruct', 32); }, update: points => { diff --git a/examples/params_test/structs.js b/examples/params_test/structs.js new file mode 100644 index 00000000..66dcea06 --- /dev/null +++ b/examples/params_test/structs.js @@ -0,0 +1,11 @@ +export const structs = /*wgsl*/` + struct Variable{ + init: i32, + color: vec4f, + } + + struct TestStruct { + color1: vec4f, + value: f32, + } +`; \ No newline at end of file diff --git a/examples/params_test/vert.js b/examples/params_test/vert.js index fdf316e3..24d15d10 100644 --- a/examples/params_test/vert.js +++ b/examples/params_test/vert.js @@ -1,5 +1,9 @@ +import { structs } from './structs.js'; + const vert = /*wgsl*/` +${structs} + @vertex fn main( @location(0) position: vec4, diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index b0f115bd..10197962 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -251,7 +251,7 @@ export default class Points { * Multiply this by number of properties in the struct if necessary. * @param {string} structName Name of the struct already existing on the * shader that will be the array of the Storage - * @param {Number} structSize this tells how many sub items the struct has + * @param {Number} structSize number of bytes used by the struct; this includes padding. * @param {boolean} read if this is going to be used to read data back * @param {ShaderType} shaderType this tells to what shader the storage is bound */ @@ -606,6 +606,7 @@ export default class Points { * @returns string with bindings */ _createDynamicGroupBindings(shaderType, internal) { + // `internal` here is a flag for a custom pass internal = internal || false; if (!shaderType) { throw '`ShaderType` is required'; @@ -925,7 +926,7 @@ export default class Points { const values = new Float32Array(storageItem.array); storageItem.buffer = this._createAndMapBuffer(values, usage); } else { - storageItem.buffer = this._createBuffer(storageItem.size * storageItem.structSize * 4, usage); + storageItem.buffer = this._createBuffer(storageItem.size * storageItem.structSize, usage); } }); //-------------------------------------------- @@ -940,7 +941,7 @@ export default class Points { //let layerValues = []; let layersSize = 0; this._layers.forEach(layerItem => { - layersSize += layerItem.size * layerItem.structSize * 4; + layersSize += layerItem.size * layerItem.structSize; }); this._layers.buffer = this._createBuffer(layersSize, GPUBufferUsage.STORAGE); } From c69d7cc1a672b77f638b706000ba9a40315536de Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 26 Nov 2023 14:04:14 -0600 Subject: [PATCH 04/55] Update absulit.points.module.js - Fix to reading size that changed because now I'm setting manually the byte size. --- src/absulit.points.module.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 10197962..87051c36 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -932,7 +932,7 @@ export default class Points { //-------------------------------------------- this._readStorage.forEach(readStorageItem => { readStorageItem.buffer = this._device.createBuffer({ - size: readStorageItem.size * 4, + size: readStorageItem.size, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ }); }); From f0f797265293814d7cec2f97149ec75affdbced3 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 26 Nov 2023 15:21:15 -0600 Subject: [PATCH 05/55] Update absulit.points.module.js - corrected extra bytes flag --- src/absulit.points.module.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 87051c36..cf13f4f8 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -576,8 +576,8 @@ export default class Points { * @param {Function} callback function to be called when the event occurs */ addEventListener(name, callback, structSize) { - // this extra 1 is for the boolean flag in the Event struct - let data = Array(structSize + 1).fill(0); + // this extra 4 is for the boolean flag in the Event struct + let data = Array(structSize + 4).fill(0); this.addStorageMap(name, data, 'Event', true); this._events.set(this._events_ids, { From 650eb3d81947f6a8996eca82db5032dd002eec60 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 26 Nov 2023 16:17:04 -0600 Subject: [PATCH 06/55] layer fix and all demos corrected - The byte size has to be manually set in the struct size definition --- examples/audio1/index.js | 4 ++-- examples/audio2/index.js | 4 ++-- examples/data1/index.js | 2 +- examples/dithering3_1/index.js | 2 +- examples/dithering3_2/index.js | 2 +- examples/mouseclickscroll1/index.js | 2 +- examples/noise1/index.js | 4 ++-- examples/params_test/index.js | 2 ++ examples/shapes2/index.js | 2 +- src/absulit.points.module.js | 2 +- 10 files changed, 14 insertions(+), 12 deletions(-) diff --git a/examples/audio1/index.js b/examples/audio1/index.js index fd04ba3c..7876898c 100644 --- a/examples/audio1/index.js +++ b/examples/audio1/index.js @@ -20,9 +20,9 @@ const base = { audio = points.addAudio('audio', './../../audio/cognitive_dissonance.mp3', volume, loop, false); points.addEventListener('click_event', data => { audio.play(); - }, 2); + }, 4); // points.addAudio('audio', 'https://mdn.github.io/voice-change-o-matic/audio/concert-crowd.ogg', volume, loop); - points.addStorage('result', 10, 'f32', 1); + points.addStorage('result', 10, 'f32', 4); }, /** * diff --git a/examples/audio2/index.js b/examples/audio2/index.js index 19479d50..b2f65548 100644 --- a/examples/audio2/index.js +++ b/examples/audio2/index.js @@ -23,10 +23,10 @@ const base = { points.addEventListener('click_event', data => { audio.play(); - }, 2); + }, 4); - points.addStorage('result', 10, 'f32', 1); + points.addStorage('result', 10, 'f32', 4); // RenderPasses.filmgrain(points); // RenderPasses.bloom(points, .1); diff --git a/examples/data1/index.js b/examples/data1/index.js index 7d8a8e33..6b2c10a8 100644 --- a/examples/data1/index.js +++ b/examples/data1/index.js @@ -29,7 +29,7 @@ const data1 = { let resultMatrixBufferSize = 2 + firstMatrix[0] * secondMatrix[1]; console.log(resultMatrixBufferSize); - points.addStorage('resultMatrix', 1, 'Matrix', resultMatrixBufferSize, true); + points.addStorage('resultMatrix', 1, 'Matrix', resultMatrixBufferSize * 4, true); }, update: async points => { diff --git a/examples/dithering3_1/index.js b/examples/dithering3_1/index.js index f0066260..88dcb6b0 100644 --- a/examples/dithering3_1/index.js +++ b/examples/dithering3_1/index.js @@ -20,7 +20,7 @@ const dithering3 = { await points.addTextureImage('image', './../img/absulit_800x800.jpg'); points.addBindingTexture('outputTex', 'computeTexture'); points.addLayers(2); - points.addStorage('variables', 1, 'Variable', 1, false, ShaderType.COMPUTE); + points.addStorage('variables', 1, 'Variable', 16, false, ShaderType.COMPUTE); }, update: points => { diff --git a/examples/dithering3_2/index.js b/examples/dithering3_2/index.js index 8a318d3b..0581f3cf 100644 --- a/examples/dithering3_2/index.js +++ b/examples/dithering3_2/index.js @@ -21,7 +21,7 @@ const dithering3 = { await points.addTextureImage('image', './../img/absulit_800x800.jpg'); points.addBindingTexture('outputTex', 'computeTexture'); points.addLayers(2); - points.addStorage('variables', 1, 'Variable', 1, false, ShaderType.COMPUTE); + points.addStorage('variables', 1, 'Variable', 16, false, ShaderType.COMPUTE); }, update: points => { diff --git a/examples/mouseclickscroll1/index.js b/examples/mouseclickscroll1/index.js index 0b5fa06e..a4dcf253 100644 --- a/examples/mouseclickscroll1/index.js +++ b/examples/mouseclickscroll1/index.js @@ -5,7 +5,7 @@ const mouseclickscroll1 = { vert, frag, init: async points => { - points.addStorage('variables', 1, 'Variable', 4); + points.addStorage('variables', 1, 'Variable', 16); }, update: points => { diff --git a/examples/noise1/index.js b/examples/noise1/index.js index 9655fcba..a6adcfda 100644 --- a/examples/noise1/index.js +++ b/examples/noise1/index.js @@ -6,8 +6,8 @@ const noise1 = { init: async points => { const numPoints = 800*800; points.addUniform('value_noise_data_length', numPoints); - points.addStorage('value_noise_data', numPoints, 'f32', 1); - points.addStorage('variables', 1, 'Variable', 1); + points.addStorage('value_noise_data', numPoints, 'f32', 4); + points.addStorage('variables', 1, 'Variable', 4); }, update: points => { diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 4c4daf7a..6c50fda3 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -13,6 +13,8 @@ const base = { */ init: async points => { points.addStorageMap('test', [1,0,0,.5], 'vec4f'); + + points.addStorage('variables', 1, 'Variable', 32); points.addStorage('test2', 1, 'TestStruct', 32); }, diff --git a/examples/shapes2/index.js b/examples/shapes2/index.js index 87c4d8a2..b7cdff79 100644 --- a/examples/shapes2/index.js +++ b/examples/shapes2/index.js @@ -9,7 +9,7 @@ const shapes2 = { init: async points => { const numPoints = 800*800; points.addUniform('numPoints', numPoints); - points.addStorage('points', numPoints, 'vec4', 4); + points.addStorage('points', numPoints, 'vec4', 16); points.addSampler('feedbackSampler', null); points.addBindingTexture('outputTex', 'computeTexture'); }, diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index cf13f4f8..ce206028 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -332,7 +332,7 @@ export default class Points { name: `layer${layerIndex}`, size: this._canvas.width * this._canvas.height, structName: 'vec4', - structSize: 4, + structSize: 16, array: null, buffer: null, internal: this._internal From a9deadf9d9c8897e90d94e5b368ee4eb03dc17a6 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Fri, 1 Dec 2023 20:05:50 -0600 Subject: [PATCH 07/55] progress on data-size module - To get the byte size of structs --- examples/params_test/index.js | 43 +++++++++++++++++++- examples/params_test/structs.js | 4 +- src/absulit.points.module.js | 12 +++++- src/data-size.js | 72 +++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 src/data-size.js diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 6c50fda3..4da1d8e2 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -2,6 +2,9 @@ import vert from './vert.js'; import compute from './compute.js'; import frag from './frag.js'; import Points from '../../src/absulit.points.module.js'; +// import { wgslTypeSize } from '../../src/wgslTypeSize.js'; +import { makeShaderDataDefinitions } from './../../src/data-definitions.js'; +import { dataSize } from '../../src/data-size.js'; const base = { vert, @@ -12,11 +15,49 @@ const base = { * @param {Points} points */ init: async points => { - points.addStorageMap('test', [1,0,0,.5], 'vec4f'); + // console.log(makeShaderDataDefinitions(`struct Params { + // sliderA:f32, + // sliderB:f32, + // sliderC:f32, + // test3:vec4f, + // time:f32, + // epoch:f32, + // screenWidth:f32, + // screenHeight:f32, + // mouseX:f32, + // mouseY:f32, + // mouseClick:f32, + // mouseDown:f32, + // mouseWheel:f32, + // mouseDeltaX:f32, + // mouseDeltaY:f32, + + // }`)) + + const result = dataSize(` + struct Variable{ + init: i32, + color: vec4f, + } + + struct Variable2 { + v: vec4f, + //f: i32, + } + + `); + console.log(result) + + + points.addStorageMap('test', [1, 0, 0, .5], 'vec4f'); points.addStorage('variables', 1, 'Variable', 32); points.addStorage('test2', 1, 'TestStruct', 32); + + points.addUniform('test3', [1, 0, 0, 1], 'vec4f', 16) + + }, update: points => { diff --git a/examples/params_test/structs.js b/examples/params_test/structs.js index 66dcea06..2f37318e 100644 --- a/examples/params_test/structs.js +++ b/examples/params_test/structs.js @@ -8,4 +8,6 @@ export const structs = /*wgsl*/` color1: vec4f, value: f32, } -`; \ No newline at end of file +`; + + diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index ce206028..c52ae278 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -205,7 +205,7 @@ export default class Points { * @param {string} name name of the Param, you can invoke it later in shaders as `Params.[name]` * @param {Number} value Number will be converted to `f32` */ - addUniform(name, value) { + addUniform(name, value, structName, structSize) { if (this._nameExists(this._uniforms, name)) { return; } @@ -213,6 +213,8 @@ export default class Points { this._uniforms.push({ name: name, value: value, + type: structName, + size: structSize, internal: this._internal }); } @@ -723,6 +725,7 @@ export default class Points { let dynamicStructParams = ''; this._uniforms.forEach(variable => { + // console.log(variable) let uniformType = variable.type || 'f32'; dynamicStructParams += /*wgsl*/`${variable.name}:${uniformType}, \n\t`; }); @@ -907,8 +910,12 @@ export default class Points { /** @private */ _createParametersUniforms() { - const values = new Float32Array(this._uniforms.map(v => v.value)); + const values = new Float32Array(this._uniforms.map(v => v.value).flat(1)); + // console.log(values) this._uniforms.buffer = this._createAndMapBuffer(values, GPUBufferUsage.UNIFORM); + // console.log(this._uniforms.buffer) + // debugger + } /** @private */ @@ -1198,6 +1205,7 @@ export default class Points { ); } }); + // console.log(entries) } if (this._layers.length) { diff --git a/src/data-size.js b/src/data-size.js new file mode 100644 index 00000000..d33d0bff --- /dev/null +++ b/src/data-size.js @@ -0,0 +1,72 @@ +// ignore comments +const removeCommentsRE = /^(?:(?!\/\/|\/*.*\/).|\n)+/gim + +// struct name: +const getStructNameRE = /struct\s+?(\w+)\s*{[^}]+}\n?/g + +// what's inside a struct: +const insideStructRE = /struct\s+?\w+\s*{([^}]+)}\n?/g + +// you have to separete the result by splitting new lines + +// TODO SARK 3h:49 + +function removeComments(value) { + const matches = value.matchAll(removeCommentsRE); + let result = ''; + for (const match of matches) { + const captured = match[0] + result += captured; + } + return result; +} + +function getInsideStruct(value) { + const matches = value.matchAll(insideStructRE); + let lines = null; + for (const match of matches) { + lines = match[1].split('\n'); + lines = lines.map(element => element.trim()) + .filter(e => e !== ''); + } + return lines; +} + +function getStructName(value) { + const matches = value.matchAll(getStructNameRE); + let result = {}; + for (const match of matches) { + const captured = match[0] + const name = match[1]; + console.log(name, captured); + // result += captured; + const lines = getInsideStruct(captured); + result[name] = { + captured, + lines + } + } + console.log(result); + // return result; +} + +export const dataSize = value => { + + console.log('---- dataSize', value); + + const noCommentsValue = removeComments(value); + console.log('---- dataSize', noCommentsValue); + getStructName(noCommentsValue) + +} + + +// // const result = re.exec(value); +// const matches = value.matchAll(removeCommentsRE); +// for (const match of matches) { +// console.log(match) +// const captured = match[0] +// const name = match[1] +// // console.log(name) +// console.log(captured) +// } \ No newline at end of file From c0e93bafc715b18018caf28bb937bd34fe924dba Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 2 Dec 2023 13:27:27 -0600 Subject: [PATCH 08/55] filtering types and list with types --- examples/params_test/index.js | 1 + src/data-size.js | 56 +++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 4da1d8e2..c6a62259 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -38,6 +38,7 @@ const base = { struct Variable{ init: i32, color: vec4f, + another: i32 , } struct Variable2 { diff --git a/src/data-size.js b/src/data-size.js index d33d0bff..7e294591 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -1,3 +1,48 @@ + +const size_4_align_4 = { size: 4, align: 4 }; +const size_8_align_8 = { size: 8, align: 8 }; +const size_12_align_16 = { size: 12, align: 16 }; +const size_16_align_16 = { size: 16, align: 16 }; +const size_16_align_8 = { size: 16, align: 8 }; +const size_32_align_8 = { size: 32, align: 8 }; +const size_24_align_16 = { size: 24, align: 16 }; +const size_48_align_16 = { size: 48, align: 16 }; +const size_32_align_16 = { size: 32, align: 16 }; +const size_64_align_16 = { size: 64, align: 16 }; + +const typeSizes = { + 'bool': size_4_align_4, + 'f32': size_4_align_4, + 'i32': size_4_align_4, + 'u32': size_4_align_4, + + 'vec2': size_8_align_8, + 'vec2': size_8_align_8, + 'vec2': size_8_align_8, + 'vec2': size_8_align_8, + + 'vec3': size_12_align_16, + 'vec3': size_12_align_16, + 'vec3': size_12_align_16, + 'vec3': size_12_align_16, + + 'vec4': size_16_align_16, + 'vec4': size_16_align_16, + 'vec4': size_16_align_16, + 'vec4': size_16_align_16, + 'mat2x2': size_16_align_8, + 'mat2x3': size_32_align_8, + 'mat2x4': size_32_align_8, + 'mat3x2': size_24_align_16, + 'mat3x3': size_48_align_16, + 'mat3x4': size_48_align_16, + 'mat4x2': size_32_align_16, + 'mat4x3': size_64_align_16, + 'mat4x4': size_64_align_16, +} + + + // ignore comments const removeCommentsRE = /^(?:(?!\/\/|\/*.*\/).|\n)+/gim @@ -9,8 +54,6 @@ const insideStructRE = /struct\s+?\w+\s*{([^}]+)}\n?/g // you have to separete the result by splitting new lines -// TODO SARK 3h:49 - function removeComments(value) { const matches = value.matchAll(removeCommentsRE); let result = ''; @@ -41,9 +84,16 @@ function getStructName(value) { console.log(name, captured); // result += captured; const lines = getInsideStruct(captured); + const types = lines.map(l => { + const right = l.split(':')[1]; + const type = right.split(',')[0].trim() + return type; + }) result[name] = { captured, - lines + lines, + types, + unique_types: [...new Set(types)] } } console.log(result); From 91e8ceeba4343a64b6136d6fcf63e8a1751ba568 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 2 Dec 2023 13:47:16 -0600 Subject: [PATCH 09/55] Update data-size.js - simplified types versions --- src/data-size.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/data-size.js b/src/data-size.js index 7e294591..91cf8e64 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -21,11 +21,21 @@ const typeSizes = { 'vec2': size_8_align_8, 'vec2': size_8_align_8, + // 'vec2': size_8_align_8, + 'vec2f': size_8_align_8, + 'vec2i': size_8_align_8, + 'vec2u': size_8_align_8, + 'vec3': size_12_align_16, 'vec3': size_12_align_16, 'vec3': size_12_align_16, 'vec3': size_12_align_16, + // 'vec3': size_12_align_16, + 'vec3f': size_12_align_16, + 'vec3i': size_12_align_16, + 'vec3u': size_12_align_16, + 'vec4': size_16_align_16, 'vec4': size_16_align_16, 'vec4': size_16_align_16, @@ -39,8 +49,21 @@ const typeSizes = { 'mat4x2': size_32_align_16, 'mat4x3': size_64_align_16, 'mat4x4': size_64_align_16, -} + // 'vec4': size_16_align_16, + 'vec4f': size_16_align_16, + 'vec4i': size_16_align_16, + 'vec4u': size_16_align_16, + 'mat2x2f': size_16_align_8, + 'mat2x3f': size_32_align_8, + 'mat2x4f': size_32_align_8, + 'mat3x2f': size_24_align_16, + 'mat3x3f': size_48_align_16, + 'mat3x4f': size_48_align_16, + 'mat4x2f': size_32_align_16, + 'mat4x3f': size_64_align_16, + 'mat4x4f': size_64_align_16, +} // ignore comments From df6170a89d8ee9462df118a789f66c4739f25b5d Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 2 Dec 2023 14:14:12 -0600 Subject: [PATCH 10/55] assigning alignment for later --- examples/params_test/index.js | 2 +- src/data-size.js | 27 ++++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index c6a62259..e2efaca7 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -37,7 +37,7 @@ const base = { const result = dataSize(` struct Variable{ init: i32, - color: vec4f, + // color: vec4f, another: i32 , } diff --git a/src/data-size.js b/src/data-size.js index 91cf8e64..46407e9c 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -98,9 +98,9 @@ function getInsideStruct(value) { return lines; } -function getStructName(value) { +function getStructDataByName(value) { const matches = value.matchAll(getStructNameRE); - let result = {}; + let result = new Map(); for (const match of matches) { const captured = match[0] const name = match[1]; @@ -112,25 +112,34 @@ function getStructName(value) { const type = right.split(',')[0].trim() return type; }) - result[name] = { + result.set(name, { captured, lines, types, unique_types: [...new Set(types)] - } + }); } - console.log(result); - // return result; + // console.log(result); + return result; } export const dataSize = value => { - console.log('---- dataSize', value); const noCommentsValue = removeComments(value); console.log('---- dataSize', noCommentsValue); - getStructName(noCommentsValue) - + const structData = getStructDataByName(noCommentsValue); + console.log('---- dataSize', structData); + let maxAlign = 0 + for (const [structDatumKey, structDatum] of structData) { + console.log(`${structDatumKey} = `, structDatum.unique_types); + + structDatum.unique_types.forEach(ut => { + const align = typeSizes[ut].align; + maxAlign = align > maxAlign ? align : maxAlign; + structDatum.maxAlign = maxAlign; + }); + } } From facb310b1e83cba96eb4bd96f819b1ea6b448bc4 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 2 Dec 2023 15:59:30 -0600 Subject: [PATCH 11/55] first working code of data-size module - It obtains the right size of the struct --- examples/params_test/index.js | 25 ++++++++++++++++++-- src/data-size.js | 44 ++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index e2efaca7..b62c9969 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -37,13 +37,34 @@ const base = { const result = dataSize(` struct Variable{ init: i32, - // color: vec4f, + color: vec4f, another: i32 , } + struct Params { + sliderA:f32, + sliderB:f32, + sliderC:f32, + test3:vec4f, + time:f32, + epoch:f32, + screenWidth:f32, + screenHeight:f32, + mouseX:f32, + mouseY:f32, + mouseClick:f32, + mouseDown:f32, + mouseWheel:f32, + mouseDeltaX:f32, + mouseDeltaY:f32, + + } + + struct Variable2 { v: vec4f, - //f: i32, + f: i32, + z: i32, } `); diff --git a/src/data-size.js b/src/data-size.js index 46407e9c..8b9e6bdd 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -123,6 +123,18 @@ function getStructDataByName(value) { return result; } +function addBytesToAlign(bytes, aligment){ + const remainder = bytes % aligment + let result = 0; + if(remainder !== 0){ + // if not multiple we obtain the diff + // and add it to byteCounter to make it fit the alignment + const multipleDiff = aligment - remainder + result = bytes = multipleDiff + } + return result; +} + export const dataSize = value => { console.log('---- dataSize', value); @@ -132,13 +144,43 @@ export const dataSize = value => { console.log('---- dataSize', structData); let maxAlign = 0 for (const [structDatumKey, structDatum] of structData) { - console.log(`${structDatumKey} = `, structDatum.unique_types); + // console.log(`${structDatumKey} = `, structDatum.unique_types); + // to obtain the higher max alignment, but this can be also calculated + // in the next step structDatum.unique_types.forEach(ut => { const align = typeSizes[ut].align; maxAlign = align > maxAlign ? align : maxAlign; structDatum.maxAlign = maxAlign; }); + + console.log('START --------------------------------------') + let byteCounter = 0; + structDatum.types.forEach((t, i) => { + const currentType = t; + const nextType = structDatum.types[i + 1]; + const currentTypeData = typeSizes[currentType] + const nextTypeData = typeSizes[nextType] + + byteCounter += currentTypeData.size; + if(currentTypeData.size === structDatum.maxAlign){ + return + } + + if(!nextType){ + return + } + + if(nextTypeData.align == structDatum.maxAlign){ + byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); + } + }); + + byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); + + console.log('---- byteCounter', byteCounter) + console.log('NEXT --------------------------------------') + } } From cce4ae2d8944cb90469dc927df79d2dfe0ba74e8 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 2 Dec 2023 18:51:32 -0600 Subject: [PATCH 12/55] cleaning code --- examples/params_test/index.js | 34 +++++++++------------------ src/data-size.js | 43 +++++++---------------------------- 2 files changed, 19 insertions(+), 58 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index b62c9969..65f8299c 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -34,6 +34,7 @@ const base = { // }`)) + var startTime = performance.now() const result = dataSize(` struct Variable{ init: i32, @@ -41,33 +42,20 @@ const base = { another: i32 , } - struct Params { - sliderA:f32, - sliderB:f32, - sliderC:f32, - test3:vec4f, - time:f32, - epoch:f32, - screenWidth:f32, - screenHeight:f32, - mouseX:f32, - mouseY:f32, - mouseClick:f32, - mouseDown:f32, - mouseWheel:f32, - mouseDeltaX:f32, - mouseDeltaY:f32, - - } - - struct Variable2 { v: vec4f, - f: i32, - z: i32, + f: vec3f, + a: f32, + z: vec2f, + b: f32, + c: f32, + d: mat4x4f, + // vv: Variable, } - `); + var endTime = performance.now() + + console.log(`Call to doSomething took ${endTime - startTime} milliseconds`) console.log(result) diff --git a/src/data-size.js b/src/data-size.js index 8b9e6bdd..d9825189 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -104,8 +104,6 @@ function getStructDataByName(value) { for (const match of matches) { const captured = match[0] const name = match[1]; - console.log(name, captured); - // result += captured; const lines = getInsideStruct(captured); const types = lines.map(l => { const right = l.split(':')[1]; @@ -119,14 +117,13 @@ function getStructDataByName(value) { unique_types: [...new Set(types)] }); } - // console.log(result); return result; } -function addBytesToAlign(bytes, aligment){ +function addBytesToAlign(bytes, aligment) { const remainder = bytes % aligment let result = 0; - if(remainder !== 0){ + if (remainder !== 0) { // if not multiple we obtain the diff // and add it to byteCounter to make it fit the alignment const multipleDiff = aligment - remainder @@ -136,17 +133,11 @@ function addBytesToAlign(bytes, aligment){ } export const dataSize = value => { - console.log('---- dataSize', value); - const noCommentsValue = removeComments(value); - console.log('---- dataSize', noCommentsValue); const structData = getStructDataByName(noCommentsValue); - console.log('---- dataSize', structData); let maxAlign = 0 for (const [structDatumKey, structDatum] of structData) { - // console.log(`${structDatumKey} = `, structDatum.unique_types); - - // to obtain the higher max alignment, but this can be also calculated + // to obtain the higher max alignment, but this can be also calculated // in the next step structDatum.unique_types.forEach(ut => { const align = typeSizes[ut].align; @@ -154,7 +145,6 @@ export const dataSize = value => { structDatum.maxAlign = maxAlign; }); - console.log('START --------------------------------------') let byteCounter = 0; structDatum.types.forEach((t, i) => { const currentType = t; @@ -163,34 +153,17 @@ export const dataSize = value => { const nextTypeData = typeSizes[nextType] byteCounter += currentTypeData.size; - if(currentTypeData.size === structDatum.maxAlign){ - return - } - - if(!nextType){ + if ((currentTypeData.size === structDatum.maxAlign) || !nextType) { return } - if(nextTypeData.align == structDatum.maxAlign){ + if (nextTypeData.align == structDatum.maxAlign) { byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); } }); - byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); - - console.log('---- byteCounter', byteCounter) - console.log('NEXT --------------------------------------') - + byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); + structDatum.bytes = byteCounter } + return structData; } - - -// // const result = re.exec(value); -// const matches = value.matchAll(removeCommentsRE); -// for (const match of matches) { -// console.log(match) -// const captured = match[0] -// const name = match[1] -// // console.log(name) -// console.log(captured) -// } \ No newline at end of file From 5d6544d5a6307f13962b3a2e60542b525d212f6b Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 2 Dec 2023 19:53:32 -0600 Subject: [PATCH 13/55] retrieve data from substructs --- examples/params_test/index.js | 26 ++++++++----------- src/data-size.js | 47 ++++++++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 65f8299c..078444b5 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -36,22 +36,18 @@ const base = { var startTime = performance.now() const result = dataSize(` - struct Variable{ - init: i32, - color: vec4f, - another: i32 , - } + struct Ex4a { + velocity: vec3f, + }; - struct Variable2 { - v: vec4f, - f: vec3f, - a: f32, - z: vec2f, - b: f32, - c: f32, - d: mat4x4f, - // vv: Variable, - } + struct Ex4 { + orientation: vec3f, + size: f32, + // direction: array, + scale: f32, + info: Ex4a, + friction: f32, + }; `); var endTime = performance.now() diff --git a/src/data-size.js b/src/data-size.js index d9825189..31d5788f 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -107,7 +107,7 @@ function getStructDataByName(value) { const lines = getInsideStruct(captured); const types = lines.map(l => { const right = l.split(':')[1]; - const type = right.split(',')[0].trim() + const type = right.slice(',', -1).trim() return type; }) result.set(name, { @@ -137,22 +137,57 @@ export const dataSize = value => { const structData = getStructDataByName(noCommentsValue); let maxAlign = 0 for (const [structDatumKey, structDatum] of structData) { + // to obtain the higher max alignment, but this can be also calculated // in the next step structDatum.unique_types.forEach(ut => { - const align = typeSizes[ut].align; - maxAlign = align > maxAlign ? align : maxAlign; - structDatum.maxAlign = maxAlign; + console.log(typeSizes[ut], ut) + + // if it doesn't exists in typeSizes is an Array or a new Struct + if(!typeSizes[ut]){ + const UT = structData.get(ut) + console.log(UT); + // return; + + const align = UT.maxAlign; + maxAlign = align > maxAlign ? align : maxAlign; + structDatum.maxAlign = maxAlign; + }else{ + + const align = typeSizes[ut].align; + maxAlign = align > maxAlign ? align : maxAlign; + structDatum.maxAlign = maxAlign; + } + }); let byteCounter = 0; structDatum.types.forEach((t, i) => { const currentType = t; const nextType = structDatum.types[i + 1]; - const currentTypeData = typeSizes[currentType] - const nextTypeData = typeSizes[nextType] + let currentTypeData = typeSizes[currentType] + let nextTypeData = typeSizes[nextType] + + if(!currentTypeData){ + console.log(t, i, currentType); + const UT = structData.get(currentType) + console.log(UT); + if(UT){ + currentTypeData = {size: UT.bytes, align: UT.maxAlign} + } + } + + if(!nextTypeData){ + console.log(t, i, nextType); + const UT = structData.get(nextType) + console.log(UT); + if(UT){ + nextTypeData = {size: UT.bytes, align: UT.maxAlign} + } + } byteCounter += currentTypeData.size; + console.log(nextType, nextTypeData) if ((currentTypeData.size === structDatum.maxAlign) || !nextType) { return } From 95bd06e563d6378118109bb3e754fb9166629fc8 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 2 Dec 2023 20:01:46 -0600 Subject: [PATCH 14/55] cleaning code - better names and docs in code --- src/data-size.js | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/data-size.js b/src/data-size.js index 31d5788f..8912b642 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -141,19 +141,14 @@ export const dataSize = value => { // to obtain the higher max alignment, but this can be also calculated // in the next step structDatum.unique_types.forEach(ut => { - console.log(typeSizes[ut], ut) - // if it doesn't exists in typeSizes is an Array or a new Struct if(!typeSizes[ut]){ - const UT = structData.get(ut) - console.log(UT); + const sd = structData.get(ut) // return; - - const align = UT.maxAlign; + const align = sd.maxAlign; maxAlign = align > maxAlign ? align : maxAlign; structDatum.maxAlign = maxAlign; }else{ - const align = typeSizes[ut].align; maxAlign = align > maxAlign ? align : maxAlign; structDatum.maxAlign = maxAlign; @@ -168,26 +163,26 @@ export const dataSize = value => { let currentTypeData = typeSizes[currentType] let nextTypeData = typeSizes[nextType] + // if currentTypeData or nextTypeData have no data it means + // it's a struct or an array + // if it's a struct the data is already saved in structData + // because it was calculated previously + // assuming the struct was declared previously if(!currentTypeData){ - console.log(t, i, currentType); - const UT = structData.get(currentType) - console.log(UT); - if(UT){ - currentTypeData = {size: UT.bytes, align: UT.maxAlign} + const sd = structData.get(currentType) + if(sd){ + currentTypeData = {size: sd.bytes, align: sd.maxAlign} } } - + // read above if(!nextTypeData){ - console.log(t, i, nextType); - const UT = structData.get(nextType) - console.log(UT); - if(UT){ - nextTypeData = {size: UT.bytes, align: UT.maxAlign} + const sd = structData.get(nextType) + if(sd){ + nextTypeData = {size: sd.bytes, align: sd.maxAlign} } } byteCounter += currentTypeData.size; - console.log(nextType, nextTypeData) if ((currentTypeData.size === structDatum.maxAlign) || !nextType) { return } From 6ab02a5c3b258180b7d0c12f07b092153db3d49f Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 2 Dec 2023 20:19:00 -0600 Subject: [PATCH 15/55] placeholder code for arrays - if is an array it must calculate the size and alignment and that's it - it also has to calculate it if is an array of struct --- examples/params_test/index.js | 2 +- src/data-size.js | 57 ++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 078444b5..437b40e6 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -43,7 +43,7 @@ const base = { struct Ex4 { orientation: vec3f, size: f32, - // direction: array, + direction: array, scale: f32, info: Ex4a, friction: f32, diff --git a/src/data-size.js b/src/data-size.js index 8912b642..3a25d632 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -142,13 +142,19 @@ export const dataSize = value => { // in the next step structDatum.unique_types.forEach(ut => { // if it doesn't exists in typeSizes is an Array or a new Struct - if(!typeSizes[ut]){ - const sd = structData.get(ut) - // return; - const align = sd.maxAlign; - maxAlign = align > maxAlign ? align : maxAlign; - structDatum.maxAlign = maxAlign; - }else{ + if (!typeSizes[ut]) { + console.log(ut); + if (ut.indexOf('array') != -1) { + + } else { + const sd = structData.get(ut) + // return; + const align = sd.maxAlign; + maxAlign = align > maxAlign ? align : maxAlign; + structDatum.maxAlign = maxAlign; + } + + } else { const align = typeSizes[ut].align; maxAlign = align > maxAlign ? align : maxAlign; structDatum.maxAlign = maxAlign; @@ -168,17 +174,38 @@ export const dataSize = value => { // if it's a struct the data is already saved in structData // because it was calculated previously // assuming the struct was declared previously - if(!currentTypeData){ - const sd = structData.get(currentType) - if(sd){ - currentTypeData = {size: sd.bytes, align: sd.maxAlign} + if (!currentTypeData) { + + if (currentType) { + if (currentType.indexOf('array') != -1) { + //TODO: here + currentTypeData = { size: 0, align: 0 } + } else { + + const sd = structData.get(currentType) + if (sd) { + currentTypeData = { size: sd.bytes, align: sd.maxAlign } + } + + } } + } // read above - if(!nextTypeData){ - const sd = structData.get(nextType) - if(sd){ - nextTypeData = {size: sd.bytes, align: sd.maxAlign} + console.log(nextTypeData, nextType); + if (!nextTypeData) { + console.log('array? ', nextTypeData, nextType); + if (nextType) { + + if (nextType.indexOf('array') != -1) { + //TODO: here + nextTypeData = { size: 0, align: 0 } + } else { + const sd = structData.get(nextType) + if (sd) { + nextTypeData = { size: sd.bytes, align: sd.maxAlign } + } + } } } From 3f18fa117fecf9e0521e0d1fbc90d40437bbf573 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 2 Dec 2023 20:34:40 -0600 Subject: [PATCH 16/55] new regex to be used later in arrays --- src/data-size.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/data-size.js b/src/data-size.js index 3a25d632..1249eb2e 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -75,6 +75,8 @@ const getStructNameRE = /struct\s+?(\w+)\s*{[^}]+}\n?/g // what's inside a struct: const insideStructRE = /struct\s+?\w+\s*{([^}]+)}\n?/g +const arrayTypeAndAmountRE = /\s*<\s*([^,]+)\s*,\s*(\d+)\s*>/ + // you have to separete the result by splitting new lines function removeComments(value) { From dba32e4f52bfc8c0368dbb8e346af8784bc5f925 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 13:19:38 -0600 Subject: [PATCH 17/55] progress but there's a bug - an alignment is provided wrong --- examples/params_test/index.js | 33 +++++++++++++----- src/data-size.js | 65 ++++++++++++++++++++++++++++++----- 2 files changed, 82 insertions(+), 16 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 437b40e6..ecbff252 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -36,23 +36,40 @@ const base = { var startTime = performance.now() const result = dataSize(` - struct Ex4a { + struct Ex { velocity: vec3f, }; - struct Ex4 { - orientation: vec3f, - size: f32, - direction: array, - scale: f32, - info: Ex4a, + struct Ex1 { + direction: array, friction: f32, }; + + // struct Ex2 { + // direction: array, + // friction: f32, + // }; + + // struct Ex3 { + // direction: array, + // }; + + // struct ExA { + // orientation: vec3f, + // size: f32, + // scale: f32, + // info: Ex, + // direction: array, + // friction: f32, + // }; `); var endTime = performance.now() console.log(`Call to doSomething took ${endTime - startTime} milliseconds`) - console.log(result) + for(let [r,c] of result){ + console.log(r,c.bytes) + + } points.addStorageMap('test', [1, 0, 0, .5], 'vec4f'); diff --git a/src/data-size.js b/src/data-size.js index 1249eb2e..e6153ace 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -75,7 +75,7 @@ const getStructNameRE = /struct\s+?(\w+)\s*{[^}]+}\n?/g // what's inside a struct: const insideStructRE = /struct\s+?\w+\s*{([^}]+)}\n?/g -const arrayTypeAndAmountRE = /\s*<\s*([^,]+)\s*,\s*(\d+)\s*>/ +const arrayTypeAndAmountRE = /\s*<\s*([^,]+)\s*,\s*(\d+)\s*>/g // you have to separete the result by splitting new lines @@ -122,6 +122,17 @@ function getStructDataByName(value) { return result; } +function getArrayTypeAndAmount(value) { + const matches = value.matchAll(arrayTypeAndAmountRE); + let result = []; + for (const match of matches) { + const type = match[1]; + const amount = match[2]; + result.push({ type, amount: Number(amount) }); + } + return result; +} + function addBytesToAlign(bytes, aligment) { const remainder = bytes % aligment let result = 0; @@ -137,17 +148,33 @@ function addBytesToAlign(bytes, aligment) { export const dataSize = value => { const noCommentsValue = removeComments(value); const structData = getStructDataByName(noCommentsValue); - let maxAlign = 0 for (const [structDatumKey, structDatum] of structData) { // to obtain the higher max alignment, but this can be also calculated // in the next step structDatum.unique_types.forEach(ut => { + let maxAlign = 0 // if it doesn't exists in typeSizes is an Array or a new Struct if (!typeSizes[ut]) { - console.log(ut); if (ut.indexOf('array') != -1) { + + const [d] = getArrayTypeAndAmount(ut); + const t = typeSizes[d.type] + if (t) { + const align = t.align; + maxAlign = align > maxAlign ? align : maxAlign; + structDatum.maxAlign = maxAlign; + + } else { + const sd = structData.get(d.type); + const align = sd.maxAlign; + maxAlign = align > maxAlign ? align : maxAlign; + structDatum.maxAlign = maxAlign; + } + + + } else { const sd = structData.get(ut) // return; @@ -181,10 +208,23 @@ export const dataSize = value => { if (currentType) { if (currentType.indexOf('array') != -1) { //TODO: here - currentTypeData = { size: 0, align: 0 } + const [d] = getArrayTypeAndAmount(currentType); + const t = typeSizes[d.type] + if (t) { + // if array, the size is equal to the align + // currentTypeData = { size: t.align * d.amount, align: t.align } + currentTypeData = { size: t.size * d.amount, align: t.align } + // currentTypeData = { size: 0, align: 0 } + } else { + const sd = structData.get(d.type); + if (sd) { + currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign } + } + } + } else { - const sd = structData.get(currentType) + const sd = structData.get(currentType); if (sd) { currentTypeData = { size: sd.bytes, align: sd.maxAlign } } @@ -194,14 +234,23 @@ export const dataSize = value => { } // read above - console.log(nextTypeData, nextType); if (!nextTypeData) { - console.log('array? ', nextTypeData, nextType); if (nextType) { if (nextType.indexOf('array') != -1) { //TODO: here - nextTypeData = { size: 0, align: 0 } + const [d] = getArrayTypeAndAmount(nextType); + const t = typeSizes[d.type] + if (t) { + // nextTypeData = { size: t.align * d.amount, align: t.align } + nextTypeData = { size: t.size * d.amount, align: t.align } + // nextTypeData = { size: 0, align: 0 } + } else { + const sd = structData.get(d.type); + if (sd) { + nextTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign } + } + } } else { const sd = structData.get(nextType) if (sd) { From bc570c172af635ee0a4750713e6e19f2f7eaa6ef Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 13:36:15 -0600 Subject: [PATCH 18/55] bug fixed - the maxAlign didn't remain, so a new smaller value could overwrite an old higher value --- examples/params_test/index.js | 35 ++++++++++++++++++----------------- src/data-size.js | 8 +------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index ecbff252..3ddbd0d0 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -45,23 +45,24 @@ const base = { friction: f32, }; - // struct Ex2 { - // direction: array, - // friction: f32, - // }; - - // struct Ex3 { - // direction: array, - // }; - - // struct ExA { - // orientation: vec3f, - // size: f32, - // scale: f32, - // info: Ex, - // direction: array, - // friction: f32, - // }; + struct Ex2 { + direction: array, + friction: f32, + }; + + struct Ex3 { + direction: array, + }; + + struct ExA { + orientation: vec3f, + size: f32, + scale: f32, + info: Ex, + friction: f32, + direction: array, + direction2: array, + }; `); var endTime = performance.now() diff --git a/src/data-size.js b/src/data-size.js index e6153ace..ed828349 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -153,12 +153,11 @@ export const dataSize = value => { // to obtain the higher max alignment, but this can be also calculated // in the next step structDatum.unique_types.forEach(ut => { - let maxAlign = 0 + let maxAlign = structDatum.maxAlign || 0; // if it doesn't exists in typeSizes is an Array or a new Struct if (!typeSizes[ut]) { if (ut.indexOf('array') != -1) { - const [d] = getArrayTypeAndAmount(ut); const t = typeSizes[d.type] if (t) { @@ -172,9 +171,6 @@ export const dataSize = value => { maxAlign = align > maxAlign ? align : maxAlign; structDatum.maxAlign = maxAlign; } - - - } else { const sd = structData.get(ut) // return; @@ -207,7 +203,6 @@ export const dataSize = value => { if (currentType) { if (currentType.indexOf('array') != -1) { - //TODO: here const [d] = getArrayTypeAndAmount(currentType); const t = typeSizes[d.type] if (t) { @@ -238,7 +233,6 @@ export const dataSize = value => { if (nextType) { if (nextType.indexOf('array') != -1) { - //TODO: here const [d] = getArrayTypeAndAmount(nextType); const t = typeSizes[d.type] if (t) { From 854b123bb19e362d8652486baec7ff667fafb3a6 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 13:39:38 -0600 Subject: [PATCH 19/55] function to verify if string has array in it --- src/data-size.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/data-size.js b/src/data-size.js index ed828349..eace2d35 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -145,6 +145,15 @@ function addBytesToAlign(bytes, aligment) { return result; } +/** + * + * @param {String} value + * @returns {boolean} + */ +function isArray(value) { + return value.indexOf('array') != -1; +} + export const dataSize = value => { const noCommentsValue = removeComments(value); const structData = getStructDataByName(noCommentsValue); @@ -156,7 +165,7 @@ export const dataSize = value => { let maxAlign = structDatum.maxAlign || 0; // if it doesn't exists in typeSizes is an Array or a new Struct if (!typeSizes[ut]) { - if (ut.indexOf('array') != -1) { + if (isArray(ut)) { const [d] = getArrayTypeAndAmount(ut); const t = typeSizes[d.type] @@ -202,7 +211,7 @@ export const dataSize = value => { if (!currentTypeData) { if (currentType) { - if (currentType.indexOf('array') != -1) { + if (isArray(currentType)) { const [d] = getArrayTypeAndAmount(currentType); const t = typeSizes[d.type] if (t) { @@ -232,7 +241,7 @@ export const dataSize = value => { if (!nextTypeData) { if (nextType) { - if (nextType.indexOf('array') != -1) { + if (isArray(nextType)) { const [d] = getArrayTypeAndAmount(nextType); const t = typeSizes[d.type] if (t) { From 90eb9853c39744297ae733f17da5996732d1fbab Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 13:42:19 -0600 Subject: [PATCH 20/55] adding semicolons - also documenting function --- src/data-size.js | 52 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/data-size.js b/src/data-size.js index eace2d35..a7b6101a 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -83,7 +83,7 @@ function removeComments(value) { const matches = value.matchAll(removeCommentsRE); let result = ''; for (const match of matches) { - const captured = match[0] + const captured = match[0]; result += captured; } return result; @@ -104,12 +104,12 @@ function getStructDataByName(value) { const matches = value.matchAll(getStructNameRE); let result = new Map(); for (const match of matches) { - const captured = match[0] + const captured = match[0]; const name = match[1]; const lines = getInsideStruct(captured); const types = lines.map(l => { const right = l.split(':')[1]; - const type = right.slice(',', -1).trim() + const type = right.slice(',', -1).trim(); return type; }) result.set(name, { @@ -134,20 +134,20 @@ function getArrayTypeAndAmount(value) { } function addBytesToAlign(bytes, aligment) { - const remainder = bytes % aligment + const remainder = bytes % aligment; let result = 0; if (remainder !== 0) { // if not multiple we obtain the diff // and add it to byteCounter to make it fit the alignment - const multipleDiff = aligment - remainder - result = bytes = multipleDiff + const multipleDiff = aligment - remainder; + result = bytes = multipleDiff; } return result; } /** - * - * @param {String} value + * Check if string has 'array' in it + * @param {String} value * @returns {boolean} */ function isArray(value) { @@ -168,7 +168,7 @@ export const dataSize = value => { if (isArray(ut)) { const [d] = getArrayTypeAndAmount(ut); - const t = typeSizes[d.type] + const t = typeSizes[d.type]; if (t) { const align = t.align; maxAlign = align > maxAlign ? align : maxAlign; @@ -181,7 +181,7 @@ export const dataSize = value => { structDatum.maxAlign = maxAlign; } } else { - const sd = structData.get(ut) + const sd = structData.get(ut); // return; const align = sd.maxAlign; maxAlign = align > maxAlign ? align : maxAlign; @@ -200,8 +200,8 @@ export const dataSize = value => { structDatum.types.forEach((t, i) => { const currentType = t; const nextType = structDatum.types[i + 1]; - let currentTypeData = typeSizes[currentType] - let nextTypeData = typeSizes[nextType] + let currentTypeData = typeSizes[currentType]; + let nextTypeData = typeSizes[nextType]; // if currentTypeData or nextTypeData have no data it means // it's a struct or an array @@ -213,16 +213,16 @@ export const dataSize = value => { if (currentType) { if (isArray(currentType)) { const [d] = getArrayTypeAndAmount(currentType); - const t = typeSizes[d.type] + const t = typeSizes[d.type]; if (t) { // if array, the size is equal to the align - // currentTypeData = { size: t.align * d.amount, align: t.align } - currentTypeData = { size: t.size * d.amount, align: t.align } - // currentTypeData = { size: 0, align: 0 } + // currentTypeData = { size: t.align * d.amount, align: t.align }; + currentTypeData = { size: t.size * d.amount, align: t.align }; + // currentTypeData = { size: 0, align: 0 }; } else { const sd = structData.get(d.type); if (sd) { - currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign } + currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; } } @@ -230,7 +230,7 @@ export const dataSize = value => { const sd = structData.get(currentType); if (sd) { - currentTypeData = { size: sd.bytes, align: sd.maxAlign } + currentTypeData = { size: sd.bytes, align: sd.maxAlign }; } } @@ -243,21 +243,21 @@ export const dataSize = value => { if (isArray(nextType)) { const [d] = getArrayTypeAndAmount(nextType); - const t = typeSizes[d.type] + const t = typeSizes[d.type]; if (t) { - // nextTypeData = { size: t.align * d.amount, align: t.align } - nextTypeData = { size: t.size * d.amount, align: t.align } - // nextTypeData = { size: 0, align: 0 } + // nextTypeData = { size: t.align * d.amount, align: t.align }; + nextTypeData = { size: t.size * d.amount, align: t.align }; + // nextTypeData = { size: 0, align: 0 }; } else { const sd = structData.get(d.type); if (sd) { - nextTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign } + nextTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; } } } else { const sd = structData.get(nextType) if (sd) { - nextTypeData = { size: sd.bytes, align: sd.maxAlign } + nextTypeData = { size: sd.bytes, align: sd.maxAlign }; } } } @@ -265,7 +265,7 @@ export const dataSize = value => { byteCounter += currentTypeData.size; if ((currentTypeData.size === structDatum.maxAlign) || !nextType) { - return + return; } if (nextTypeData.align == structDatum.maxAlign) { @@ -274,7 +274,7 @@ export const dataSize = value => { }); byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); - structDatum.bytes = byteCounter + structDatum.bytes = byteCounter; } return structData; } From e826e0abee27c597bef30dcc857e293f72afe1d3 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 15:19:34 -0600 Subject: [PATCH 21/55] simplified code a bit removing ifs --- examples/params_test/index.js | 61 +++++++++++++++++++---------------- src/data-size.js | 36 ++++++--------------- 2 files changed, 43 insertions(+), 54 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 3ddbd0d0..00166ddc 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -36,37 +36,44 @@ const base = { var startTime = performance.now() const result = dataSize(` - struct Ex { - velocity: vec3f, - }; - - struct Ex1 { - direction: array, - friction: f32, - }; - - struct Ex2 { - direction: array, - friction: f32, - }; - - struct Ex3 { - direction: array, - }; - - struct ExA { - orientation: vec3f, - size: f32, - scale: f32, - info: Ex, - friction: f32, - direction: array, - direction2: array, - }; + struct Ex { + velocity: vec3f, + }; + + struct Ex1 { + direction: array, + friction: f32, + }; + + struct Ex2 { + direction: array, + friction: f32, + }; + + struct Ex3 { + direction: array, + }; + + struct ExA { + orientation: vec3f, + size: f32, + scale: f32, + info: Ex, + friction: f32, + direction: array, + direction2: array, + }; + + struct Event { + updated: u32, + data: array, + } + `); var endTime = performance.now() console.log(`Call to doSomething took ${endTime - startTime} milliseconds`) + console.log(result); for(let [r,c] of result){ console.log(r,c.bytes) diff --git a/src/data-size.js b/src/data-size.js index a7b6101a..87f49876 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -163,37 +163,24 @@ export const dataSize = value => { // in the next step structDatum.unique_types.forEach(ut => { let maxAlign = structDatum.maxAlign || 0; + let align = 0; // if it doesn't exists in typeSizes is an Array or a new Struct if (!typeSizes[ut]) { if (isArray(ut)) { - const [d] = getArrayTypeAndAmount(ut); - const t = typeSizes[d.type]; - if (t) { - const align = t.align; - maxAlign = align > maxAlign ? align : maxAlign; - structDatum.maxAlign = maxAlign; - - } else { - const sd = structData.get(d.type); - const align = sd.maxAlign; - maxAlign = align > maxAlign ? align : maxAlign; - structDatum.maxAlign = maxAlign; - } + // if it's not in tySizes is an struct, + //therefore probably stored in structData + const t = typeSizes[d.type] || structData.get(d.type); + align = t.align || t.maxAlign; } else { const sd = structData.get(ut); - // return; - const align = sd.maxAlign; - maxAlign = align > maxAlign ? align : maxAlign; - structDatum.maxAlign = maxAlign; + align = sd.maxAlign; } - } else { - const align = typeSizes[ut].align; - maxAlign = align > maxAlign ? align : maxAlign; - structDatum.maxAlign = maxAlign; + align = typeSizes[ut].align; } - + maxAlign = align > maxAlign ? align : maxAlign; + structDatum.maxAlign = maxAlign; }); let byteCounter = 0; @@ -209,7 +196,6 @@ export const dataSize = value => { // because it was calculated previously // assuming the struct was declared previously if (!currentTypeData) { - if (currentType) { if (isArray(currentType)) { const [d] = getArrayTypeAndAmount(currentType); @@ -225,9 +211,7 @@ export const dataSize = value => { currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; } } - } else { - const sd = structData.get(currentType); if (sd) { currentTypeData = { size: sd.bytes, align: sd.maxAlign }; @@ -235,12 +219,10 @@ export const dataSize = value => { } } - } // read above if (!nextTypeData) { if (nextType) { - if (isArray(nextType)) { const [d] = getArrayTypeAndAmount(nextType); const t = typeSizes[d.type]; From d65a0eef98b28c6a0bf173009951b27ce78f6e68 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 18:54:48 -0600 Subject: [PATCH 22/55] Checking arrays separately - If they are arrays check the last colon, check for spaces, and if there's a value at at the end of the type because that means something different later --- examples/params_test/index.js | 58 +++++++++++++++++------------------ src/data-size.js | 12 +++++++- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 00166ddc..47093b7a 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -36,38 +36,38 @@ const base = { var startTime = performance.now() const result = dataSize(` - struct Ex { - velocity: vec3f, - }; - - struct Ex1 { - direction: array, - friction: f32, - }; - - struct Ex2 { - direction: array, - friction: f32, - }; - - struct Ex3 { - direction: array, - }; - - struct ExA { - orientation: vec3f, - size: f32, - scale: f32, - info: Ex, - friction: f32, - direction: array, - direction2: array, - }; + // struct Ex { + // velocity: vec3f , + // }; + + // struct Ex1 { + // direction: array, + // friction: f32, + // }; + + // struct Ex2 { + // direction: array, + // friction: f32, + // }; + + // struct Ex3 { + // direction: array, + // }; + + // struct ExA { + // orientation: vec3f, + // size: f32, + // scale: f32, + // info: Ex, + // friction: f32, + // direction: array, + // direction2: array, + // }; struct Event { updated: u32, - data: array, - } + data: array + } `); var endTime = performance.now() diff --git a/src/data-size.js b/src/data-size.js index 87f49876..cbd7d036 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -77,6 +77,8 @@ const insideStructRE = /struct\s+?\w+\s*{([^}]+)}\n?/g const arrayTypeAndAmountRE = /\s*<\s*([^,]+)\s*,\s*(\d+)\s*>/g +const arrayIntegrityRE = /\s*(array\s*<\s*\w+\s*(?:,\s*\d+)?\s*>)\s*,?/g + // you have to separete the result by splitting new lines function removeComments(value) { @@ -109,9 +111,17 @@ function getStructDataByName(value) { const lines = getInsideStruct(captured); const types = lines.map(l => { const right = l.split(':')[1]; - const type = right.slice(',', -1).trim(); + console.log(right); + let type = ''; + if (isArray(right)) { + const arrayMatch = right.matchAll(arrayIntegrityRE); + type = arrayMatch.next().value[1]; + } else { + type = right.split(',')[0].trim(); + } return type; }) + console.log(types); result.set(name, { captured, lines, From 14f5159f83bdf81d8aca44116667c6c244120c0e Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 19:19:31 -0600 Subject: [PATCH 23/55] Check if array has an amount - If there's no amount it should ignore it because the array is dynamic --- examples/params_test/index.js | 2 +- src/data-size.js | 71 +++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 47093b7a..95a0fad5 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -66,7 +66,7 @@ const base = { struct Event { updated: u32, - data: array + data: array } `); diff --git a/src/data-size.js b/src/data-size.js index cbd7d036..de2b0f2d 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -75,7 +75,7 @@ const getStructNameRE = /struct\s+?(\w+)\s*{[^}]+}\n?/g // what's inside a struct: const insideStructRE = /struct\s+?\w+\s*{([^}]+)}\n?/g -const arrayTypeAndAmountRE = /\s*<\s*([^,]+)\s*,\s*(\d+)\s*>/g +const arrayTypeAndAmountRE = /\s*<\s*([^,]+)\s*,?\s*(\d+)?\s*>/g const arrayIntegrityRE = /\s*(array\s*<\s*\w+\s*(?:,\s*\d+)?\s*>)\s*,?/g @@ -178,10 +178,13 @@ export const dataSize = value => { if (!typeSizes[ut]) { if (isArray(ut)) { const [d] = getArrayTypeAndAmount(ut); - // if it's not in tySizes is an struct, - //therefore probably stored in structData - const t = typeSizes[d.type] || structData.get(d.type); - align = t.align || t.maxAlign; + console.log(d) + if(!!d.amount){ + // if it's not in tySizes is an struct, + //therefore probably stored in structData + const t = typeSizes[d.type] || structData.get(d.type); + align = t.align || t.maxAlign; + } } else { const sd = structData.get(ut); align = sd.maxAlign; @@ -209,16 +212,18 @@ export const dataSize = value => { if (currentType) { if (isArray(currentType)) { const [d] = getArrayTypeAndAmount(currentType); - const t = typeSizes[d.type]; - if (t) { - // if array, the size is equal to the align - // currentTypeData = { size: t.align * d.amount, align: t.align }; - currentTypeData = { size: t.size * d.amount, align: t.align }; - // currentTypeData = { size: 0, align: 0 }; - } else { - const sd = structData.get(d.type); - if (sd) { - currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; + if(!!d.amount){ + const t = typeSizes[d.type]; + if (t) { + // if array, the size is equal to the align + // currentTypeData = { size: t.align * d.amount, align: t.align }; + currentTypeData = { size: t.size * d.amount, align: t.align }; + // currentTypeData = { size: 0, align: 0 }; + } else { + const sd = structData.get(d.type); + if (sd) { + currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; + } } } } else { @@ -235,15 +240,17 @@ export const dataSize = value => { if (nextType) { if (isArray(nextType)) { const [d] = getArrayTypeAndAmount(nextType); - const t = typeSizes[d.type]; - if (t) { - // nextTypeData = { size: t.align * d.amount, align: t.align }; - nextTypeData = { size: t.size * d.amount, align: t.align }; - // nextTypeData = { size: 0, align: 0 }; - } else { - const sd = structData.get(d.type); - if (sd) { - nextTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; + if(!!d.amount){ + const t = typeSizes[d.type]; + if (t) { + // nextTypeData = { size: t.align * d.amount, align: t.align }; + nextTypeData = { size: t.size * d.amount, align: t.align }; + // nextTypeData = { size: 0, align: 0 }; + } else { + const sd = structData.get(d.type); + if (sd) { + nextTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; + } } } } else { @@ -255,13 +262,19 @@ export const dataSize = value => { } } - byteCounter += currentTypeData.size; - if ((currentTypeData.size === structDatum.maxAlign) || !nextType) { - return; + console.log(currentTypeData, currentType); + if(!!currentTypeData){ + byteCounter += currentTypeData.size; + if ((currentTypeData.size === structDatum.maxAlign) || !nextType) { + return; + } } - if (nextTypeData.align == structDatum.maxAlign) { - byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); + console.log(nextTypeData, nextType); + if(!!nextTypeData){ + if (nextTypeData.align == structDatum.maxAlign) { + byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); + } } }); From 2aff8e8af7119491058824382a2bdccf762f4f3a Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 19:39:55 -0600 Subject: [PATCH 24/55] Checks if type exists and 0 mounts to throw errors --- examples/params_test/index.js | 8 ++++---- src/data-size.js | 26 +++++++++++++++----------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 95a0fad5..0da2cd81 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -36,9 +36,9 @@ const base = { var startTime = performance.now() const result = dataSize(` - // struct Ex { - // velocity: vec3f , - // }; + struct Ex { + velocity: vec3f , + }; // struct Ex1 { // direction: array, @@ -66,7 +66,7 @@ const base = { struct Event { updated: u32, - data: array + data: array } `); diff --git a/src/data-size.js b/src/data-size.js index de2b0f2d..a7a016b7 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -111,7 +111,6 @@ function getStructDataByName(value) { const lines = getInsideStruct(captured); const types = lines.map(l => { const right = l.split(':')[1]; - console.log(right); let type = ''; if (isArray(right)) { const arrayMatch = right.matchAll(arrayIntegrityRE); @@ -121,7 +120,6 @@ function getStructDataByName(value) { } return type; }) - console.log(types); result.set(name, { captured, lines, @@ -178,11 +176,13 @@ export const dataSize = value => { if (!typeSizes[ut]) { if (isArray(ut)) { const [d] = getArrayTypeAndAmount(ut); - console.log(d) - if(!!d.amount){ + const t = typeSizes[d.type] || structData.get(d.type); + if (!t) { + throw new Error(`${d.type} type has not been declared previously`) + } + if (!!d.amount) { // if it's not in tySizes is an struct, //therefore probably stored in structData - const t = typeSizes[d.type] || structData.get(d.type); align = t.align || t.maxAlign; } } else { @@ -212,7 +212,10 @@ export const dataSize = value => { if (currentType) { if (isArray(currentType)) { const [d] = getArrayTypeAndAmount(currentType); - if(!!d.amount){ + if (d.amount == 0) { + throw new Error(`${currentType} has an amount of 0`); + } + if (!!d.amount) { const t = typeSizes[d.type]; if (t) { // if array, the size is equal to the align @@ -240,7 +243,10 @@ export const dataSize = value => { if (nextType) { if (isArray(nextType)) { const [d] = getArrayTypeAndAmount(nextType); - if(!!d.amount){ + if (d.amount == 0) { + throw new Error(`${nextType} has an amount of 0`); + } + if (!!d.amount) { const t = typeSizes[d.type]; if (t) { // nextTypeData = { size: t.align * d.amount, align: t.align }; @@ -262,16 +268,14 @@ export const dataSize = value => { } } - console.log(currentTypeData, currentType); - if(!!currentTypeData){ + if (!!currentTypeData) { byteCounter += currentTypeData.size; if ((currentTypeData.size === structDatum.maxAlign) || !nextType) { return; } } - console.log(nextTypeData, nextType); - if(!!nextTypeData){ + if (!!nextTypeData) { if (nextTypeData.align == structDatum.maxAlign) { byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); } From ddb883ad3d4d2c605150d2c3cd9990734e6c7aa0 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 19:47:47 -0600 Subject: [PATCH 25/55] Extra check for alignment if array has a struct - The alignment has diff rule for the alignment if the array type is a struct --- examples/params_test/index.js | 2 +- src/data-size.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 0da2cd81..4cc3d258 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -66,7 +66,7 @@ const base = { struct Event { updated: u32, - data: array + data: array } `); diff --git a/src/data-size.js b/src/data-size.js index a7a016b7..f16f3876 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -184,6 +184,12 @@ export const dataSize = value => { // if it's not in tySizes is an struct, //therefore probably stored in structData align = t.align || t.maxAlign; + } else { + // check if strucData and get the align + const t = structData.get(d.type) + if (t) { + align = t.maxAlign; + } } } else { const sd = structData.get(ut); From 3f578137638eb4b0c8e5dffdd5d02e11055f5534 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 3 Dec 2023 19:50:47 -0600 Subject: [PATCH 26/55] amount check not actually required --- examples/params_test/index.js | 2 +- src/data-size.js | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 4cc3d258..5422d866 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -66,7 +66,7 @@ const base = { struct Event { updated: u32, - data: array + data: array } `); diff --git a/src/data-size.js b/src/data-size.js index f16f3876..d9c92238 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -180,17 +180,11 @@ export const dataSize = value => { if (!t) { throw new Error(`${d.type} type has not been declared previously`) } - if (!!d.amount) { - // if it's not in tySizes is an struct, - //therefore probably stored in structData - align = t.align || t.maxAlign; - } else { - // check if strucData and get the align - const t = structData.get(d.type) - if (t) { - align = t.maxAlign; - } - } + + // if it's not in typeSizes is a struct, + //therefore probably stored in structData + align = t.align || t.maxAlign; + } else { const sd = structData.get(ut); align = sd.maxAlign; From a7184e37ab90d769d28e3d5cb06aad18770a03f2 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Mon, 4 Dec 2023 20:52:48 -0600 Subject: [PATCH 27/55] Progress on binding data-size with Points - There's an issue and it's that the data needs the padding, you can't just send the data plainly --- examples/params_test/frag.js | 2 +- examples/params_test/index.js | 91 +++++++++++++++++++++++------------ src/absulit.points.module.js | 35 +++++++++++--- src/data-size.js | 4 +- 4 files changed, 91 insertions(+), 41 deletions(-) diff --git a/examples/params_test/frag.js b/examples/params_test/frag.js index 0ff363ae..3fe36cd9 100644 --- a/examples/params_test/frag.js +++ b/examples/params_test/frag.js @@ -30,7 +30,7 @@ fn main( finalColor = variables.color; - return finalColor; + return params.test3; } `; diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 5422d866..e24a7462 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -36,38 +36,69 @@ const base = { var startTime = performance.now() const result = dataSize(` - struct Ex { - velocity: vec3f , - }; - // struct Ex1 { - // direction: array, - // friction: f32, - // }; - - // struct Ex2 { - // direction: array, - // friction: f32, - // }; - - // struct Ex3 { - // direction: array, - // }; - - // struct ExA { - // orientation: vec3f, - // size: f32, - // scale: f32, - // info: Ex, - // friction: f32, - // direction: array, - // direction2: array, - // }; - - struct Event { - updated: u32, - data: array + struct Light { + mode: u32, + power: f32, + range: f32, + innerAngle: f32, + outerAngle: f32, + direction: vec3f, + position: vec3f, + }; + + struct FSInput { + colorMult: vec4f, + specularFactor: f32, + lights: array, + }; + + struct VSInput { + projectionMatrix: mat4x4f, + viewMatrix: mat4x4f, + modelMatrix: mat4x4f, + normalMatrix: mat4x4f, + }; + + @group(0) @binding(0) var vsUni: VSInput; + @group(0) @binding(1) var fsUni: FSInput; + @group(0) @binding(2) var diffuseSampler: sampler; + @group(0) @binding(3) var diffuseTexture: texture_2d; + + struct Attribs { + @location(0) position: vec4f, + @location(1) normal: vec3f, + @location(2) texcoord: vec2f, + }; + + struct VSOutput { + @builtin(position) position: vec4f, + @location(0) texcoord: vec2f, + @location(1) normal: vec3f, + }; + + @vertex fn vs(vin: Attribs) -> VSOutput { + var vout: VSOutput; + vout.position = vsUni.projectionMatrix * vsUni.viewMatrix * vsUni.modelMatrix * vin.position; + vout.texcoord = vin.texcoord; + vout.normal = (vsUni.normalMatrix * vec4f(vin.normal, 0)).xyz; + return vout; + } + + @fragment fn fs(vout: VSOutput) -> @location(0) vec4f { + let normal = normalize(vout.normal); + var l = 0.0; + for (var i = 0; i < 2; i++) { + let light = fsUni.lights[i]; + l += clamp(dot(normal, light.direction), 0.0, 1.0); + } + + let color = textureSample(diffuseTexture, diffuseSampler, vout.texcoord); + return vec4f(color.rgb * clamp(l, 0.0, 1.0), color.a); } + + + `); var endTime = performance.now() diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index c52ae278..6fca53af 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -6,6 +6,7 @@ import Coordinate from './coordinate.js'; import RGBAColor from './color.js'; import defaultStructs from './core/defaultStructs.js'; import { defaultVertexBody } from './core/defaultFunctions.js'; +import { dataSize, typeSizes } from './data-size.js'; export default class Points { constructor(canvasId) { @@ -724,10 +725,10 @@ export default class Points { let dynamicGroupBindingsFragment = ''; let dynamicStructParams = ''; - this._uniforms.forEach(variable => { - // console.log(variable) - let uniformType = variable.type || 'f32'; - dynamicStructParams += /*wgsl*/`${variable.name}:${uniformType}, \n\t`; + this._uniforms.forEach(u => { + console.log(u) + u.type = u.type || 'f32'; + dynamicStructParams += /*wgsl*/`${u.name}:${u.type}, \n\t`; }); if (this._uniforms.length) { @@ -763,6 +764,18 @@ export default class Points { renderPass.hasVertexShader && (renderPass.compiledShaders.vertex = colorsVertWGSL); renderPass.hasComputeShader && (renderPass.compiledShaders.compute = colorsComputeWGSL); renderPass.hasFragmentShader && (renderPass.compiledShaders.fragment = colorsFragWGSL); + + renderPass.dataSize = dataSize(colorsVertWGSL + colorsComputeWGSL + colorsFragWGSL) + console.log(renderPass.dataSize); + + // since uniforms are in a sigle struct + // this is only required for storage + this._storage.forEach(s => { + if (!s.mapped) { + const d = renderPass.dataSize.get(s.structName); + s.structSize = d.bytes; + } + }); } /** @@ -880,10 +893,12 @@ export default class Points { * @param {Boolean} mappedAtCreation * @returns mapped buffer */ - _createAndMapBuffer(data, usage, mappedAtCreation = true) { + _createAndMapBuffer(data, usage, mappedAtCreation = true, size) { + // const paramsDataSize = this._renderPasses[0].dataSize.get('Params') + // console.log(data.byteLength, size, data); const buffer = this._device.createBuffer({ mappedAtCreation: mappedAtCreation, - size: data.byteLength, + size: size || data.byteLength , usage: usage, }); @@ -911,8 +926,12 @@ export default class Points { /** @private */ _createParametersUniforms() { const values = new Float32Array(this._uniforms.map(v => v.value).flat(1)); - // console.log(values) - this._uniforms.buffer = this._createAndMapBuffer(values, GPUBufferUsage.UNIFORM); + console.log(values) + + const paramsDataSize = this._renderPasses[0].dataSize.get('Params') + // console.log(data.byteLength, paramsDataSize.bytes); + + this._uniforms.buffer = this._createAndMapBuffer(values, GPUBufferUsage.UNIFORM, true, paramsDataSize.bytes); // console.log(this._uniforms.buffer) // debugger diff --git a/src/data-size.js b/src/data-size.js index d9c92238..0ba27647 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -10,7 +10,7 @@ const size_48_align_16 = { size: 48, align: 16 }; const size_32_align_16 = { size: 32, align: 16 }; const size_64_align_16 = { size: 64, align: 16 }; -const typeSizes = { +export const typeSizes = { 'bool': size_4_align_4, 'f32': size_4_align_4, 'i32': size_4_align_4, @@ -165,8 +165,8 @@ function isArray(value) { export const dataSize = value => { const noCommentsValue = removeComments(value); const structData = getStructDataByName(noCommentsValue); + console.log('----- A: ', typeSizes[value]); for (const [structDatumKey, structDatum] of structData) { - // to obtain the higher max alignment, but this can be also calculated // in the next step structDatum.unique_types.forEach(ut => { From 61c221a8955a386ab9ff56cc219738398057d813 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Tue, 5 Dec 2023 19:28:28 -0600 Subject: [PATCH 28/55] list of variable names --- src/data-size.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/data-size.js b/src/data-size.js index 0ba27647..812558d6 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -119,12 +119,21 @@ function getStructDataByName(value) { type = right.split(',')[0].trim(); } return type; - }) + }); + + const names = lines.map(l => { + const left = l.split(':')[0]; + let name = ''; + name = left.split(',')[0].trim(); + return name; + }); + result.set(name, { captured, lines, types, - unique_types: [...new Set(types)] + unique_types: [...new Set(types)], + names, }); } return result; From 6eb77bf6dcebb819f6a624ca0cd94e6b8dcfea7e Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Tue, 5 Dec 2023 20:13:47 -0600 Subject: [PATCH 29/55] padding counter --- src/data-size.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/data-size.js b/src/data-size.js index 812558d6..e1f7095a 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -207,11 +207,14 @@ export const dataSize = value => { let byteCounter = 0; structDatum.types.forEach((t, i) => { + const name = structDatum.names[i]; const currentType = t; const nextType = structDatum.types[i + 1]; let currentTypeData = typeSizes[currentType]; let nextTypeData = typeSizes[nextType]; + structDatum.paddings = structDatum.paddings || {}; + // if currentTypeData or nextTypeData have no data it means // it's a struct or an array // if it's a struct the data is already saved in structData @@ -286,7 +289,9 @@ export const dataSize = value => { if (!!nextTypeData) { if (nextTypeData.align == structDatum.maxAlign) { + const lastByteCounter = byteCounter; byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); + structDatum.paddings[name] = (byteCounter - lastByteCounter) / 4; } } }); From 1cf836aee6026245bc3fae1e6cc0b2637430b887 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Tue, 5 Dec 2023 20:42:52 -0600 Subject: [PATCH 30/55] connecting data-size to points - Now data-size calculates the uniform sizes - Needs more testing and removal of extra non needed params - Also check on other functions that send data to the GPU --- examples/params_test/index.js | 21 +-------------------- src/absulit.points.module.js | 27 +++++++++++++++++---------- src/data-size.js | 2 +- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index e24a7462..46eaa77d 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -2,8 +2,6 @@ import vert from './vert.js'; import compute from './compute.js'; import frag from './frag.js'; import Points from '../../src/absulit.points.module.js'; -// import { wgslTypeSize } from '../../src/wgslTypeSize.js'; -import { makeShaderDataDefinitions } from './../../src/data-definitions.js'; import { dataSize } from '../../src/data-size.js'; const base = { @@ -15,24 +13,7 @@ const base = { * @param {Points} points */ init: async points => { - // console.log(makeShaderDataDefinitions(`struct Params { - // sliderA:f32, - // sliderB:f32, - // sliderC:f32, - // test3:vec4f, - // time:f32, - // epoch:f32, - // screenWidth:f32, - // screenHeight:f32, - // mouseX:f32, - // mouseY:f32, - // mouseClick:f32, - // mouseDown:f32, - // mouseWheel:f32, - // mouseDeltaX:f32, - // mouseDeltaY:f32, - - // }`)) + var startTime = performance.now() const result = dataSize(` diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 6fca53af..ee15dde9 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -726,7 +726,6 @@ export default class Points { let dynamicStructParams = ''; this._uniforms.forEach(u => { - console.log(u) u.type = u.type || 'f32'; dynamicStructParams += /*wgsl*/`${u.name}:${u.type}, \n\t`; }); @@ -898,7 +897,7 @@ export default class Points { // console.log(data.byteLength, size, data); const buffer = this._device.createBuffer({ mappedAtCreation: mappedAtCreation, - size: size || data.byteLength , + size: size || data.byteLength, usage: usage, }); @@ -925,16 +924,24 @@ export default class Points { /** @private */ _createParametersUniforms() { - const values = new Float32Array(this._uniforms.map(v => v.value).flat(1)); - console.log(values) - const paramsDataSize = this._renderPasses[0].dataSize.get('Params') - // console.log(data.byteLength, paramsDataSize.bytes); - - this._uniforms.buffer = this._createAndMapBuffer(values, GPUBufferUsage.UNIFORM, true, paramsDataSize.bytes); - // console.log(this._uniforms.buffer) - // debugger + const paddings = paramsDataSize.paddings; + + // we check the paddings list and add 0's to just the ones that need it + const values = new Float32Array(this._uniforms.map(v => { + const padding = paddings[v.name]; + if (padding) { + if (v.value.constructor !== Array) { + v.value = [v.value]; + } + for (let i = 0; i < padding; i++) { + v.value.push(0); + } + } + return v.value; + }).flat(1)); + this._uniforms.buffer = this._createAndMapBuffer(values, GPUBufferUsage.UNIFORM, true, paramsDataSize.bytes); } /** @private */ diff --git a/src/data-size.js b/src/data-size.js index e1f7095a..30a32302 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -174,7 +174,7 @@ function isArray(value) { export const dataSize = value => { const noCommentsValue = removeComments(value); const structData = getStructDataByName(noCommentsValue); - console.log('----- A: ', typeSizes[value]); + for (const [structDatumKey, structDatum] of structData) { // to obtain the higher max alignment, but this can be also calculated // in the next step From 3a0804da7bd273cd50be3e3dc7327836eed3d41e Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Wed, 6 Dec 2023 18:54:01 -0600 Subject: [PATCH 31/55] missing check if struct does not exist - If no struct is found then you have to check the default sizes - Maybe it should return that by default --- examples/params_test/index.js | 2 +- src/absulit.points.module.js | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 46eaa77d..880daaa5 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -98,7 +98,7 @@ const base = { points.addStorage('variables', 1, 'Variable', 32); points.addStorage('test2', 1, 'TestStruct', 32); - points.addUniform('test3', [1, 0, 0, 1], 'vec4f', 16) + points.addUniform('test3', [1, 0, 0, 1], 'vec4f'); }, diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index ee15dde9..8ce50433 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -204,9 +204,10 @@ export default class Points { * from the outside, and unless changed it remains * consistent. To change it use `updateUniform()` * @param {string} name name of the Param, you can invoke it later in shaders as `Params.[name]` - * @param {Number} value Number will be converted to `f32` + * @param {Number|Array} value Single number or a list of numbers + * @param {string} structName type as `f32` or a custom struct */ - addUniform(name, value, structName, structSize) { + addUniform(name, value, structName) { if (this._nameExists(this._uniforms, name)) { return; } @@ -215,7 +216,7 @@ export default class Points { name: name, value: value, type: structName, - size: structSize, + size: null, internal: this._internal }); } @@ -771,8 +772,8 @@ export default class Points { // this is only required for storage this._storage.forEach(s => { if (!s.mapped) { - const d = renderPass.dataSize.get(s.structName); - s.structSize = d.bytes; + const d = renderPass.dataSize.get(s.structName) || typeSizes[s.structName]; + s.structSize = d.bytes || d.size; } }); } From 366b6580e55de0e3eacc2defaf780f28d710fe26 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Wed, 6 Dec 2023 19:27:58 -0600 Subject: [PATCH 32/55] Edge case for array - If array has no amount it still needs a default size and alignment --- src/absulit.points.module.js | 1 - src/data-size.js | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 8ce50433..2fbbaaab 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -766,7 +766,6 @@ export default class Points { renderPass.hasFragmentShader && (renderPass.compiledShaders.fragment = colorsFragWGSL); renderPass.dataSize = dataSize(colorsVertWGSL + colorsComputeWGSL + colorsFragWGSL) - console.log(renderPass.dataSize); // since uniforms are in a sigle struct // this is only required for storage diff --git a/src/data-size.js b/src/data-size.js index 30a32302..bf87a842 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -240,6 +240,9 @@ export const dataSize = value => { currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; } } + } else { + // if is an array with no amount then use these default values + currentTypeData = { size: 16, align: 16 }; } } else { const sd = structData.get(currentType); From 155ef00532d1256d3d1503117c4854b73384027e Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Wed, 6 Dec 2023 19:53:49 -0600 Subject: [PATCH 33/55] mouse and screen changed to vec2 - With the power of dataSize we can do things like that now --- README.md | 4 ++-- examples/audio1/frag.js | 2 +- examples/audio2/frag.js | 2 +- examples/base/frag.js | 2 +- examples/basic.html | 2 +- examples/events1/frag.js | 2 +- examples/mouseclickscroll1/frag.js | 2 +- examples/pointstitle1/frag.js | 12 +++++------ examples/random3/compute.js | 4 ++-- examples/renderpasses1/renderpass1/frag.js | 2 +- examples/renderpasses1/renderpass2/frag.js | 2 +- examples/renderpasses2/renderpass1/frag.js | 2 +- examples/shapes2/compute.js | 6 +++--- examples/spritesheet1/frag.js | 8 +++---- src/UniformKeys.js | 6 ++---- src/absulit.points.module.js | 21 ++++++++++++------- src/core/RenderPasses/bloom/frag.js | 2 +- src/core/RenderPasses/blur/frag.js | 2 +- .../RenderPasses/chromaticAberration/frag.js | 2 +- src/core/RenderPasses/color/frag.js | 2 +- src/core/RenderPasses/filmgrain/frag.js | 2 +- src/core/RenderPasses/grayscale/frag.js | 2 +- src/core/RenderPasses/lensDistortion/frag.js | 2 +- src/core/RenderPasses/pixelate/frag.js | 2 +- src/core/RenderPasses/waves/frag.js | 2 +- src/core/debug.js | 4 ++-- src/core/defaultFunctions.js | 6 +++--- src/core/image.js | 16 +++++++------- src/core/valuenoise.js | 4 ++-- 29 files changed, 65 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index fc0640e8..78e0515f 100644 --- a/README.md +++ b/README.md @@ -281,7 +281,7 @@ fn main( } ``` -The `defaultVertexBody` returns a `Fragment` struct that provides the parameters for `frag.js` , it adds a ratio parameter with the ratio of the width and height of the canvas, and the mouse position as a `vec2` . The mouse position is different from the `params.mouseX` and `params.mouseY` , but it uses its values to calculate them in the UV space. The uv is ratio corrected, meaning that if your canvas is wider than taller, a portion of the uv will be out of bounds to mantain the aspect ratio. This might change later to a new uv[some name] to differentiate them, and still have the regular uv space to calculate the screen. Right now if you need to do that in a different canvas size rather than a 1:1 dimension, you have to use ratio to deconstruct the original value. +The `defaultVertexBody` returns a `Fragment` struct that provides the parameters for `frag.js` , it adds a ratio parameter with the ratio of the width and height of the canvas, and the mouse position as a `vec2` . The mouse position is different from the `params.mouse.x` and `params.mouse.y` , but it uses its values to calculate them in the UV space. The uv is ratio corrected, meaning that if your canvas is wider than taller, a portion of the uv will be out of bounds to mantain the aspect ratio. This might change later to a new uv[some name] to differentiate them, and still have the regular uv space to calculate the screen. Right now if you need to do that in a different canvas size rather than a 1:1 dimension, you have to use ratio to deconstruct the original value. ```rust // defaultStructs.js @@ -289,7 +289,7 @@ struct Fragment { @builtin(position) position: vec4, @location(0) color: vec4, // vertex color @location(1) uv: vec2, // uv coordinate - @location(2) ratio: vec2, // relation between `params.screenWidth` and `params.screenHeight` + @location(2) ratio: vec2, // relation between `params.screen.x` and `params.screen.y` @location(3) uvr: vec2, // uv with aspect ratio corrected using `ratio` @location(4) mouse: vec2 // mouse coordinates normalized between 0..1 } diff --git a/examples/audio1/frag.js b/examples/audio1/frag.js index e2cc6423..d71e277a 100644 --- a/examples/audio1/frag.js +++ b/examples/audio1/frag.js @@ -19,7 +19,7 @@ ${RED} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/examples/audio2/frag.js b/examples/audio2/frag.js index fedb157a..50bf57da 100644 --- a/examples/audio2/frag.js +++ b/examples/audio2/frag.js @@ -23,7 +23,7 @@ ${texturePosition} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/examples/base/frag.js b/examples/base/frag.js index 89df7845..af964bb5 100644 --- a/examples/base/frag.js +++ b/examples/base/frag.js @@ -8,7 +8,7 @@ ${fnusin} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/examples/basic.html b/examples/basic.html index 9d73b7b5..f80c9b47 100644 --- a/examples/basic.html +++ b/examples/basic.html @@ -41,7 +41,7 @@ fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/examples/events1/frag.js b/examples/events1/frag.js index 3fec0c20..156d41cd 100644 --- a/examples/events1/frag.js +++ b/examples/events1/frag.js @@ -10,7 +10,7 @@ ${WHITE + RED + GREEN + BLUE + YELLOW} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/examples/mouseclickscroll1/frag.js b/examples/mouseclickscroll1/frag.js index 59b1e917..1432390f 100644 --- a/examples/mouseclickscroll1/frag.js +++ b/examples/mouseclickscroll1/frag.js @@ -16,7 +16,7 @@ ${RED + GREEN} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/examples/pointstitle1/frag.js b/examples/pointstitle1/frag.js index 59f21dcb..db3638cc 100644 --- a/examples/pointstitle1/frag.js +++ b/examples/pointstitle1/frag.js @@ -25,7 +25,7 @@ const CHROMATICDISPLACEMENT = 0.003695; fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 @@ -38,16 +38,16 @@ fn main( let subuv = fract(uvr * vec2(numColumns, numRows)); let subuvColor = vec4(subuv, 0, 1); - let pixelsWidth = params.screenWidth / numColumns; - let pixelsHeight = params.screenHeight / numRows; - let dx = pixelsWidth * (1. / params.screenWidth); - let dy = pixelsHeight * (1. / params.screenHeight); + let pixelsWidth = params.screen.x / numColumns; + let pixelsHeight = params.screen.y / numRows; + let dx = pixelsWidth * (1. / params.screen.x); + let dy = pixelsHeight * (1. / params.screen.y); let pixeleduv = vec2(dx*floor( uvr.x / dx), dy * floor( uvr.y / dy)); let pixeleduvColor = vec4(pixeleduv, 0, 1); let fontPosition = vec2(0.,0.); let charSize = vec2(8u,22u); - let charSizeF32 = vec2(f32(charSize.x) / params.screenWidth, f32(charSize.y) / params.screenHeight); + let charSizeF32 = vec2(f32(charSize.x) / params.screen.x, f32(charSize.y) / params.screen.y); let charAIndex = 33u; // A let chars = array(15,14,8,13,19,18); diff --git a/examples/random3/compute.js b/examples/random3/compute.js index 53675adb..b8d6c0b8 100644 --- a/examples/random3/compute.js +++ b/examples/random3/compute.js @@ -18,8 +18,8 @@ fn main( @builtin(local_invocation_id) LocalInvocationID: vec3 ) { - let numColumns:f32 = params.screenWidth; - let numRows:f32 = params.screenHeight; + let numColumns:f32 = params.screen.x; + let numRows:f32 = params.screen.y; rand_seed.x += f32(WorkGroupID.x); rand_seed.y += f32(WorkGroupID.y); diff --git a/examples/renderpasses1/renderpass1/frag.js b/examples/renderpasses1/renderpass1/frag.js index 00966c0c..3affbd1e 100644 --- a/examples/renderpasses1/renderpass1/frag.js +++ b/examples/renderpasses1/renderpass1/frag.js @@ -10,7 +10,7 @@ ${fusin} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/examples/renderpasses1/renderpass2/frag.js b/examples/renderpasses1/renderpass2/frag.js index 5521c271..3e65863f 100644 --- a/examples/renderpasses1/renderpass2/frag.js +++ b/examples/renderpasses1/renderpass2/frag.js @@ -16,7 +16,7 @@ ${blur9} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/examples/renderpasses2/renderpass1/frag.js b/examples/renderpasses2/renderpass1/frag.js index aced6a82..5bfa6c0f 100644 --- a/examples/renderpasses2/renderpass1/frag.js +++ b/examples/renderpasses2/renderpass1/frag.js @@ -10,7 +10,7 @@ ${fusin} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/examples/shapes2/compute.js b/examples/shapes2/compute.js index 21c4f8c6..4f552d12 100644 --- a/examples/shapes2/compute.js +++ b/examples/shapes2/compute.js @@ -17,7 +17,7 @@ struct Colors{ } fn getPointsIndex(position:vec2) -> u32{ - return position.y + (position.x * u32(params.screenWidth)); + return position.y + (position.x * u32(params.screen.x)); } fn getColorAt(position:vec2) -> vec4 { @@ -59,8 +59,8 @@ fn main( @builtin(workgroup_id) WorkGroupID: vec3, @builtin(local_invocation_id) LocalInvocationID: vec3 ) { - let numColumns:f32 = params.screenWidth; - let numRows:f32 = params.screenHeight; + let numColumns:f32 = params.screen.x; + let numRows:f32 = params.screen.y; var x = 450.; var y = 450.; diff --git a/examples/spritesheet1/frag.js b/examples/spritesheet1/frag.js index 757a4ae2..81bb320a 100644 --- a/examples/spritesheet1/frag.js +++ b/examples/spritesheet1/frag.js @@ -35,17 +35,17 @@ fn main( let size = vec2(8u,22u); let sizeF32 = vec2(f32(size.x),f32(size.y)); - let cellRatio = vec2(sizeF32.x/params.screenWidth,sizeF32.y/params.screenHeight)*ratio; + let cellRatio = vec2(sizeF32.x/params.screen.x,sizeF32.y/params.screen.y)*ratio; let displaceInX = vec2(cellRatio.x, 0); let start0char = 16u; - var numberToDecode = params.mouseX; + var numberToDecode = params.mouse.x; let digits = RED * decodeNumberSprite(numberToDecode, start0char, image, imageSampler, startPosition, uvr * scaleDigits, ratio, size).r; // ----------------------------------------------- - numberToDecode = params.mouseY; - let startPosition2 = startPosition - vec2(0, sizeF32.x/params.screenHeight)*ratio; + numberToDecode = params.mouse.y; + let startPosition2 = startPosition - vec2(0, sizeF32.x/params.screen.y)*ratio; let digits2 = GREEN * decodeNumberSprite(numberToDecode, start0char, image, imageSampler, startPosition2, uvr * scaleDigits, ratio, size).r; diff --git a/src/UniformKeys.js b/src/UniformKeys.js index 51f8f5e1..89da04a2 100644 --- a/src/UniformKeys.js +++ b/src/UniformKeys.js @@ -3,10 +3,8 @@ export default class UniformKeys { static TIME = 'time'; static EPOCH = 'epoch'; - static SCREEN_WIDTH = 'screenWidth'; - static SCREEN_HEIGHT = 'screenHeight'; - static MOUSE_X = 'mouseX'; - static MOUSE_Y = 'mouseY'; + static SCREEN = 'screen'; + static MOUSE = 'mouse'; static MOUSE_CLICK = 'mouseClick'; static MOUSE_DOWN = 'mouseDown'; static MOUSE_WHEEL = 'mouseWheel'; diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 2fbbaaab..299882a8 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -789,10 +789,12 @@ export default class Points { // initializing internal uniforms this.addUniform(UniformKeys.TIME, this._time); this.addUniform(UniformKeys.EPOCH, this._epoch); - this.addUniform(UniformKeys.SCREEN_WIDTH, 0); - this.addUniform(UniformKeys.SCREEN_HEIGHT, 0); - this.addUniform(UniformKeys.MOUSE_X, this._mouseX); - this.addUniform(UniformKeys.MOUSE_Y, this._mouseY); + // this.addUniform(UniformKeys.SCREEN_WIDTH, 0); + // this.addUniform(UniformKeys.SCREEN_HEIGHT, 0); + this.addUniform(UniformKeys.SCREEN, [0, 0], 'vec2f'); + // this.addUniform(UniformKeys.MOUSE_X, this._mouseX); + // this.addUniform(UniformKeys.MOUSE_Y, this._mouseY); + this.addUniform(UniformKeys.MOUSE, [0, 0], 'vec2f'); this.addUniform(UniformKeys.MOUSE_CLICK, this._mouseClick); this.addUniform(UniformKeys.MOUSE_DOWN, this._mouseDown); this.addUniform(UniformKeys.MOUSE_WHEEL, this._mouseWheel); @@ -1417,10 +1419,13 @@ export default class Points { this._epoch = new Date() / 1000; this.updateUniform(UniformKeys.TIME, this._time); this.updateUniform(UniformKeys.EPOCH, this._epoch); - this.updateUniform(UniformKeys.SCREEN_WIDTH, this._canvas.width); - this.updateUniform(UniformKeys.SCREEN_HEIGHT, this._canvas.height); - this.updateUniform(UniformKeys.MOUSE_X, this._mouseX); - this.updateUniform(UniformKeys.MOUSE_Y, this._mouseY); + // this.updateUniform(UniformKeys.SCREEN_WIDTH, this._canvas.width); + // this.updateUniform(UniformKeys.SCREEN_HEIGHT, this._canvas.height); + this.updateUniform(UniformKeys.SCREEN, [this._canvas.width, this._canvas.height]); + // this.updateUniform(UniformKeys.MOUSE_X, this._mouseX); + // this.updateUniform(UniformKeys.MOUSE_Y, this._mouseY); + this.updateUniform(UniformKeys.MOUSE, [this._mouseX, this._mouseY]); + this.updateUniform(UniformKeys.MOUSE_CLICK, this._mouseClick); this.updateUniform(UniformKeys.MOUSE_DOWN, this._mouseDown); this.updateUniform(UniformKeys.MOUSE_WHEEL, this._mouseWheel); diff --git a/src/core/RenderPasses/bloom/frag.js b/src/core/RenderPasses/bloom/frag.js index 15a7ee15..d89e2105 100644 --- a/src/core/RenderPasses/bloom/frag.js +++ b/src/core/RenderPasses/bloom/frag.js @@ -12,7 +12,7 @@ ${PI} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/src/core/RenderPasses/blur/frag.js b/src/core/RenderPasses/blur/frag.js index 963495b8..3ca2325c 100644 --- a/src/core/RenderPasses/blur/frag.js +++ b/src/core/RenderPasses/blur/frag.js @@ -12,7 +12,7 @@ ${blur9} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/src/core/RenderPasses/chromaticAberration/frag.js b/src/core/RenderPasses/chromaticAberration/frag.js index c9e3aa3b..f7dbb653 100644 --- a/src/core/RenderPasses/chromaticAberration/frag.js +++ b/src/core/RenderPasses/chromaticAberration/frag.js @@ -7,7 +7,7 @@ ${texturePosition} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/src/core/RenderPasses/color/frag.js b/src/core/RenderPasses/color/frag.js index 02ffa7d1..fa1a8fbc 100644 --- a/src/core/RenderPasses/color/frag.js +++ b/src/core/RenderPasses/color/frag.js @@ -7,7 +7,7 @@ ${texturePosition} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/src/core/RenderPasses/filmgrain/frag.js b/src/core/RenderPasses/filmgrain/frag.js index 42a51ed8..bddfa3a5 100644 --- a/src/core/RenderPasses/filmgrain/frag.js +++ b/src/core/RenderPasses/filmgrain/frag.js @@ -11,7 +11,7 @@ ${snoise} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/src/core/RenderPasses/grayscale/frag.js b/src/core/RenderPasses/grayscale/frag.js index 174c40b6..5444278b 100644 --- a/src/core/RenderPasses/grayscale/frag.js +++ b/src/core/RenderPasses/grayscale/frag.js @@ -12,7 +12,7 @@ ${WHITE} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/src/core/RenderPasses/lensDistortion/frag.js b/src/core/RenderPasses/lensDistortion/frag.js index 04d7f8f3..9cc39140 100644 --- a/src/core/RenderPasses/lensDistortion/frag.js +++ b/src/core/RenderPasses/lensDistortion/frag.js @@ -25,7 +25,7 @@ fn angle(p1:vec2, p2:vec2) -> f32 { fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/src/core/RenderPasses/pixelate/frag.js b/src/core/RenderPasses/pixelate/frag.js index 7a5d0849..f04b7771 100644 --- a/src/core/RenderPasses/pixelate/frag.js +++ b/src/core/RenderPasses/pixelate/frag.js @@ -8,7 +8,7 @@ ${pixelateTexturePosition} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/src/core/RenderPasses/waves/frag.js b/src/core/RenderPasses/waves/frag.js index 609144d7..98ebd123 100644 --- a/src/core/RenderPasses/waves/frag.js +++ b/src/core/RenderPasses/waves/frag.js @@ -10,7 +10,7 @@ ${snoise} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 diff --git a/src/core/debug.js b/src/core/debug.js index d66b798d..a292ec18 100644 --- a/src/core/debug.js +++ b/src/core/debug.js @@ -17,8 +17,8 @@ fn showDebugCross(position:vec2, color:vec4, uv:vec2) -> vec4, uv:vec2) -> vec4 { - let ratioX = params.screenWidth / params.screenHeight; - let ratioY = 1 / ratioX / (params.screenHeight / params.screenWidth); + let ratioX = params.screen.x / params.screen.y; + let ratioY = 1 / ratioX / (params.screen.y / params.screen.x); let ratio = vec2(ratioX, ratioY); let topRight = vec2(1, 1) * ratio; diff --git a/src/core/defaultFunctions.js b/src/core/defaultFunctions.js index 2baddf55..3de69a8f 100644 --- a/src/core/defaultFunctions.js +++ b/src/core/defaultFunctions.js @@ -2,14 +2,14 @@ export const defaultVertexBody = /*wgsl*/` fn defaultVertexBody(position: vec4, color: vec4, uv: vec2) -> Fragment { var result: Fragment; - let ratioX = params.screenWidth / params.screenHeight; - let ratioY = 1 / ratioX / (params.screenHeight / params.screenWidth); + let ratioX = params.screen.x / params.screen.y; + let ratioY = 1 / ratioX / (params.screen.y / params.screen.x); result.ratio = vec2(ratioX, ratioY); result.position = vec4(position); result.color = vec4(color); result.uv = uv; result.uvr = vec2(uv.x * result.ratio.x, uv.y); - result.mouse = vec2(params.mouseX / params.screenWidth, params.mouseY / params.screenHeight); + result.mouse = vec2(params.mouse.x / params.screen.x, params.mouse.y / params.screen.y); result.mouse = result.mouse * vec2(1,-1) - vec2(0, -1); // flip and move up return result; diff --git a/src/core/image.js b/src/core/image.js index 794d8523..d2f686e5 100644 --- a/src/core/image.js +++ b/src/core/image.js @@ -13,7 +13,7 @@ fn texturePosition(texture:texture_2d, aSampler:sampler, position:vec2 let dims: vec2 = textureDimensions(texture, 0); let dimsF32 = vec2(dims); - let minScreenSize = min(params.screenHeight, params.screenWidth); + let minScreenSize = min(params.screen.y, params.screen.x); let imageRatio = dimsF32 / minScreenSize; let displaceImagePosition = position * flipTextureCoordinates / imageRatio + vec2(0, 1); @@ -49,7 +49,7 @@ fn textureExternalPosition(texture:texture_external, aSampler:sampler, position: let dims: vec2 = textureDimensions(texture); let dimsF32 = vec2(f32(dims.x), f32(dims.y)); - let minScreenSize = min(params.screenHeight, params.screenWidth); + let minScreenSize = min(params.screen.y, params.screen.x); let imageRatio = dimsF32 / minScreenSize; let displaceImagePosition = position * flipTextureCoordinates / imageRatio + vec2(0, 1); @@ -84,7 +84,7 @@ fn sprite(texture:texture_2d, aSampler:sampler, position:vec2, uv:vec2 let dimsF32 = vec2(dims); let sizeF32 = vec2(size); - let minScreenSize = min(params.screenHeight, params.screenWidth); + let minScreenSize = min(params.screen.y, params.screen.x); let imageRatio = dimsF32 / minScreenSize; let numColumns = (dims.x) / (size.x); @@ -129,7 +129,7 @@ fn decodeNumberSprite( ) -> vec4 { let sizeF32 = vec2(f32(size.x),f32(size.y)); - let cellRatio = vec2(sizeF32.x/params.screenWidth,sizeF32.y/params.screenHeight)*ratio; + let cellRatio = vec2(sizeF32.x/params.screen.x,sizeF32.y/params.screen.y)*ratio; let displaceInX = vec2(cellRatio.x, 0); @@ -155,8 +155,8 @@ fn decodeNumberSprite( */ export const pixelateTexture = /*wgsl*/` fn pixelateTexture(texture:texture_2d, textureSampler:sampler, pixelsWidth:f32, pixelsHeight:f32, uv:vec2) -> vec4 { - let dx = pixelsWidth * (1. / params.screenWidth); - let dy = pixelsHeight * (1. / params.screenHeight); + let dx = pixelsWidth * (1. / params.screen.x); + let dy = pixelsHeight * (1. / params.screen.y); let coord = vec2(dx*floor( uv.x / dx), dy * floor( uv.y / dy)); @@ -165,8 +165,8 @@ fn pixelateTexture(texture:texture_2d, textureSampler:sampler, pixelsWidth: `; export const pixelateTexturePosition = /*wgsl*/` fn pixelateTexturePosition(texture:texture_2d, textureSampler:sampler, position:vec2, pixelsWidth:f32, pixelsHeight:f32, uv:vec2) -> vec4 { - let dx = pixelsWidth * (1. / params.screenWidth); - let dy = pixelsHeight * (1. / params.screenHeight); + let dx = pixelsWidth * (1. / params.screen.x); + let dy = pixelsHeight * (1. / params.screen.y); let coord = vec2(dx*floor( uv.x / dx), dy * floor( uv.y / dy)); diff --git a/src/core/valuenoise.js b/src/core/valuenoise.js index 7f741594..c534f160 100644 --- a/src/core/valuenoise.js +++ b/src/core/valuenoise.js @@ -7,8 +7,8 @@ ${rand} const value_noise_cellsize = 64; fn valueNoise(){ - let width = i32(params.screenWidth); - let height = i32(params.screenHeight); + let width = i32(params.screen.x); + let height = i32(params.screen.y); let cellSize = 64; _ = value_noise_data[0]; From 329264018a320868f72e0e3f006df81db62acbdf Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Wed, 6 Dec 2023 20:03:46 -0600 Subject: [PATCH 34/55] Update absulit.points.module.js - removing commented out lines --- src/absulit.points.module.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 299882a8..27325c6e 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -789,11 +789,7 @@ export default class Points { // initializing internal uniforms this.addUniform(UniformKeys.TIME, this._time); this.addUniform(UniformKeys.EPOCH, this._epoch); - // this.addUniform(UniformKeys.SCREEN_WIDTH, 0); - // this.addUniform(UniformKeys.SCREEN_HEIGHT, 0); this.addUniform(UniformKeys.SCREEN, [0, 0], 'vec2f'); - // this.addUniform(UniformKeys.MOUSE_X, this._mouseX); - // this.addUniform(UniformKeys.MOUSE_Y, this._mouseY); this.addUniform(UniformKeys.MOUSE, [0, 0], 'vec2f'); this.addUniform(UniformKeys.MOUSE_CLICK, this._mouseClick); this.addUniform(UniformKeys.MOUSE_DOWN, this._mouseDown); @@ -1419,11 +1415,7 @@ export default class Points { this._epoch = new Date() / 1000; this.updateUniform(UniformKeys.TIME, this._time); this.updateUniform(UniformKeys.EPOCH, this._epoch); - // this.updateUniform(UniformKeys.SCREEN_WIDTH, this._canvas.width); - // this.updateUniform(UniformKeys.SCREEN_HEIGHT, this._canvas.height); this.updateUniform(UniformKeys.SCREEN, [this._canvas.width, this._canvas.height]); - // this.updateUniform(UniformKeys.MOUSE_X, this._mouseX); - // this.updateUniform(UniformKeys.MOUSE_Y, this._mouseY); this.updateUniform(UniformKeys.MOUSE, [this._mouseX, this._mouseY]); this.updateUniform(UniformKeys.MOUSE_CLICK, this._mouseClick); From 6ebf938a59bdae62ba7512124c2454608918f422 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Thu, 7 Dec 2023 19:10:49 -0600 Subject: [PATCH 35/55] A few changes to make it work on FF --- examples/circleblur/frag.js | 4 +-- examples/dithering1/frag.js | 42 +++++++++++----------- examples/random1/frag.js | 4 +-- examples/random2/frag.js | 4 +-- examples/renderpasses1/renderpass1/frag.js | 4 +-- src/core/animation.js | 2 +- src/core/defaultFunctions.js | 4 +-- src/core/effects.js | 6 ++-- src/core/image.js | 4 +-- src/core/sdf.js | 2 +- 10 files changed, 38 insertions(+), 38 deletions(-) diff --git a/examples/circleblur/frag.js b/examples/circleblur/frag.js index b38dc617..7c1449a4 100644 --- a/examples/circleblur/frag.js +++ b/examples/circleblur/frag.js @@ -29,10 +29,10 @@ fn main( let texColorCompute = texturePosition(computeTexture, feedbackSampler, startPosition, uv, false); - let d = distance(uvr, vec2(.5 + .1 * fusin(2), .5 + .1 * fusin(4.123))); + let d = distance(uvr, vec2(.5 + .1 * fusin(2.), .5 + .1 * fusin(4.123))); var c = 1.; if(d > .1){ - c = 0; + c = 0.; } let decayR = texColor.r * .9 * texColor2.r; diff --git a/examples/dithering1/frag.js b/examples/dithering1/frag.js index 58dacc11..f4afdd9c 100644 --- a/examples/dithering1/frag.js +++ b/examples/dithering1/frag.js @@ -18,27 +18,27 @@ ${orderedDithering_threshold_map} const numPaletteItems = 21; const getClosestColorInPalette_palette = array< vec4, numPaletteItems>( - vec4(255./255, 69./255, 0, 1.), - vec4(255./255, 168./255, 0, 1.), - vec4(255./255, 214./255, 53./255, 1.), - vec4(0, 204./255, 120./255, 1.), - vec4(126./255, 237./255, 86./255, 1.), - vec4(0./255, 117./255, 111./255, 1.), - vec4(0./255, 158./255, 170./255, 1.), - vec4(36./255, 80./255, 164./255, 1.), - vec4(54./255, 144./255, 234./255, 1.), - vec4(81./255, 233./255, 244./255, 1.), - vec4(73./255, 58./255, 193./255, 1.), - vec4(106./255, 92./255, 255./255, 1.), - vec4(129./255, 30./255, 159./255, 1.), - vec4(180./255, 74./255, 192./255, 1.), - vec4(255./255, 56./255, 129./255, 1.), - vec4(255./255, 153./255, 170./255, 1.), - vec4(109./255, 72./255, 48./255, 1.), - vec4(156./255, 105./255, 38./255, 1.), - vec4(0, 0, 0, 1.), - vec4(137./255, 141./255, 144./255, 1.), - vec4(212./255, 215./255, 217./255, 1.), + vec4(255./255., 69./255., 0., 1.), + vec4(255./255., 168./255., 0, 1.), + vec4(255./255., 214./255., 53./255., 1.), + vec4(0., 204./255., 120./255., 1.), + vec4(126./255., 237./255., 86./255., 1.), + vec4(0./255., 117./255., 111./255., 1.), + vec4(0./255., 158./255., 170./255., 1.), + vec4(36./255., 80./255., 164./255., 1.), + vec4(54./255., 144./255., 234./255., 1.), + vec4(81./255., 233./255., 244./255., 1.), + vec4(73./255., 58./255., 193./255., 1.), + vec4(106./255., 92./255., 255./255., 1.), + vec4(129./255., 30./255., 159./255., 1.), + vec4(180./255., 74./255., 192./255., 1.), + vec4(255./255., 56./255., 129./255., 1.), + vec4(255./255., 153./255., 170./255., 1.), + vec4(109./255., 72./255., 48./255., 1.), + vec4(156./255., 105./255., 38./255., 1.), + vec4(0., 0., 0., 1.), + vec4(137./255., 141./255., 144./255., 1.), + vec4(212./255., 215./255., 217./255., 1.), ); diff --git a/examples/random1/frag.js b/examples/random1/frag.js index 45dcd621..7f7735a3 100644 --- a/examples/random1/frag.js +++ b/examples/random1/frag.js @@ -21,10 +21,10 @@ fn main( let texColorCompute = texturePosition(computeTexture, computeTextureSampler, startPosition, uvr, false); - let d = distance(uvr, vec2(.5 + .1 * fusin(2), .5 + .1 * fusin(4.123))); + let d = distance(uvr, vec2(.5 + .1 * fusin(2.), .5 + .1 * fusin(4.123))); var c = 1.; if(d > .1){ - c = 0; + c = 0.; } diff --git a/examples/random2/frag.js b/examples/random2/frag.js index 0588ffe1..a8f24859 100644 --- a/examples/random2/frag.js +++ b/examples/random2/frag.js @@ -22,10 +22,10 @@ fn main( let texColorCompute = texturePosition(computeTexture, feedbackSampler, startPosition, uvr, false); - let d = distance(uvr, vec2(.5 + .1 * fusin(2), .5 + .1 * fusin(4.123))); + let d = distance(uvr, vec2(.5 + .1 * fusin(2.), .5 + .1 * fusin(4.123))); var c = 1.; if(d > .1){ - c = 0; + c = 0.; } let finalColor:vec4 = vec4(c) + texColorCompute; diff --git a/examples/renderpasses1/renderpass1/frag.js b/examples/renderpasses1/renderpass1/frag.js index 3affbd1e..889d4202 100644 --- a/examples/renderpasses1/renderpass1/frag.js +++ b/examples/renderpasses1/renderpass1/frag.js @@ -20,10 +20,10 @@ fn main( // first render pass doesn't use the feedback texture, it's the second pass // _ = texturePosition(feedbackTexture, feedbackSampler, vec2(0,0), uvr, true); - let d = distance(uvr, vec2(.5 + .1 * fusin(2), .5 + .1 * fusin(4.123))); + let d = distance(uvr, vec2(.5 + .1 * fusin(2.), .5 + .1 * fusin(4.123))); var c = 1.; if(d > .1){ - c = 0; + c = 0.; } let finalColor = imageColor + c * vec4(1); diff --git a/src/core/animation.js b/src/core/animation.js index 89470213..0bb4915b 100644 --- a/src/core/animation.js +++ b/src/core/animation.js @@ -31,6 +31,6 @@ fn fucos(speed: f32) -> f32{ */ export const fnusin = /*wgsl*/` fn fnusin(speed: f32) -> f32{ - return (sin(params.time * speed) + 1) * .5; + return (sin(params.time * speed) + 1.) * .5; } `; \ No newline at end of file diff --git a/src/core/defaultFunctions.js b/src/core/defaultFunctions.js index 3de69a8f..2835aa1d 100644 --- a/src/core/defaultFunctions.js +++ b/src/core/defaultFunctions.js @@ -3,14 +3,14 @@ fn defaultVertexBody(position: vec4, color: vec4, uv: vec2) -> Fr var result: Fragment; let ratioX = params.screen.x / params.screen.y; - let ratioY = 1 / ratioX / (params.screen.y / params.screen.x); + let ratioY = 1. / ratioX / (params.screen.y / params.screen.x); result.ratio = vec2(ratioX, ratioY); result.position = vec4(position); result.color = vec4(color); result.uv = uv; result.uvr = vec2(uv.x * result.ratio.x, uv.y); result.mouse = vec2(params.mouse.x / params.screen.x, params.mouse.y / params.screen.y); - result.mouse = result.mouse * vec2(1,-1) - vec2(0, -1); // flip and move up + result.mouse = result.mouse * vec2(1.,-1.) - vec2(0., -1.); // flip and move up return result; } diff --git a/src/core/effects.js b/src/core/effects.js index 4b3bab72..7c3ea4cd 100644 --- a/src/core/effects.js +++ b/src/core/effects.js @@ -1,9 +1,9 @@ export const euclideanDistance = /*wgsl*/` fn euclideanDistance(color:vec4, distanceColor:vec4) -> f32{ return sqrt( - pow(color.r - distanceColor.r, 2) + - pow(color.g - distanceColor.g, 2) + - pow(color.b - distanceColor.b, 2) + pow(color.r - distanceColor.r, 2.) + + pow(color.g - distanceColor.g, 2.) + + pow(color.b - distanceColor.b, 2.) ); } `; diff --git a/src/core/image.js b/src/core/image.js index d2f686e5..5a7aeb36 100644 --- a/src/core/image.js +++ b/src/core/image.js @@ -16,7 +16,7 @@ fn texturePosition(texture:texture_2d, aSampler:sampler, position:vec2 let minScreenSize = min(params.screen.y, params.screen.x); let imageRatio = dimsF32 / minScreenSize; - let displaceImagePosition = position * flipTextureCoordinates / imageRatio + vec2(0, 1); + let displaceImagePosition = position * flipTextureCoordinates / imageRatio + vec2(0., 1.); let top = position + vec2(0, imageRatio.y); let imageUV = uv / imageRatio * flipTexture + displaceImagePosition; @@ -27,7 +27,7 @@ fn texturePosition(texture:texture_2d, aSampler:sampler, position:vec2 let isBeyondTop = uv.y > top.y ; let isBeyondBottom = uv.y < position.y; if(crop && (isBeyondTop || isBeyondBottom || isBeyondImageLeft || isBeyondImageRight)){ - rgbaImage = vec4(0); + rgbaImage = vec4(0.); } return rgbaImage; diff --git a/src/core/sdf.js b/src/core/sdf.js index 9d4010e2..ba6d0d3a 100644 --- a/src/core/sdf.js +++ b/src/core/sdf.js @@ -32,7 +32,7 @@ fn sdfLine(p1:vec2, p2:vec2, pixelStroke:f32, uv:vec2)->f32{ export const sdfCircle = /*wgsl*/` fn sdfCircle(position:vec2, radius: f32, feather: f32, uv:vec2) -> f32 { let d = distance(uv, position); - let st = 1 - smoothstep(radius, radius + feather, d); + let st = 1. - smoothstep(radius, radius + feather, d); return st; } `; From 5a0690e2fc6c99c9d1c5cbaca3005896351703b3 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Thu, 7 Dec 2023 19:48:22 -0600 Subject: [PATCH 36/55] size asignation for read occurs later - Moved that code after because the dataSize call is ready there --- examples/dithering3_1/index.js | 2 +- examples/dithering3_2/index.js | 2 +- src/absulit.points.module.js | 34 +++++++++++++++------------------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/examples/dithering3_1/index.js b/examples/dithering3_1/index.js index 88dcb6b0..3d6578fe 100644 --- a/examples/dithering3_1/index.js +++ b/examples/dithering3_1/index.js @@ -20,7 +20,7 @@ const dithering3 = { await points.addTextureImage('image', './../img/absulit_800x800.jpg'); points.addBindingTexture('outputTex', 'computeTexture'); points.addLayers(2); - points.addStorage('variables', 1, 'Variable', 16, false, ShaderType.COMPUTE); + points.addStorage('variables', 1, 'Variable', false, ShaderType.COMPUTE); }, update: points => { diff --git a/examples/dithering3_2/index.js b/examples/dithering3_2/index.js index 0581f3cf..2d3237f0 100644 --- a/examples/dithering3_2/index.js +++ b/examples/dithering3_2/index.js @@ -21,7 +21,7 @@ const dithering3 = { await points.addTextureImage('image', './../img/absulit_800x800.jpg'); points.addBindingTexture('outputTex', 'computeTexture'); points.addLayers(2); - points.addStorage('variables', 1, 'Variable', 16, false, ShaderType.COMPUTE); + points.addStorage('variables', 1, 'Variable', false, ShaderType.COMPUTE); }, update: points => { diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 27325c6e..a99cd945 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -255,11 +255,10 @@ export default class Points { * Multiply this by number of properties in the struct if necessary. * @param {string} structName Name of the struct already existing on the * shader that will be the array of the Storage - * @param {Number} structSize number of bytes used by the struct; this includes padding. * @param {boolean} read if this is going to be used to read data back * @param {ShaderType} shaderType this tells to what shader the storage is bound */ - addStorage(name, size, structName, structSize, read, shaderType, arrayData) { + addStorage(name, size, structName, read, shaderType, arrayData) { if (this._nameExists(this._storage, name)) { return; } @@ -268,20 +267,12 @@ export default class Points { name: name, size: size, structName: structName, - structSize: structSize, + // structSize: null, shaderType: shaderType, read: read, buffer: null, internal: this._internal }); - - if (read) { - let storageItem = { - name: name, - size: structSize * size - } - this._readStorage.push(storageItem); - } } addStorageMap(name, arrayData, structName, read, shaderType) { @@ -298,14 +289,6 @@ export default class Points { read: read, internal: this._internal }); - - if (read) { - let storageItem = { - name: name, - size: arrayData.length, - } - this._readStorage.push(storageItem); - } } updateStorageMap(name, arrayData) { @@ -949,7 +932,20 @@ export default class Points { //-------------------------------------------- this._storage.forEach(storageItem => { let usage = GPUBufferUsage.STORAGE; + if (storageItem.read) { + let readStorageItem = { + name: storageItem.name, + size: storageItem.size + } + if (storageItem.mapped) { + readStorageItem = { + name: storageItem.name, + size: storageItem.array.length, + } + } + + this._readStorage.push(readStorageItem); usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC; } storageItem.usage = usage; From d61b937d2c92a5b607e844eb358673d5d6543c20 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Thu, 7 Dec 2023 20:03:56 -0600 Subject: [PATCH 37/55] data example bug fixed --- examples/data1/index.js | 2 +- src/absulit.points.module.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/data1/index.js b/examples/data1/index.js index 6b2c10a8..7463d2fa 100644 --- a/examples/data1/index.js +++ b/examples/data1/index.js @@ -29,7 +29,7 @@ const data1 = { let resultMatrixBufferSize = 2 + firstMatrix[0] * secondMatrix[1]; console.log(resultMatrixBufferSize); - points.addStorage('resultMatrix', 1, 'Matrix', resultMatrixBufferSize * 4, true); + points.addStorage('resultMatrix', 1, 'Matrix', true); }, update: async points => { diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index a99cd945..39976bbb 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -936,7 +936,7 @@ export default class Points { if (storageItem.read) { let readStorageItem = { name: storageItem.name, - size: storageItem.size + size: storageItem.structSize } if (storageItem.mapped) { readStorageItem = { From 5c88122f5a29fa83f0dc18bf4fadd3ede8be369a Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Thu, 7 Dec 2023 20:08:34 -0600 Subject: [PATCH 38/55] changes on test demo --- examples/params_test/frag.js | 4 +-- examples/params_test/index.js | 46 +++++++++++++++++------------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/params_test/frag.js b/examples/params_test/frag.js index 3fe36cd9..5ebb7f9b 100644 --- a/examples/params_test/frag.js +++ b/examples/params_test/frag.js @@ -12,7 +12,7 @@ ${rand} fn main( @location(0) color: vec4, @location(1) uv: vec2, - @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(2) ratio: vec2, // relation between params.screen.x and params.screen.y @location(3) uvr: vec2, // uv with aspect ratio corrected @location(4) mouse: vec2, @builtin(position) position: vec4 @@ -30,7 +30,7 @@ fn main( finalColor = variables.color; - return params.test3; + return variables.color; } `; diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 880daaa5..852e044a 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -5,18 +5,18 @@ import Points from '../../src/absulit.points.module.js'; import { dataSize } from '../../src/data-size.js'; const base = { - vert, - compute, - frag, - /** - * - * @param {Points} points - */ - init: async points => { + vert, + compute, + frag, + /** + * + * @param {Points} points + */ + init: async points => { - var startTime = performance.now() - const result = dataSize(` + var startTime = performance.now() + const result = dataSize(` struct Light { mode: u32, @@ -82,29 +82,29 @@ const base = { `); - var endTime = performance.now() + var endTime = performance.now() - console.log(`Call to doSomething took ${endTime - startTime} milliseconds`) - console.log(result); - for(let [r,c] of result){ - console.log(r,c.bytes) + console.log(`Call to doSomething took ${endTime - startTime} milliseconds`) + console.log(result); + for (let [r, c] of result) { + console.log(r, c.bytes) - } + } - points.addStorageMap('test', [1, 0, 0, .5], 'vec4f'); + points.addStorageMap('test', [0, 0, 1, .5], 'vec4f'); - points.addStorage('variables', 1, 'Variable', 32); - points.addStorage('test2', 1, 'TestStruct', 32); + points.addStorage('variables', 1, 'Variable'); + points.addStorage('test2', 1, 'TestStruct'); - points.addUniform('test3', [1, 0, 0, 1], 'vec4f'); + points.addUniform('test3', [1, 0, 0, 1], 'vec4f'); - }, - update: points => { + }, + update: points => { - } + } } export default base; \ No newline at end of file From 854594ed460d460ca4d57d630f132ff0adc271fa Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Fri, 8 Dec 2023 20:07:21 -0600 Subject: [PATCH 39/55] More updates to fit Firefox - mostly floats --- examples/data1/index.js | 4 +-- examples/dithering2/frag.js | 40 +++++++++++++++--------------- examples/dithering3_1/compute.js | 2 +- examples/dithering3_1/frag.js | 40 +++++++++++++++--------------- examples/dithering3_2/compute.js | 2 +- examples/dithering3_2/frag.js | 40 +++++++++++++++--------------- examples/dithering4/frag.js | 40 +++++++++++++++--------------- examples/events1/frag.js | 16 ++++++------ examples/imagetexture2/frag.js | 4 +-- examples/imagetexture3/frag.js | 2 +- examples/mouse1/frag.js | 4 +-- examples/mouseclickscroll1/frag.js | 8 +++--- examples/noise1/frag.js | 8 +++--- examples/noisecircle1/frag.js | 8 +++--- examples/params_test/frag.js | 2 +- examples/pointstitle1/frag.js | 2 +- src/core/color.js | 6 ++--- src/core/debug.js | 4 +-- src/core/image.js | 4 +-- src/core/random.js | 6 ++--- webgpu_demo_reference/snail1.js | 2 +- 21 files changed, 122 insertions(+), 122 deletions(-) diff --git a/examples/data1/index.js b/examples/data1/index.js index 7463d2fa..e8ed4c42 100644 --- a/examples/data1/index.js +++ b/examples/data1/index.js @@ -27,8 +27,8 @@ const data1 = { points.addStorageMap('secondMatrix', secondMatrix, 'Matrix'); - let resultMatrixBufferSize = 2 + firstMatrix[0] * secondMatrix[1]; - console.log(resultMatrixBufferSize); + // let resultMatrixBufferSize = 2 + firstMatrix[0] * secondMatrix[1]; + // console.log(resultMatrixBufferSize); points.addStorage('resultMatrix', 1, 'Matrix', true); }, update: async points => { diff --git a/examples/dithering2/frag.js b/examples/dithering2/frag.js index 84330fb7..42b630d3 100644 --- a/examples/dithering2/frag.js +++ b/examples/dithering2/frag.js @@ -18,27 +18,27 @@ ${orderedDithering_threshold_map} const numPaletteItems = 21; const getClosestColorInPalette_palette = array< vec4, numPaletteItems>( - vec4(255./255, 69./255, 0, 1.), - vec4(255./255, 168./255, 0, 1.), - vec4(255./255, 214./255, 53./255, 1.), - vec4(0, 204./255, 120./255, 1.), - vec4(126./255, 237./255, 86./255, 1.), - vec4(0./255, 117./255, 111./255, 1.), - vec4(0./255, 158./255, 170./255, 1.), - vec4(36./255, 80./255, 164./255, 1.), - vec4(54./255, 144./255, 234./255, 1.), - vec4(81./255, 233./255, 244./255, 1.), - vec4(73./255, 58./255, 193./255, 1.), - vec4(106./255, 92./255, 255./255, 1.), - vec4(129./255, 30./255, 159./255, 1.), - vec4(180./255, 74./255, 192./255, 1.), - vec4(255./255, 56./255, 129./255, 1.), - vec4(255./255, 153./255, 170./255, 1.), - vec4(109./255, 72./255, 48./255, 1.), - vec4(156./255, 105./255, 38./255, 1.), + vec4(255./255., 69./255., 0, 1.), + vec4(255./255., 168./255., 0, 1.), + vec4(255./255., 214./255., 53./255., 1.), + vec4(0, 204./255., 120./255., 1.), + vec4(126./255., 237./255., 86./255., 1.), + vec4(0./255., 117./255., 111./255., 1.), + vec4(0./255., 158./255., 170./255., 1.), + vec4(36./255., 80./255., 164./255., 1.), + vec4(54./255., 144./255., 234./255., 1.), + vec4(81./255., 233./255., 244./255., 1.), + vec4(73./255., 58./255., 193./255., 1.), + vec4(106./255., 92./255., 255./255., 1.), + vec4(129./255., 30./255., 159./255., 1.), + vec4(180./255., 74./255., 192./255., 1.), + vec4(255./255., 56./255., 129./255., 1.), + vec4(255./255., 153./255., 170./255., 1.), + vec4(109./255., 72./255., 48./255., 1.), + vec4(156./255., 105./255., 38./255., 1.), vec4(0, 0, 0, 1.), - vec4(137./255, 141./255, 144./255, 1.), - vec4(212./255, 215./255, 217./255, 1.), + vec4(137./255., 141./255., 144./255., 1.), + vec4(212./255., 215./255., 217./255., 1.), ); diff --git a/examples/dithering3_1/compute.js b/examples/dithering3_1/compute.js index 33172a8a..7c084200 100644 --- a/examples/dithering3_1/compute.js +++ b/examples/dithering3_1/compute.js @@ -27,7 +27,7 @@ fn main( let numRowsPiece:i32 = i32(numRows / f32(workgroupSize)); var layerIndex = 0; - if(variables.init == 0){ + if(variables.init == 0.){ for (var indexColumns:i32 = 0; indexColumns < numColumnsPiece; indexColumns++) { let x:f32 = f32(WorkGroupID.x) * f32(numColumnsPiece) + f32(indexColumns); diff --git a/examples/dithering3_1/frag.js b/examples/dithering3_1/frag.js index 84faa5fc..f5d6744b 100644 --- a/examples/dithering3_1/frag.js +++ b/examples/dithering3_1/frag.js @@ -18,27 +18,27 @@ ${orderedDithering_threshold_map} const numPaletteItems = 21; const getClosestColorInPalette_palette = array< vec4, numPaletteItems>( - vec4(255./255, 69./255, 0, 1.), - vec4(255./255, 168./255, 0, 1.), - vec4(255./255, 214./255, 53./255, 1.), - vec4(0, 204./255, 120./255, 1.), - vec4(126./255, 237./255, 86./255, 1.), - vec4(0./255, 117./255, 111./255, 1.), - vec4(0./255, 158./255, 170./255, 1.), - vec4(36./255, 80./255, 164./255, 1.), - vec4(54./255, 144./255, 234./255, 1.), - vec4(81./255, 233./255, 244./255, 1.), - vec4(73./255, 58./255, 193./255, 1.), - vec4(106./255, 92./255, 255./255, 1.), - vec4(129./255, 30./255, 159./255, 1.), - vec4(180./255, 74./255, 192./255, 1.), - vec4(255./255, 56./255, 129./255, 1.), - vec4(255./255, 153./255, 170./255, 1.), - vec4(109./255, 72./255, 48./255, 1.), - vec4(156./255, 105./255, 38./255, 1.), + vec4(255./255., 69./255., 0, 1.), + vec4(255./255., 168./255., 0, 1.), + vec4(255./255., 214./255., 53./255., 1.), + vec4(0., 204./255., 120./255., 1.), + vec4(126./255., 237./255., 86./255., 1.), + vec4(0./255., 117./255., 111./255., 1.), + vec4(0./255., 158./255., 170./255., 1.), + vec4(36./255., 80./255., 164./255., 1.), + vec4(54./255., 144./255., 234./255., 1.), + vec4(81./255., 233./255., 244./255., 1.), + vec4(73./255., 58./255., 193./255., 1.), + vec4(106./255., 92./255., 255./255., 1.), + vec4(129./255., 30./255., 159./255., 1.), + vec4(180./255., 74./255., 192./255., 1.), + vec4(255./255., 56./255., 129./255., 1.), + vec4(255./255., 153./255., 170./255., 1.), + vec4(109./255., 72./255., 48./255., 1.), + vec4(156./255., 105./255., 38./255., 1.), vec4(0, 0, 0, 1.), - vec4(137./255, 141./255, 144./255, 1.), - vec4(212./255, 215./255, 217./255, 1.), + vec4(137./255., 141./255., 144./255., 1.), + vec4(212./255., 215./255., 217./255., 1.), ); diff --git a/examples/dithering3_2/compute.js b/examples/dithering3_2/compute.js index 6d3e0bca..8da296e0 100644 --- a/examples/dithering3_2/compute.js +++ b/examples/dithering3_2/compute.js @@ -20,7 +20,7 @@ fn main( let dims = textureDimensions(image); var layerIndex = 0; - if(variables.init == 0){ + if(variables.init == 0.){ let pointIndex = i32(GlobalId.y + (GlobalId.x * dims.x)); diff --git a/examples/dithering3_2/frag.js b/examples/dithering3_2/frag.js index d6c48df1..5d32f394 100644 --- a/examples/dithering3_2/frag.js +++ b/examples/dithering3_2/frag.js @@ -18,27 +18,27 @@ ${orderedDithering_threshold_map} const numPaletteItems = 21; const getClosestColorInPalette_palette = array< vec4, numPaletteItems>( - vec4(255./255, 69./255, 0, 1.), - vec4(255./255, 168./255, 0, 1.), - vec4(255./255, 214./255, 53./255, 1.), - vec4(0, 204./255, 120./255, 1.), - vec4(126./255, 237./255, 86./255, 1.), - vec4(0./255, 117./255, 111./255, 1.), - vec4(0./255, 158./255, 170./255, 1.), - vec4(36./255, 80./255, 164./255, 1.), - vec4(54./255, 144./255, 234./255, 1.), - vec4(81./255, 233./255, 244./255, 1.), - vec4(73./255, 58./255, 193./255, 1.), - vec4(106./255, 92./255, 255./255, 1.), - vec4(129./255, 30./255, 159./255, 1.), - vec4(180./255, 74./255, 192./255, 1.), - vec4(255./255, 56./255, 129./255, 1.), - vec4(255./255, 153./255, 170./255, 1.), - vec4(109./255, 72./255, 48./255, 1.), - vec4(156./255, 105./255, 38./255, 1.), + vec4(255./255., 69./255., 0, 1.), + vec4(255./255., 168./255., 0, 1.), + vec4(255./255., 214./255., 53./255., 1.), + vec4(0., 204./255., 120./255., 1.), + vec4(126./255., 237./255., 86./255., 1.), + vec4(0./255., 117./255., 111./255., 1.), + vec4(0./255., 158./255., 170./255., 1.), + vec4(36./255., 80./255., 164./255., 1.), + vec4(54./255., 144./255., 234./255., 1.), + vec4(81./255., 233./255., 244./255., 1.), + vec4(73./255., 58./255., 193./255., 1.), + vec4(106./255., 92./255., 255./255., 1.), + vec4(129./255., 30./255., 159./255., 1.), + vec4(180./255., 74./255., 192./255., 1.), + vec4(255./255., 56./255., 129./255., 1.), + vec4(255./255., 153./255., 170./255., 1.), + vec4(109./255., 72./255., 48./255., 1.), + vec4(156./255., 105./255., 38./255., 1.), vec4(0, 0, 0, 1.), - vec4(137./255, 141./255, 144./255, 1.), - vec4(212./255, 215./255, 217./255, 1.), + vec4(137./255., 141./255., 144./255., 1.), + vec4(212./255., 215./255., 217./255., 1.), ); diff --git a/examples/dithering4/frag.js b/examples/dithering4/frag.js index bdcb632e..a2c32b2e 100644 --- a/examples/dithering4/frag.js +++ b/examples/dithering4/frag.js @@ -16,27 +16,27 @@ ${orderedDithering_threshold_map} const numPaletteItems = 21; const getClosestColorInPalette_palette = array< vec4, numPaletteItems>( - vec4(255./255, 69./255, 0, 1.), - vec4(255./255, 168./255, 0, 1.), - vec4(255./255, 214./255, 53./255, 1.), - vec4(0, 204./255, 120./255, 1.), - vec4(126./255, 237./255, 86./255, 1.), - vec4(0./255, 117./255, 111./255, 1.), - vec4(0./255, 158./255, 170./255, 1.), - vec4(36./255, 80./255, 164./255, 1.), - vec4(54./255, 144./255, 234./255, 1.), - vec4(81./255, 233./255, 244./255, 1.), - vec4(73./255, 58./255, 193./255, 1.), - vec4(106./255, 92./255, 255./255, 1.), - vec4(129./255, 30./255, 159./255, 1.), - vec4(180./255, 74./255, 192./255, 1.), - vec4(255./255, 56./255, 129./255, 1.), - vec4(255./255, 153./255, 170./255, 1.), - vec4(109./255, 72./255, 48./255, 1.), - vec4(156./255, 105./255, 38./255, 1.), + vec4(255./255., 69./255., 0, 1.), + vec4(255./255., 168./255., 0, 1.), + vec4(255./255., 214./255., 53./255., 1.), + vec4(0., 204./255., 120./255., 1.), + vec4(126./255., 237./255., 86./255., 1.), + vec4(0./255., 117./255., 111./255., 1.), + vec4(0./255., 158./255., 170./255., 1.), + vec4(36./255., 80./255., 164./255., 1.), + vec4(54./255., 144./255., 234./255., 1.), + vec4(81./255., 233./255., 244./255., 1.), + vec4(73./255., 58./255., 193./255., 1.), + vec4(106./255., 92./255., 255./255., 1.), + vec4(129./255., 30./255., 159./255., 1.), + vec4(180./255., 74./255., 192./255., 1.), + vec4(255./255., 56./255., 129./255., 1.), + vec4(255./255., 153./255., 170./255., 1.), + vec4(109./255., 72./255., 48./255., 1.), + vec4(156./255., 105./255., 38./255., 1.), vec4(0, 0, 0, 1.), - vec4(137./255, 141./255, 144./255, 1.), - vec4(212./255, 215./255, 217./255, 1.), + vec4(137./255., 141./255., 144./255., 1.), + vec4(212./255., 215./255., 217./255., 1.), ); ${PI} diff --git a/examples/events1/frag.js b/examples/events1/frag.js index 156d41cd..05c75214 100644 --- a/examples/events1/frag.js +++ b/examples/events1/frag.js @@ -20,18 +20,18 @@ fn main( var circle1Radius = .01; var circle2Radius = .01; - if(params.time % 1 == 0){ + if(params.time % 1. == 0.){ circle1Radius = .1; - left_blink.data[0] = 1; - left_blink.data[1] = 1; - left_blink.updated = 1; + left_blink.data[0] = 1.; + left_blink.data[1] = 1.; + left_blink.updated = 1u; } - if(params.time % 2 == 0){ + if(params.time % 2. == 0.){ circle2Radius = .1; - right_blink.data[0] = 2; - right_blink.data[1] = 2; - right_blink.updated = 1; + right_blink.data[0] = 2.; + right_blink.data[1] = 2.; + right_blink.updated = 1u; } let circleValue1 = sdfCircle(vec2f(.2,.5), circle1Radius, 0., uvr); diff --git a/examples/imagetexture2/frag.js b/examples/imagetexture2/frag.js index 7dc47d33..7d883a86 100644 --- a/examples/imagetexture2/frag.js +++ b/examples/imagetexture2/frag.js @@ -23,7 +23,7 @@ fn main( @builtin(position) position: vec4 ) -> @location(0) vec4 { - let n1 = snoise(uv * 10); + let n1 = snoise(uv * 10.); let dims: vec2 = textureDimensions(image, 0); var dimsRatio = f32(dims.x) / f32(dims.y); @@ -37,7 +37,7 @@ fn main( let d = distance(uv, rgbaImage.xy); //let finalColor:vec4 = vec4(b); - let finalColor:vec4 = mix( vec4(1,0,0,1) , vec4(1,1,0,1) , b) * fnusin(d); + let finalColor:vec4 = mix( vec4(1,0,0,1.) , vec4(1,1,0,1.) , b) * fnusin(d); //let finalColor:vec4 = rgbaImage; diff --git a/examples/imagetexture3/frag.js b/examples/imagetexture3/frag.js index 1d61d37d..d4e6f170 100644 --- a/examples/imagetexture3/frag.js +++ b/examples/imagetexture3/frag.js @@ -18,7 +18,7 @@ fn main( @builtin(position) position: vec4 ) -> @location(0) vec4 { - let lines = sin( uv.x*(uv.x + 3 * fnusin(1)) ) ; + let lines = sin( uv.x*(uv.x + 3. * fnusin(1.)) ) ; let startPosition = vec2(0.); let rgbaImage = texturePosition(image, feedbackSampler, startPosition, uvr * lines / params.sliderA, false); //* .998046; diff --git a/examples/mouse1/frag.js b/examples/mouse1/frag.js index 59e5db5f..a9847ee4 100644 --- a/examples/mouse1/frag.js +++ b/examples/mouse1/frag.js @@ -21,9 +21,9 @@ fn main( let startPosition = mouse * ratio;//vec2(.0); - let positionCross = showDebugCross(startPosition, vec4(1,0,0,1), uv * ratio); + let positionCross = showDebugCross(startPosition, vec4(1,0,0,1.), uv * ratio); - let frame = showDebugFrame(vec4(1,0,0,1), uvr); + let frame = showDebugFrame(vec4(1,0,0,1.), uvr); let finalColor:vec4 = positionCross + frame; diff --git a/examples/mouseclickscroll1/frag.js b/examples/mouseclickscroll1/frag.js index 1432390f..b9a3654b 100644 --- a/examples/mouseclickscroll1/frag.js +++ b/examples/mouseclickscroll1/frag.js @@ -22,15 +22,15 @@ fn main( @builtin(position) position: vec4 ) -> @location(0) vec4 { - if(variables.init == 0){ + if(variables.init == 0.){ variables.circleRadius = .1; variables.circlePosition = vec2(.5, .5) * ratio; - variables.init = 1; + variables.init = 1.; } if(params.mouseWheel == 1.){ - if(params.mouseDeltaY > 0){ + if(params.mouseDeltaY > 0.){ variables.circleRadius += .0001; }else{ variables.circleRadius -= .0001; @@ -42,7 +42,7 @@ fn main( } let circleValue = sdfCircle(variables.circlePosition, variables.circleRadius, 0., uvr); - var finalColor = vec4(1) * circleValue; + var finalColor = vec4(1.) * circleValue; if(params.mouseDown == 1.){ finalColor *= GREEN; diff --git a/examples/noise1/frag.js b/examples/noise1/frag.js index 112f855d..6c5959e4 100644 --- a/examples/noise1/frag.js +++ b/examples/noise1/frag.js @@ -26,14 +26,14 @@ fn main( let c = fnusin(uvr.x * uvr.y * 10.); let d = distance(a,b); let f = d * uvr.x * uvr.y; - let n1 = snoise(uvr * 200 * params.sliderA + 10 * fnusin(.01)); - let n2 = snoise(uvr * 200 * params.sliderB + 10 * fnusin(.02)); - let n3 = snoise(uvr * 200 * params.sliderC + 10 * fnusin(.03)); + let n1 = snoise(uvr * 200. * params.sliderA + 10. * fnusin(.01)); + let n2 = snoise(uvr * 200. * params.sliderB + 10. * fnusin(.02)); + let n3 = snoise(uvr * 200. * params.sliderC + 10. * fnusin(.03)); //let finalColor:vec4 = vec4(a*d*n2,f*c*a*n3,f * n1, 1.); //let finalColor = vec4(fract(n1 * n2 + n3)); let n4 = fract(n1 * n2 + n3); //let finalColor = vec4(n4, uvr.x - n4, 0, 1); - let finalColor = mix( vec4(1, 0, 0, 1) , vec4(1, 1, 0, 1), n4 ); + let finalColor = mix( vec4(1, 0, 0, 1.) , vec4(1, 1, 0, 1.), n4 ); return finalColor; } diff --git a/examples/noisecircle1/frag.js b/examples/noisecircle1/frag.js index 21084043..07629596 100644 --- a/examples/noisecircle1/frag.js +++ b/examples/noisecircle1/frag.js @@ -22,11 +22,11 @@ fn main( var circle = sdfCircle(vec2(.5,.5) * ratio, .2, .1, uvr); - var n1 = (snoise(uvr * 5.14 + 200 * fract(time * -.01))+1)*.5; - //var n2 = (snoise(uvr * 15.14 + 200 * fract(time * -.01))+1)*.5; + var n1 = (snoise(uvr * 5.14 + 200. * fract(time * -.01))+1.)*.5; + //var n2 = (snoise(uvr * 15.14 + 200. * fract(time * -.01))+1.)*.5; let skewMask = vec2(1, 1.1); - let mask = (1-sdfCircle(vec2(.5,.5) * ratio, .0999, .5, uvr * skewMask )); - let result = vec4(1) * mask * n1 * circle + circle; + let mask = (1.-sdfCircle(vec2(.5,.5) * ratio, .0999, .5, uvr * skewMask )); + let result = vec4(1.) * mask * n1 * circle + circle; var finalColor:vec4 = mask * vec4(1,.5,0,1) + mix( vec4(1,0,0,result.a), vec4(1,.5,0,1), result ); diff --git a/examples/params_test/frag.js b/examples/params_test/frag.js index 5ebb7f9b..0d5cb22c 100644 --- a/examples/params_test/frag.js +++ b/examples/params_test/frag.js @@ -20,7 +20,7 @@ fn main( var finalColor:vec4 = vec4(); - if(variables.init == 0){ + if(variables.init == 0.){ rand_seed = uvr + params.time; rand(); finalColor = vec4(rand_seed, 0, 1); diff --git a/examples/pointstitle1/frag.js b/examples/pointstitle1/frag.js index db3638cc..5cb789d0 100644 --- a/examples/pointstitle1/frag.js +++ b/examples/pointstitle1/frag.js @@ -31,7 +31,7 @@ fn main( @builtin(position) position: vec4 ) -> @location(0) vec4 { - let n1 = snoise(uvr * 100 * 0.0016 /*params.sliderA*/ + params.time * .1); + let n1 = snoise(uvr * 100. * 0.0016 /*params.sliderA*/ + params.time * .1); let numColumns = 400. * 0.2662 * n1; // params.sliderB; let numRows = 400. * 0.3765; // params.sliderC; diff --git a/src/core/color.js b/src/core/color.js index c5be9688..494e5644 100644 --- a/src/core/color.js +++ b/src/core/color.js @@ -39,7 +39,7 @@ const BLACK = vec4(0.,0.,0.,1.); export const layer = /*wgsl*/` // https://stackoverflow.com/a/24501192/507186 fn layer(back:vec4, front: vec4) -> vec4 { - return front * front.a + back * (1 - front.a); + return front * front.a + back * (1. - front.a); } `; @@ -50,7 +50,7 @@ fn hsvAux(h:f32, s:f32, v:f32, n:f32) -> f32 { }; fn RGBAFromHSV(h:f32, s:f32, v:f32) -> vec4{ - return vec4(hsvAux(h, s, v, 5), hsvAux(h, s, v, 3), hsvAux(h, s, v, 1), 1); + return vec4(hsvAux(h, s, v, 5.), hsvAux(h, s, v, 3.), hsvAux(h, s, v, 1.), 1.); } `; @@ -66,7 +66,7 @@ fn bloom(input:f32, iterations:i32, intensity:f32) -> f32 { let iterationsF32 = f32(iterations); for (var k = 0; k < iterations; k++) { for (var n = 0; n < iterations; n++) { - let coef = cos(2.0 * PI * f32(k) * f32(n) / iterationsF32 ); + let coef = cos(2. * PI * f32(k) * f32(n) / iterationsF32 ); output += input * coef * intensity; } } diff --git a/src/core/debug.js b/src/core/debug.js index a292ec18..a50349d0 100644 --- a/src/core/debug.js +++ b/src/core/debug.js @@ -18,10 +18,10 @@ fn showDebugCross(position:vec2, color:vec4, uv:vec2) -> vec4, uv:vec2) -> vec4 { let ratioX = params.screen.x / params.screen.y; - let ratioY = 1 / ratioX / (params.screen.y / params.screen.x); + let ratioY = 1. / ratioX / (params.screen.y / params.screen.x); let ratio = vec2(ratioX, ratioY); - let topRight = vec2(1, 1) * ratio; + let topRight = vec2(1., 1.) * ratio; let topLeft = vec2(0., 1.); let bottomLeft = vec2(0., 0.); let bottomRight = vec2(1., 0.) * ratio; diff --git a/src/core/image.js b/src/core/image.js index 5a7aeb36..54319688 100644 --- a/src/core/image.js +++ b/src/core/image.js @@ -93,7 +93,7 @@ fn sprite(texture:texture_2d, aSampler:sampler, position:vec2, uv:vec2 let y = f32(index / numColumns); let cell = vec2(x, y); - let cellIndex = cell + vec2(0,1); + let cellIndex = cell + vec2(0,1.); let cellSize = sizeF32 / minScreenSize; let cellSizeInImage = cellSize / imageRatio; @@ -109,7 +109,7 @@ fn sprite(texture:texture_2d, aSampler:sampler, position:vec2, uv:vec2 let isBeyondTop = uv.y > position.y + cellSize.y; let isBeyondBottom = uv.y < position.y; if(isBeyondTop || isBeyondBottom || isBeyondImageLeft || isBeyondImageRight){ - rgbaImage = vec4(0); + rgbaImage = vec4(0.); } return rgbaImage; diff --git a/src/core/random.js b/src/core/random.js index a6253679..5551d8d1 100644 --- a/src/core/random.js +++ b/src/core/random.js @@ -1,9 +1,9 @@ export const random = /*wgsl*/` -var a = 1664525; -var c = 1013904223; +var a:i32 = 1664525; +var c:i32 = 1013904223; var m = pow(2, 32); -var seed = 958736; +var seed:i32 = 958736; fn nextRand() -> i32 { seed = (a * seed + c) % i32(m); diff --git a/webgpu_demo_reference/snail1.js b/webgpu_demo_reference/snail1.js index 9b6e921d..186e5df7 100644 --- a/webgpu_demo_reference/snail1.js +++ b/webgpu_demo_reference/snail1.js @@ -238,7 +238,7 @@ async function init() { ]; // array = [[]]; - array = [[312, 845, 869, 494, 667], [716, 660, 255, 130, 767], [121, 506, 480, 792, 334], [218, 639, 57, 434, 13], [14, 572, 501, 965, 729], [760, 359, 572, 123, 824], [275, 935, 466, 485, 721], [369, 892, 860, 334, 498], [968, 351, 177, 264, 542], [308, 574, 624, 823, 85], [246, 462, 960, 878, 954], [424, 829, 331, 50, 293], [504, 562, 668, 623, 508], [578, 20, 761, 773, 678], [959, 933, 995, 998, 837], [99, 741, 501, 841, 352], [965, 157, 114, 261, 118], [432, 221, 847, 713, 719], [664, 1, 737, 364, 702], [323, 310, 166, 280, 501]] + array = [[312, 845, 869, 494, 667], [716, 660, 255., 130, 767], [121, 506, 480, 792, 334], [218, 639, 57, 434, 13], [14, 572, 501, 965, 729], [760, 359, 572, 123, 824], [275, 935, 466, 485, 721], [369, 892, 860, 334, 498], [968, 351, 177, 264, 542], [308, 574, 624, 823, 85], [246, 462, 960, 878, 954], [424, 829, 331, 50, 293], [504, 562, 668, 623, 508], [578, 20, 761, 773, 678], [959, 933, 995, 998, 837], [99, 741, 501, 841, 352], [965, 157, 114, 261, 118], [432, 221, 847, 713, 719], [664, 1, 737, 364, 702], [323, 310, 166, 280, 501]] const r = await snail(array) console.log(r); From a2a71159abe34a2a92cf664d9bf7ce01171c0386 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 9 Dec 2023 15:44:22 -0600 Subject: [PATCH 40/55] moved struct for testing - This struct is not used on the other demo, but is the one causing trouble --- examples/params_test/frag.js | 5 +++++ examples/shapes2/compute.js | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/params_test/frag.js b/examples/params_test/frag.js index 0d5cb22c..47407519 100644 --- a/examples/params_test/frag.js +++ b/examples/params_test/frag.js @@ -8,6 +8,11 @@ ${fnusin} ${structs} ${rand} +struct Colors{ + // items: array< vec4, 800*800 > + items: array< vec4, 640000 > +} + @fragment fn main( @location(0) color: vec4, diff --git a/examples/shapes2/compute.js b/examples/shapes2/compute.js index 4f552d12..682e626f 100644 --- a/examples/shapes2/compute.js +++ b/examples/shapes2/compute.js @@ -12,9 +12,10 @@ ${sdfLine2} ${sdfCircle} ${fnusin} -struct Colors{ - items: array< vec4, 800*800 > -} +// struct Colors{ +// // items: array< vec4, 800*800 > +// items: array< vec4, 640000 > +// } fn getPointsIndex(position:vec2) -> u32{ return position.y + (position.x * u32(params.screen.x)); From 0590ddafafe3134178d25693b82cfb7563944a69 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 9 Dec 2023 19:08:54 -0600 Subject: [PATCH 41/55] MouseDelta as vec2f --- examples/mouseclickscroll1/frag.js | 2 +- examples/params_test/index.js | 22 +++++++++++++--------- src/UniformKeys.js | 3 +-- src/absulit.points.module.js | 16 +++++----------- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/examples/mouseclickscroll1/frag.js b/examples/mouseclickscroll1/frag.js index b9a3654b..8d7b6191 100644 --- a/examples/mouseclickscroll1/frag.js +++ b/examples/mouseclickscroll1/frag.js @@ -30,7 +30,7 @@ fn main( } if(params.mouseWheel == 1.){ - if(params.mouseDeltaY > 0.){ + if(params.mouseDelta.y > 0.){ variables.circleRadius += .0001; }else{ variables.circleRadius -= .0001; diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 852e044a..882d859e 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -27,37 +27,37 @@ const base = { direction: vec3f, position: vec3f, }; - + struct FSInput { colorMult: vec4f, specularFactor: f32, lights: array, }; - + struct VSInput { projectionMatrix: mat4x4f, viewMatrix: mat4x4f, modelMatrix: mat4x4f, normalMatrix: mat4x4f, }; - + @group(0) @binding(0) var vsUni: VSInput; @group(0) @binding(1) var fsUni: FSInput; @group(0) @binding(2) var diffuseSampler: sampler; @group(0) @binding(3) var diffuseTexture: texture_2d; - + struct Attribs { @location(0) position: vec4f, @location(1) normal: vec3f, @location(2) texcoord: vec2f, }; - + struct VSOutput { @builtin(position) position: vec4f, @location(0) texcoord: vec2f, @location(1) normal: vec3f, }; - + @vertex fn vs(vin: Attribs) -> VSOutput { var vout: VSOutput; vout.position = vsUni.projectionMatrix * vsUni.viewMatrix * vsUni.modelMatrix * vin.position; @@ -65,7 +65,7 @@ const base = { vout.normal = (vsUni.normalMatrix * vec4f(vin.normal, 0)).xyz; return vout; } - + @fragment fn fs(vout: VSOutput) -> @location(0) vec4f { let normal = normalize(vout.normal); var l = 0.0; @@ -73,11 +73,11 @@ const base = { let light = fsUni.lights[i]; l += clamp(dot(normal, light.direction), 0.0, 1.0); } - + let color = textureSample(diffuseTexture, diffuseSampler, vout.texcoord); return vec4f(color.rgb * clamp(l, 0.0, 1.0), color.a); } - + @@ -100,6 +100,10 @@ const base = { points.addUniform('test3', [1, 0, 0, 1], 'vec4f'); + // points.addUniform('test4', [1, 0, 0, 1], 'array< vec4, 1 >'); + // TODO: throw error if using array in uniform? + // points.addUniform('test5', [1,1,1,1], 'array'); + }, update: points => { diff --git a/src/UniformKeys.js b/src/UniformKeys.js index 89da04a2..fb6d9ee4 100644 --- a/src/UniformKeys.js +++ b/src/UniformKeys.js @@ -8,6 +8,5 @@ export default class UniformKeys { static MOUSE_CLICK = 'mouseClick'; static MOUSE_DOWN = 'mouseDown'; static MOUSE_WHEEL = 'mouseWheel'; - static MOUSE_DELTA_X = 'mouseDeltaX'; - static MOUSE_DELTA_Y = 'mouseDeltaY'; + static MOUSE_DELTA = 'mouseDelta'; } \ No newline at end of file diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 39976bbb..a85274f1 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -93,9 +93,7 @@ export default class Points { /** @private */ this._mouseWheel = false; /** @private */ - this._mouseDeltaX = 0; - /** @private */ - this._mouseDeltaY = 0; + this._mouseDelta = [0, 0]; /** @private */ this._fullscreen = false; @@ -127,8 +125,7 @@ export default class Points { this._canvas.addEventListener('wheel', e => { this._mouseWheel = true; - this._mouseDeltaX = e.deltaX; - this._mouseDeltaY = e.deltaY; + this._mouseDelta = [e.deltaX, e.deltaY]; }); this._originalCanvasWidth = this._canvas.clientWidth; this._originalCanvasHeigth = this._canvas.clientHeight; @@ -777,8 +774,7 @@ export default class Points { this.addUniform(UniformKeys.MOUSE_CLICK, this._mouseClick); this.addUniform(UniformKeys.MOUSE_DOWN, this._mouseDown); this.addUniform(UniformKeys.MOUSE_WHEEL, this._mouseWheel); - this.addUniform(UniformKeys.MOUSE_DELTA_X, this._mouseDeltaX); - this.addUniform(UniformKeys.MOUSE_DELTA_Y, this._mouseDeltaY); + this.addUniform(UniformKeys.MOUSE_DELTA, this._mouseDelta, 'vec2f'); let hasComputeShaders = this._renderPasses.some(renderPass => renderPass.hasComputeShader); if (!hasComputeShaders && this._bindingTextures.length) { @@ -1417,8 +1413,7 @@ export default class Points { this.updateUniform(UniformKeys.MOUSE_CLICK, this._mouseClick); this.updateUniform(UniformKeys.MOUSE_DOWN, this._mouseDown); this.updateUniform(UniformKeys.MOUSE_WHEEL, this._mouseWheel); - this.updateUniform(UniformKeys.MOUSE_DELTA_X, this._mouseDeltaX); - this.updateUniform(UniformKeys.MOUSE_DELTA_Y, this._mouseDeltaY); + this.updateUniform(UniformKeys.MOUSE_DELTA, this._mouseDelta); //-------------------------------------------- this._createParametersUniforms(); @@ -1553,8 +1548,7 @@ export default class Points { // reset mouse values because it doesn't happen by itself this._mouseClick = false; this._mouseWheel = false; - this._mouseDeltaX = 0; - this._mouseDeltaY = 0; + this._mouseDelta = [0, 0]; await this.read(); } From 3136a9f457cc82d1450019ee43121e3183ddbbf8 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Mon, 11 Dec 2023 19:25:06 -0600 Subject: [PATCH 42/55] Better paddings - Fixed issue with wrong paddings - Created new function that fixes this issue --- src/absulit.points.module.js | 23 +++++++++++++++-------- src/data-size.js | 27 +++++++++++++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index a85274f1..f533cbc0 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -6,7 +6,7 @@ import Coordinate from './coordinate.js'; import RGBAColor from './color.js'; import defaultStructs from './core/defaultStructs.js'; import { defaultVertexBody } from './core/defaultFunctions.js'; -import { dataSize, typeSizes } from './data-size.js'; +import { dataSize, isArray, typeSizes } from './data-size.js'; export default class Points { constructor(canvasId) { @@ -205,6 +205,9 @@ export default class Points { * @param {string} structName type as `f32` or a custom struct */ addUniform(name, value, structName) { + if(structName && isArray(structName)){ + throw `${structName} is an array, which is currently not supported for Uniforms.`; + } if (this._nameExists(this._uniforms, name)) { return; } @@ -870,14 +873,11 @@ export default class Points { * @returns mapped buffer */ _createAndMapBuffer(data, usage, mappedAtCreation = true, size) { - // const paramsDataSize = this._renderPasses[0].dataSize.get('Params') - // console.log(data.byteLength, size, data); const buffer = this._device.createBuffer({ mappedAtCreation: mappedAtCreation, size: size || data.byteLength, usage: usage, }); - new Float32Array(buffer.getMappedRange()).set(data); buffer.unmap(); return buffer; @@ -905,7 +905,8 @@ export default class Points { const paddings = paramsDataSize.paddings; // we check the paddings list and add 0's to just the ones that need it - const values = new Float32Array(this._uniforms.map(v => { + + let arrayValues = this._uniforms.map(v => { const padding = paddings[v.name]; if (padding) { if (v.value.constructor !== Array) { @@ -916,8 +917,16 @@ export default class Points { } } return v.value; - }).flat(1)); + }).flat(1); + const finalPadding = paddings['']; + if (finalPadding) { + for (let i = 0; i < finalPadding; i++) { + arrayValues.push(0); + } + } + + const values = new Float32Array(arrayValues); this._uniforms.buffer = this._createAndMapBuffer(values, GPUBufferUsage.UNIFORM, true, paramsDataSize.bytes); } @@ -1221,7 +1230,6 @@ export default class Points { ); } }); - // console.log(entries) } if (this._layers.length) { @@ -1691,5 +1699,4 @@ export default class Points { videoRecordStop() { this.mediaRecorder.stop(); } - } diff --git a/src/data-size.js b/src/data-size.js index bf87a842..a40e21df 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -162,12 +162,22 @@ function addBytesToAlign(bytes, aligment) { return result; } +function getPadding(bytes, aligment, nextTypeDataSize) { + const nextMultiple = (bytes + aligment - 1) & ~(aligment - 1) + const needsPadding = (bytes + nextTypeDataSize) > nextMultiple; + let padAmount = 0 + if (needsPadding) { + padAmount = nextMultiple - bytes; + } + return padAmount; +} + /** * Check if string has 'array' in it * @param {String} value * @returns {boolean} */ -function isArray(value) { +export function isArray(value) { return value.indexOf('array') != -1; } @@ -291,15 +301,20 @@ export const dataSize = value => { } if (!!nextTypeData) { - if (nextTypeData.align == structDatum.maxAlign) { - const lastByteCounter = byteCounter; - byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); - structDatum.paddings[name] = (byteCounter - lastByteCounter) / 4; + const padAmount = getPadding(byteCounter, structDatum.maxAlign, nextTypeData.size) + if (padAmount) { + structDatum.paddings[name] = padAmount / 4; + byteCounter += padAmount; } } }); - byteCounter += addBytesToAlign(byteCounter, structDatum.maxAlign); + const padAmount = getPadding(byteCounter, structDatum.maxAlign, 16) + if (padAmount) { + structDatum.paddings[''] = padAmount / 4; + byteCounter += padAmount; + } + structDatum.bytes = byteCounter; } return structData; From 7f11b4bc5cdf198279e753a82cf67f9258f8c1f2 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Wed, 13 Dec 2023 19:36:43 -0600 Subject: [PATCH 43/55] Fix to multiple render passes non shareable dataSize - A shared dataSize for the demo and we run all shaders into one call for this --- src/absulit.points.module.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index f533cbc0..63552f09 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -205,7 +205,7 @@ export default class Points { * @param {string} structName type as `f32` or a custom struct */ addUniform(name, value, structName) { - if(structName && isArray(structName)){ + if (structName && isArray(structName)) { throw `${structName} is an array, which is currently not supported for Uniforms.`; } if (this._nameExists(this._uniforms, name)) { @@ -747,14 +747,21 @@ export default class Points { renderPass.hasVertexShader && (renderPass.compiledShaders.vertex = colorsVertWGSL); renderPass.hasComputeShader && (renderPass.compiledShaders.compute = colorsComputeWGSL); renderPass.hasFragmentShader && (renderPass.compiledShaders.fragment = colorsFragWGSL); + } + + _generateDataSize = () => { + const allShaders = this._renderPasses.map(renderPass => { + const { vertex, compute, fragment } = renderPass.compiledShaders; + return vertex + compute + fragment;; + }).join('\n'); - renderPass.dataSize = dataSize(colorsVertWGSL + colorsComputeWGSL + colorsFragWGSL) + this._dataSize = dataSize(allShaders); // since uniforms are in a sigle struct // this is only required for storage this._storage.forEach(s => { if (!s.mapped) { - const d = renderPass.dataSize.get(s.structName) || typeSizes[s.structName]; + const d = this._dataSize.get(s.structName) || typeSizes[s.structName]; s.structSize = d.bytes || d.size; } }); @@ -785,6 +792,7 @@ export default class Points { } this._renderPasses.forEach(this._compileRenderPass); + this._generateDataSize(); // @@ -901,7 +909,7 @@ export default class Points { /** @private */ _createParametersUniforms() { - const paramsDataSize = this._renderPasses[0].dataSize.get('Params') + const paramsDataSize = this._dataSize.get('Params') const paddings = paramsDataSize.paddings; // we check the paddings list and add 0's to just the ones that need it From 9dab2e7682ac6a97c500ea5c61cadb2c1d5d6ee4 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Thu, 14 Dec 2023 19:13:43 -0600 Subject: [PATCH 44/55] extracted code as function - to be used in other places --- src/data-size.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/data-size.js b/src/data-size.js index a40e21df..14881bfb 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -139,7 +139,7 @@ function getStructDataByName(value) { return result; } -function getArrayTypeAndAmount(value) { +export function getArrayTypeAndAmount(value) { const matches = value.matchAll(arrayTypeAndAmountRE); let result = []; for (const match of matches) { @@ -181,6 +181,18 @@ export function isArray(value) { return value.indexOf('array') != -1; } +export function getArrayAlign(structName, structData){ + const [d] = getArrayTypeAndAmount(structName); + const t = typeSizes[d.type] || structData.get(d.type); + if (!t) { + throw new Error(`${d.type} type has not been declared previously`) + } + + // if it's not in typeSizes is a struct, + //therefore probably stored in structData + return t.align || t.maxAlign; +} + export const dataSize = value => { const noCommentsValue = removeComments(value); const structData = getStructDataByName(noCommentsValue); @@ -194,16 +206,7 @@ export const dataSize = value => { // if it doesn't exists in typeSizes is an Array or a new Struct if (!typeSizes[ut]) { if (isArray(ut)) { - const [d] = getArrayTypeAndAmount(ut); - const t = typeSizes[d.type] || structData.get(d.type); - if (!t) { - throw new Error(`${d.type} type has not been declared previously`) - } - - // if it's not in typeSizes is a struct, - //therefore probably stored in structData - align = t.align || t.maxAlign; - + align = getArrayAlign(ut, structData); } else { const sd = structData.get(ut); align = sd.maxAlign; From fed62d738a876c1b09d227f27ba37568bb64783a Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Thu, 14 Dec 2023 19:38:35 -0600 Subject: [PATCH 45/55] extracted code to a function - To be used in the main library - This because in storage what are props in uniforms here are first class, so they need to be parsed apart - Maybe this needs to be moved to the data-size library or simplify it better but they are already two calls to the data-size library --- examples/dithering3_2/compute.js | 2 +- src/absulit.points.module.js | 11 ++++-- src/data-size.js | 67 +++++++++++++------------------- 3 files changed, 36 insertions(+), 44 deletions(-) diff --git a/examples/dithering3_2/compute.js b/examples/dithering3_2/compute.js index 8da296e0..6d3e0bca 100644 --- a/examples/dithering3_2/compute.js +++ b/examples/dithering3_2/compute.js @@ -20,7 +20,7 @@ fn main( let dims = textureDimensions(image); var layerIndex = 0; - if(variables.init == 0.){ + if(variables.init == 0){ let pointIndex = i32(GlobalId.y + (GlobalId.x * dims.x)); diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 63552f09..dad8852e 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -6,7 +6,7 @@ import Coordinate from './coordinate.js'; import RGBAColor from './color.js'; import defaultStructs from './core/defaultStructs.js'; import { defaultVertexBody } from './core/defaultFunctions.js'; -import { dataSize, isArray, typeSizes } from './data-size.js'; +import { dataSize, getArrayAlign, getArrayTypeAndAmount, getArrayTypeData, isArray, typeSizes } from './data-size.js'; export default class Points { constructor(canvasId) { @@ -761,8 +761,13 @@ export default class Points { // this is only required for storage this._storage.forEach(s => { if (!s.mapped) { - const d = this._dataSize.get(s.structName) || typeSizes[s.structName]; - s.structSize = d.bytes || d.size; + if (isArray(s.structName)) { + const typeData = getArrayTypeData(s.structName, this._dataSize); + s.structSize = typeData.size; + } else { + const d = this._dataSize.get(s.structName) || typeSizes[s.structName]; + s.structSize = d.bytes || d.size; + } } }); } diff --git a/src/data-size.js b/src/data-size.js index 14881bfb..916a9ac7 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -181,7 +181,7 @@ export function isArray(value) { return value.indexOf('array') != -1; } -export function getArrayAlign(structName, structData){ +export function getArrayAlign(structName, structData) { const [d] = getArrayTypeAndAmount(structName); const t = typeSizes[d.type] || structData.get(d.type); if (!t) { @@ -193,6 +193,30 @@ export function getArrayAlign(structName, structData){ return t.align || t.maxAlign; } +export function getArrayTypeData(currentType, structData) { + const [d] = getArrayTypeAndAmount(currentType); + if (d.amount == 0) { + throw new Error(`${currentType} has an amount of 0`); + } + // if is an array with no amount then use these default values + let currentTypeData = { size: 16, align: 16 }; + if (!!d.amount) { + const t = typeSizes[d.type]; + if (t) { + // if array, the size is equal to the align + // currentTypeData = { size: t.align * d.amount, align: t.align }; + currentTypeData = { size: t.size * d.amount, align: t.align }; + // currentTypeData = { size: 0, align: 0 }; + } else { + const sd = structData.get(d.type); + if (sd) { + currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; + } + } + } + return currentTypeData; +} + export const dataSize = value => { const noCommentsValue = removeComments(value); const structData = getStructDataByName(noCommentsValue); @@ -236,33 +260,12 @@ export const dataSize = value => { if (!currentTypeData) { if (currentType) { if (isArray(currentType)) { - const [d] = getArrayTypeAndAmount(currentType); - if (d.amount == 0) { - throw new Error(`${currentType} has an amount of 0`); - } - if (!!d.amount) { - const t = typeSizes[d.type]; - if (t) { - // if array, the size is equal to the align - // currentTypeData = { size: t.align * d.amount, align: t.align }; - currentTypeData = { size: t.size * d.amount, align: t.align }; - // currentTypeData = { size: 0, align: 0 }; - } else { - const sd = structData.get(d.type); - if (sd) { - currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; - } - } - } else { - // if is an array with no amount then use these default values - currentTypeData = { size: 16, align: 16 }; - } + currentTypeData = getArrayTypeData(currentType, structData); } else { const sd = structData.get(currentType); if (sd) { currentTypeData = { size: sd.bytes, align: sd.maxAlign }; } - } } } @@ -270,23 +273,7 @@ export const dataSize = value => { if (!nextTypeData) { if (nextType) { if (isArray(nextType)) { - const [d] = getArrayTypeAndAmount(nextType); - if (d.amount == 0) { - throw new Error(`${nextType} has an amount of 0`); - } - if (!!d.amount) { - const t = typeSizes[d.type]; - if (t) { - // nextTypeData = { size: t.align * d.amount, align: t.align }; - nextTypeData = { size: t.size * d.amount, align: t.align }; - // nextTypeData = { size: 0, align: 0 }; - } else { - const sd = structData.get(d.type); - if (sd) { - nextTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; - } - } - } + nextTypeData = getArrayTypeData(nextType, structData); } else { const sd = structData.get(nextType) if (sd) { From d21e2dac0bc7a8abebd69c645755bbfeac267cb3 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Thu, 14 Dec 2023 19:40:03 -0600 Subject: [PATCH 46/55] type correction in comment --- src/absulit.points.module.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index dad8852e..5b7bac1f 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -774,7 +774,7 @@ export default class Points { /** * One time function to call to initialize the shaders. - * @param {array} renderPasses Collection of RenderPass, which contain Vertex, Compute and Fragment shaders. + * @param {Array} renderPasses Collection of RenderPass, which contain Vertex, Compute and Fragment shaders. * @returns false | undefined */ async init(renderPasses) { From d1cef1fe6c93abcc3c08ed95e96156590415e493 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 16 Dec 2023 10:16:20 -0600 Subject: [PATCH 47/55] Removed size param from addStorage - The size was an easy way to create arrays, but since this value can be passed in the structName as an array amount this is not needed anymore - Fixed all the examples by removing the extra parameters --- examples/audio1/index.js | 2 +- examples/audio2/index.js | 2 +- examples/data1/index.js | 3 ++- examples/dithering3_1/compute.js | 2 +- examples/dithering3_1/index.js | 2 +- examples/dithering3_2/index.js | 2 +- examples/events1/index.js | 2 -- examples/layers1/index.js | 2 +- examples/mouseclickscroll1/index.js | 2 +- examples/noise1/index.js | 4 ++-- examples/params_test/frag.js | 8 ++++---- examples/params_test/index.js | 6 ++++-- examples/params_test/structs.js | 2 +- examples/shapes1/index.js | 2 +- examples/shapes2/index.js | 2 +- src/absulit.points.module.js | 7 ++++--- 16 files changed, 26 insertions(+), 24 deletions(-) diff --git a/examples/audio1/index.js b/examples/audio1/index.js index 7876898c..96c1a3ee 100644 --- a/examples/audio1/index.js +++ b/examples/audio1/index.js @@ -22,7 +22,7 @@ const base = { audio.play(); }, 4); // points.addAudio('audio', 'https://mdn.github.io/voice-change-o-matic/audio/concert-crowd.ogg', volume, loop); - points.addStorage('result', 10, 'f32', 4); + points.addStorage('result', 'f32'); }, /** * diff --git a/examples/audio2/index.js b/examples/audio2/index.js index b2f65548..d8832043 100644 --- a/examples/audio2/index.js +++ b/examples/audio2/index.js @@ -26,7 +26,7 @@ const base = { }, 4); - points.addStorage('result', 10, 'f32', 4); + points.addStorage('result', 'array', 4); // RenderPasses.filmgrain(points); // RenderPasses.bloom(points, .1); diff --git a/examples/data1/index.js b/examples/data1/index.js index e8ed4c42..ba3a1d75 100644 --- a/examples/data1/index.js +++ b/examples/data1/index.js @@ -27,9 +27,10 @@ const data1 = { points.addStorageMap('secondMatrix', secondMatrix, 'Matrix'); + // original lines as reference: // let resultMatrixBufferSize = 2 + firstMatrix[0] * secondMatrix[1]; // console.log(resultMatrixBufferSize); - points.addStorage('resultMatrix', 1, 'Matrix', true); + points.addStorage('resultMatrix', 'Matrix', true); }, update: async points => { diff --git a/examples/dithering3_1/compute.js b/examples/dithering3_1/compute.js index 7c084200..33172a8a 100644 --- a/examples/dithering3_1/compute.js +++ b/examples/dithering3_1/compute.js @@ -27,7 +27,7 @@ fn main( let numRowsPiece:i32 = i32(numRows / f32(workgroupSize)); var layerIndex = 0; - if(variables.init == 0.){ + if(variables.init == 0){ for (var indexColumns:i32 = 0; indexColumns < numColumnsPiece; indexColumns++) { let x:f32 = f32(WorkGroupID.x) * f32(numColumnsPiece) + f32(indexColumns); diff --git a/examples/dithering3_1/index.js b/examples/dithering3_1/index.js index 3d6578fe..94f4e555 100644 --- a/examples/dithering3_1/index.js +++ b/examples/dithering3_1/index.js @@ -20,7 +20,7 @@ const dithering3 = { await points.addTextureImage('image', './../img/absulit_800x800.jpg'); points.addBindingTexture('outputTex', 'computeTexture'); points.addLayers(2); - points.addStorage('variables', 1, 'Variable', false, ShaderType.COMPUTE); + points.addStorage('variables', 'Variable', false, ShaderType.COMPUTE); }, update: points => { diff --git a/examples/dithering3_2/index.js b/examples/dithering3_2/index.js index 2d3237f0..cfe87aee 100644 --- a/examples/dithering3_2/index.js +++ b/examples/dithering3_2/index.js @@ -21,7 +21,7 @@ const dithering3 = { await points.addTextureImage('image', './../img/absulit_800x800.jpg'); points.addBindingTexture('outputTex', 'computeTexture'); points.addLayers(2); - points.addStorage('variables', 1, 'Variable', false, ShaderType.COMPUTE); + points.addStorage('variables', 'Variable', false, ShaderType.COMPUTE); }, update: points => { diff --git a/examples/events1/index.js b/examples/events1/index.js index f9b3bc5b..eb735d11 100644 --- a/examples/events1/index.js +++ b/examples/events1/index.js @@ -12,8 +12,6 @@ const base = { * @param {Points} points */ init: async points => { - // points.addStorage('event', 1, 'array', 4, true); - points.addEventListener('left_blink', data => { console.log('---- Left Circle'); }, 4); diff --git a/examples/layers1/index.js b/examples/layers1/index.js index d5e1b96e..ba10630c 100644 --- a/examples/layers1/index.js +++ b/examples/layers1/index.js @@ -8,7 +8,7 @@ const layers1 = { init: async points => { const numPoints = 800*800; points.addUniform('numPoints', numPoints); - // points.addStorage('points', numPoints, 'vec4', 4); + // points.addStorage('points', numPoints, `array, ${numPoints}>`, 4); points.addLayers(2); }, update: points => { diff --git a/examples/mouseclickscroll1/index.js b/examples/mouseclickscroll1/index.js index a4dcf253..b5141a78 100644 --- a/examples/mouseclickscroll1/index.js +++ b/examples/mouseclickscroll1/index.js @@ -5,7 +5,7 @@ const mouseclickscroll1 = { vert, frag, init: async points => { - points.addStorage('variables', 1, 'Variable', 16); + points.addStorage('variables', 'Variable'); }, update: points => { diff --git a/examples/noise1/index.js b/examples/noise1/index.js index a6adcfda..591c67ae 100644 --- a/examples/noise1/index.js +++ b/examples/noise1/index.js @@ -6,8 +6,8 @@ const noise1 = { init: async points => { const numPoints = 800*800; points.addUniform('value_noise_data_length', numPoints); - points.addStorage('value_noise_data', numPoints, 'f32', 4); - points.addStorage('variables', 1, 'Variable', 4); + points.addStorage('value_noise_data', `array`); + points.addStorage('variables', 'Variable'); }, update: points => { diff --git a/examples/params_test/frag.js b/examples/params_test/frag.js index 47407519..07b9de3b 100644 --- a/examples/params_test/frag.js +++ b/examples/params_test/frag.js @@ -8,10 +8,10 @@ ${fnusin} ${structs} ${rand} -struct Colors{ - // items: array< vec4, 800*800 > - items: array< vec4, 640000 > -} +// struct Colors{ +// // items: array< vec4, 800*800 > +// items: array< vec4, 640000 > +// } @fragment fn main( diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 882d859e..345799b0 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -95,11 +95,13 @@ const base = { points.addStorageMap('test', [0, 0, 1, .5], 'vec4f'); - points.addStorage('variables', 1, 'Variable'); - points.addStorage('test2', 1, 'TestStruct'); + points.addStorage('variables', 'Variable'); + points.addStorage('test2', 'TestStruct'); points.addUniform('test3', [1, 0, 0, 1], 'vec4f'); + points.addStorage('anim', 'array'); + // points.addUniform('test4', [1, 0, 0, 1], 'array< vec4, 1 >'); // TODO: throw error if using array in uniform? // points.addUniform('test5', [1,1,1,1], 'array'); diff --git a/examples/params_test/structs.js b/examples/params_test/structs.js index 2f37318e..c14004e3 100644 --- a/examples/params_test/structs.js +++ b/examples/params_test/structs.js @@ -1,6 +1,6 @@ export const structs = /*wgsl*/` struct Variable{ - init: i32, + init: f32, color: vec4f, } diff --git a/examples/shapes1/index.js b/examples/shapes1/index.js index d9a82a1b..5a4f4f2d 100644 --- a/examples/shapes1/index.js +++ b/examples/shapes1/index.js @@ -9,7 +9,7 @@ const shapes1 = { init: async points => { const numPoints = 128; points.addUniform('numPoints', numPoints); - points.addStorage('points', numPoints, 'vec2', 2); + points.addStorage('points', `array, ${numPoints}>`); }, update: points => { diff --git a/examples/shapes2/index.js b/examples/shapes2/index.js index b7cdff79..22a2ac1d 100644 --- a/examples/shapes2/index.js +++ b/examples/shapes2/index.js @@ -9,7 +9,7 @@ const shapes2 = { init: async points => { const numPoints = 800*800; points.addUniform('numPoints', numPoints); - points.addStorage('points', numPoints, 'vec4', 16); + points.addStorage('points', `array, ${numPoints}>`); points.addSampler('feedbackSampler', null); points.addBindingTexture('outputTex', 'computeTexture'); }, diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 5b7bac1f..1c20eddf 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -211,7 +211,7 @@ export default class Points { if (this._nameExists(this._uniforms, name)) { return; } - // TODO: add a third parameter with a type, so a struct can be defined and pass things like booleans + this._uniforms.push({ name: name, value: value, @@ -258,14 +258,14 @@ export default class Points { * @param {boolean} read if this is going to be used to read data back * @param {ShaderType} shaderType this tells to what shader the storage is bound */ - addStorage(name, size, structName, read, shaderType, arrayData) { + addStorage(name, structName, read, shaderType, arrayData) { if (this._nameExists(this._storage, name)) { return; } this._storage.push({ mapped: !!arrayData, name: name, - size: size, + size: 1, // TODO: remove structName: structName, // structSize: null, shaderType: shaderType, @@ -563,6 +563,7 @@ export default class Points { * @param {Function} callback function to be called when the event occurs */ addEventListener(name, callback, structSize) { + // TODO: remove structSize // this extra 4 is for the boolean flag in the Event struct let data = Array(structSize + 4).fill(0); this.addStorageMap(name, data, 'Event', true); From 09c160971173a37eb2e00d4dae7f7d82ce3472af Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 16 Dec 2023 13:21:06 -0600 Subject: [PATCH 48/55] removed size since is not required anymore - Size reference for old arrays - Since this name is not used maybe I can change storageSize to size later --- src/absulit.points.module.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 1c20eddf..6e231e5d 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -265,7 +265,7 @@ export default class Points { this._storage.push({ mapped: !!arrayData, name: name, - size: 1, // TODO: remove + // size: 1, // TODO: remove structName: structName, // structSize: null, shaderType: shaderType, @@ -611,14 +611,6 @@ export default class Points { let internalCheck = internal == storageItem.internal; if (!storageItem.shaderType && internalCheck || storageItem.shaderType == shaderType && internalCheck) { let T = storageItem.structName; - if (!storageItem.mapped) { - if (storageItem.array?.length) { - storageItem.size = storageItem.array.length; - } - if (storageItem.size > 1) { - T = `array<${storageItem.structName}>`; - } - } dynamicGroupBindings += /*wgsl*/`@group(${groupId}) @binding(${bindingIndex}) var ${storageItem.name}: ${T};\n` bindingIndex += 1; } @@ -972,7 +964,7 @@ export default class Points { const values = new Float32Array(storageItem.array); storageItem.buffer = this._createAndMapBuffer(values, usage); } else { - storageItem.buffer = this._createBuffer(storageItem.size * storageItem.structSize, usage); + storageItem.buffer = this._createBuffer(storageItem.structSize, usage); } }); //-------------------------------------------- From 9afca78d5e5e7c0bb77a87e8d12c6e2b283e2f7a Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 16 Dec 2023 19:15:32 -0600 Subject: [PATCH 49/55] deep clone uniforms to avoid double paddinds - New calls to createParametersUniforms make duplicates in paddings - I previously added a flag but this would not fixe it for updateUniforms call --- examples/main.js | 1 + examples/params_test/index.js | 77 ++++--------------- examples/webgpu_particles_1/index.js | 81 ++++++++++++++++++++ examples/webgpu_particles_1/pass0/compute.js | 19 +++++ examples/webgpu_particles_1/pass0/frag.js | 16 ++++ examples/webgpu_particles_1/pass0/index.js | 7 ++ examples/webgpu_particles_1/pass0/structs.js | 21 +++++ examples/webgpu_particles_1/pass0/vert.js | 19 +++++ examples/webgpu_particles_1/pass1/compute.js | 13 ++++ examples/webgpu_particles_1/pass1/frag.js | 29 +++++++ examples/webgpu_particles_1/pass1/index.js | 7 ++ examples/webgpu_particles_1/pass1/vert.js | 15 ++++ examples/webgpu_particles_1/readme | 6 ++ src/absulit.points.module.js | 5 +- 14 files changed, 253 insertions(+), 63 deletions(-) create mode 100644 examples/webgpu_particles_1/index.js create mode 100644 examples/webgpu_particles_1/pass0/compute.js create mode 100644 examples/webgpu_particles_1/pass0/frag.js create mode 100644 examples/webgpu_particles_1/pass0/index.js create mode 100644 examples/webgpu_particles_1/pass0/structs.js create mode 100644 examples/webgpu_particles_1/pass0/vert.js create mode 100644 examples/webgpu_particles_1/pass1/compute.js create mode 100644 examples/webgpu_particles_1/pass1/frag.js create mode 100644 examples/webgpu_particles_1/pass1/index.js create mode 100644 examples/webgpu_particles_1/pass1/vert.js create mode 100644 examples/webgpu_particles_1/readme diff --git a/examples/main.js b/examples/main.js index dade6576..35f78cd7 100644 --- a/examples/main.js +++ b/examples/main.js @@ -93,6 +93,7 @@ const shaderProjects = [ { name: 'UVs 1', path: './uvs1/index.js' }, { name: 'Video Texture 1', path: './videotexture1/index.js' }, { name: 'PARAMS TEST', path: './params_test/index.js' }, + { name: 'WebGPU Particles 1', path: './webgpu_particles_1/index.js' }, ] const shaderNames = {}; diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 345799b0..01c155b8 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -18,66 +18,23 @@ const base = { var startTime = performance.now() const result = dataSize(` - struct Light { - mode: u32, - power: f32, - range: f32, - innerAngle: f32, - outerAngle: f32, - direction: vec3f, - position: vec3f, - }; - - struct FSInput { - colorMult: vec4f, - specularFactor: f32, - lights: array, - }; - - struct VSInput { - projectionMatrix: mat4x4f, - viewMatrix: mat4x4f, - modelMatrix: mat4x4f, - normalMatrix: mat4x4f, - }; - - @group(0) @binding(0) var vsUni: VSInput; - @group(0) @binding(1) var fsUni: FSInput; - @group(0) @binding(2) var diffuseSampler: sampler; - @group(0) @binding(3) var diffuseTexture: texture_2d; - - struct Attribs { - @location(0) position: vec4f, - @location(1) normal: vec3f, - @location(2) texcoord: vec2f, - }; - - struct VSOutput { - @builtin(position) position: vec4f, - @location(0) texcoord: vec2f, - @location(1) normal: vec3f, - }; - - @vertex fn vs(vin: Attribs) -> VSOutput { - var vout: VSOutput; - vout.position = vsUni.projectionMatrix * vsUni.viewMatrix * vsUni.modelMatrix * vin.position; - vout.texcoord = vin.texcoord; - vout.normal = (vsUni.normalMatrix * vec4f(vin.normal, 0)).xyz; - return vout; - } - - @fragment fn fs(vout: VSOutput) -> @location(0) vec4f { - let normal = normalize(vout.normal); - var l = 0.0; - for (var i = 0; i < 2; i++) { - let light = fsUni.lights[i]; - l += clamp(dot(normal, light.direction), 0.0, 1.0); - } - - let color = textureSample(diffuseTexture, diffuseSampler, vout.texcoord); - return vec4f(color.rgb * clamp(l, 0.0, 1.0), color.a); - } - + struct Params { + sliderA:f32, + sliderB:f32, + sliderC:f32, + right:vec3, + up:vec3, + modelViewProjectionMatrix:mat4x4, + time:f32, + epoch:f32, + screen:vec2f, + mouse:vec2f, + mouseClick:f32, + mouseDown:f32, + mouseDelta:vec2f, + mouseWheel:f32, + + } diff --git a/examples/webgpu_particles_1/index.js b/examples/webgpu_particles_1/index.js new file mode 100644 index 00000000..91020935 --- /dev/null +++ b/examples/webgpu_particles_1/index.js @@ -0,0 +1,81 @@ +import Points from './../../src/absulit.points.module.js'; +import RenderPass from '../../src/RenderPass.js'; + +import { + vec3, + mat4, +} from 'https://wgpu-matrix.org/dist/2.x/wgpu-matrix.module.js'; + +import renderPass0 from './pass0/index.js'; + +const base = { + renderPasses: [ + renderPass0 + ], + /** + * + * @param {Points} points + */ + init: async points => { + // const aspect = points.canvas.width / points.canvas.height; + + // const projection = mat4.perspective((2 * Math.PI) / 5, aspect, 1, 100.0); + const view = mat4.create(); + const mvp = mat4.create(); + + + const modelViewProjectionMatrix = [ + mvp[0], mvp[1], mvp[2], mvp[3], + mvp[4], mvp[5], mvp[6], mvp[7], + mvp[8], mvp[9], mvp[10], mvp[11], + mvp[12], mvp[13], mvp[14], mvp[15] + ]; + + const right = [view[0], view[4], view[8]] + + const up = [view[1], view[5], view[9]] + + // const data = [ + // // modelViewProjectionMatrix + // mvp[0], mvp[1], mvp[2], mvp[3], + // mvp[4], mvp[5], mvp[6], mvp[7], + // mvp[8], mvp[9], mvp[10], mvp[11], + // mvp[12], mvp[13], mvp[14], mvp[15], + + // view[0], view[4], view[8], // right + + // 0, // padding + + // view[1], view[5], view[9], // up + + // 0, // padding + // ] + + // const modelViewProjectionMatrix = [ + // 7, 7, 7, 7, + // 7, 7, 7, 7, + // 7, 7, 7, 7, + // 7, 7, 7, 7 + // ]; + + // const right = [8, 8, 8] + + // const up = [9, 9, 9] + + + + + points.addUniform('right', right, 'vec3'); + points.addUniform('up', up, 'vec3'); + points.addUniform('modelViewProjectionMatrix', modelViewProjectionMatrix, 'mat4x4'); + + // points.addUniform('render_params', data, 'RenderParams'); + + // TODO: bug, invert MOUSE_DELTA and MOUSE_WHEEL positions in addUniforms + }, + update: points => { + + } +} + +export default base; \ No newline at end of file diff --git a/examples/webgpu_particles_1/pass0/compute.js b/examples/webgpu_particles_1/pass0/compute.js new file mode 100644 index 00000000..e79e692c --- /dev/null +++ b/examples/webgpu_particles_1/pass0/compute.js @@ -0,0 +1,19 @@ +import { structs } from './structs.js'; + +const compute = /*wgsl*/` + +${structs} + + + +@compute @workgroup_size(8,8,1) +fn main( + @builtin(global_invocation_id) GlobalId: vec3, + @builtin(workgroup_id) WorkGroupID: vec3, + @builtin(local_invocation_id) LocalInvocationID: vec3 +) { + let time = params.time; +} +`; + +export default compute; diff --git a/examples/webgpu_particles_1/pass0/frag.js b/examples/webgpu_particles_1/pass0/frag.js new file mode 100644 index 00000000..312593c1 --- /dev/null +++ b/examples/webgpu_particles_1/pass0/frag.js @@ -0,0 +1,16 @@ +import { structs } from './structs.js'; + +const frag = /*wgsl*/` + +${structs} + +@fragment +fn main(in : VertexOutput) -> @location(0) vec4 { + var color = in.color; + // Apply a circular particle alpha mask + color.a = color.a * max(1.0 - length(in.quad_pos), 0.0); + return color; +} +`; + +export default frag; diff --git a/examples/webgpu_particles_1/pass0/index.js b/examples/webgpu_particles_1/pass0/index.js new file mode 100644 index 00000000..d3d4a7c2 --- /dev/null +++ b/examples/webgpu_particles_1/pass0/index.js @@ -0,0 +1,7 @@ +import vert from './vert.js'; +import frag from './frag.js'; +import compute from './compute.js'; + +import RenderPass from './../../../src/RenderPass.js'; + +export default new RenderPass(vert, frag, compute); diff --git a/examples/webgpu_particles_1/pass0/structs.js b/examples/webgpu_particles_1/pass0/structs.js new file mode 100644 index 00000000..3dbd41c4 --- /dev/null +++ b/examples/webgpu_particles_1/pass0/structs.js @@ -0,0 +1,21 @@ +export const structs = /*wgsl*/` + +struct RenderParams { + modelViewProjectionMatrix : mat4x4, + right : vec3, + up : vec3 +} + +struct VertexInput { + @location(0) position : vec3, + @location(1) color : vec4, + @location(2) quad_pos : vec2, // -1..+1 +} + +struct VertexOutput { + @builtin(position) position : vec4, + @location(0) color : vec4, + @location(1) quad_pos : vec2, // -1..+1 +} + +`; \ No newline at end of file diff --git a/examples/webgpu_particles_1/pass0/vert.js b/examples/webgpu_particles_1/pass0/vert.js new file mode 100644 index 00000000..d6169e68 --- /dev/null +++ b/examples/webgpu_particles_1/pass0/vert.js @@ -0,0 +1,19 @@ +import { structs } from './structs.js'; + +const vert = /*wgsl*/` + +${structs} + +@vertex +fn main(in : VertexInput) -> VertexOutput { + var quad_pos = mat2x3(params.right, params.up) * in.quad_pos; + var position = in.position + quad_pos * 0.01; + var out : VertexOutput; + out.position = params.modelViewProjectionMatrix * vec4(position, 1.0); + out.color = in.color; + out.quad_pos = in.quad_pos; + return out; +} +`; + +export default vert; diff --git a/examples/webgpu_particles_1/pass1/compute.js b/examples/webgpu_particles_1/pass1/compute.js new file mode 100644 index 00000000..00dd5ed7 --- /dev/null +++ b/examples/webgpu_particles_1/pass1/compute.js @@ -0,0 +1,13 @@ +const compute = /*wgsl*/` + +@compute @workgroup_size(8,8,1) +fn main( + @builtin(global_invocation_id) GlobalId: vec3, + @builtin(workgroup_id) WorkGroupID: vec3, + @builtin(local_invocation_id) LocalInvocationID: vec3 +) { + let time = params.time; +} +`; + +export default compute; diff --git a/examples/webgpu_particles_1/pass1/frag.js b/examples/webgpu_particles_1/pass1/frag.js new file mode 100644 index 00000000..f9006d24 --- /dev/null +++ b/examples/webgpu_particles_1/pass1/frag.js @@ -0,0 +1,29 @@ +import { fnusin } from '../../../src/core/animation.js'; + +const frag = /*wgsl*/` + +${fnusin} + +@fragment +fn main( + @location(0) color: vec4, + @location(1) uv: vec2, + @location(2) ratio: vec2, // relation between params.screenWidth and params.screenHeight + @location(3) uvr: vec2, // uv with aspect ratio corrected + @location(4) mouse: vec2, + @builtin(position) position: vec4 +) -> @location(0) vec4 { + + let cellSize = 20. + 10. * fnusin(1.); + let a = sin(uvr.x * cellSize) * sin(uvr.y * cellSize); + let b = sin(uvr.x * uvr.y * 10. * 9.1 * .25 ); + let c = fnusin(uvr.x * uvr.y * 10.); + let d = distance(a,b); + let f = d * uvr.x * uvr.y; + let finalColor:vec4 = vec4(a*d,f*c*a,f, 1.); + + return finalColor; +} +`; + +export default frag; diff --git a/examples/webgpu_particles_1/pass1/index.js b/examples/webgpu_particles_1/pass1/index.js new file mode 100644 index 00000000..d3d4a7c2 --- /dev/null +++ b/examples/webgpu_particles_1/pass1/index.js @@ -0,0 +1,7 @@ +import vert from './vert.js'; +import frag from './frag.js'; +import compute from './compute.js'; + +import RenderPass from './../../../src/RenderPass.js'; + +export default new RenderPass(vert, frag, compute); diff --git a/examples/webgpu_particles_1/pass1/vert.js b/examples/webgpu_particles_1/pass1/vert.js new file mode 100644 index 00000000..fdf316e3 --- /dev/null +++ b/examples/webgpu_particles_1/pass1/vert.js @@ -0,0 +1,15 @@ +const vert = /*wgsl*/` + +@vertex +fn main( + @location(0) position: vec4, + @location(1) color: vec4, + @location(2) uv: vec2, + @builtin(vertex_index) vertexIndex: u32 +) -> Fragment { + + return defaultVertexBody(position, color, uv); +} +`; + +export default vert; diff --git a/examples/webgpu_particles_1/readme b/examples/webgpu_particles_1/readme new file mode 100644 index 00000000..a5d20954 --- /dev/null +++ b/examples/webgpu_particles_1/readme @@ -0,0 +1,6 @@ +This are the particles from this demo + +https://webgpu.github.io/webgpu-samples/samples/particles + +this will not work since unifors are still f32, and they need to be reworked +to support other data types \ No newline at end of file diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 6e231e5d..4ede561e 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -265,7 +265,6 @@ export default class Points { this._storage.push({ mapped: !!arrayData, name: name, - // size: 1, // TODO: remove structName: structName, // structSize: null, shaderType: shaderType, @@ -911,8 +910,8 @@ export default class Points { const paddings = paramsDataSize.paddings; // we check the paddings list and add 0's to just the ones that need it - - let arrayValues = this._uniforms.map(v => { + const uniformsClone = JSON.parse(JSON.stringify(this._uniforms)); + let arrayValues = uniformsClone.map(v => { const padding = paddings[v.name]; if (padding) { if (v.value.constructor !== Array) { From c5b1aa3e4272ca1abae7a6c7aa8779fcdfaa5909 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 16 Dec 2023 19:54:48 -0600 Subject: [PATCH 50/55] Fix to default size - This selects size from struct in a no amount array as default value. Size 16 is not enough with structs. --- examples/webgpu_particles_1/index.js | 5 ++ examples/webgpu_particles_1/pass0/compute.js | 67 +++++++++++++++++-- examples/webgpu_particles_1/pass0/structs.js | 16 +++++ examples/webgpu_particles_1/webgpu.png | Bin 0 -> 38482 bytes src/data-size.js | 3 + 5 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 examples/webgpu_particles_1/webgpu.png diff --git a/examples/webgpu_particles_1/index.js b/examples/webgpu_particles_1/index.js index 91020935..7eaebb74 100644 --- a/examples/webgpu_particles_1/index.js +++ b/examples/webgpu_particles_1/index.js @@ -68,7 +68,12 @@ const base = { points.addUniform('right', right, 'vec3'); points.addUniform('up', up, 'vec3'); points.addUniform('modelViewProjectionMatrix', modelViewProjectionMatrix, 'mat4x4'); + + points.addUniform('deltaTime', 0); + points.addUniform('seed', [0,0,0,0], 'vec4f'); + points.addStorage('data', 'Particles'); + await points.addTextureImage('texture', 'webgpu_particles_1/webgpu.png'); // points.addUniform('render_params', data, 'RenderParams'); // TODO: bug, invert MOUSE_DELTA and MOUSE_WHEEL positions in addUniforms diff --git a/examples/webgpu_particles_1/pass0/compute.js b/examples/webgpu_particles_1/pass0/compute.js index e79e692c..ef451803 100644 --- a/examples/webgpu_particles_1/pass0/compute.js +++ b/examples/webgpu_particles_1/pass0/compute.js @@ -4,15 +4,74 @@ const compute = /*wgsl*/` ${structs} +var rand_seed : vec2; + +fn init_rand(invocation_id : u32, seed : vec4) { + rand_seed = seed.xz; + rand_seed = fract(rand_seed * cos(35.456+f32(invocation_id) * seed.yw)); + rand_seed = fract(rand_seed * cos(41.235+f32(invocation_id) * seed.xw)); +} + +fn rand() -> f32 { + rand_seed.x = fract(cos(dot(rand_seed, vec2(23.14077926, 232.61690225))) * 136.8168); + rand_seed.y = fract(cos(dot(rand_seed, vec2(54.47856553, 345.84153136))) * 534.7645); + return rand_seed.y; +} @compute @workgroup_size(8,8,1) fn main( - @builtin(global_invocation_id) GlobalId: vec3, - @builtin(workgroup_id) WorkGroupID: vec3, - @builtin(local_invocation_id) LocalInvocationID: vec3 + @builtin(global_invocation_id) global_invocation_id : vec3 ) { - let time = params.time; + let idx = global_invocation_id.x; + + init_rand(idx, params.seed); + + var particle = data.particles[idx]; + + // Apply gravity + particle.velocity.z = particle.velocity.z - params.deltaTime * 0.5; + + // Basic velocity integration + particle.position = particle.position + params.deltaTime * particle.velocity; + + // Age each particle. Fade out before vanishing. + particle.lifetime = particle.lifetime - params.deltaTime; + particle.color.a = smoothstep(0.0, 0.5, particle.lifetime); + + // If the lifetime has gone negative, then the particle is dead and should be + // respawned. + if (particle.lifetime < 0.0) { + // Use the probability map to find where the particle should be spawned. + // Starting with the 1x1 mip level. + var coord : vec2; + for (var level = u32(textureNumLevels(texture) - 1); level > 0; level--) { + // Load the probability value from the mip-level + // Generate a random number and using the probabilty values, pick the + // next texel in the next largest mip level: + // + // 0.0 probabilites.r probabilites.g probabilites.b 1.0 + // | | | | | + // | TOP-LEFT | TOP-RIGHT | BOTTOM-LEFT | BOTTOM_RIGHT | + // + let probabilites = textureLoad(texture, coord, level); + let value = vec4(rand()); + let mask = (value >= vec4(0.0, probabilites.xyz)) & (value < probabilites); + coord = coord * 2; + coord.x = coord.x + select(0, 1, any(mask.yw)); // x y + coord.y = coord.y + select(0, 1, any(mask.zw)); // z w + } + let uv = vec2(coord) / vec2(textureDimensions(texture)); + particle.position = vec3((uv - 0.5) * 3.0 * vec2(1.0, -1.0), 0.0); + particle.color = textureLoad(texture, coord, 0); + particle.velocity.x = (rand() - 0.5) * 0.1; + particle.velocity.y = (rand() - 0.5) * 0.1; + particle.velocity.z = rand() * 0.3; + particle.lifetime = 0.5 + rand() * 3.0; + } + + // Store the new particle value + data.particles[idx] = particle; } `; diff --git a/examples/webgpu_particles_1/pass0/structs.js b/examples/webgpu_particles_1/pass0/structs.js index 3dbd41c4..60ee6ed8 100644 --- a/examples/webgpu_particles_1/pass0/structs.js +++ b/examples/webgpu_particles_1/pass0/structs.js @@ -18,4 +18,20 @@ struct VertexOutput { @location(1) quad_pos : vec2, // -1..+1 } +struct SimulationParams { + deltaTime : f32, + seed : vec4, + } + +struct Particle { + position : vec3, + lifetime : f32, + color : vec4, + velocity : vec3, +} + +struct Particles { + particles : array, +} + `; \ No newline at end of file diff --git a/examples/webgpu_particles_1/webgpu.png b/examples/webgpu_particles_1/webgpu.png new file mode 100644 index 0000000000000000000000000000000000000000..a44b73ead9903e05cae19355b54ad274ed8147ea GIT binary patch literal 38482 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 IdF!zM14p*&djJ3c literal 0 HcmV?d00001 diff --git a/src/data-size.js b/src/data-size.js index 916a9ac7..40bcd919 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -213,6 +213,9 @@ export function getArrayTypeData(currentType, structData) { currentTypeData = { size: sd.bytes * d.amount, align: sd.maxAlign }; } } + } else { + const t = typeSizes[d.type] || structData.get(d.type); + currentTypeData = { size: t.bytes, align: t.maxAlign }; } return currentTypeData; } From 967f09ffdd2c50ccd1fd3706c5e226dbf175161b Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sat, 16 Dec 2023 21:08:56 -0600 Subject: [PATCH 51/55] check size or bytes --- src/absulit.points.module.js | 3 +++ src/data-size.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/absulit.points.module.js b/src/absulit.points.module.js index 4ede561e..c7911dfd 100644 --- a/src/absulit.points.module.js +++ b/src/absulit.points.module.js @@ -758,6 +758,9 @@ export default class Points { s.structSize = typeData.size; } else { const d = this._dataSize.get(s.structName) || typeSizes[s.structName]; + if(!d){ + throw `${s.structName} has not been defined.` + } s.structSize = d.bytes || d.size; } } diff --git a/src/data-size.js b/src/data-size.js index 40bcd919..013072b0 100644 --- a/src/data-size.js +++ b/src/data-size.js @@ -215,7 +215,7 @@ export function getArrayTypeData(currentType, structData) { } } else { const t = typeSizes[d.type] || structData.get(d.type); - currentTypeData = { size: t.bytes, align: t.maxAlign }; + currentTypeData = { size: t.size || t.bytes, align: t.maxAlign }; } return currentTypeData; } From fcadc9455c97e0520493888f3aae9a945a44b087 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 17 Dec 2023 14:13:51 -0600 Subject: [PATCH 52/55] progress on pass 1 --- examples/webgpu_particles_1/index.js | 15 +++++-- examples/webgpu_particles_1/pass1/compute.js | 12 ++++-- examples/webgpu_particles_1/pass1/index.js | 2 +- examples/webgpu_particles_1/structs.js | 45 ++++++++++++++++++++ 4 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 examples/webgpu_particles_1/structs.js diff --git a/examples/webgpu_particles_1/index.js b/examples/webgpu_particles_1/index.js index 7eaebb74..2531d9ff 100644 --- a/examples/webgpu_particles_1/index.js +++ b/examples/webgpu_particles_1/index.js @@ -7,10 +7,12 @@ import { } from 'https://wgpu-matrix.org/dist/2.x/wgpu-matrix.module.js'; import renderPass0 from './pass0/index.js'; +import renderPass1 from './pass1/index.js'; const base = { renderPasses: [ - renderPass0 + // renderPass0, + renderPass1, ], /** * @@ -68,15 +70,20 @@ const base = { points.addUniform('right', right, 'vec3'); points.addUniform('up', up, 'vec3'); points.addUniform('modelViewProjectionMatrix', modelViewProjectionMatrix, 'mat4x4'); - + points.addUniform('deltaTime', 0); - points.addUniform('seed', [0,0,0,0], 'vec4f'); + points.addUniform('seed', [0, 0, 0, 0], 'vec4f'); points.addStorage('data', 'Particles'); await points.addTextureImage('texture', 'webgpu_particles_1/webgpu.png'); // points.addUniform('render_params', data, 'RenderParams'); - // TODO: bug, invert MOUSE_DELTA and MOUSE_WHEEL positions in addUniforms + points.addUniform('ubo_width', 1, 'u32'); + // points.addStorage() + points.addStorage('buf_in', 'Buffer', true); + points.addStorage('buf_out', 'Buffer'); + + points.addBindingTexture('tex_out', 'tex_in') }, update: points => { diff --git a/examples/webgpu_particles_1/pass1/compute.js b/examples/webgpu_particles_1/pass1/compute.js index 00dd5ed7..c63c1a0d 100644 --- a/examples/webgpu_particles_1/pass1/compute.js +++ b/examples/webgpu_particles_1/pass1/compute.js @@ -1,12 +1,16 @@ +import { structs } from '../structs.js'; + const compute = /*wgsl*/` +${structs} + @compute @workgroup_size(8,8,1) fn main( - @builtin(global_invocation_id) GlobalId: vec3, - @builtin(workgroup_id) WorkGroupID: vec3, - @builtin(local_invocation_id) LocalInvocationID: vec3 + @builtin(global_invocation_id) coord : vec3 ) { - let time = params.time; + _ = &buf_in; + let offset = coord.x + coord.y * params.ubo_width; + buf_out.weights[offset] = textureLoad(tex_in, vec2(coord.xy), 0).w; } `; diff --git a/examples/webgpu_particles_1/pass1/index.js b/examples/webgpu_particles_1/pass1/index.js index d3d4a7c2..47366d5e 100644 --- a/examples/webgpu_particles_1/pass1/index.js +++ b/examples/webgpu_particles_1/pass1/index.js @@ -4,4 +4,4 @@ import compute from './compute.js'; import RenderPass from './../../../src/RenderPass.js'; -export default new RenderPass(vert, frag, compute); +export default new RenderPass(null, null, compute); diff --git a/examples/webgpu_particles_1/structs.js b/examples/webgpu_particles_1/structs.js new file mode 100644 index 00000000..72000c06 --- /dev/null +++ b/examples/webgpu_particles_1/structs.js @@ -0,0 +1,45 @@ +export const structs = /*wgsl*/` + +struct RenderParams { + modelViewProjectionMatrix : mat4x4, + right : vec3, + up : vec3 +} + +struct VertexInput { + @location(0) position : vec3, + @location(1) color : vec4, + @location(2) quad_pos : vec2, // -1..+1 +} + +struct VertexOutput { + @builtin(position) position : vec4, + @location(0) color : vec4, + @location(1) quad_pos : vec2, // -1..+1 +} + +struct SimulationParams { + deltaTime : f32, + seed : vec4, + } + +struct Particle { + position : vec3, + lifetime : f32, + color : vec4, + velocity : vec3, +} + +struct Particles { + particles : array, +} + +struct UBO { + width : u32, +} + +struct Buffer { + weights : array, +} + +`; From 6b93452041af029e056f3625524a207b5dfb639d Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 17 Dec 2023 14:19:30 -0600 Subject: [PATCH 53/55] corrected structs reference --- examples/webgpu_particles_1/index.js | 4 ++-- examples/webgpu_particles_1/pass0/compute.js | 2 +- examples/webgpu_particles_1/pass0/frag.js | 2 +- examples/webgpu_particles_1/pass0/vert.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/webgpu_particles_1/index.js b/examples/webgpu_particles_1/index.js index 2531d9ff..4ffb0d28 100644 --- a/examples/webgpu_particles_1/index.js +++ b/examples/webgpu_particles_1/index.js @@ -11,8 +11,8 @@ import renderPass1 from './pass1/index.js'; const base = { renderPasses: [ - // renderPass0, - renderPass1, + renderPass0, + // renderPass1, ], /** * diff --git a/examples/webgpu_particles_1/pass0/compute.js b/examples/webgpu_particles_1/pass0/compute.js index ef451803..1a7ed053 100644 --- a/examples/webgpu_particles_1/pass0/compute.js +++ b/examples/webgpu_particles_1/pass0/compute.js @@ -1,4 +1,4 @@ -import { structs } from './structs.js'; +import { structs } from '../structs.js'; const compute = /*wgsl*/` diff --git a/examples/webgpu_particles_1/pass0/frag.js b/examples/webgpu_particles_1/pass0/frag.js index 312593c1..675356f6 100644 --- a/examples/webgpu_particles_1/pass0/frag.js +++ b/examples/webgpu_particles_1/pass0/frag.js @@ -1,4 +1,4 @@ -import { structs } from './structs.js'; +import { structs } from '../structs.js'; const frag = /*wgsl*/` diff --git a/examples/webgpu_particles_1/pass0/vert.js b/examples/webgpu_particles_1/pass0/vert.js index d6169e68..6e0f67c7 100644 --- a/examples/webgpu_particles_1/pass0/vert.js +++ b/examples/webgpu_particles_1/pass0/vert.js @@ -1,4 +1,4 @@ -import { structs } from './structs.js'; +import { structs } from '../structs.js'; const vert = /*wgsl*/` From eba69afe741a9167e3edb3d8b9ef0b97956fddd6 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 17 Dec 2023 15:07:27 -0600 Subject: [PATCH 54/55] Update main.js - commenting out test projects --- examples/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/main.js b/examples/main.js index 35f78cd7..d25d1761 100644 --- a/examples/main.js +++ b/examples/main.js @@ -92,8 +92,8 @@ const shaderProjects = [ { name: 'Spritesheet 1', path: './spritesheet1/index.js' }, { name: 'UVs 1', path: './uvs1/index.js' }, { name: 'Video Texture 1', path: './videotexture1/index.js' }, - { name: 'PARAMS TEST', path: './params_test/index.js' }, - { name: 'WebGPU Particles 1', path: './webgpu_particles_1/index.js' }, + // { name: 'PARAMS TEST', path: './params_test/index.js' }, + // { name: 'WebGPU Particles 1', path: './webgpu_particles_1/index.js' }, ] const shaderNames = {}; From 43188d577620b61ced6f6c1da5574a817e487ea2 Mon Sep 17 00:00:00 2001 From: Sebastian Sanabria Date: Sun, 17 Dec 2023 16:22:39 -0600 Subject: [PATCH 55/55] Updated docs --- README.md | 129 +++++++++++++--------------------- examples/params_test/frag.js | 2 + examples/params_test/index.js | 2 + 3 files changed, 52 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index 78e0515f..b5a40461 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ const points = new Points('gl-canvas'); // create your render pass with three shaders as follow const renderPasses = [ - new RenderPass( + new RenderPass( /*wgsl*/ ` // add @vertex string `, @@ -238,10 +238,12 @@ Globally there's a uniform struct called `Params` and its instance called `param struct Params { time:f32, epoch:f32, - screenWidth:f32, - screenHeight:f32, - mouseX:f32, - mouseY:f32, + screen:vec2f, + mouse:vec2f, + mouseClick:f32, + mouseDown:f32, + mouseWheel:f32, + mouseDelta:vec2f, } ``` @@ -249,10 +251,8 @@ struct Params { | ------------- |:------------- | -----: | | time | seconds since the app started | 10.11 | | epoch | seconds since jan 1st 1970 UTC | 1674958734.777| -| screenWidth | pixels in x dimension | 800 | -| screenHeight | pixels in y dimension | 600 | -| mouseX | mouse x coordinate from 0 to screenWidth | 100 | -| mouseY | mouse y coordinate from 0 to screenHeight | 150 | +| screen | pixels in x and y dimensions | 800, 600 | +| mouse | mouse coordinates from (0, 0) to screen | 100, 150 | ```rust // frag.js @@ -334,13 +334,21 @@ You can call one of the following methods, you pair the data with a `key` name, ## Uniforms - addUniform -Uniforms are sent separately in the `main.js` file and they are all combined in the shaders in the struct called `params` . Currently, by default, all values are `f32` . Uniforms can not be modified at runtime inside the shaders, they can only receive data from the JavaScript side. +Uniforms are sent separately in the `main.js` file and they are all combined in the shaders in the struct called `params` . By default, all values are `f32` if no Struct or Type is specified in the third parameter. If values have more than one dimension (`array`, `vec2f`, `vec3f`, `vec4f`...) the data has to be send as an array. Uniforms can not be modified at runtime inside the shaders, they can only receive data from the JavaScript side. + +--- + +> **Note:** structs as uniform types have very basic support and it will be fixed in later updates + +--- ```js // main.js async function init() { let renderPasses = [shaders.vert, shaders.compute, shaders.frag]; points.addUniform('myKeyName', 0); // 0 is your default value + points.addUniform('myTestVec2', [0.2, 2.1], 'vec2f'); // array of lenght 2 as data + points.addUniform('myTestStruct', [99, 1, 2, 3], 'MyTestStruct'); // prop value is 99 and the rest is a vec3f // more init code await points.init(renderPasses); @@ -350,7 +358,18 @@ async function init() { ```rust // frag.js -let aValue = params.myKeyName; + +struct MyTestStruct { + prop: f32, + another_prop: vec3f +} + +let aValue = params.myKeyName; // 0 + +let bValue = params.myTestVec2; // 0.2, 2.1 + +let cValue1 = params.myTestStruct.prop; // 99 +let cValue2 = params.myTestStruct.another_prop; // 1, 2, 3 ``` ## Sampler - addSampler @@ -446,67 +465,6 @@ Common uses: * Store colors * Store results from a heavy calculation in the compute shader ---- - -> **Note:** This method is one with tricky parameters, it's fully documented in the module, but here is an overview: -> -> - name - name this property/variable will have inside the shader -> - size - number of items it will allocate -> - structName - You can use one of the default structs/types like `f32` , `i32` , `u32` , but if you use a more complex one you have to pair it properly with structSize. If it's a custom `struct` it has to be declared in the shader or it will throw an error. -> - structSize - if the `struct` you reference in `structName` has 4 properties then you have to add `4` . If it's only a f32 then here you should place `1` . If the `struct` has vectors in it, the size of the vector counts: - -```rust -// structSize: 1 -f32 -u32 -i32 - -// structSize: 2 -vec2 -vec2 -vec2 -vec2f -vec2i -vec2u - -// structSize: 3 -vec3 -vec3 -vec3 -vec3f -vec3i -vec3u - -// structSize: 4 -vec4 -vec4 -vec4 -vec4f -vec4i -vec4u - -// CUSTOM STRUCTS - -// structSize: 3 -struct Variables { - value1: vec2f, - value2: f32, -} - -// structSize: 5 -struct Variables2 { - value1: vec3f, - value2: i32, - value3: u32, -} - -``` - ---- - -> **Note:** if the size of the storage is greater than `1` then it's created as an array in the shader and you have to access its items like an array, but if size is just `1` you can access its properties directly. Please check the following example for reference. - ---- ```js // main.js @@ -514,8 +472,8 @@ async function init() { let renderPasses = [shaders.vert, shaders.compute, shaders.frag]; const numPoints = 800 * 800; - points.addStorage('value_noise_data', numPoints, 'f32', 1); // size is 640,000 - points.addStorage('variables', 1, 'Variable', 1); // size is 1 + points.addStorage('value_noise_data', `array`); + points.addStorage('variables', 'Variable'); // more init code await points.init(renderPasses); @@ -546,8 +504,8 @@ variables.isCreated = 1; You can also add a default type instead of a custom struct in `structName`: ```js -points.addStorage('myVar', 1, 'f32', 1); // size is 1 -points.addStorage('myVar2', 1, 'vec2f', 2); // size is 2 +points.addStorage('myVar', 'f32'); +points.addStorage('myVar2', 'vec2f'); ``` ## StorageMap - addStorageMap @@ -559,7 +517,7 @@ Creates a Storage in the same way as a `addStorage` does, except it can be set w async function init() { let renderPasses = [shaders.vert, shaders.compute, shaders.frag]; - points.addStorageMap('values', [1.0, 99.0], 'f32'); + points.addStorageMap('values', [1.0, 99.0], 'array'); // more init code await points.init(renderPasses); @@ -578,6 +536,13 @@ let c = values[1]; If you require to send data as a texture from the Compute Shader to the Fragment shader and you do not want to use a Storage, you can use a `addBindingTexture()` , then in the compute shader a variable will exist where you can write colors to it, and in the Fragment Shader will exist a variable to read data from it. +--- + +> **Note:** Currently only supporting creating a write texture on Compute shader and a read texture on Fragment shader. + +--- + + ```js // main.js async function init() { @@ -802,11 +767,12 @@ async function init() { // this is before any GPU calculation, so it's ok let data = []; - for (let k = 0; k < 800 * 800; k++) { + let dataAmount = 800 * 800; + for (let k = 0; k < dataAmount k++) { data.push(Math.random()); } // it doesn't require size because uses the data to size it - points.addStorageMap('rands', data, 'f32'); + points.addStorageMap('rands', data, `array`); // more init code await points.init(renderPasses); @@ -816,7 +782,8 @@ async function init() { function update() { // this is a processor hog let data = []; - for (let k = 0; k < 800 * 800; k++) { + let dataAmount = 800 * 800; + for (let k = 0; k < dataAmount; k++) { data.push(Math.random()); } points.updateStorageMap('rands', data); @@ -835,7 +802,7 @@ First declare a storage as in `examples/data1/index.js` ```js // the last parameter as `true` means you will use this `Storage` to read back -points.addStorage('resultMatrix', 1, 'Matrix', resultMatrixBufferSize, true); +points.addStorage('resultMatrix', 'Matrix', true); ``` Read the data back after modification diff --git a/examples/params_test/frag.js b/examples/params_test/frag.js index 07b9de3b..673b6a48 100644 --- a/examples/params_test/frag.js +++ b/examples/params_test/frag.js @@ -34,6 +34,8 @@ fn main( } finalColor = variables.color; + let c = values[1]; + return variables.color; } diff --git a/examples/params_test/index.js b/examples/params_test/index.js index 01c155b8..454bf659 100644 --- a/examples/params_test/index.js +++ b/examples/params_test/index.js @@ -59,6 +59,8 @@ const base = { points.addStorage('anim', 'array'); + points.addStorageMap('values', [1.0, 99.0], 'array'); + // points.addUniform('test4', [1, 0, 0, 1], 'array< vec4, 1 >'); // TODO: throw error if using array in uniform? // points.addUniform('test5', [1,1,1,1], 'array');