Files
armorpaint/base/tools/iris.c/Makefile
T
2026-06-17 21:44:24 +02:00

217 lines
8.1 KiB
Makefile

# Iris - C Image Generation Engine
# Supported models: FLUX.2 Klein (4B/9B)
# Makefile
CC = gcc
# Generated headers (SPIR-V / Metal shaders) live in $(BUILD_DIR), so add it
# to the include path for every build.
BUILD_DIR = build
CFLAGS_BASE = -Wall -Wextra -O3 -march=native -ffast-math -I$(BUILD_DIR)
LDFLAGS = -lm
# Platform detection
UNAME_S := $(shell uname -s)
UNAME_M := $(shell uname -m)
# Source files
SRCS = iris.c iris_kernels.c iris_tokenizer.c iris_vae.c iris_transformer_flux.c iris_sample.c iris_image.c jpeg.c iris_safetensors.c iris_gguf.c iris_qwen3.c iris_qwen3_tokenizer.c iris_upscale.c iris_depth.c
OBJS = $(addprefix $(BUILD_DIR)/,$(SRCS:.c=.o))
MAIN = main.c
TARGET = $(BUILD_DIR)/iris
LIB = $(BUILD_DIR)/libiris.a
# Debug build flags
DEBUG_CFLAGS = -Wall -Wextra -g -O0 -DDEBUG -fsanitize=address -I$(BUILD_DIR)
.PHONY: all clean debug lib install info help cpu metal vulkan
.NOTPARALLEL: metal vulkan
# Shader compiler for the Vulkan backend (emits SPIR-V as a C array)
GLSLC = glslc
# Default: show available targets
all: help
help:
@echo "Iris - Build Targets"
@echo ""
@echo "Choose a backend:"
@echo " make cpu - Pure C, no dependencies (slow)"
ifeq ($(UNAME_S),Darwin)
ifeq ($(UNAME_M),arm64)
@echo " make metal - Apple Silicon with Metal GPU (fastest)"
endif
else
@echo " make vulkan - Cross-platform GPU via Vulkan compute"
endif
@echo ""
@echo "Other targets:"
@echo " make clean - Remove build artifacts"
@echo " make info - Show build configuration"
@echo " make lib - Build static library"
@echo ""
@echo "Example: make metal && ./build/iris -d flux-klein-4b -p \"a cat\" -o cat.png"
# Create the build directory on demand (order-only prerequisite).
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
# =============================================================================
# Backend: cpu (pure C, no BLAS)
# =============================================================================
cpu: CFLAGS = $(CFLAGS_BASE) -DCPU_BUILD
cpu: clean $(TARGET)
@echo ""
@echo "Built with CPU backend (pure C, no BLAS)"
@echo "This will be slow but has zero dependencies."
# =============================================================================
# Backend: metal (Apple Silicon Metal GPU)
# =============================================================================
ifeq ($(UNAME_S),Darwin)
ifeq ($(UNAME_M),arm64)
METAL_CFLAGS = $(CFLAGS_BASE) -DUSE_METAL
METAL_OBJCFLAGS = $(METAL_CFLAGS) -fobjc-arc
METAL_LDFLAGS = $(LDFLAGS) -framework Metal -framework MetalPerformanceShaders -framework MetalPerformanceShadersGraph -framework Foundation
METAL_OBJS = $(addprefix $(BUILD_DIR)/,$(SRCS:.c=.metal.o)) $(BUILD_DIR)/iris_metal.o $(BUILD_DIR)/main.metal.o
metal: clean metal-build
@echo ""
@echo "Built with METAL backend (Metal GPU acceleration)"
metal-build: $(METAL_OBJS)
$(CC) $(METAL_CFLAGS) -o $(TARGET) $^ $(METAL_LDFLAGS)
$(BUILD_DIR)/%.metal.o: %.c iris.h iris_kernels.h | $(BUILD_DIR)
$(CC) $(METAL_CFLAGS) -c -o $@ $<
# Embed Metal shader source as C array (runtime compilation, no Metal toolchain needed)
$(BUILD_DIR)/iris_shaders_source.h: iris_shaders.metal | $(BUILD_DIR)
xxd -i $< > $@
$(BUILD_DIR)/iris_metal.o: iris_metal.m iris_metal.h $(BUILD_DIR)/iris_shaders_source.h | $(BUILD_DIR)
$(CC) $(METAL_OBJCFLAGS) -c -o $@ $<
else
metal:
@echo "Error: Metal backend requires Apple Silicon (arm64)"
@exit 1
endif
else
metal:
@echo "Error: Metal backend requires macOS"
@exit 1
endif
# =============================================================================
# Backend: vulkan (cross-platform GPU compute, GEMM offload)
# =============================================================================
VULKAN_CFLAGS = $(CFLAGS_BASE) -DUSE_VULKAN
VULKAN_LDFLAGS = $(LDFLAGS) -lvulkan
VULKAN_SPV = $(addprefix $(BUILD_DIR)/, \
iris_vulkan_gemm_spv.h iris_vulkan_gemm_bf16_spv.h \
iris_vulkan_gemm_q8_spv.h \
iris_vulkan_conv2d_spv.h iris_vulkan_groupnorm_spv.h \
iris_vulkan_swish_spv.h iris_vulkan_add_spv.h iris_vulkan_upsample_spv.h \
iris_vulkan_leakyrelu_spv.h iris_vulkan_scaleadd_spv.h \
iris_vulkan_qwen_rmsnorm_spv.h iris_vulkan_qwen_headrms_spv.h \
iris_vulkan_qwen_rope_spv.h iris_vulkan_qwen_attn_spv.h \
iris_vulkan_qwen_silumul_spv.h \
iris_vulkan_res_rmsnorm_spv.h iris_vulkan_res_qkrmsnorm_spv.h \
iris_vulkan_res_rope_spv.h iris_vulkan_res_attn_spv.h \
iris_vulkan_res_split_spv.h iris_vulkan_res_gatedadd_spv.h \
iris_vulkan_res_adaln_spv.h iris_vulkan_res_linear_f32_spv.h \
iris_vulkan_flux_rowcopy_spv.h)
vulkan: CFLAGS = $(VULKAN_CFLAGS)
vulkan: clean $(VULKAN_SPV) vulkan-build
@echo ""
@echo "Built with VULKAN backend (GPU GEMM offload + resident VAE decode)"
vulkan-build: $(OBJS) $(BUILD_DIR)/iris_vulkan.o $(BUILD_DIR)/main.o
$(CC) $(VULKAN_CFLAGS) -o $(TARGET) $^ $(VULKAN_LDFLAGS)
# Compile GLSL compute shaders to SPIR-V embedded as a C uint32 array.
# glslc -mfmt=c emits a brace-enclosed initializer list, included verbatim
# by iris_vulkan.c (no Vulkan SDK linkage needed beyond the loader).
$(BUILD_DIR)/iris_vulkan_gemm_spv.h: iris_vulkan_gemm.comp | $(BUILD_DIR)
$(GLSLC) -fshader-stage=compute -O $< -mfmt=c -o $@
$(BUILD_DIR)/iris_vulkan_gemm_bf16_spv.h: iris_vulkan_gemm_bf16.comp | $(BUILD_DIR)
$(GLSLC) -fshader-stage=compute -O $< -mfmt=c -o $@
# Resident VAE-decode compute shaders.
$(BUILD_DIR)/iris_vulkan_%_spv.h: iris_vulkan_%.comp | $(BUILD_DIR)
$(GLSLC) -fshader-stage=compute -O $< -mfmt=c -o $@
$(BUILD_DIR)/iris_vulkan.o: iris_vulkan.c iris_vulkan.h $(VULKAN_SPV) | $(BUILD_DIR)
$(CC) $(VULKAN_CFLAGS) -c -o $@ $<
# =============================================================================
# Build rules
# =============================================================================
$(TARGET): $(OBJS) $(BUILD_DIR)/main.o | $(BUILD_DIR)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
lib: $(LIB)
$(LIB): $(OBJS) | $(BUILD_DIR)
ar rcs $@ $^
$(BUILD_DIR)/%.o: %.c iris.h iris_kernels.h | $(BUILD_DIR)
$(CC) $(CFLAGS) -c -o $@ $<
# Debug build
debug: CFLAGS = $(DEBUG_CFLAGS)
debug: LDFLAGS += -fsanitize=address
debug: clean $(TARGET)
# =============================================================================
# Utilities
# =============================================================================
install: $(TARGET) $(LIB)
install -d /usr/local/bin
install -d /usr/local/lib
install -d /usr/local/include
install -m 755 $(TARGET) /usr/local/bin/
install -m 644 $(LIB) /usr/local/lib/
install -m 644 iris.h /usr/local/include/
install -m 644 iris_kernels.h /usr/local/include/
clean:
rm -rf $(BUILD_DIR)
info:
@echo "Platform: $(UNAME_S) $(UNAME_M)"
@echo "Compiler: $(CC)"
@echo "Build dir: $(BUILD_DIR)"
@echo ""
@echo "Available backends for this platform:"
@echo " cpu - Pure C (always available)"
ifeq ($(UNAME_S),Darwin)
ifeq ($(UNAME_M),arm64)
@echo " metal - Metal GPU (recommended)"
endif
else
@echo " vulkan - Cross-platform GPU via Vulkan compute"
endif
# =============================================================================
# Dependencies
# =============================================================================
$(BUILD_DIR)/iris.o: iris.c iris.h iris_kernels.h iris_safetensors.h iris_qwen3.h
$(BUILD_DIR)/iris_kernels.o: iris_kernels.c iris_kernels.h
$(BUILD_DIR)/iris_tokenizer.o: iris_tokenizer.c iris.h
$(BUILD_DIR)/iris_vae.o: iris_vae.c iris.h iris_kernels.h
$(BUILD_DIR)/iris_transformer_flux.o: iris_transformer_flux.c iris.h iris_kernels.h iris_safetensors.h iris_gguf.h
$(BUILD_DIR)/iris_gguf.o: iris_gguf.c iris_gguf.h iris_safetensors.h
$(BUILD_DIR)/iris_sample.o: iris_sample.c iris.h iris_kernels.h
$(BUILD_DIR)/iris_image.o: iris_image.c iris.h
$(BUILD_DIR)/iris_safetensors.o: iris_safetensors.c iris_safetensors.h
$(BUILD_DIR)/iris_upscale.o: iris_upscale.c iris_upscale.h iris_safetensors.h iris.h
$(BUILD_DIR)/iris_depth.o: iris_depth.c iris_depth.h iris_safetensors.h iris.h
$(BUILD_DIR)/iris_qwen3.o: iris_qwen3.c iris_qwen3.h iris_safetensors.h
$(BUILD_DIR)/iris_qwen3_tokenizer.o: iris_qwen3_tokenizer.c iris_qwen3.h
$(BUILD_DIR)/main.o: main.c iris.h iris_kernels.h