Skip to content
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

Public Backend API #654

Merged
merged 37 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
5283043
Add backend api
carson-katri Apr 28, 2023
aac3ea3
Implement Diffusers backend and move optimization UI
carson-katri Apr 28, 2023
c5ee30d
Functional text to image
carson-katri Apr 28, 2023
7af82bd
Add test backend addon
carson-katri Apr 28, 2023
07b972a
Fix optimization eval
carson-katri Apr 29, 2023
40d47f3
Add support for showing messages during generation
carson-katri May 5, 2023
3450579
Allow backends to report fixable errors
carson-katri May 8, 2023
74185e0
Fix compatibility with `main`
carson-katri Jul 7, 2023
d35025d
Update inpaint for latest diffusers
carson-katri Jul 7, 2023
4c4aadf
Update depth_to_image for latest diffusers
carson-katri Jul 7, 2023
3b1f2cc
Support ControlNet
carson-katri Jul 23, 2023
264ca3e
Add support for Stable Diffusion XL (#694)
carson-katri Aug 14, 2023
88f89fa
Fix node-based rendering with engine-level backend selection
carson-katri Aug 14, 2023
d11b8e9
Fix ControlNet nodes
carson-katri Aug 14, 2023
3c44361
Model Loading Improvements and Safetensors Importing (#703)
NullSenseStudio Sep 8, 2023
6234dc3
Add cache: 'pip' to packager and remove stabilityai builds
carson-katri Sep 8, 2023
f3cc3eb
Add cancellation to backend API and attempt to fix GH actions caching
carson-katri Sep 9, 2023
7c1bdef
try quotes and backslash
carson-katri Sep 9, 2023
bdbc35b
try wildcard
carson-katri Sep 9, 2023
01bd184
Update projection to use backends
carson-katri Sep 9, 2023
3a3976d
Update render pass to use backend
carson-katri Sep 9, 2023
3af4bc9
Functional upscaling
carson-katri Sep 9, 2023
0d3f65e
Improve upscaling and other generation types UI
carson-katri Sep 9, 2023
9b72c2f
Add align=True to projection button
carson-katri Sep 9, 2023
5a7c661
Upgrade diffusers to 0.20.2
carson-katri Sep 9, 2023
0ba55c0
Update diffusers_backend.py
carson-katri Sep 17, 2023
5420906
Update diffusers_backend.py
carson-katri Sep 17, 2023
9a1164e
Update diffusers_backend.py
carson-katri Sep 17, 2023
e5ddd28
Update generator_process/actions/upscale.py
carson-katri Sep 17, 2023
bbaa8e5
Update operators/dream_texture.py
carson-katri Sep 17, 2023
8ee8dce
Move init_image logic out of generate_args
carson-katri Sep 17, 2023
0c7d138
Merge branch 'backend-api' of github.com:carson-katri/dream-textures …
carson-katri Sep 17, 2023
8d065b3
Update validation logic
carson-katri Sep 17, 2023
12eea79
Fix projection validation
carson-katri Sep 17, 2023
c9b2bce
fix vae tiling
NullSenseStudio Sep 17, 2023
ac5c164
partially fix outpaint
NullSenseStudio Sep 17, 2023
3c0b109
outpaint strength=1
NullSenseStudio Sep 17, 2023
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
60 changes: 5 additions & 55 deletions .github/workflows/package-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: '3.10'
cache: 'pip'
cache-dependency-path: '**/win-linux-cuda.txt'
- name: Install dependencies into target
shell: bash
run: 'python -m pip install -r requirements/win-linux-cuda.txt --no-cache-dir --target .python_dependencies'
Expand All @@ -65,6 +67,8 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: '3.10'
cache: 'pip'
cache-dependency-path: '**/win-dml.txt'
- name: Install dependencies into target
shell: bash
run: 'python -m pip install -r requirements/win-dml.txt --no-cache-dir --target .python_dependencies'
Expand All @@ -79,58 +83,4 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: dream_textures-windows-directml
path: dream_textures-windows-directml.zip
windows-dreamstudio:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
path: dream_textures
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies into target
shell: bash
run: 'python -m pip install -r requirements/dreamstudio.txt --no-cache-dir --target .python_dependencies'
working-directory: dream_textures
- name: Archive Release
uses: thedoctor0/zip-release@main
with:
type: zip
filename: dream_textures-windows-dreamstudio.zip
exclusions: '*.git*'
- name: Archive and upload artifact
uses: actions/upload-artifact@v3
with:
name: dream_textures-windows-dreamstudio
path: dream_textures-windows-dreamstudio.zip
# No universal wheels for grpcio means we need separate macOS installations for Intel/ARM.
# GitHub Actions does not have Apple Silicon runners, so that build still needs to be created manually.
macos-intel-dreamstudio:
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
path: dream_textures
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies into target
shell: bash
run: 'python -m pip install -r requirements/dreamstudio.txt --no-cache-dir --target .python_dependencies'
working-directory: dream_textures
- name: Archive Release
uses: thedoctor0/zip-release@main
with:
type: zip
filename: dream_textures-macos-intel-dreamstudio.zip
exclusions: '*.git*'
- name: Archive and upload artifact
uses: actions/upload-artifact@v3
with:
name: dream_textures-macos-intel-dreamstudio
path: dream_textures-macos-intel-dreamstudio.zip
path: dream_textures-windows-directml.zip
8 changes: 8 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def clear_modules():

from . import engine

from .diffusers_backend import DiffusersBackend

requirements_path_items = (
('requirements/win-linux-cuda.txt', 'Linux/Windows (CUDA)', 'Linux or Windows with NVIDIA GPU'),
('requirements/mac-mps-cpu.txt', 'Apple Silicon', 'Apple M1/M2'),
Expand Down Expand Up @@ -127,6 +129,9 @@ def project_use_controlnet(self, context):
register_render_pass()

register_default_presets()

# Register the default backend.
bpy.utils.register_class(DiffusersBackend)

def unregister():
for cls in PREFERENCE_CLASSES:
Expand All @@ -143,4 +148,7 @@ def unregister():

unregister_render_pass()

# Unregister the default backend
bpy.utils.unregister_class(DiffusersBackend)

kill_generator()
2 changes: 2 additions & 0 deletions api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .models import *
from .backend import *
1 change: 1 addition & 0 deletions api/backend/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .backend import *
143 changes: 143 additions & 0 deletions api/backend/backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
try:
import bpy
from typing import Callable, List, Tuple
from ..models.generation_arguments import GenerationArguments
from ..models.generation_result import GenerationResult
from ..models.model import Model

StepCallback = Callable[[List[GenerationResult]], bool]
Callback = Callable[[List[GenerationResult] | Exception], None]

class Backend(bpy.types.PropertyGroup):
"""A backend for Dream Textures.

Provide the following methods to create a valid backend.

```python
def list_models(self) -> List[Model]
def generate(
self,
arguments: GenerationArguments,

step_callback: StepCallback,
callback: Callback
)
```
"""

@classmethod
def register(cls):
from ...property_groups.dream_prompt import DreamPrompt
setattr(DreamPrompt, cls._attribute(), bpy.props.PointerProperty(type=cls))

@classmethod
def unregister(cls):
from ...property_groups.dream_prompt import DreamPrompt
delattr(DreamPrompt, cls._attribute())

@classmethod
def _id(cls) -> str:
return f"{cls.__module__}.{cls.__name__}"

@classmethod
def _attribute(cls) -> str:
return cls._id().replace('.', '_')

@classmethod
def _lookup(cls, id):
return next(
(backend for backend in cls._list_backends() if backend._id() == id),
next(iter(cls._list_backends()), None)
)

@classmethod
def _list_backends(cls):
return cls.__subclasses__()

def list_models(self, context) -> List[Model]:
"""Provide a list of available models.

The `id` of the model will be provided.
"""
...

def list_controlnet_models(self, context) -> List[Model]:
"""Provide a list of available ControlNet models.

The `id` of the model will be provided.
"""
return []

def list_schedulers(self, context) -> List[str]:
"""Provide a list of available schedulers."""
...

def draw_prompt(self, layout, context):
"""Draw additional UI in the 'Prompt' panel"""
...

def draw_advanced(self, layout, context):
"""Draw additional UI in the 'Advanced' panel"""
...

def draw_speed_optimizations(self, layout, context):
"""Draw additional UI in the 'Speed Optimizations' panel"""
...

def draw_memory_optimizations(self, layout, context):
"""Draw additional UI in the 'Memory Optimizations' panel"""
...

def draw_extra(self, layout, context):
"""Draw additional UI in the panel"""
...

def get_batch_size(self, context) -> int:
"""Return the selected batch size for the backend (if applicable).

A default implementation is provided that returns `1`.
"""
return 1

def generate(
self,
arguments: GenerationArguments,
step_callback: StepCallback,
callback: Callback
):
"""
A request to generate an image.

If the `step_callback` returns `False`, the generation should be cancelled.
After cancelling, `callback` should be called with an `InterruptedError`.
"""
...

def validate(
self,
arguments: GenerationArguments
):
"""Validates the given arguments in the UI without generating.

This validation should occur as quickly as possible.

To report problems with the inputs, raise a `ValueError`.
Use the `FixItError` to provide a solution to the problem as well.

```python
if arguments.steps % 2 == 0:
throw FixItError(
"The number of steps is even",
solution=FixItError.UpdateGenerationArgumentsSolution(
title="Add 1 more step",
arguments=dataclasses.replace(
arguments,
steps=arguments.steps + 1
)
)
)
```
"""
...
except:
pass
7 changes: 7 additions & 0 deletions api/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .generation_result import *
from .model import *
from .prompt import *
from .seamless_axes import *
from .step_preview_mode import *
from .task import *
from .fix_it_error import *
14 changes: 14 additions & 0 deletions api/models/control_net.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from dataclasses import dataclass
from typing import Tuple, List
from numpy.typing import NDArray

@dataclass
class ControlNet:
model: str
"""The selected ControlNet model used for generation"""

image: NDArray
"""The control image"""

strength: float
"""The strength of the ControlNet's influence"""
41 changes: 41 additions & 0 deletions api/models/fix_it_error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from typing import Callable, Any
from .generation_arguments import GenerationArguments
from dataclasses import dataclass

class FixItError(Exception):
"""An exception with a solution.

Call the `draw` method to render the UI elements responsible for resolving this error.
"""
def __init__(self, message, solution: 'Solution'):
super().__init__(message)

self._solution = solution

def _draw(self, dream_prompt, context, layout):
self._solution._draw(dream_prompt, context, layout)

@dataclass
class Solution:
def _draw(self, dream_prompt, context, layout):
...

@dataclass
class ChangeProperty(Solution):
"""Prompts the user to change the given `property` of the `GenerationArguments`."""
property: str

def _draw(self, dream_prompt, context, layout):
layout.prop(dream_prompt, self.property)

@dataclass
class RunOperator(Solution):
"""Runs the given operator"""
title: str
operator: str
modify_operator: Callable[[Any], None]

def _draw(self, dream_prompt, context, layout):
self.modify_operator(
layout.operator(self.operator, text=self.title)
)
Loading