From 5ab36e04333fecc56a9f71446e2b415874aa041a Mon Sep 17 00:00:00 2001 From: Mary Hipp Date: Thu, 18 Jul 2024 20:04:44 -0400 Subject: [PATCH] add warning if no upscale model or no tile controlnet for base model --- .../src/common/hooks/useIsReadyToEnqueue.ts | 4 ++ .../graph/buildMultidiffusionUpscaleGraph.ts | 5 +- .../features/parameters/store/upscaleSlice.ts | 11 +++- .../MultidiffusionWarning.tsx | 59 +++++++++++++++++++ .../UpscaleSettingsAccordion.tsx | 4 +- 5 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/MultidiffusionWarning.tsx diff --git a/invokeai/frontend/web/src/common/hooks/useIsReadyToEnqueue.ts b/invokeai/frontend/web/src/common/hooks/useIsReadyToEnqueue.ts index d1876484b6..e61361e29a 100644 --- a/invokeai/frontend/web/src/common/hooks/useIsReadyToEnqueue.ts +++ b/invokeai/frontend/web/src/common/hooks/useIsReadyToEnqueue.ts @@ -203,6 +203,10 @@ const createSelector = (templates: Templates) => if (!upscale.upscaleModel) { reasons.push({ content: "No upscale model selected" }) } + + if (!upscale.tileControlnetModel) { + reasons.push({ content: "No valid tile controlnet available" }) + } } else { // Handling for all other tabs selectControlAdapterAll(controlAdapters) 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 2199bdcc58..a0d233a5c9 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildMultidiffusionUpscaleGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildMultidiffusionUpscaleGraph.ts @@ -3,6 +3,7 @@ import type { GraphType } from 'features/nodes/util/graph/generation/Graph'; import { Graph } from 'features/nodes/util/graph/generation/Graph'; import { isParamESRGANModelName } from 'features/parameters/store/postprocessingSlice'; import { assert } from 'tsafe'; + import { CLIP_SKIP, CONTROL_NET_COLLECT, ESRGAN, IMAGE_TO_LATENTS, LATENTS_TO_IMAGE, MAIN_MODEL_LOADER, NEGATIVE_CONDITIONING, NOISE, POSITIVE_CONDITIONING, RESIZE, SDXL_MODEL_LOADER, TILED_MULTI_DIFFUSION_DENOISE_LATENTS, UNSHARP_MASK, VAE_LOADER } from './constants'; import { addLoRAs } from './generation/addLoRAs'; import { addSDXLLoRas } from './generation/addSDXLLoRAs'; @@ -25,8 +26,8 @@ export const buildMultidiffusionUpscsaleGraph = async (state: RootState): Promis assert(model, 'No model found in state'); assert(upscaleModel, 'No upscale model found in state'); assert(upscaleInitialImage, 'No initial image found in state'); - assert(isParamESRGANModelName(upscaleModel.name), "") - assert(scale) + assert(isParamESRGANModelName(upscaleModel.name), "Model must be valid upscale model") + assert(scale, 'Scale is required') const g = new Graph() diff --git a/invokeai/frontend/web/src/features/parameters/store/upscaleSlice.ts b/invokeai/frontend/web/src/features/parameters/store/upscaleSlice.ts index 51ef40e013..58f60290a4 100644 --- a/invokeai/frontend/web/src/features/parameters/store/upscaleSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/upscaleSlice.ts @@ -2,7 +2,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; import type { PersistConfig, RootState } from 'app/store/store'; import type { ParameterSpandrelImageToImageModel } from 'features/parameters/types/parameterSchemas'; -import type { ImageDTO } from 'services/api/types'; +import type { ControlNetModelConfig, ImageDTO } from 'services/api/types'; interface UpscaleState { @@ -14,6 +14,7 @@ interface UpscaleState { creativity: number; tiledVAE: boolean; scale: number | null; + tileControlnetModel: ControlNetModelConfig | null } const initialUpscaleState: UpscaleState = { @@ -24,7 +25,8 @@ const initialUpscaleState: UpscaleState = { structure: 0, creativity: 0, tiledVAE: false, - scale: null + scale: null, + tileControlnetModel: null }; export const upscaleSlice = createSlice({ @@ -60,10 +62,13 @@ export const upscaleSlice = createSlice({ scaleChanged: (state, action: PayloadAction) => { state.scale = action.payload; }, + tileControlnetModelChanged: (state, action: PayloadAction) => { + state.tileControlnetModel = action.payload; + }, }, }); -export const { upscaleModelChanged, upscaleInitialImageChanged, tiledVAEChanged, structureChanged, creativityChanged, sharpnessChanged, scaleChanged } = upscaleSlice.actions; +export const { upscaleModelChanged, upscaleInitialImageChanged, tiledVAEChanged, structureChanged, creativityChanged, sharpnessChanged, scaleChanged, tileControlnetModelChanged } = upscaleSlice.actions; export const selectUpscalelice = (state: RootState) => state.upscale; diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/MultidiffusionWarning.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/MultidiffusionWarning.tsx new file mode 100644 index 0000000000..99b8037b27 --- /dev/null +++ b/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/MultidiffusionWarning.tsx @@ -0,0 +1,59 @@ +import { Flex, Link, Text } from '@invoke-ai/ui-library'; +import { useAppDispatch, useAppSelector } from '../../../../app/store/storeHooks'; +import { useControlNetModels } from '../../../../services/api/hooks/modelsByType'; +import { useCallback, useEffect, useMemo } from 'react'; +import { tileControlnetModelChanged } from '../../../parameters/store/upscaleSlice'; +import { MODEL_TYPE_SHORT_MAP } from '../../../parameters/types/constants'; +import { setActiveTab } from '../../../ui/store/uiSlice'; + +export const MultidiffusionWarning = () => { + const model = useAppSelector((s) => s.generation.model); + const { tileControlnetModel, upscaleModel } = useAppSelector((s) => s.upscale); + const dispatch = useAppDispatch(); + const [modelConfigs, { isLoading }] = useControlNetModels(); + const disabledTabs = useAppSelector((s) => s.config.disabledTabs); + const shouldShowButton = useMemo(() => !disabledTabs.includes('models'), [disabledTabs]); + + useEffect(() => { + const validModel = modelConfigs.find((cnetModel) => { + return cnetModel.base === model?.base && cnetModel.name.toLowerCase().includes('tile'); + }); + dispatch(tileControlnetModelChanged(validModel || null)); + }, [model?.base, modelConfigs, dispatch]); + + const warningText = useMemo(() => { + if (!model) { + return `a model`; + } + + if (!upscaleModel && !tileControlnetModel) { + return `an upscaler model and ${MODEL_TYPE_SHORT_MAP[model.base]} tile controlnet`; + } + if (!upscaleModel) { + return 'an upscaler model'; + } + if (!tileControlnetModel) { + return `a ${MODEL_TYPE_SHORT_MAP[model.base]} tile controlnet`; + } + }, [model?.base, upscaleModel, tileControlnetModel]); + + const handleGoToModelManager = useCallback(() => { + dispatch(setActiveTab('models')); + }, [dispatch]); + + if (!warningText || isLoading || !shouldShowButton) { + return <>; + } + + return ( + + + Visit{' '} + + Model Manager + {' '} + to install {warningText} required by this feature + + + ); +}; diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleSettingsAccordion.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleSettingsAccordion.tsx index c7dc8f312d..263cb71d32 100644 --- a/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleSettingsAccordion.tsx +++ b/invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleSettingsAccordion.tsx @@ -5,6 +5,7 @@ import ParamCreativity from 'features/parameters/components/Upscale/ParamCreativ import ParamSharpness from 'features/parameters/components/Upscale/ParamSharpness'; import ParamSpandrelModel from 'features/parameters/components/Upscale/ParamSpandrelModel'; import ParamStructure from 'features/parameters/components/Upscale/ParamStructure'; +import { ParamTiledVAEToggle } from 'features/parameters/components/Upscale/ParamTiledVAEToggle'; import { selectUpscalelice } from 'features/parameters/store/upscaleSlice'; import { useExpanderToggle } from 'features/settingsAccordions/hooks/useExpanderToggle'; import { useStandaloneAccordionToggle } from 'features/settingsAccordions/hooks/useStandaloneAccordionToggle'; @@ -13,7 +14,7 @@ import { useTranslation } from 'react-i18next'; import { UpscaleInitialImage } from './UpscaleInitialImage'; import { UpscaleSizeDetails } from './UpscaleSizeDetails'; -import { ParamTiledVAEToggle } from '../../../parameters/components/Upscale/ParamTiledVAEToggle'; +import { MultidiffusionWarning } from './MultidiffusionWarning'; const selector = createMemoizedSelector([selectUpscalelice], (upscale) => { const badges: string[] = []; @@ -46,6 +47,7 @@ export const UpscaleSettingsAccordion = memo(() => { +