diff --git a/backend/go/stablediffusion-ggml/CMakeLists.txt b/backend/go/stablediffusion-ggml/CMakeLists.txt deleted file mode 100644 index f80aa2702b76..000000000000 --- a/backend/go/stablediffusion-ggml/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -cmake_minimum_required(VERSION 3.12) -project(gosd LANGUAGES C CXX) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -add_subdirectory(./sources/stablediffusion-ggml.cpp) - -add_library(gosd MODULE gosd.cpp) -target_link_libraries(gosd PRIVATE stable-diffusion ggml stdc++fs) - -target_include_directories(gosd PUBLIC - stable-diffusion.cpp - stable-diffusion.cpp/thirdparty -) - -set_property(TARGET gosd PROPERTY CXX_STANDARD 17) -set_target_properties(gosd PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/backend/go/stablediffusion-ggml/Makefile b/backend/go/stablediffusion-ggml/Makefile index d4983430f5d3..831da0bff378 100644 --- a/backend/go/stablediffusion-ggml/Makefile +++ b/backend/go/stablediffusion-ggml/Makefile @@ -1,15 +1,28 @@ +INCLUDE_PATH := $(abspath ./) +LIBRARY_PATH := $(abspath ./) + +AR?=ar CMAKE_ARGS?= BUILD_TYPE?= NATIVE?=false +CUDA_LIBPATH?=/usr/local/cuda/lib64/ +ONEAPI_VARS?=/opt/intel/oneapi/setvars.sh +# keep standard at C11 and C++11 +CXXFLAGS = -I. -I$(INCLUDE_PATH)/sources/stablediffusion-ggml.cpp/thirdparty -I$(INCLUDE_PATH)/sources/stablediffusion-ggml.cpp/ggml/include -I$(INCLUDE_PATH)/sources/stablediffusion-ggml.cpp -O3 -DNDEBUG -std=c++17 -fPIC GOCMD?=go +CGO_LDFLAGS?= +# Avoid parent make file overwriting CGO_LDFLAGS which is needed for hipblas +CGO_LDFLAGS_SYCL= GO_TAGS?= +LD_FLAGS?= # stablediffusion.cpp (ggml) STABLEDIFFUSION_GGML_REPO?=https://github.com/leejet/stable-diffusion.cpp STABLEDIFFUSION_GGML_VERSION?=5900ef6605c6fbf7934239f795c13c97bc993853 -CMAKE_ARGS+=-DGGML_MAX_NAME=128 +# Disable Shared libs as we are linking on static gRPC and we can't mix shared and static +CMAKE_ARGS+=-DBUILD_SHARED_LIBS=OFF -DGGML_MAX_NAME=128 -DSD_USE_SYSTEM_GGML=OFF ifeq ($(NATIVE),false) CMAKE_ARGS+=-DGGML_NATIVE=OFF @@ -18,6 +31,7 @@ endif # If build type is cublas, then we set -DGGML_CUDA=ON to CMAKE_ARGS automatically ifeq ($(BUILD_TYPE),cublas) CMAKE_ARGS+=-DSD_CUDA=ON -DGGML_CUDA=ON + CGO_LDFLAGS+=-lcublas -lcudart -L$(CUDA_LIBPATH) -L$(CUDA_LIBPATH)/stubs/ -lcuda # If build type is openblas then we set -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS # to CMAKE_ARGS automatically else ifeq ($(BUILD_TYPE),openblas) @@ -32,12 +46,14 @@ else ifeq ($(BUILD_TYPE),hipblas) # But if it's OSX without metal, disable it here else ifeq ($(BUILD_TYPE),vulkan) CMAKE_ARGS+=-DSD_VULKAN=ON -DGGML_VULKAN=ON + CGO_LDFLAGS+=-lvulkan else ifeq ($(OS),Darwin) ifneq ($(BUILD_TYPE),metal) CMAKE_ARGS+=-DSD_METAL=OFF -DGGML_METAL=OFF else CMAKE_ARGS+=-DSD_METAL=ON -DGGML_METAL=ON CMAKE_ARGS+=-DGGML_METAL_EMBED_LIBRARY=ON + TARGET+=--target ggml-metal endif endif @@ -47,6 +63,12 @@ ifeq ($(BUILD_TYPE),sycl_f16) -DCMAKE_CXX_COMPILER=icpx \ -DSD_SYCL=ON \ -DGGML_SYCL_F16=ON + export CC=icx + export CXX=icpx + CGO_LDFLAGS_SYCL += -fsycl -L${DNNLROOT}/lib -ldnnl ${MKLROOT}/lib/intel64/libmkl_sycl.a -fiopenmp -fopenmp-targets=spir64 -lOpenCL + CGO_LDFLAGS_SYCL += $(shell pkg-config --libs mkl-static-lp64-gomp) + CGO_CXXFLAGS += -fiopenmp -fopenmp-targets=spir64 + CGO_CXXFLAGS += $(shell pkg-config --cflags mkl-static-lp64-gomp ) endif ifeq ($(BUILD_TYPE),sycl_f32) @@ -54,24 +76,73 @@ ifeq ($(BUILD_TYPE),sycl_f32) -DCMAKE_C_COMPILER=icx \ -DCMAKE_CXX_COMPILER=icpx \ -DSD_SYCL=ON + export CC=icx + export CXX=icpx + CGO_LDFLAGS_SYCL += -fsycl -L${DNNLROOT}/lib -ldnnl ${MKLROOT}/lib/intel64/libmkl_sycl.a -fiopenmp -fopenmp-targets=spir64 -lOpenCL + CGO_LDFLAGS_SYCL += $(shell pkg-config --libs mkl-static-lp64-gomp) + CGO_CXXFLAGS += -fiopenmp -fopenmp-targets=spir64 + CGO_CXXFLAGS += $(shell pkg-config --cflags mkl-static-lp64-gomp ) endif +# warnings +# CXXFLAGS += -Wall -Wextra -Wpedantic -Wcast-qual -Wno-unused-function + +# Find all .a archives in ARCHIVE_DIR +# (ggml can have different backends cpu, cuda, etc., each backend generates a .a archive) +GGML_ARCHIVE_DIR := build/ggml/src/ +ALL_ARCHIVES := $(shell find $(GGML_ARCHIVE_DIR) -type f -name '*.a') +ALL_OBJS := $(shell find $(GGML_ARCHIVE_DIR) -type f -name '*.o') + +# Name of the single merged library +COMBINED_LIB := libggmlall.a + +# Instead of using the archives generated by GGML, use the object files directly to avoid overwriting objects with the same base name +$(COMBINED_LIB): $(ALL_ARCHIVES) + @echo "Merging all .o into $(COMBINED_LIB): $(ALL_OBJS)" + rm -f $@ + ar -qc $@ $(ALL_OBJS) + # Ensure we have a proper index + ranlib $@ + +build/libstable-diffusion.a: + @echo "Building SD with $(BUILD_TYPE) build type and $(CMAKE_ARGS)" +ifneq (,$(findstring sycl,$(BUILD_TYPE))) + +bash -c "source $(ONEAPI_VARS); \ + mkdir -p build && \ + cd build && \ + cmake $(CMAKE_ARGS) ../sources/stablediffusion-ggml.cpp && \ + cmake --build . --config Release" +else + mkdir -p build && \ + cd build && \ + cmake $(CMAKE_ARGS) ../sources/stablediffusion-ggml.cpp && \ + cmake --build . --config Release +endif + $(MAKE) $(COMBINED_LIB) + +gosd.o: +ifneq (,$(findstring sycl,$(BUILD_TYPE))) + +bash -c "source $(ONEAPI_VARS); \ + $(CXX) $(CXXFLAGS) gosd.cpp -o gosd.o -c" +else + $(CXX) $(CXXFLAGS) gosd.cpp -o gosd.o -c +endif + +## stablediffusion (ggml) sources/stablediffusion-ggml.cpp: git clone --recursive $(STABLEDIFFUSION_GGML_REPO) sources/stablediffusion-ggml.cpp && \ cd sources/stablediffusion-ggml.cpp && \ git checkout $(STABLEDIFFUSION_GGML_VERSION) && \ git submodule update --init --recursive --depth 1 --single-branch -libgosd.so: sources/stablediffusion-ggml.cpp CMakeLists.txt gosd.cpp gosd.h - mkdir -p build && \ - cd build && \ - cmake .. $(CMAKE_ARGS) && \ - cmake --build . --config Release -j$(JOBS) && \ - cd .. && \ - mv build/libgosd.so ./ +libsd.a: sources/stablediffusion-ggml.cpp build/libstable-diffusion.a gosd.o + cp $(INCLUDE_PATH)/build/libstable-diffusion.a ./libsd.a + $(AR) rcs libsd.a gosd.o -stablediffusion-ggml: main.go gosd.go libgosd.so - CGO_ENABLED=0 $(GOCMD) build -tags "$(GO_TAGS)" -o stablediffusion-ggml ./ +stablediffusion-ggml: libsd.a + CGO_LDFLAGS="$(CGO_LDFLAGS) $(CGO_LDFLAGS_SYCL)" C_INCLUDE_PATH="$(INCLUDE_PATH)" LIBRARY_PATH="$(LIBRARY_PATH)" \ + CC="$(CC)" CXX="$(CXX)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" \ + $(GOCMD) build -ldflags "$(LD_FLAGS)" -tags "$(GO_TAGS)" -o stablediffusion-ggml ./ package: bash package.sh @@ -79,4 +150,4 @@ package: build: stablediffusion-ggml package clean: - rm -rf libgosd.o build stablediffusion-ggml + rm -rf gosd.o libsd.a build $(COMBINED_LIB) diff --git a/backend/go/stablediffusion-ggml/gosd.cpp b/backend/go/stablediffusion-ggml/gosd.cpp index 7e5efb6ecfe5..b8db574747e4 100644 --- a/backend/go/stablediffusion-ggml/gosd.cpp +++ b/backend/go/stablediffusion-ggml/gosd.cpp @@ -1,4 +1,3 @@ -#include #define GGML_MAX_NAME 128 #include @@ -58,7 +57,7 @@ sd_ctx_t* sd_c; sample_method_t sample_method; // Copied from the upstream CLI -static void sd_log_cb(enum sd_log_level_t level, const char* log, void* data) { +void sd_log_cb(enum sd_log_level_t level, const char* log, void* data) { //SDParams* params = (SDParams*)data; const char* level_str; @@ -89,33 +88,33 @@ static void sd_log_cb(enum sd_log_level_t level, const char* log, void* data) { fflush(stderr); } -int load_model(const char *model, char *model_path, char* options[], int threads, int diff) { - fprintf (stderr, "Loading model: %p=%s\n", model, model); +int load_model(char *model, char *model_path, char* options[], int threads, int diff) { + fprintf (stderr, "Loading model!\n"); sd_set_log_callback(sd_log_cb, NULL); - const char *stableDiffusionModel = ""; + char *stableDiffusionModel = ""; if (diff == 1 ) { stableDiffusionModel = model; model = ""; } // decode options. Options are in form optname:optvale, or if booleans only optname. - const char *clip_l_path = ""; - const char *clip_g_path = ""; - const char *t5xxl_path = ""; - const char *vae_path = ""; - const char *scheduler = ""; - const char *sampler = ""; + char *clip_l_path = ""; + char *clip_g_path = ""; + char *t5xxl_path = ""; + char *vae_path = ""; + char *scheduler = ""; + char *sampler = ""; char *lora_dir = model_path; bool lora_dir_allocated = false; - fprintf(stderr, "parsing options: %p\n", options); + fprintf(stderr, "parsing options\n"); // If options is not NULL, parse options for (int i = 0; options[i] != NULL; i++) { - const char *optname = strtok(options[i], ":"); - const char *optval = strtok(NULL, ":"); + char *optname = strtok(options[i], ":"); + char *optval = strtok(NULL, ":"); if (optval == NULL) { optval = "true"; } @@ -148,8 +147,7 @@ int load_model(const char *model, char *model_path, char* options[], int threads lora_dir_allocated = true; fprintf(stderr, "Lora dir resolved to: %s\n", lora_dir); } else { - lora_dir = strdup(optval); - lora_dir_allocated = true; + lora_dir = optval; fprintf(stderr, "No model path provided, using lora dir as-is: %s\n", lora_dir); } } @@ -228,7 +226,7 @@ int load_model(const char *model, char *model_path, char* options[], int threads return 0; } -int gen_image(char *text, char *negativeText, int width, int height, int steps, int64_t seed, char *dst, float cfg_scale, char *src_image, float strength, char *mask_image, char **ref_images, int ref_images_count) { +int gen_image(char *text, char *negativeText, int width, int height, int steps, int seed , char *dst, float cfg_scale, char *src_image, float strength, char *mask_image, char **ref_images, int ref_images_count) { sd_image_t* results; @@ -254,14 +252,14 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, // Handle input image for img2img bool has_input_image = (src_image != NULL && strlen(src_image) > 0); bool has_mask_image = (mask_image != NULL && strlen(mask_image) > 0); - + uint8_t* input_image_buffer = NULL; uint8_t* mask_image_buffer = NULL; std::vector default_mask_image_vec; - + if (has_input_image) { fprintf(stderr, "Loading input image: %s\n", src_image); - + int c = 0; int img_width = 0; int img_height = 0; @@ -275,29 +273,29 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, free(input_image_buffer); return 1; } - + // Resize input image if dimensions don't match if (img_width != width || img_height != height) { fprintf(stderr, "Resizing input image from %dx%d to %dx%d\n", img_width, img_height, width, height); - + uint8_t* resized_image_buffer = (uint8_t*)malloc(height * width * 3); if (resized_image_buffer == NULL) { fprintf(stderr, "Failed to allocate memory for resized image\n"); free(input_image_buffer); return 1; } - + stbir_resize(input_image_buffer, img_width, img_height, 0, resized_image_buffer, width, height, 0, STBIR_TYPE_UINT8, 3, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_BOX, STBIR_COLORSPACE_SRGB, nullptr); - + free(input_image_buffer); input_image_buffer = resized_image_buffer; } - + p.init_image = {(uint32_t)width, (uint32_t)height, 3, input_image_buffer}; p.strength = strength; fprintf(stderr, "Using img2img with strength: %.2f\n", strength); @@ -306,11 +304,11 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, p.init_image = {(uint32_t)width, (uint32_t)height, 3, NULL}; p.strength = 0.0f; } - + // Handle mask image for inpainting if (has_mask_image) { fprintf(stderr, "Loading mask image: %s\n", mask_image); - + int c = 0; int mask_width = 0; int mask_height = 0; @@ -320,11 +318,11 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, if (input_image_buffer) free(input_image_buffer); return 1; } - + // Resize mask if dimensions don't match if (mask_width != width || mask_height != height) { fprintf(stderr, "Resizing mask image from %dx%d to %dx%d\n", mask_width, mask_height, width, height); - + uint8_t* resized_mask_buffer = (uint8_t*)malloc(height * width); if (resized_mask_buffer == NULL) { fprintf(stderr, "Failed to allocate memory for resized mask\n"); @@ -332,18 +330,18 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, if (input_image_buffer) free(input_image_buffer); return 1; } - + stbir_resize(mask_image_buffer, mask_width, mask_height, 0, resized_mask_buffer, width, height, 0, STBIR_TYPE_UINT8, 1, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_BOX, STBIR_COLORSPACE_SRGB, nullptr); - + free(mask_image_buffer); mask_image_buffer = resized_mask_buffer; } - + p.mask_image = {(uint32_t)width, (uint32_t)height, 1, mask_image_buffer}; fprintf(stderr, "Using inpainting with mask\n"); } else { @@ -355,17 +353,17 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, // Handle reference images std::vector ref_images_vec; std::vector ref_image_buffers; - + if (ref_images_count > 0 && ref_images != NULL) { fprintf(stderr, "Loading %d reference images\n", ref_images_count); - + for (int i = 0; i < ref_images_count; i++) { if (ref_images[i] == NULL || strlen(ref_images[i]) == 0) { continue; } - + fprintf(stderr, "Loading reference image %d: %s\n", i + 1, ref_images[i]); - + int c = 0; int ref_width = 0; int ref_height = 0; @@ -379,33 +377,33 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, free(ref_image_buffer); continue; } - + // Resize reference image if dimensions don't match if (ref_width != width || ref_height != height) { fprintf(stderr, "Resizing reference image from %dx%d to %dx%d\n", ref_width, ref_height, width, height); - + uint8_t* resized_ref_buffer = (uint8_t*)malloc(height * width * 3); if (resized_ref_buffer == NULL) { fprintf(stderr, "Failed to allocate memory for resized reference image\n"); free(ref_image_buffer); continue; } - + stbir_resize(ref_image_buffer, ref_width, ref_height, 0, resized_ref_buffer, width, height, 0, STBIR_TYPE_UINT8, 3, STBIR_ALPHA_CHANNEL_NONE, 0, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_FILTER_BOX, STBIR_COLORSPACE_SRGB, nullptr); - + free(ref_image_buffer); ref_image_buffer = resized_ref_buffer; } - + ref_image_buffers.push_back(ref_image_buffer); ref_images_vec.push_back({(uint32_t)width, (uint32_t)height, 3, ref_image_buffer}); } - + if (!ref_images_vec.empty()) { p.ref_images = ref_images_vec.data(); p.ref_images_count = ref_images_vec.size(); @@ -456,12 +454,12 @@ int gen_image(char *text, char *negativeText, int width, int height, int steps, for (auto buffer : ref_image_buffers) { if (buffer) free(buffer); } - fprintf (stderr, "gen_image is done: %s", dst); + fprintf (stderr, "gen_image is done", dst); return 0; } int unload() { free_sd_ctx(sd_c); - return 0; } + diff --git a/backend/go/stablediffusion-ggml/gosd.go b/backend/go/stablediffusion-ggml/gosd.go index 6a1d7535cdf3..221ba4294e99 100644 --- a/backend/go/stablediffusion-ggml/gosd.go +++ b/backend/go/stablediffusion-ggml/gosd.go @@ -1,10 +1,15 @@ package main +// #cgo CXXFLAGS: -I${SRCDIR}/sources/stablediffusion-ggml.cpp/thirdparty -I${SRCDIR}/sources/stablediffusion-ggml.cpp -I${SRCDIR}/sources/stablediffusion-ggml.cpp/ggml/include +// #cgo LDFLAGS: -L${SRCDIR}/ -lsd -lstdc++ -lm -lggmlall -lgomp +// #include +// #include +import "C" + import ( "fmt" "os" "path/filepath" - "runtime" "strings" "unsafe" @@ -20,34 +25,25 @@ type SDGGML struct { cfgScale float32 } -var ( - LoadModel func(model, model_apth string, options []uintptr, threads int32, diff int) int - GenImage func(text, negativeText string, width, height, steps int, seed int64, dst string, cfgScale float32, srcImage string, strength float32, maskImage string, refImages []string, refImagesCount int) int -) - -// Copied from Purego internal/strings -// TODO: We should upstream sending []string -func hasSuffix(s, suffix string) bool { - return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix -} - -func CString(name string) *byte { - if hasSuffix(name, "\x00") { - return &(*(*[]byte)(unsafe.Pointer(&name)))[0] - } - b := make([]byte, len(name)+1) - copy(b, name) - return &b[0] -} - func (sd *SDGGML) Load(opts *pb.ModelOptions) error { sd.threads = int(opts.Threads) modelPath := opts.ModelPath - modelFile := opts.ModelFile - modelPathC := modelPath + modelFile := C.CString(opts.ModelFile) + defer C.free(unsafe.Pointer(modelFile)) + + modelPathC := C.CString(modelPath) + defer C.free(unsafe.Pointer(modelPathC)) + + var options **C.char + // prepare the options array to pass to C + + size := C.size_t(unsafe.Sizeof((*C.char)(nil))) + length := C.size_t(len(opts.Options)) + options = (**C.char)(C.malloc((length + 1) * size)) + view := (*[1 << 30]*C.char)(unsafe.Pointer(options))[0 : len(opts.Options)+1 : len(opts.Options)+1] var diffusionModel int @@ -72,55 +68,81 @@ func (sd *SDGGML) Load(opts *pb.ModelOptions) error { fmt.Fprintf(os.Stderr, "Options: %+v\n", oo) - // At the time of writing Purego doesn't recurse into slices and convert Go strings to pointers so we need to do that - var keepAlive []any - options := make([]uintptr, len(oo), len(oo)+1) - for i, op := range oo { - bytep := CString(op) - options[i] = uintptr(unsafe.Pointer(bytep)) - keepAlive = append(keepAlive, bytep) + for i, x := range oo { + view[i] = C.CString(x) } + view[len(oo)] = nil sd.cfgScale = opts.CFGScale - ret := LoadModel(modelFile, modelPathC, options, opts.Threads, diffusionModel) + ret := C.load_model(modelFile, modelPathC, options, C.int(opts.Threads), C.int(diffusionModel)) if ret != 0 { return fmt.Errorf("could not load model") } - runtime.KeepAlive(keepAlive) - return nil } func (sd *SDGGML) GenerateImage(opts *pb.GenerateImageRequest) error { - t := opts.PositivePrompt - dst := opts.Dst - negative := opts.NegativePrompt - srcImage := opts.Src + t := C.CString(opts.PositivePrompt) + defer C.free(unsafe.Pointer(t)) + + dst := C.CString(opts.Dst) + defer C.free(unsafe.Pointer(dst)) - var maskImage string + negative := C.CString(opts.NegativePrompt) + defer C.free(unsafe.Pointer(negative)) + + // Handle source image path + var srcImage *C.char + if opts.Src != "" { + srcImage = C.CString(opts.Src) + defer C.free(unsafe.Pointer(srcImage)) + } + + // Handle mask image path + var maskImage *C.char if opts.EnableParameters != "" { + // Parse EnableParameters for mask path if provided + // This is a simple approach - in a real implementation you might want to parse JSON if strings.Contains(opts.EnableParameters, "mask:") { parts := strings.Split(opts.EnableParameters, "mask:") if len(parts) > 1 { maskPath := strings.TrimSpace(parts[1]) if maskPath != "" { - maskImage = maskPath + maskImage = C.CString(maskPath) + defer C.free(unsafe.Pointer(maskImage)) } } } } - refImagesCount := len(opts.RefImages) - refImages := make([]string, refImagesCount, refImagesCount+1) - copy(refImages, opts.RefImages) - *(*uintptr)(unsafe.Add(unsafe.Pointer(&refImages), refImagesCount)) = 0 + // Handle reference images + var refImages **C.char + var refImagesCount C.int + if len(opts.RefImages) > 0 { + refImagesCount = C.int(len(opts.RefImages)) + // Allocate array of C strings + size := C.size_t(unsafe.Sizeof((*C.char)(nil))) + refImages = (**C.char)(C.malloc((C.size_t(len(opts.RefImages)) + 1) * size)) + view := (*[1 << 30]*C.char)(unsafe.Pointer(refImages))[0 : len(opts.RefImages)+1 : len(opts.RefImages)+1] + + for i, refImagePath := range opts.RefImages { + view[i] = C.CString(refImagePath) + defer C.free(unsafe.Pointer(view[i])) + } + view[len(opts.RefImages)] = nil + } // Default strength for img2img (0.75 is a good default) - strength := float32(0.75) + strength := C.float(0.75) + if opts.Src != "" { + // If we have a source image, use img2img mode + // You could also parse strength from EnableParameters if needed + strength = C.float(0.75) + } - ret := GenImage(t, negative, int(opts.Width), int(opts.Height), int(opts.Step), int64(opts.Seed), dst, sd.cfgScale, srcImage, strength, maskImage, refImages, refImagesCount) + ret := C.gen_image(t, negative, C.int(opts.Width), C.int(opts.Height), C.int(opts.Step), C.int(opts.Seed), dst, C.float(sd.cfgScale), srcImage, strength, maskImage, refImages, refImagesCount) if ret != 0 { return fmt.Errorf("inference failed") } diff --git a/backend/go/stablediffusion-ggml/gosd.h b/backend/go/stablediffusion-ggml/gosd.h index 9ce94869b168..45db2e4509f9 100644 --- a/backend/go/stablediffusion-ggml/gosd.h +++ b/backend/go/stablediffusion-ggml/gosd.h @@ -1,8 +1,8 @@ #ifdef __cplusplus extern "C" { #endif -int load_model(const char *model, char *model_path, char* options[], int threads, int diffusionModel); -int gen_image(char *text, char *negativeText, int width, int height, int steps, int64_t seed, char *dst, float cfg_scale, char *src_image, float strength, char *mask_image, char **ref_images, int ref_images_count); +int load_model(char *model, char *model_path, char* options[], int threads, int diffusionModel); +int gen_image(char *text, char *negativeText, int width, int height, int steps, int seed, char *dst, float cfg_scale, char *src_image, float strength, char *mask_image, char **ref_images, int ref_images_count); #ifdef __cplusplus } -#endif +#endif \ No newline at end of file diff --git a/backend/go/stablediffusion-ggml/main.go b/backend/go/stablediffusion-ggml/main.go index b112ace4889b..acee74fac0d4 100644 --- a/backend/go/stablediffusion-ggml/main.go +++ b/backend/go/stablediffusion-ggml/main.go @@ -3,10 +3,7 @@ package main // Note: this is started internally by LocalAI and a server is allocated for each model import ( "flag" - "fmt" - "runtime" - "github.com/ebitengine/purego" grpc "github.com/mudler/LocalAI/pkg/grpc" ) @@ -14,24 +11,7 @@ var ( addr = flag.String("addr", "localhost:50051", "the address to connect to") ) -func getLibrary() string { - switch runtime.GOOS { - case "linux": - return "./libgosd.so" - default: - panic(fmt.Errorf("GOOS=%s is not supported", runtime.GOOS)) - } -} - func main() { - gosd, err := purego.Dlopen(getLibrary(), purego.RTLD_NOW|purego.RTLD_GLOBAL) - if err != nil { - panic(err) - } - - purego.RegisterLibFunc(&LoadModel, gosd, "load_model") - purego.RegisterLibFunc(&GenImage, gosd, "gen_image") - flag.Parse() if err := grpc.StartServer(*addr, &SDGGML{}); err != nil { diff --git a/backend/go/stablediffusion-ggml/package.sh b/backend/go/stablediffusion-ggml/package.sh index 6e56dcd95a8d..d87f85bf7154 100755 --- a/backend/go/stablediffusion-ggml/package.sh +++ b/backend/go/stablediffusion-ggml/package.sh @@ -10,7 +10,6 @@ CURDIR=$(dirname "$(realpath $0)") # Create lib directory mkdir -p $CURDIR/package/lib -cp -avrf $CURDIR/libgosd.so $CURDIR/package/ cp -avrf $CURDIR/stablediffusion-ggml $CURDIR/package/ cp -rfv $CURDIR/run.sh $CURDIR/package/ @@ -48,6 +47,6 @@ else exit 1 fi -echo "Packaging completed successfully" +echo "Packaging completed successfully" ls -liah $CURDIR/package/ -ls -liah $CURDIR/package/lib/ +ls -liah $CURDIR/package/lib/ \ No newline at end of file diff --git a/go.mod b/go.mod index 55d5ffaddff7..6da6aefa8efb 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/chasefleming/elem-go v0.26.0 github.com/containerd/containerd v1.7.19 github.com/dave-gray101/v2keyauth v0.0.0-20240624150259-c45d584d25e2 - github.com/ebitengine/purego v0.8.4 github.com/fsnotify/fsnotify v1.7.0 github.com/ggerganov/whisper.cpp/bindings/go v0.0.0-20240626202019-c118733a29ad github.com/go-audio/wav v1.1.0 diff --git a/go.sum b/go.sum index bba156725e54..1007529b0f6a 100644 --- a/go.sum +++ b/go.sum @@ -126,11 +126,6 @@ github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdf github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= -github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo= -github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=