Skip to content

Commit

Permalink
Merge pull request #70 from martinlaxenaire/develop
Browse files Browse the repository at this point in the history
v0.6.0
  • Loading branch information
martinlaxenaire committed May 7, 2024
2 parents 6cf7238 + eff24a6 commit 4fd3f57
Show file tree
Hide file tree
Showing 519 changed files with 12,582 additions and 8,540 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ window.addEventListener('load', async () => {

## Limitations

Since gpu-curtains is mostly made to create quads based on HTML elements, it may lack some common 3D engines features.
gpu-curtains is mostly made to create quads based on HTML elements, it may lack some common 3D engines features (even tho it is slowly evolving towards a real 3D engine).

If you need a real 3D engine that could handle complex geometries or advanced rendering mechanics, then you should probably go with another library like [three.js](https://github.com/mrdoob/three.js) or [Babylon.js](https://github.com/BabylonJS).
If you need a more robust 3D engine that could handle complex geometries or advanced rendering mechanics, then you should probably go with another library like [three.js](https://github.com/mrdoob/three.js) or [Babylon.js](https://github.com/BabylonJS).

## Contributing

Expand Down
15 changes: 9 additions & 6 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

- GPUDeviceManager (can handle multiple renderers / canvases)
- Renderers (GPURenderer, GPUCameraRenderer, GPUCurtainsRenderer)
- Scene graph with Object3D, ProjectedObject3D, DOMObject3D
- Scene class with scene graph for Object3D, ProjectedObject3D, DOMObject3D
- Camera
- Geometries
- Materials (Material, RenderMaterial, ComputeMaterial)
- Bindings & BindGroups
- Buffer & Bindings & BindGroups
- Render + Compute Pipelines (async by default)
- PipelineManager to cache RenderPipeline + set only needed BindGroup
- Meshes (Mesh, DOMMesh, FullscreenPlane, Plane)
- Compute passes
- Scene class
- Texture & RenderTexture (with storage & depth) classes
- Texture (including storage & depth) & DOMTexture classes
- Sampler class
- RenderTarget (render to textures)
- RenderPass (render pass descriptors) with MRT support
Expand All @@ -23,16 +23,19 @@
- Basic CacheManager
- Scroll + resize, frustum culling check
- GPUCurtains
- OrbitControls

## Work in progress

- Examples & tests
- glTF loading

## TODO / possible improvements

- Add Mat3 class + normalMatrix to ProjectedObject3D?
- Mesh raycasting
- Lights management?
- Improve typedoc documentation?
- Use constants for WebGPU buffers and textures flags/usages? Add to options/parameters?
- Use render bundles? Probably not suited to the library tho
- Use indirect draw calls?
- Mesh raycasting?
- More examples & tests?
24 changes: 20 additions & 4 deletions dist/esm/core/bindGroups/BindGroup.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class BindGroup {
bindings.forEach((binding) => {
if ("buffer" in binding) {
this.renderer.deviceManager.bufferBindings.set(binding.cacheKey, binding);
binding.buffer.consumers.add(this.uuid);
}
});
this.bindings = [...this.bindings, ...bindings];
Expand All @@ -76,18 +77,21 @@ class BindGroup {
* @returns - a {@link bindings} array
*/
createInputBindings(bindingType = "uniform", inputs = {}) {
const bindings = [
let bindings = [
...Object.keys(inputs).map((inputKey) => {
const binding = inputs[inputKey];
if (!binding.struct)
return;
const bindingParams = {
label: toKebabCase(binding.label || inputKey),
name: inputKey,
bindingType,
visibility: binding.access === "read_write" ? "compute" : binding.visibility,
visibility: binding.access === "read_write" ? ["compute"] : binding.visibility,
useStruct: true,
// by default
access: binding.access ?? "read",
// read by default
...binding.usage && { usage: binding.usage },
struct: binding.struct,
...binding.shouldCopyResult !== void 0 && { shouldCopyResult: binding.shouldCopyResult }
};
Expand All @@ -114,6 +118,7 @@ class BindGroup {
});
})
].flat();
bindings = bindings.filter(Boolean);
bindings.forEach((binding) => {
this.renderer.deviceManager.bufferBindings.set(binding.cacheKey, binding);
});
Expand Down Expand Up @@ -211,6 +216,17 @@ class BindGroup {
this.bindGroupLayout = null;
this.needsPipelineFlush = true;
}
/**
* Called when the {@link core/renderers/GPUDeviceManager.GPUDeviceManager#device | device} has been restored to update our bindings.
*/
restoreContext() {
if (this.shouldCreateBindGroup) {
this.createBindGroup();
}
for (const bufferBinding of this.bufferBindings) {
bufferBinding.shouldUpdate = true;
}
}
/**
* Get all {@link BindGroup#bindings | bind group bindings} that handle a {@link GPUBuffer}
*/
Expand All @@ -226,13 +242,13 @@ class BindGroup {
createBindingBuffer(binding) {
binding.buffer.createBuffer(this.renderer, {
label: this.options.label + ": " + binding.bindingType + " buffer from: " + binding.label,
usage: binding.bindingType === "uniform" ? GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC | GPUBufferUsage.VERTEX : GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC | GPUBufferUsage.VERTEX
usage: [...["copySrc", "copyDst", binding.bindingType], ...binding.options.usage]
});
if ("resultBuffer" in binding) {
binding.resultBuffer.createBuffer(this.renderer, {
label: this.options.label + ": Result buffer from: " + binding.label,
size: binding.arrayBuffer.byteLength,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
usage: ["copyDst", "mapRead"]
});
}
}
Expand Down
4 changes: 2 additions & 2 deletions dist/esm/core/bindGroups/TextureBindGroup.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BindGroup } from './BindGroup.mjs';
import { isRenderer } from '../renderers/utils.mjs';
import { Texture } from '../textures/Texture.mjs';
import { DOMTexture } from '../textures/DOMTexture.mjs';

class TextureBindGroup extends BindGroup {
/**
Expand Down Expand Up @@ -76,7 +76,7 @@ class TextureBindGroup extends BindGroup {
*/
updateTextures() {
for (const texture of this.textures) {
if (texture instanceof Texture) {
if (texture instanceof DOMTexture) {
if (texture.options.fromTexture && texture.options.fromTexture.sourceUploaded && !texture.sourceUploaded) {
texture.copy(texture.options.fromTexture);
}
Expand Down
22 changes: 8 additions & 14 deletions dist/esm/core/bindings/Binding.mjs
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
import { toCamelCase } from '../../utils/utils.mjs';
import { getBindingVisibility } from './utils.mjs';

class Binding {
/**
* Binding constructor
* @param parameters - {@link BindingParams | parameters} used to create our {@link Binding}
*/
constructor({ label = "Uniform", name = "uniform", bindingType = "uniform", visibility = "all" }) {
constructor({
label = "Uniform",
name = "uniform",
bindingType = "uniform",
visibility = ["vertex", "fragment", "compute"]
}) {
this.label = label;
this.name = toCamelCase(name);
this.bindingType = bindingType;
this.visibility = visibility ? (() => {
switch (visibility) {
case "vertex":
return GPUShaderStage.VERTEX;
case "fragment":
return GPUShaderStage.FRAGMENT;
case "compute":
return GPUShaderStage.COMPUTE;
case "all":
default:
return GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;
}
})() : GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;
this.visibility = getBindingVisibility(visibility);
this.options = {
label,
name,
Expand Down
2 changes: 2 additions & 0 deletions dist/esm/core/bindings/BufferBinding.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class BufferBinding extends Binding {
visibility,
useStruct = true,
access = "read",
usage = [],
struct = {}
}) {
bindingType = bindingType ?? "uniform";
Expand All @@ -28,6 +29,7 @@ class BufferBinding extends Binding {
...this.options,
useStruct,
access,
usage,
struct
};
this.cacheKey += `${useStruct},${access},`;
Expand Down
2 changes: 1 addition & 1 deletion dist/esm/core/bindings/TextureBinding.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class TextureBinding extends Binding {
}) {
bindingType = bindingType ?? "texture";
if (bindingType === "storage") {
visibility = "compute";
visibility = ["compute"];
}
super({ label, name, bindingType, visibility });
this.options = {
Expand Down
5 changes: 3 additions & 2 deletions dist/esm/core/bindings/WritableBufferBinding.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ class WritableBufferBinding extends BufferBinding {
visibility,
useStruct = true,
access = "read_write",
usage = [],
struct = {},
shouldCopyResult = false
}) {
bindingType = "storage";
visibility = "compute";
super({ label, name, bindingType, visibility, useStruct, access, struct });
visibility = ["compute"];
super({ label, name, bindingType, visibility, useStruct, access, usage, struct });
this.options = {
...this.options,
shouldCopyResult
Expand Down
12 changes: 11 additions & 1 deletion dist/esm/core/bindings/utils.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
const bindingVisibilities = /* @__PURE__ */ new Map([
["vertex", GPUShaderStage.VERTEX],
["fragment", GPUShaderStage.FRAGMENT],
["compute", GPUShaderStage.COMPUTE]
]);
const getBindingVisibility = (visibilities = []) => {
return visibilities.reduce((acc, v) => {
return acc | bindingVisibilities.get(v);
}, 0);
};
const bufferLayouts = {
i32: { numElements: 1, align: 4, size: 4, type: "i32", View: Int32Array },
u32: { numElements: 1, align: 4, size: 4, type: "u32", View: Uint32Array },
Expand Down Expand Up @@ -114,4 +124,4 @@ const getBindGroupLayoutTextureBindingCacheKey = (binding) => {
})();
};

export { getBindGroupLayoutBindingType, getBindGroupLayoutTextureBindingCacheKey, getBindGroupLayoutTextureBindingType, getBindingWGSLVarType, getBufferLayout, getTextureBindingWGSLVarType };
export { getBindGroupLayoutBindingType, getBindGroupLayoutTextureBindingCacheKey, getBindGroupLayoutTextureBindingType, getBindingVisibility, getBindingWGSLVarType, getBufferLayout, getTextureBindingWGSLVarType };
12 changes: 9 additions & 3 deletions dist/esm/core/buffers/Buffer.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { generateUUID } from '../../utils/utils.mjs';
import { getBufferUsages } from './utils.mjs';

class Buffer {
/**
Expand All @@ -8,7 +9,7 @@ class Buffer {
constructor({
label = "Buffer",
size = 0,
usage = GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
usage = ["copySrc", "copyDst"],
mappedAtCreation = false
} = {}) {
this.type = "Buffer";
Expand All @@ -18,7 +19,7 @@ class Buffer {
this.options = {
label,
size,
usage,
usage: getBufferUsages(usage),
mappedAtCreation
};
}
Expand All @@ -36,7 +37,12 @@ class Buffer {
* @param options - optional way to update the {@link options} previously set before creating the {@link GPUBuffer}.
*/
createBuffer(renderer, options = {}) {
this.options = { ...this.options, ...options };
const { usage, ...staticOptions } = options;
this.options = {
...this.options,
...staticOptions,
...usage !== void 0 && { usage: getBufferUsages(usage) }
};
this.setBuffer(renderer.createBuffer(this));
}
/**
Expand Down
19 changes: 19 additions & 0 deletions dist/esm/core/buffers/utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const bufferUsages = /* @__PURE__ */ new Map([
["copySrc", GPUBufferUsage.COPY_SRC],
["copyDst", GPUBufferUsage.COPY_DST],
["index", GPUBufferUsage.INDEX],
["indirect", GPUBufferUsage.INDIRECT],
["mapRead", GPUBufferUsage.MAP_READ],
["mapWrite", GPUBufferUsage.MAP_WRITE],
["queryResolve", GPUBufferUsage.QUERY_RESOLVE],
["storage", GPUBufferUsage.STORAGE],
["uniform", GPUBufferUsage.UNIFORM],
["vertex", GPUBufferUsage.VERTEX]
]);
const getBufferUsages = (usages = []) => {
return usages.reduce((acc, v) => {
return acc | bufferUsages.get(v);
}, 0);
};

export { getBufferUsages };
Loading

0 comments on commit 4fd3f57

Please sign in to comment.