diff --git a/.github/workflows/backends.yml b/.github/workflows/backends.yml new file mode 100644 index 0000000..1f506e9 --- /dev/null +++ b/.github/workflows/backends.yml @@ -0,0 +1,277 @@ +name: backends + +on: + workflow_dispatch: + inputs: + version: + description: 'version' + required: true + type: string + commit: + description: 'sd.cpp commit' + required: true + type: string + +jobs: + windows: + runs-on: windows-latest + + strategy: + matrix: + include: + - build: 'noavx' + defines: '-DGGML_AVX=OFF -DGGML_AVX2=OFF -DGGML_FMA=OFF -DSD_BUILD_SHARED_LIBS=ON' + - build: 'avx' + defines: '-DGGML_AVX2=OFF -DSD_BUILD_SHARED_LIBS=ON' + - build: 'avx2' + defines: '-DGGML_AVX2=ON -DSD_BUILD_SHARED_LIBS=ON' + - build: 'avx512' + defines: '-DGGML_AVX512=ON -DSD_BUILD_SHARED_LIBS=ON' + - build: 'cuda11' + defines: '-DSD_CUBLAS=ON -DSD_BUILD_SHARED_LIBS=ON' + - build: 'cuda12' + defines: '-DSD_CUBLAS=ON -DSD_BUILD_SHARED_LIBS=ON' + - build: 'rocm5' + defines: '-G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DSD_HIPBLAS=ON -DCMAKE_BUILD_TYPE=Release -DAMDGPU_TARGETS="gfx1100;gfx1102;gfx1030" -DSD_BUILD_SHARED_LIBS=ON' + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4.1.2 + with: + repository: 'leejet/stable-diffusion.cpp' + ref: '${{ github.event.inputs.commit }}' + submodules: recursive + + - name: Install cuda-toolkit + id: cuda-toolkit-11 + if: ${{ matrix.build == 'cuda11' }} + uses: Jimver/cuda-toolkit@v0.2.14 + with: + cuda: '11.7.1' + method: network + sub-packages: '["nvcc", "cudart", "cublas", "cublas_dev", "thrust", "visual_studio_integration"]' + + - name: Install cuda-toolkit + id: cuda-toolkit-12 + if: ${{ matrix.build == 'cuda12' }} + uses: Jimver/cuda-toolkit@v0.2.14 + with: + cuda: '12.2.0' + method: network + sub-packages: '["nvcc", "cudart", "cublas", "cublas_dev", "thrust", "visual_studio_integration"]' + + - name: Install rocm-toolkit + id: rocm-toolkit + if: ${{ matrix.build == 'rocm5' }} + uses: Cyberhan123/rocm-toolkit@v0.1.0 + with: + rocm: '5.5.0' + + - name: Install Ninja + id: install-ninja + if: ${{ matrix.build == 'rocm5' }} + uses: urkle/action-get-ninja@v1 + with: + version: 1.11.1 + + - name: Build + id: cmake_build + run: | + mkdir build + cd build + cmake .. ${{ matrix.defines }} + cmake --build . --config Release + + - name: Upload artifact + id: upload_artifact + if: ${{ matrix.build != 'rocm5' }} + uses: actions/upload-artifact@v4.3.1 + with: + name: windows-${{ matrix.build }} + path: .\build\bin\Release\stable-diffusion.dll + + - name: Upload artifact Rocm + id: upload_artifact_rocm + if: ${{ matrix.build == 'rocm5' }} + uses: actions/upload-artifact@v4.3.1 + with: + name: windows-${{ matrix.build }} + path: .\build\bin\stable-diffusion.dll + + linux: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - build: 'noavx' + defines: '-DGGML_AVX=OFF -DGGML_AVX2=OFF -DGGML_FMA=OFF -DSD_BUILD_SHARED_LIBS=ON' + - build: 'avx' + defines: '-DGGML_AVX2=OFF -DSD_BUILD_SHARED_LIBS=ON' + - build: 'avx2' + defines: '-DGGML_AVX2=ON -DSD_BUILD_SHARED_LIBS=ON' + - build: 'avx512' + defines: '-DGGML_AVX512=ON -DSD_BUILD_SHARED_LIBS=ON' + - build: 'cuda11' + defines: '-DSD_CUBLAS=ON -DSD_BUILD_SHARED_LIBS=ON' + - build: 'cuda12' + defines: '-DSD_CUBLAS=ON -DSD_BUILD_SHARED_LIBS=ON' + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4.1.2 + with: + repository: 'leejet/stable-diffusion.cpp' + ref: '${{ github.event.inputs.commit }}' + submodules: recursive + + - name: Install cuda-toolkit + id: cuda-toolkit-11 + if: ${{ matrix.build == 'cuda11' }} + uses: Jimver/cuda-toolkit@v0.2.14 + with: + cuda: '11.7.1' + method: network + + - name: Install cuda-toolkit + id: cuda-toolkit-12 + if: ${{ matrix.build == 'cuda12' }} + uses: Jimver/cuda-toolkit@v0.2.14 + with: + cuda: '12.2.0' + method: network + + - name: Build + id: cmake_build + run: | + mkdir build + cd build + cmake .. ${{ matrix.defines }} + cmake --build . --config Release + + - name: Upload artifact + id: upload_artifact + uses: actions/upload-artifact@v4.3.1 + with: + name: linux-${{ matrix.build }} + path: ./build/bin/libstable-diffusion.so + + linux-hip: + runs-on: ubuntu-22.04 + container: rocm/dev-ubuntu-22.04:6.0.2 + + steps: + - name: Dependencies + id: depends + run: | + sudo apt-get update + sudo apt-get install -y build-essential git cmake rocblas-dev hipblas-dev + hipconfig + + - name: Clone + id: checkout + uses: actions/checkout@v3 + with: + repository: 'leejet/stable-diffusion.cpp' + ref: '${{ github.event.inputs.commit }}' + submodules: recursive + + - name: Build + id: cmake_build + run: | + mkdir build + cd build + cmake .. -DCMAKE_C_COMPILER=hipcc -DCMAKE_CXX_COMPILER=hipcc -DSD_HIPBLAS=ON -DCMAKE_BUILD_TYPE=Release -DAMDGPU_TARGETS="gfx1100;gfx1102;gfx1030" -DSD_BUILD_SHARED_LIBS=ON + cmake --build . --config Release + + - name: Upload artifact Rocm + id: upload_artifact_rocm + uses: actions/upload-artifact@v4.3.1 + with: + name: linux-rocm6 + path: ./build/bin/libstable-diffusion.so + + osx: + runs-on: macos-latest + + strategy: + matrix: + include: + - build: 'noavx' + defines: '-DCMAKE_OSX_ARCHITECTURES="x86_64" -DGGML_AVX=OFF -DGGML_AVX2=OFF -DGGML_FMA=OFF -DSD_BUILD_SHARED_LIBS=ON' + - build: 'avx' + defines: '-DCMAKE_OSX_ARCHITECTURES="x86_64" -DGGML_AVX2=OFF -DSD_BUILD_SHARED_LIBS=ON' + - build: 'avx2' + defines: '-DCMAKE_OSX_ARCHITECTURES="x86_64" -DGGML_AVX2=ON -DSD_BUILD_SHARED_LIBS=ON' + - build: 'avx512' + defines: '-DCMAKE_OSX_ARCHITECTURES="x86_64" -DGGML_AVX512=ON -DSD_BUILD_SHARED_LIBS=ON' + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4.1.2 + with: + repository: 'leejet/stable-diffusion.cpp' + ref: '${{ github.event.inputs.commit }}' + submodules: recursive + + - name: Build + id: cmake_build + run: | + mkdir build + cd build + cmake .. ${{ matrix.defines }} + cmake --build . --config Release + + - name: Upload artifact + id: upload_artifact + uses: actions/upload-artifact@v4.3.1 + with: + name: osx-${{ matrix.build }} + path: ./build/bin/libstable-diffusion.dylib + + release: + runs-on: ubuntu-latest + + needs: + - windows + - linux + - linux-hip + - osx + + steps: + - name: Checkout + id: checkout + uses: actions/checkout@v4.1.2 + + - name: Download artifacts + id: download_artifacts + uses: actions/download-artifact@v4 + with: + path: Backends + + - name: Display structure of downloaded files + run: ls -R + + - name: Setup nuget + id: setup_nuget + uses: NuGet/setup-nuget@v2.0.0 + + - name: Pack + id: pack + run: | + nuget pack ./Backends/StableDiffusion.NET.Backend.Cpu.nuspec -version ${{ github.event.inputs.version }} + nuget pack ./Backends/StableDiffusion.NET.Backend.Cuda.nuspec -version ${{ github.event.inputs.version }} + nuget pack ./Backends/StableDiffusion.NET.Backend.Rocm.nuspec -version ${{ github.event.inputs.version }} + + - name: Upload artifacts + id: upload_artifacts + uses: actions/upload-artifact@v4.3.1 + with: + name: StableDiffusion.NET.Backend-Nugets + path: ./*.nupkg + + - name: Nuget Push + id: nuget_push + run: dotnet nuget push **\*.nupkg --skip-duplicate --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..0323b21 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,57 @@ +name: Release + +on: + workflow_dispatch: + inputs: + version: + description: 'version' + required: true + type: string + +jobs: + build: + runs-on: windows-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install .NET Core + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Restore dependencies + run: dotnet restore + + - name: Build + run: dotnet build --no-restore --configuration Release /p:Version=${{ github.event.inputs.version }} + + - name: Test + run: dotnet test --no-build --verbosity normal --configuration Release + + - name: Upload Nuget Build Artifact + uses: actions/upload-artifact@v4.3.1 + with: + name: StableDiffusion.NET-Nuget + path: StableDiffusion.NET\bin\Release\*.nupkg + if-no-files-found: error + + - name: List files + run: tree + + - name: Release + uses: softprops/action-gh-release@v2.0.4 + with: + tag_name: ${{ github.event.inputs.version }} + generate_release_notes: true + files: StableDiffusion.NET/bin/Release/net8.0/StableDiffusion.NET.dll + + - name: Nuget Push + id: nuget_push + run: | + dotnet nuget push **\*.nupkg --skip-duplicate --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json + dotnet nuget push **\*.snupkg --skip-duplicate --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json + \ No newline at end of file diff --git a/ImageCreationUI/ActionCommand.cs b/ImageCreationUI/ActionCommand.cs new file mode 100644 index 0000000..2b87fdb --- /dev/null +++ b/ImageCreationUI/ActionCommand.cs @@ -0,0 +1,42 @@ +using System.Windows.Input; + +namespace ImageCreationUI; + +public class ActionCommand(Action command, Func? canExecute = null) : ICommand +{ + #region Events + + public event EventHandler? CanExecuteChanged; + + #endregion + + #region Methods + + public bool CanExecute(object? parameter) => canExecute?.Invoke() ?? true; + + public void Execute(object? parameter) => command.Invoke(); + + public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); + + #endregion +} + +public class ActionCommand(Action command, Func? canExecute = null) : ICommand + where T : class +{ + #region Events + + public event EventHandler? CanExecuteChanged; + + #endregion + + #region Methods + + public bool CanExecute(object? parameter) => canExecute?.Invoke((T)parameter!) ?? true; + + public void Execute(object? parameter) => command.Invoke((T)parameter!); + + public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); + + #endregion +} \ No newline at end of file diff --git a/ImageCreationUI/App.xaml b/ImageCreationUI/App.xaml new file mode 100644 index 0000000..84ead37 --- /dev/null +++ b/ImageCreationUI/App.xaml @@ -0,0 +1,4 @@ + diff --git a/ImageCreationUI/App.xaml.cs b/ImageCreationUI/App.xaml.cs new file mode 100644 index 0000000..d92161c --- /dev/null +++ b/ImageCreationUI/App.xaml.cs @@ -0,0 +1,14 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace ImageCreationUI +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } + +} diff --git a/ImageCreationUI/Converter/ImageToImageSourceConverter.cs b/ImageCreationUI/Converter/ImageToImageSourceConverter.cs new file mode 100644 index 0000000..6370177 --- /dev/null +++ b/ImageCreationUI/Converter/ImageToImageSourceConverter.cs @@ -0,0 +1,33 @@ +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Windows.Data; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using StableDiffusion.NET.Helper.Images; + +namespace ImageCreationUI.Converter; + +[ValueConversion(typeof(IImage), typeof(ImageSource))] +public class ImageToImageSourceConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + Bitmap? bitmap = (value as IImage)?.ToBitmap(); + if (bitmap == null) return null; + + using MemoryStream ms = new(); + bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); + ms.Position = 0; + + BitmapImage bitmapImage = new(); + bitmapImage.BeginInit(); + bitmapImage.StreamSource = ms; + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + + return bitmapImage; + } + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotSupportedException(); +} \ No newline at end of file diff --git a/ImageCreationUI/Extensions/ImageExtension.cs b/ImageCreationUI/Extensions/ImageExtension.cs new file mode 100644 index 0000000..dbc7e3e --- /dev/null +++ b/ImageCreationUI/Extensions/ImageExtension.cs @@ -0,0 +1,45 @@ +using System.Drawing; +using System.Drawing.Imaging; +using StableDiffusion.NET.Helper.Images.Colors; +using StableDiffusion.NET.Helper.Images; +using System.IO; + +namespace ImageCreationUI; + +public static class ImageExtension +{ + public static Bitmap ToBitmap(this IImage image) => image.AsRefImage().ToBitmap(); + public static Bitmap ToBitmap(this Image image) => image.AsRefImage().ToBitmap(); + + public static unsafe Bitmap ToBitmap(this RefImage image) + { + Bitmap output = new(image.Width, image.Height, PixelFormat.Format24bppRgb); + Rectangle rect = new(0, 0, image.Width, image.Height); + BitmapData bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat); + + nint ptr = bmpData.Scan0; + foreach (ReadOnlyRefEnumerable row in image.Rows) + { + Span target = new((void*)ptr, bmpData.Stride); + for (int i = 0; i < row.Length; i++) + { + ColorRGB srcColor = row[i]; + target[i] = new ColorBGR(srcColor.B, srcColor.G, srcColor.R); + } + + ptr += bmpData.Stride; + } + + output.UnlockBits(bmpData); + return output; + } + + public static byte[] ToPng(this IImage image) + { + using Bitmap bitmap = image.ToBitmap(); + using MemoryStream ms = new(); + bitmap.Save(ms, ImageFormat.Png); + + return ms.ToArray(); + } +} \ No newline at end of file diff --git a/ImageCreationUI/ImageCreationUI.csproj b/ImageCreationUI/ImageCreationUI.csproj new file mode 100644 index 0000000..f5e25c8 --- /dev/null +++ b/ImageCreationUI/ImageCreationUI.csproj @@ -0,0 +1,20 @@ + + + + WinExe + net8.0-windows + enable + enable + true + true + + + + + + + + + + + diff --git a/ImageCreationUI/ImageCreationUI.csproj.DotSettings b/ImageCreationUI/ImageCreationUI.csproj.DotSettings new file mode 100644 index 0000000..17962b1 --- /dev/null +++ b/ImageCreationUI/ImageCreationUI.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/ImageCreationUI/MainWindow.xaml b/ImageCreationUI/MainWindow.xaml new file mode 100644 index 0000000..e185201 --- /dev/null +++ b/ImageCreationUI/MainWindow.xaml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + +