Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better pipeline creation #96

Merged
merged 4 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 1 addition & 7 deletions dist/esm/core/materials/ComputeMaterial.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,7 @@ class ComputeMaterial extends Material {
* Set (or reset) the current {@link pipelineEntry}. Use the {@link Renderer#pipelineManager | renderer pipelineManager} to check whether we can get an already created {@link ComputePipelineEntry} from cache or if we should create a new one.
*/
setPipelineEntry() {
this.pipelineEntry = this.renderer.pipelineManager.createComputePipeline({
renderer: this.renderer,
label: this.options.label + " compute pipeline",
shaders: this.options.shaders,
useAsync: this.options.useAsyncPipeline,
bindGroups: this.bindGroups
});
this.pipelineEntry = this.renderer.pipelineManager.createComputePipeline(this);
}
/**
* Compile the {@link ComputePipelineEntry}
Expand Down
17 changes: 16 additions & 1 deletion dist/esm/core/materials/Material.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Material {
} = parameters;
this.options = {
shaders,
label,
label: label || this.constructor.name,
useAsyncPipeline: useAsyncPipeline === void 0 ? true : useAsyncPipeline,
...uniforms !== void 0 && { uniforms },
...storages !== void 0 && { storages },
Expand Down Expand Up @@ -73,6 +73,21 @@ class Material {
get ready() {
return !!(this.renderer.ready && this.pipelineEntry && this.pipelineEntry.pipeline && this.pipelineEntry.ready);
}
/**
* Get the {@link Material} pipeline buffers cache key based on its {@link BindGroup} cache keys.
* @returns - Current cache key.
* @readonly
*/
get cacheKey() {
let cacheKey = "";
this.bindGroups.forEach((bindGroup) => {
bindGroup.bindings.forEach((binding) => {
cacheKey += binding.name + ",";
});
cacheKey += bindGroup.pipelineCacheKey;
});
return cacheKey;
}
/**
* Called when the {@link core/renderers/GPUDeviceManager.GPUDeviceManager#device | device} has been lost to prepare everything for restoration.
* Basically set all the {@link GPUBuffer} to null so they will be reset next time we try to render
Expand Down
19 changes: 10 additions & 9 deletions dist/esm/core/materials/RenderMaterial.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,7 @@ class RenderMaterial extends Material {
* Set (or reset) the current {@link pipelineEntry}. Use the {@link Renderer#pipelineManager | renderer pipelineManager} to check whether we can get an already created {@link RenderPipelineEntry} from cache or if we should create a new one.
*/
setPipelineEntry() {
this.pipelineEntry = this.renderer.pipelineManager.createRenderPipeline({
renderer: this.renderer,
label: this.options.label + " render pipeline",
shaders: this.options.shaders,
useAsync: this.options.useAsyncPipeline,
rendering: this.options.rendering,
attributes: this.attributes,
bindGroups: this.bindGroups
});
this.pipelineEntry = this.renderer.pipelineManager.createRenderPipeline(this);
}
/**
* Compile the {@link RenderPipelineEntry}
Expand Down Expand Up @@ -195,6 +187,15 @@ New rendering options: ${JSON.stringify(
layoutCacheKey: geometry.layoutCacheKey
};
}
/**
* Get the {@link RenderMaterial} pipeline buffers cache key based on its {@link core/bindGroups/BindGroup.BindGroup | BindGroup} cache keys and eventually {@link attributes} cache keys.
* @returns - Current cache key.
* @readonly
*/
get cacheKey() {
let cacheKey = this.attributes?.layoutCacheKey || "";
return cacheKey + super.cacheKey;
}
/* BIND GROUPS */
/**
* Get whether this {@link RenderMaterial} uses the renderer camera and lights bind group.
Expand Down
10 changes: 10 additions & 0 deletions dist/esm/core/meshes/mixins/MeshBaseMixin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,19 @@ ${geometry.wgslStructFragment}`
* @param material - new {@link RenderMaterial} to use
*/
useMaterial(material) {
let currentCacheKey = null;
if (this.material && this.geometry) {
currentCacheKey = this.material.cacheKey;
}
this.material = material;
if (this.geometry) {
this.material.setAttributesFromGeometry(this.geometry);
}
this.transparent = this.material.options.rendering.transparent;
this.material.options.domTextures?.filter((texture) => texture instanceof DOMTexture).forEach((texture) => this.onDOMTextureAdded(texture));
if (currentCacheKey && currentCacheKey !== this.material.cacheKey) {
this.material.setPipelineEntry();
}
}
/**
* Patch the shaders if needed, then set the Mesh material
Expand Down
1 change: 0 additions & 1 deletion dist/esm/core/pipelines/ComputePipelineEntry.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class ComputePipelineEntry extends PipelineEntry {
}
};
this.descriptor = null;
this.setPipelineEntryProperties({ bindGroups });
}
/* SHADERS */
/**
Expand Down
18 changes: 2 additions & 16 deletions dist/esm/core/pipelines/PipelineEntry.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class PipelineEntry {
bindGroups,
cacheKey
};
this.bindGroups = bindGroups;
}
/**
* Get whether the {@link pipeline} is ready, i.e. successfully compiled
Expand All @@ -42,21 +43,6 @@ class PipelineEntry {
get canCompile() {
return !this.status.compiling && !this.status.compiled && !this.status.error;
}
/**
* Set {@link PipelineEntry} properties (in this case the {@link bindGroups | bind groups})
* @param parameters - the {@link bindGroups | bind groups} to use
*/
setPipelineEntryProperties(parameters) {
const { bindGroups } = parameters;
this.setPipelineEntryBindGroups(bindGroups);
}
/**
* Set our {@link PipelineEntry#bindGroups | pipeline entry bind groups}
* @param bindGroups - {@link core/materials/Material.Material#bindGroups | bind groups} to use with this {@link PipelineEntry}
*/
setPipelineEntryBindGroups(bindGroups) {
this.bindGroups = bindGroups;
}
/* SHADERS */
/**
* Create a {@link GPUShaderModule}
Expand Down Expand Up @@ -130,7 +116,7 @@ ${formattedMessage}`);
this.status.compiling = false;
this.status.compiled = false;
this.status.error = null;
this.setPipelineEntryBindGroups(newBindGroups);
this.bindGroups = newBindGroups;
this.compilePipelineEntry();
}
/**
Expand Down
57 changes: 32 additions & 25 deletions dist/esm/core/pipelines/PipelineManager.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,27 @@ class PipelineManager {
/**
* Check if a {@link RenderPipelineEntry} has already been created with the given {@link RenderPipelineEntryParams | parameters}.
* Use it if found, else create a new one and add it to the {@link pipelineEntries} array.
* @param parameters - {@link RenderPipelineEntryParams | RenderPipelineEntry parameters}
* @returns - {@link RenderPipelineEntry}, either from cache or newly created
* @param material - {@link RenderMaterial} used to create the pipeline.
* @returns - {@link RenderPipelineEntry}, either from cache or newly created.
*/
createRenderPipeline(parameters) {
const { attributes, bindGroups } = parameters;
let cacheKey = attributes.layoutCacheKey;
bindGroups.forEach((bindGroup) => {
bindGroup.bindings.forEach((binding) => {
cacheKey += binding.name + ",";
});
cacheKey += bindGroup.pipelineCacheKey;
});
const existingPipelineEntry = this.isSameRenderPipeline({ ...parameters, cacheKey });
createRenderPipeline(material) {
const { renderer, attributes, bindGroups, cacheKey, options } = material;
const { shaders, label, useAsyncPipeline, rendering } = options;
const parameters = {
renderer,
label: label + " render pipeline",
shaders,
useAsync: useAsyncPipeline,
bindGroups,
cacheKey,
rendering,
attributes
};
const existingPipelineEntry = this.isSameRenderPipeline(parameters);
if (existingPipelineEntry) {
return existingPipelineEntry;
} else {
const pipelineEntry = new RenderPipelineEntry({ ...parameters, cacheKey });
const pipelineEntry = new RenderPipelineEntry(parameters);
this.pipelineEntries.push(pipelineEntry);
return pipelineEntry;
}
Expand All @@ -73,24 +77,27 @@ class PipelineManager {
});
}
/**
* Check if a {@link ComputePipelineEntry} has already been created with the given {@link PipelineManagerPipelineEntryParams | parameters}.
* Check if a {@link ComputePipelineEntry} has already been created with the given {@link PipelineEntryParams | parameters}.
* Use it if found, else create a new one and add it to the {@link pipelineEntries} array.
* @param parameters - {@link PipelineManagerPipelineEntryParams | PipelineEntry parameters}
* @param material - {@link ComputeMaterial} used to create the pipeline.
* @returns - newly created {@link ComputePipelineEntry}
*/
createComputePipeline(parameters) {
let cacheKey = "";
parameters.bindGroups.forEach((bindGroup) => {
bindGroup.bindings.forEach((binding) => {
cacheKey += binding.name + ",";
});
cacheKey += bindGroup.pipelineCacheKey;
});
const existingPipelineEntry = this.isSameComputePipeline({ ...parameters, cacheKey });
createComputePipeline(material) {
const { renderer, bindGroups, cacheKey, options } = material;
const { shaders, label, useAsyncPipeline } = options;
const parameters = {
renderer,
label: label + " compute pipeline",
shaders,
useAsync: useAsyncPipeline,
bindGroups,
cacheKey
};
const existingPipelineEntry = this.isSameComputePipeline(parameters);
if (existingPipelineEntry) {
return existingPipelineEntry;
} else {
const pipelineEntry = new ComputePipelineEntry({ ...parameters, cacheKey });
const pipelineEntry = new ComputePipelineEntry(parameters);
this.pipelineEntries.push(pipelineEntry);
return pipelineEntry;
}
Expand Down
9 changes: 0 additions & 9 deletions dist/esm/core/pipelines/RenderPipelineEntry.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,7 @@ class RenderPipelineEntry extends PipelineEntry {
attributes,
...renderingOptions
};
this.setPipelineEntryProperties({ attributes, bindGroups });
}
/**
* Set {@link RenderPipelineEntry} properties (in this case the {@link bindGroups | bind groups} and {@link attributes})
* @param parameters - the {@link core/materials/RenderMaterial.RenderMaterial#bindGroups | bind groups} and {@link core/materials/RenderMaterial.RenderMaterial#attributes | attributes} to use
*/
setPipelineEntryProperties(parameters) {
const { attributes, bindGroups } = parameters;
this.attributes = attributes;
this.setPipelineEntryBindGroups(bindGroups);
}
/* SHADERS */
/**
Expand Down
Loading