Skip to content

feat(ui): Expose tile size as advanced upscaling option. #8271

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions invokeai/frontend/web/public/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down Expand Up @@ -2396,6 +2410,8 @@
"upscaleModel": "Upscale Model",
"postProcessingModel": "Post-Processing Model",
"scale": "Scale",
"tileSize": "Tile Size",
"tileOverlap": "Tile Overlap",
"postProcessingMissingModelWarning": "Visit the <LinkComponent>Model Manager</LinkComponent> to install a post-processing (image to image) model.",
"missingModelsWarning": "Visit the <LinkComponent>Model Manager</LinkComponent> to install the required models:",
"mainModelDesc": "Main model (SD1.5 or SDXL architecture)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export type Feature =
| 'scale'
| 'creativity'
| 'structure'
| 'tileSize'
| 'tileOverlap'
| 'optimizedDenoising'
| 'fluxDevLicense';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@ import type { GraphBuilderReturn } from './types';

export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise<GraphBuilderReturn> => {
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');
Expand Down Expand Up @@ -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,
});

Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<FormControl>
<FormLabel>{t('upscaling.tileOverlap')}</FormLabel>
<CompositeSlider
value={tileOverlap}
defaultValue={initial}
min={sliderMin}
max={sliderMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
marks={marks}
/>
<CompositeNumberInput
value={tileOverlap}
defaultValue={initial}
min={numberInputMin}
max={numberInputMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
/>
</FormControl>
);
};

export default ParamTileOverlap;
Original file line number Diff line number Diff line change
@@ -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 (
<FormControl>
<FormLabel>{t('upscaling.tileSize')}</FormLabel>
<CompositeSlider
value={tileSize}
defaultValue={initial}
min={sliderMin}
max={sliderMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
marks={marks}
/>
<CompositeNumberInput
value={tileSize}
defaultValue={initial}
min={numberInputMin}
max={numberInputMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
/>
</FormControl>
);
};

export default ParamTileSize;
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export interface UpscaleState {
tileControlnetModel: ControlNetModelConfig | null;
scale: number;
postProcessingModel: ParameterSpandrelImageToImageModel | null;
tileSize: number;
tileOverlap: number;
}

const initialUpscaleState: UpscaleState = {
Expand All @@ -24,6 +26,8 @@ const initialUpscaleState: UpscaleState = {
tileControlnetModel: null,
scale: 4,
postProcessingModel: null,
tileSize: 1024,
tileOverlap: 128,
};

export const upscaleSlice = createSlice({
Expand Down Expand Up @@ -51,6 +55,12 @@ export const upscaleSlice = createSlice({
postProcessingModelChanged: (state, action: PayloadAction<ParameterSpandrelImageToImageModel | null>) => {
state.postProcessingModel = action.payload;
},
tileSizeChanged: (state, action: PayloadAction<number>) => {
state.tileSize = action.payload;
},
tileOverlapChanged: (state, action: PayloadAction<number>) => {
state.tileOverlap = action.payload;
},
},
});

Expand All @@ -62,6 +72,8 @@ export const {
tileControlnetModelChanged,
scaleChanged,
postProcessingModelChanged,
tileSizeChanged,
tileOverlapChanged,
} = upscaleSlice.actions;

/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
Expand All @@ -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);
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -73,6 +75,8 @@ export const UpscaleTabAdvancedSettingsAccordion = memo(() => {
{!isFLUX && !isSD3 && <ParamVAEPrecision />}
</Flex>
<ParamSeed />
<ParamTileSize />
<ParamTileOverlap />
</Flex>
</StandaloneAccordion>
);
Expand Down