mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
perf(ui): use efficient group caching instead of a compositing rect
Seems to be the same speed and it's less complex.
This commit is contained in:
parent
39d036bb37
commit
604bf4e9ec
@ -355,7 +355,6 @@ const getRPLayerId = (layerId: string) => `rp_layer_${layerId}`;
|
|||||||
const getRPLayerLineId = (layerId: string, lineId: string) => `${layerId}.line_${lineId}`;
|
const getRPLayerLineId = (layerId: string, lineId: string) => `${layerId}.line_${lineId}`;
|
||||||
export const getRPLayerObjectGroupId = (layerId: string, groupId: string) => `${layerId}.objectGroup_${groupId}`;
|
export const getRPLayerObjectGroupId = (layerId: string, groupId: string) => `${layerId}.objectGroup_${groupId}`;
|
||||||
export const getPRLayerBboxId = (layerId: string) => `${layerId}.bbox`;
|
export const getPRLayerBboxId = (layerId: string) => `${layerId}.bbox`;
|
||||||
export const getRPLayerTransparencyRectId = (layerId: string) => `${layerId}.transparency_rect`;
|
|
||||||
|
|
||||||
export const regionalPromptsPersistConfig: PersistConfig<RegionalPromptsState> = {
|
export const regionalPromptsPersistConfig: PersistConfig<RegionalPromptsState> = {
|
||||||
name: regionalPromptsSlice.name,
|
name: regionalPromptsSlice.name,
|
||||||
|
@ -9,7 +9,6 @@ import {
|
|||||||
BRUSH_PREVIEW_LAYER_ID,
|
BRUSH_PREVIEW_LAYER_ID,
|
||||||
getPRLayerBboxId,
|
getPRLayerBboxId,
|
||||||
getRPLayerObjectGroupId,
|
getRPLayerObjectGroupId,
|
||||||
getRPLayerTransparencyRectId,
|
|
||||||
REGIONAL_PROMPT_LAYER_BBOX_NAME,
|
REGIONAL_PROMPT_LAYER_BBOX_NAME,
|
||||||
REGIONAL_PROMPT_LAYER_LINE_NAME,
|
REGIONAL_PROMPT_LAYER_LINE_NAME,
|
||||||
REGIONAL_PROMPT_LAYER_NAME,
|
REGIONAL_PROMPT_LAYER_NAME,
|
||||||
@ -192,16 +191,6 @@ const renderRPLayer = (
|
|||||||
});
|
});
|
||||||
konvaLayer.add(konvaObjectGroup);
|
konvaLayer.add(konvaObjectGroup);
|
||||||
|
|
||||||
// To achieve performant transparency, we use the `source-in` blending mode on a rect that covers the entire layer.
|
|
||||||
// The brush strokes group functions as a mask for this rect, which has the layer's fill and opacity. The brush
|
|
||||||
// strokes' color doesn't matter - the only requirement is that they are not transparent.
|
|
||||||
const transparencyRect = new Konva.Rect({
|
|
||||||
id: getRPLayerTransparencyRectId(rpLayer.id),
|
|
||||||
globalCompositeOperation: 'source-in',
|
|
||||||
listening: false,
|
|
||||||
});
|
|
||||||
konvaLayer.add(transparencyRect);
|
|
||||||
|
|
||||||
stage.add(konvaLayer);
|
stage.add(konvaLayer);
|
||||||
|
|
||||||
// When a layer is added, it ends up on top of the brush preview - we need to move the preview back to the top.
|
// When a layer is added, it ends up on top of the brush preview - we need to move the preview back to the top.
|
||||||
@ -223,14 +212,20 @@ const renderRPLayer = (
|
|||||||
const konvaObjectGroup = konvaLayer.findOne<Konva.Group>(`.${REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME}`);
|
const konvaObjectGroup = konvaLayer.findOne<Konva.Group>(`.${REGIONAL_PROMPT_LAYER_OBJECT_GROUP_NAME}`);
|
||||||
assert(konvaObjectGroup, `Object group not found for layer ${rpLayer.id}`);
|
assert(konvaObjectGroup, `Object group not found for layer ${rpLayer.id}`);
|
||||||
|
|
||||||
const transparencyRect = konvaLayer.findOne<Konva.Rect>(`#${getRPLayerTransparencyRectId(rpLayer.id)}`);
|
// We use caching to handle "global" layer opacity, but caching is expensive and we should only do it when required.
|
||||||
assert(transparencyRect, `Transparency rect not found for layer ${rpLayer.id}`);
|
let groupNeedsCache = false;
|
||||||
|
|
||||||
|
if (konvaObjectGroup.opacity() !== layerOpacity) {
|
||||||
|
konvaObjectGroup.opacity(layerOpacity);
|
||||||
|
groupNeedsCache = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove deleted objects
|
// Remove deleted objects
|
||||||
const objectIds = rpLayer.objects.map(mapId);
|
const objectIds = rpLayer.objects.map(mapId);
|
||||||
for (const objectNode of konvaLayer.find(`.${REGIONAL_PROMPT_LAYER_LINE_NAME}`)) {
|
for (const objectNode of konvaLayer.find(`.${REGIONAL_PROMPT_LAYER_LINE_NAME}`)) {
|
||||||
if (!objectIds.includes(objectNode.id())) {
|
if (!objectIds.includes(objectNode.id())) {
|
||||||
objectNode.destroy();
|
objectNode.destroy();
|
||||||
|
groupNeedsCache = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,23 +257,23 @@ const renderRPLayer = (
|
|||||||
// Only update the points if they have changed. The point values are never mutated, they are only added to the array.
|
// Only update the points if they have changed. The point values are never mutated, they are only added to the array.
|
||||||
if (konvaObject.points().length !== reduxObject.points.length) {
|
if (konvaObject.points().length !== reduxObject.points.length) {
|
||||||
konvaObject.points(reduxObject.points);
|
konvaObject.points(reduxObject.points);
|
||||||
|
groupNeedsCache = true;
|
||||||
}
|
}
|
||||||
// Only update the color if it has changed.
|
// Only update the color if it has changed.
|
||||||
if (konvaObject.stroke() !== color) {
|
if (konvaObject.stroke() !== color) {
|
||||||
konvaObject.stroke(color);
|
konvaObject.stroke(color);
|
||||||
|
groupNeedsCache = true;
|
||||||
}
|
}
|
||||||
// Only update layer visibility if it has changed.
|
// Only update layer visibility if it has changed.
|
||||||
if (konvaObject.visible() !== rpLayer.isVisible) {
|
if (konvaObject.visible() !== rpLayer.isVisible) {
|
||||||
konvaObject.visible(rpLayer.isVisible);
|
konvaObject.visible(rpLayer.isVisible);
|
||||||
|
groupNeedsCache = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the layer opacity - must happen after all objects are added to the layer so the rect is the right size
|
if (groupNeedsCache) {
|
||||||
transparencyRect.setAttrs({
|
konvaObjectGroup.cache();
|
||||||
...konvaLayer.getClientRect({ skipTransform: true }),
|
}
|
||||||
fill: color,
|
|
||||||
opacity: layerOpacity,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user