@ -57,7 +57,6 @@ struct ControlsView: View {
@ State private var disclosedSteps = false
@ State private var disclosedSteps = false
@ State private var disclosedSeed = false
@ State private var disclosedSeed = false
@ State private var disclosedAdvanced = false
@ State private var disclosedAdvanced = false
@ State private var useANE = ( Settings . shared . userSelectedAttentionVariant ? ? ModelInfo . defaultAttention ) = = . splitEinsum
// TODO: r e f a c t o r d o w n l o a d w i t h s i m i l a r c o d e i n L o a d i n g . s w i f t ( i O S )
// TODO: r e f a c t o r d o w n l o a d w i t h s i m i l a r c o d e i n L o a d i n g . s w i f t ( i O S )
@ State private var stateSubscriber : Cancellable ?
@ State private var stateSubscriber : Cancellable ?
@ -82,14 +81,18 @@ struct ControlsView: View {
mustShowSafetyCheckerDisclaimer = generation . disableSafety && ! Settings . shared . safetyCheckerDisclaimerShown
mustShowSafetyCheckerDisclaimer = generation . disableSafety && ! Settings . shared . safetyCheckerDisclaimerShown
}
}
func update ANE State( ) {
func update ComputeUnits State( ) {
Settings . shared . userSelected AttentionVariant = useANE ? . splitEinsum : . original
Settings . shared . userSelected ComputeUnits = generation . computeUnits
modelDidChange ( model : Settings . shared . currentModel )
modelDidChange ( model : Settings . shared . currentModel )
}
}
func resetComputeUnitsState ( ) {
generation . computeUnits = Settings . shared . userSelectedComputeUnits ? ? ModelInfo . defaultComputeUnits
}
func modelDidChange ( model : ModelInfo ) {
func modelDidChange ( model : ModelInfo ) {
guard pipelineLoader ? . model != model || pipelineLoader ? . variant != Settings . shared . userSelectedAttentionVariant else {
guard pipelineLoader ? . model != model || pipelineLoader ? . computeUnits != generation . computeUnits else {
print ( " Reusing same model \( model ) with attention \( String ( describing : Settings . shared . userSelectedAttentionVariant ) ) " )
print ( " Reusing same model \( model ) with units \( generation . computeUnits ) " )
return
return
}
}
@ -99,7 +102,7 @@ struct ControlsView: View {
pipelineLoader ? . cancel ( )
pipelineLoader ? . cancel ( )
pipelineState = . downloading ( 0 )
pipelineState = . downloading ( 0 )
Task . init {
Task . init {
let loader = PipelineLoader ( model : model , variant: Settings . shared . userSelectedAttentionVariant , maxSeed : maxSeed )
let loader = PipelineLoader ( model : model , computeUnits: generation . computeUnits , maxSeed : maxSeed )
self . pipelineLoader = loader
self . pipelineLoader = loader
stateSubscriber = loader . statePublisher . sink { state in
stateSubscriber = loader . statePublisher . sink { state in
DispatchQueue . main . async {
DispatchQueue . main . async {
@ -128,8 +131,8 @@ struct ControlsView: View {
}
}
}
}
func isModelDownloaded ( _ model : ModelInfo , variant: AttentionVariant ? = nil ) -> Bool {
func isModelDownloaded ( _ model : ModelInfo , computeUnits: ComputeUnits ? = nil ) -> Bool {
PipelineLoader ( model : model , variant: variant ? ? Settings . shared . userSelectedAttentionVariant ) . ready
PipelineLoader ( model : model , computeUnits: computeUnits ? ? generation . computeUnits ) . ready
}
}
func modelLabel ( _ model : ModelInfo ) -> Text {
func modelLabel ( _ model : ModelInfo ) -> Text {
@ -301,21 +304,25 @@ struct ControlsView: View {
Divider ( )
Divider ( )
DisclosureGroup ( isExpanded : $ disclosedAdvanced ) {
DisclosureGroup ( isExpanded : $ disclosedAdvanced ) {
HStack {
HStack {
Toggle ( " Use Neural Engine " , isOn : $ useANE ) . onChange ( of : useANE ) { value in
Picker ( selection : $ generation . computeUnits , label : Text ( " Use " ) ) {
Text ( " GPU " ) . tag ( ComputeUnits . cpuAndGPU )
Text ( " Neural Engine " ) . tag ( ComputeUnits . cpuAndNeuralEngine )
Text ( " GPU and Neural Engine " ) . tag ( ComputeUnits . all )
} . pickerStyle ( . radioGroup ) . padding ( . leading )
Spacer ( )
}
. onChange ( of : generation . computeUnits ) { units in
guard let currentModel = ModelInfo . from ( modelVersion : model ) else { return }
guard let currentModel = ModelInfo . from ( modelVersion : model ) else { return }
let variantDownloaded = isModelDownloaded ( currentModel , variant : useANE ? . splitEinsum : . original )
let variantDownloaded = isModelDownloaded ( currentModel , computeUnits: units )
if variantDownloaded {
if variantDownloaded {
updateANEState ( )
updateComputeUnits State( )
} else {
} else {
mustShowModelDownloadDisclaimer . toggle ( )
mustShowModelDownloadDisclaimer . toggle ( )
}
}
}
}
. padding ( . leading , 10 )
Spacer ( )
}
. alert ( " Download Required " , isPresented : $ mustShowModelDownloadDisclaimer , actions : {
. alert ( " Download Required " , isPresented : $ mustShowModelDownloadDisclaimer , actions : {
Button ( " Cancel " , role : . destructive ) { useANE. toggl e( ) }
Button ( " Cancel " , role : . destructive ) { resetComputeUnitsState ( ) }
Button ( " Download " , role : . cancel ) { update ANE State( ) }
Button ( " Download " , role : . cancel ) { updateComputeUnitsState ( ) }
} , message : {
} , message : {
Text ( " This setting requires a new version of the selected model. " )
Text ( " This setting requires a new version of the selected model. " )
} )
} )