commit tile size controls

This commit is contained in:
Kent Keirsey
2025-07-11 23:21:28 -04:00
committed by psychedelicious
parent 86f4cf7857
commit 4426be9e64
8 changed files with 162 additions and 9 deletions

View File

@@ -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": [
@@ -2397,6 +2411,8 @@
"postProcessingModel": "Post-Processing Model",
"scale": "Scale",
"tileControl": "Tile Control",
"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)",

View File

@@ -67,6 +67,8 @@ export type Feature =
| 'scale'
| 'creativity'
| 'structure'
| 'tileSize'
| 'tileOverlap'
| 'optimizedDenoising'
| 'fluxDevLicense';

View File

@@ -55,9 +55,7 @@ export const ModelInstallQueue = memo(() => {
<Box layerStyle="first" p={3} borderRadius="base" w="full" h="full">
<ScrollableContent>
<Flex flexDir="column-reverse" gap="2" w="full">
{data?.map((model) => (
<ModelInstallQueueItem key={model.id} installJob={model} />
))}
{data?.map((model) => <ModelInstallQueueItem key={model.id} installJob={model} />)}
</Flex>
</ScrollableContent>
</Box>

View File

@@ -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');
@@ -58,11 +67,13 @@ export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise
g.addEdge(unsharpMask, 'width', noise, 'width');
g.addEdge(unsharpMask, 'height', noise, 'height');
const effectiveTileSize = tileSize;
const i2l = g.addNode({
type: 'i2l',
id: getPrefixedId('i2l'),
fp32: vaePrecision === 'fp32',
tile_size: 1024,
tile_size: effectiveTileSize,
tiled: true,
});
@@ -72,7 +83,7 @@ export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise
type: 'l2i',
id: getPrefixedId('l2i'),
fp32: vaePrecision === 'fp32',
tile_size: 1024,
tile_size: effectiveTileSize,
tiled: true,
board: getBoardField(state),
is_intermediate: false,
@@ -81,9 +92,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: effectiveTileSize,
tile_width: effectiveTileSize,
tile_overlap: tileOverlap || 128,
steps,
cfg_scale,
scheduler,
@@ -184,6 +195,8 @@ export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise
upscale_model: Graph.getModelMetadataField(upscaleModelConfig),
creativity,
structure,
tile_size: effectiveTileSize,
tile_overlap: tileOverlap || 128,
upscale_initial_image: {
image_name: upscaleInitialImage.image_name,
width: upscaleInitialImage.width,

View File

@@ -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;

View File

@@ -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 = 32;
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;

View File

@@ -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<ParameterSpandrelImageToImageModel | null>) => {
state.postProcessingModel = action.payload;
},
tileSizeChanged: (state, action: PayloadAction<number>) => {
state.tileSize = action.payload;
},
tileOverlapChanged: (state, action: PayloadAction<number>) => {
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);

View File

@@ -8,6 +8,8 @@ import ParamTileControlNetModel from 'features/parameters/components/Upscale/Par
import ParamFLUXVAEModelSelect from 'features/parameters/components/VAEModel/ParamFLUXVAEModelSelect';
import ParamVAEModelSelect from 'features/parameters/components/VAEModel/ParamVAEModelSelect';
import ParamVAEPrecision from 'features/parameters/components/VAEModel/ParamVAEPrecision';
import ParamTileOverlap from 'features/parameters/components/Upscale/ParamTileOverlap';
import ParamTileSize from 'features/parameters/components/Upscale/ParamTileSize';
import { useStandaloneAccordionToggle } from 'features/settingsAccordions/hooks/useStandaloneAccordionToggle';
import { memo, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
@@ -75,6 +77,8 @@ export const UpscaleTabAdvancedSettingsAccordion = memo(() => {
</Flex>
<ParamSeed />
<ParamTileControlNetModel />
<ParamTileSize />
<ParamTileOverlap />
</Flex>
</StandaloneAccordion>
);