diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index 5f8e2070c37..56619756283 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -1775,6 +1775,20 @@
"Structure controls how closely the output image will keep to the layout of the original. Low structure allows major changes, while high structure strictly maintains the original composition and layout."
]
},
+ "tileSize": {
+ "heading": "Tile Size",
+ "paragraphs": [
+ "Controls the size of tiles used during the upscaling process. Larger tiles use more memory but may produce better results.",
+ "SD1.5 models default to 768, while SDXL models default to 1024. Reduce tile size if you encounter memory issues."
+ ]
+ },
+ "tileOverlap": {
+ "heading": "Tile Overlap",
+ "paragraphs": [
+ "Controls the overlap between adjacent tiles during upscaling. Higher overlap values help reduce visible seams between tiles but use more memory.",
+ "The default value of 128 works well for most cases, but you can adjust based on your specific needs and memory constraints."
+ ]
+ },
"fluxDevLicense": {
"heading": "Non-Commercial License",
"paragraphs": [
@@ -2396,6 +2410,8 @@
"upscaleModel": "Upscale Model",
"postProcessingModel": "Post-Processing Model",
"scale": "Scale",
+ "tileSize": "Tile Size",
+ "tileOverlap": "Tile Overlap",
"postProcessingMissingModelWarning": "Visit the Model Manager to install a post-processing (image to image) model.",
"missingModelsWarning": "Visit the Model Manager to install the required models:",
"mainModelDesc": "Main model (SD1.5 or SDXL architecture)",
diff --git a/invokeai/frontend/web/src/common/components/InformationalPopover/constants.ts b/invokeai/frontend/web/src/common/components/InformationalPopover/constants.ts
index f115ab3a640..22a813b6de1 100644
--- a/invokeai/frontend/web/src/common/components/InformationalPopover/constants.ts
+++ b/invokeai/frontend/web/src/common/components/InformationalPopover/constants.ts
@@ -67,6 +67,8 @@ export type Feature =
| 'scale'
| 'creativity'
| 'structure'
+ | 'tileSize'
+ | 'tileOverlap'
| 'optimizedDenoising'
| 'fluxDevLicense';
diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildMultidiffusionUpscaleGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildMultidiffusionUpscaleGraph.ts
index 7c6192e06a4..fafedd1a5df 100644
--- a/invokeai/frontend/web/src/features/nodes/util/graph/buildMultidiffusionUpscaleGraph.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildMultidiffusionUpscaleGraph.ts
@@ -12,7 +12,16 @@ import type { GraphBuilderReturn } from './types';
export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise => {
const { model, upscaleCfgScale: cfg_scale, upscaleScheduler: scheduler, steps, vaePrecision, vae } = state.params;
- const { upscaleModel, upscaleInitialImage, structure, creativity, tileControlnetModel, scale } = state.upscale;
+ const {
+ upscaleModel,
+ upscaleInitialImage,
+ structure,
+ creativity,
+ tileControlnetModel,
+ scale,
+ tileSize,
+ tileOverlap,
+ } = state.upscale;
assert(model, 'No model selected');
assert(model.base === 'sd-1' || model.base === 'sdxl', 'Multi-Diffusion upscaling requires a SD1.5 or SDXL model');
@@ -62,7 +71,7 @@ export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise
type: 'i2l',
id: getPrefixedId('i2l'),
fp32: vaePrecision === 'fp32',
- tile_size: 1024,
+ tile_size: tileSize,
tiled: true,
});
@@ -72,7 +81,7 @@ export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise
type: 'l2i',
id: getPrefixedId('l2i'),
fp32: vaePrecision === 'fp32',
- tile_size: 1024,
+ tile_size: tileSize,
tiled: true,
board: getBoardField(state),
is_intermediate: false,
@@ -81,9 +90,9 @@ export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise
const tiledMultidiffusion = g.addNode({
type: 'tiled_multi_diffusion_denoise_latents',
id: getPrefixedId('tiled_multidiffusion_denoise_latents'),
- tile_height: 1024, // is this dependent on base model
- tile_width: 1024, // is this dependent on base model
- tile_overlap: 128,
+ tile_height: tileSize,
+ tile_width: tileSize,
+ tile_overlap: tileOverlap || 128,
steps,
cfg_scale,
scheduler,
@@ -184,6 +193,8 @@ export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise
upscale_model: Graph.getModelMetadataField(upscaleModelConfig),
creativity,
structure,
+ tile_size: tileSize,
+ tile_overlap: tileOverlap || 128,
upscale_initial_image: {
image_name: upscaleInitialImage.image_name,
width: upscaleInitialImage.width,
diff --git a/invokeai/frontend/web/src/features/parameters/components/Upscale/ParamTileOverlap.tsx b/invokeai/frontend/web/src/features/parameters/components/Upscale/ParamTileOverlap.tsx
new file mode 100644
index 00000000000..7834e53309b
--- /dev/null
+++ b/invokeai/frontend/web/src/features/parameters/components/Upscale/ParamTileOverlap.tsx
@@ -0,0 +1,53 @@
+import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
+import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import { selectTileOverlap, tileOverlapChanged } from 'features/parameters/store/upscaleSlice';
+import { useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
+
+const initial = 128;
+const sliderMin = 32;
+const sliderMax = 256;
+const numberInputMin = 16;
+const numberInputMax = 512;
+const coarseStep = 16;
+const fineStep = 8;
+const marks = [sliderMin, 128, sliderMax];
+
+const ParamTileOverlap = () => {
+ const tileOverlap = useAppSelector(selectTileOverlap);
+ const dispatch = useAppDispatch();
+ const { t } = useTranslation();
+ const onChange = useCallback(
+ (v: number) => {
+ dispatch(tileOverlapChanged(v));
+ },
+ [dispatch]
+ );
+
+ return (
+
+ {t('upscaling.tileOverlap')}
+
+
+
+ );
+};
+
+export default ParamTileOverlap;
diff --git a/invokeai/frontend/web/src/features/parameters/components/Upscale/ParamTileSize.tsx b/invokeai/frontend/web/src/features/parameters/components/Upscale/ParamTileSize.tsx
new file mode 100644
index 00000000000..c0443cb6fe1
--- /dev/null
+++ b/invokeai/frontend/web/src/features/parameters/components/Upscale/ParamTileSize.tsx
@@ -0,0 +1,53 @@
+import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
+import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import { selectTileSize, tileSizeChanged } from 'features/parameters/store/upscaleSlice';
+import { useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
+
+const initial = 1024;
+const sliderMin = 512;
+const sliderMax = 1536;
+const numberInputMin = 512;
+const numberInputMax = 1536;
+const coarseStep = 64;
+const fineStep = 64;
+const marks = [sliderMin, 1024, sliderMax];
+
+const ParamTileSize = () => {
+ const tileSize = useAppSelector(selectTileSize);
+ const dispatch = useAppDispatch();
+ const { t } = useTranslation();
+ const onChange = useCallback(
+ (v: number) => {
+ dispatch(tileSizeChanged(v));
+ },
+ [dispatch]
+ );
+
+ return (
+
+ {t('upscaling.tileSize')}
+
+
+
+ );
+};
+
+export default ParamTileSize;
diff --git a/invokeai/frontend/web/src/features/parameters/store/upscaleSlice.ts b/invokeai/frontend/web/src/features/parameters/store/upscaleSlice.ts
index a3fa9ae0aae..294d88fb481 100644
--- a/invokeai/frontend/web/src/features/parameters/store/upscaleSlice.ts
+++ b/invokeai/frontend/web/src/features/parameters/store/upscaleSlice.ts
@@ -13,6 +13,8 @@ export interface UpscaleState {
tileControlnetModel: ControlNetModelConfig | null;
scale: number;
postProcessingModel: ParameterSpandrelImageToImageModel | null;
+ tileSize: number;
+ tileOverlap: number;
}
const initialUpscaleState: UpscaleState = {
@@ -24,6 +26,8 @@ const initialUpscaleState: UpscaleState = {
tileControlnetModel: null,
scale: 4,
postProcessingModel: null,
+ tileSize: 1024,
+ tileOverlap: 128,
};
export const upscaleSlice = createSlice({
@@ -51,6 +55,12 @@ export const upscaleSlice = createSlice({
postProcessingModelChanged: (state, action: PayloadAction) => {
state.postProcessingModel = action.payload;
},
+ tileSizeChanged: (state, action: PayloadAction) => {
+ state.tileSize = action.payload;
+ },
+ tileOverlapChanged: (state, action: PayloadAction) => {
+ state.tileOverlap = action.payload;
+ },
},
});
@@ -62,6 +72,8 @@ export const {
tileControlnetModelChanged,
scaleChanged,
postProcessingModelChanged,
+ tileSizeChanged,
+ tileOverlapChanged,
} = upscaleSlice.actions;
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
@@ -88,3 +100,5 @@ export const selectTileControlNetModel = createUpscaleSelector((upscale) => upsc
export const selectStructure = createUpscaleSelector((upscale) => upscale.structure);
export const selectUpscaleInitialImage = createUpscaleSelector((upscale) => upscale.upscaleInitialImage);
export const selectUpscaleScale = createUpscaleSelector((upscale) => upscale.scale);
+export const selectTileSize = createUpscaleSelector((upscale) => upscale.tileSize);
+export const selectTileOverlap = createUpscaleSelector((upscale) => upscale.tileOverlap);
diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/AdvancedSettingsAccordion/UpscaleTabAdvancedSettingsAccordion.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/AdvancedSettingsAccordion/UpscaleTabAdvancedSettingsAccordion.tsx
index 4aa0708ac03..efeddb35940 100644
--- a/invokeai/frontend/web/src/features/settingsAccordions/components/AdvancedSettingsAccordion/UpscaleTabAdvancedSettingsAccordion.tsx
+++ b/invokeai/frontend/web/src/features/settingsAccordions/components/AdvancedSettingsAccordion/UpscaleTabAdvancedSettingsAccordion.tsx
@@ -4,6 +4,8 @@ import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppSelector } from 'app/store/storeHooks';
import { selectIsFLUX, selectIsSD3, selectParamsSlice, selectVAEKey } from 'features/controlLayers/store/paramsSlice';
import { ParamSeed } from 'features/parameters/components/Seed/ParamSeed';
+import ParamTileOverlap from 'features/parameters/components/Upscale/ParamTileOverlap';
+import ParamTileSize from 'features/parameters/components/Upscale/ParamTileSize';
import ParamFLUXVAEModelSelect from 'features/parameters/components/VAEModel/ParamFLUXVAEModelSelect';
import ParamVAEModelSelect from 'features/parameters/components/VAEModel/ParamVAEModelSelect';
import ParamVAEPrecision from 'features/parameters/components/VAEModel/ParamVAEPrecision';
@@ -73,6 +75,8 @@ export const UpscaleTabAdvancedSettingsAccordion = memo(() => {
{!isFLUX && !isSD3 && }
+
+
);