Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
A number of issues with GuernikaCore were identified in this PR which I have tried to address in this branch
shared
propertiesGenerationConfig
I also made some changes refactoring code to improve clarity.
Overwriting model data
When models are loaded (by
ImageController.loadModels()
orreloadModels()
), if a variable size model is detected, its data is copied to a temp folder and loaded from there instead. Any modifications happen to the data in the temp folder instead of the original model files.If the user's models folder is in their main volume, the
FileManager.temporaryDirectory()
folder is used, otherwise a folder is created in the same directory as the user's models folder. The folder is cleaned up by Mochi at quit, or if user changes their models folder in settings.Since the temp folder is in the same volume as the models folder, it is possible to hard link most of the data, only duplicating the following files
This is fast and efficient with disk space.
Unlike a previous PR I submitted, this makes just one copy of the model and edits it in place, and does not load a different copy of the model into memory for each different shape used.
shared
property bugsMochi allows users to queue up multiple generations, with different configurations, by storing the configurations in a queue of
GenerationConfig
objects which are sent fromImageController
toImageGenerator
.ImageGenerator
was directly accessingImageController
to get properties using itsshared
global instance reference instead, causing failures and crashes with queued jobs.e.g. from
ImageGenerator.loadPipeline()
In this example the model was being modified with the current shape dimensions from ImageController, which may no longer be the same as the dimensions of ImageController at the time the current queued job was created. If the
initImage
in thepipelineConfig
has dimensions which mismatch theinputSize
it will cause a fatal error.I moved some logic from
ImageGenerator
toImageController
, so that they wouldn't need to share data.assorted refactoring
loadPipeline()
inImageGenerator
torunGenerationJobs()
inImageController
, and has been combined with the new variable size requirementsloadPipeline()
andgenerate()
torunGenerationJobs()
hackVAE
is a very clever bit of functionality, but even when I understood what it was doing I found it very difficult to trace through the multiple nested closures. So I split it into three pure inline functions,resizeableCopy()
,modifyEncoderMil()
, andmodifyDecoderMil()
which I think are easier to read through.private
to a bunch of methods and properties which shouldn't be publicly accessible, and turned the variable size hack functions into methods ofSDModel
Variable size requirements
I want to explicitly spell out my understanding of what the variable size hack needs because if I am misunderstanding anything I want it to be obvious so that any related bugs can be caught and corrected.
VAEEncoder.mlmodelc/coremldata.bin
replaced withen-coremldata.bin
VAEDecoder.mlmodelc/coremldata.bin
replaced withde-coremldata.bin
These just need to happen once, so they get replaced in
resizeableCopy()
when the model is copied to its temp folderVAEEncoder.mlmodelc/model.mil
modified bymodifyEncoderMil()
VAEDecoder.mlmodelc/model.mil
modified bymodifyDecoderMil()
model.mil
s have to be updated every time the size changes, sosize
is now included in the pipelineHash which gets checked to reload the pipelineVAEEncoder.mlmodelc/metadata.json
modified bymodifyInputSize()
Input size must be updated when there is an input image or controlnet of a new size. The cache must be emptied to reload the image, so
loadPipeline()
is called withreduceMemory = true
which unloads existing VAEEncoder dataRemaining issues
I have commented out lines 329 and 337 of ImageController.swift
// ImageGenerator.shared.pipeline?.conditioningInput = [cinput]
// ImageGenerator.shared.pipeline?.conditioningInput = [ainput]
They have the same problem of using
shared
to set properties out of sync with the generation job queue. I am working on a fix but don't understand ControlNets well enough yet and didn't want to hold up submitting these proposed changes any longer.