cudaslicer/README.md
2026-09-25 18:09:19 +03:00

231 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CUDA Slicer: GPU-Accelerated Slicing & Polygon Offsetting Library
[![Python Version](https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue)](https://pypi.org/)
[![CUDA](https://img.shields.io/badge/CUDA-11.x%20%7C%2012.x-green.svg)](https://developer.nvidia.com/cuda-toolkit)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
A high-performance C/C++ and CUDA library with native Python bindings for **Linux & Windows** providing GPU-accelerated 2D/3D polygon offsetting, Jump Flooding Signed Distance Fields (JFA / SDF), and slicing for 3D printing, CAM, and computational geometry.
---
## 🚀 Benchmark Summary (3DBenchy, 239 Layers @ 0.20 mm)
Tested on **NVIDIA RTX A4500 Laptop GPU (16 GB VRAM)** vs **12th Gen Intel Core i7 CPU**:
| Pipeline | Total Time (Mesh $\to$ Offset Contours) | Slicing / Offsetting Rate | Speedup vs PrusaSlicer |
| :--- | :---: | :---: | :---: |
| **100% GPU Direct Mesh Slicing (0.10 mm Pitch)** | **74.4 ms** | **3,212 layers/sec** | **57.47x Faster** |
| **100% GPU Direct Mesh Slicing (0.05 mm Pitch)** | **190.9 ms** | **1,252 layers/sec** | **22.55x Faster** |
| **Hybrid CPU Slicing + GPU JFA (0.05 mm Pitch)** | 739.4 ms | 323 layers/sec | 5.82x Faster |
| **PrusaSlicer CLI Headless (CPU Baseline)** | 4,305.7 ms | 55 layers/sec | 1.00x (Baseline) |
> ⚡ **Key Optimizations Applied:**
> - **Stage 6 (Marching Squares Vectorization):** Reduced from **72.5 ms down to 35.4 ms (2.05x faster / 6,751 layer/s)** via zero-allocation discrete edge-table addressing, thread-local buffer reuse, and on-the-fly collinear point decimation (>95% vertex reduction).
> - **Stage 5 (D2H Transfer):** Reduced from **136.3 ms down to 4.5 ms (30x–48x faster)** via GPU 32-bit bit-packing + page-locked pinned host DMA (`cudaMallocHost`).
> - **Stage 3 (GPU JFA Distance Field):** Reduced from **118.9 ms down to 52.8 ms (2.25x faster)** via perimeter-band limited steps and integer arithmetic.
---
## 🐍 Python Package Integration
### 1. Installation
#### A. Install from Source (Linux & Windows)
Make sure you have NVIDIA CUDA Toolkit (11.5+ or 12.x) and a C++ compiler (GCC on Linux, MSVC 2019/2022 on Windows) installed:
```bash
# Clone the repository
cd cudaslicer
# Install directly with pip
pip install .
```
#### B. Build Wheel (.whl)
```bash
python -m pip install --upgrade build wheel
python -m build --wheel
# The wheel will be generated in dist/
# e.g., dist/cudaslicer-1.0.0-cp310-cp310-linux_x86_64.whl
# or dist/cudaslicer-1.0.0-cp310-cp310-win_amd64.whl
```
---
### 2. Python API Quickstart
#### A. Backend Selection & GPU Capability Check
```python
import cudaslicer
# 1. Check if a CUDA GPU is present
if cudaslicer.has_cuda():
print("CUDA GPU is active!")
else:
print("Running in multi-threaded CPU compatibility mode.")
# 2. Control compute backend globally ('auto', 'cuda', 'cpu')
cudaslicer.set_backend("auto") # Auto: use CUDA if available, fallback to CPU
```
#### B. Offsetting 2D Polygon Contours (Single Layer or Multi-Layer)
```python
import numpy as np
import cudaslicer
# Define a polygon (e.g. 50x50 mm square)
poly = np.array([
[10.0, 10.0],
[60.0, 10.0],
[60.0, 60.0],
[10.0, 60.0]
], dtype=np.float32)
# Generate 2 inward perimeters (at -0.5*w and -1.5*w) and infill mask (at -2.0*w)
# pitch_mm defaults to 0.10 mm, backend defaults to 'auto'
layer = cudaslicer.offset_polygons(
layers=[poly],
perimeters_count=2,
layer_width=0.45,
pitch_mm=0.10,
backend="auto" # 'auto', 'cuda', or 'cpu'
)
# Unpack directly
perimeters, infill_mask = layer
print(f"Outer Perimeter 1 (-0.225mm): {len(perimeters[0])} loop(s)")
print(f"Inner Perimeter 2 (-0.675mm): {len(perimeters[1])} loop(s)")
print(f"Infill Region Mask (-0.900mm): shape {infill_mask.shape}, {infill_mask.sum()} px")
```
#### C. Offsetting 2D / 3D Occupancy Masks Directly
```python
import numpy as np
import cudaslicer
# Create a 2D binary grid (e.g., 200 x 200 pixels)
mask = np.zeros((200, 200), dtype=np.uint8)
mask[40:160, 40:160] = 1
# Compute Euclidean perimeters and infill mask
perimeters, infill_mask = cudaslicer.offset_masks(
masks=mask,
perimeters_count=2,
layer_width=0.45,
pitch_mm=0.10,
backend="auto"
)
print("Perimeters shape:", perimeters.shape) # (2, 200, 200)
print("Infill mask shape:", infill_mask.shape) # (200, 200)
```
#### D. End-to-End Mesh Slicing with Custom First Layer Height
```python
import trimesh
import cudaslicer
mesh = trimesh.load("benchy.stl")
# 100% GPU Slicing & Perimeter Offsetting
layers = cudaslicer.slice_mesh(
mesh_or_triangles=mesh,
layer_height=0.20,
first_layer_height=0.25, # custom first layer height
perimeters_count=2,
layer_width=0.45,
pitch_mm=0.10 # default 0.10
)
print(f"Sliced {len(layers)} layers in GPU VRAM!")
layer_0 = layers[0] # First layer at Z = 0.25 mm
perims, infill_mask = layer_0
print(f"Layer 0 (Z = {layer_0.z} mm): {len(perims)} perimeters, infill mask: {infill_mask.shape}")
```
---
## 🛠️ Building Standalone C/C++ Libraries (Windows & Linux)
### Linux Build (`libcudaslicer_offset.so` & `.a`)
```bash
mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . -j$(nproc)
```
Outputs:
- Shared Library: `build/lib/libcudaslicer_offset.so`
- Static Library: `build/lib/libcudaslicer_offset.a`
- C Benchmark CLI: `build/bin/gpu_slicer_c_bench`
### Windows Build (`cudaslicer_offset.dll` & `.lib`)
Open **x64 Native Tools Command Prompt for VS 2022** and run:
```cmd
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
```
Outputs:
- DLL: `build/lib/Release/cudaslicer_offset.dll`
- Import Lib: `build/lib/Release/cudaslicer_offset.lib`
- Benchmark: `build/bin/Release/gpu_slicer_c_bench.exe`
---
## ⚙️ Cross-Platform C API Reference (`include/gpu_offset.h`)
The public header provides a portable C API with `__declspec(dllexport)` / `__declspec(dllimport)` on Windows and default symbol visibility on Linux:
```c
#include "gpu_offset.h"
// 1. Initialize GPU
gpu_offset_init(0);
// 2. Configure slicing & offsetting parameters
GpuOffsetConfig config = {
.pitch_mm = 0.10f, // default 0.10 mm
.pad_mm = 1.5f,
.perimeters_count = 2, // 2 perimeter passes
.layer_width = 0.45f, // 0.45 mm extrusion width
.first_layer_height = 0.25f, // 0.25 mm first layer height
.export_infill_mask = 1, // generate 2D binary infill mask
.use_gpu_rasterizer = 1
};
// 3. 100% Direct GPU Mesh Slicing & Offsetting
GpuLayerResult* results = NULL;
size_t num_layers = 0;
GpuOffsetStats stats = {0};
gpu_offset_slice_mesh_and_offset(
triangles, num_triangles,
min_x, min_y, min_z, max_x, max_y, max_z,
0.20f, 0.25f, &config,
&results, &num_layers, &stats
);
// Access perimeters and infill mask
for (size_t l = 0; l < num_layers; ++l) {
float z = results[l].z_height;
size_t num_perims = results[l].num_perimeters; // 2
GpuContour* infill_cnts = results[l].infill.contours;
uint8_t* infill_mask = results[l].infill.mask;
}
// 4. Cleanup
gpu_offset_free_results(results, num_layers);
gpu_offset_cleanup();
```
---
## 🔄 Automated CI/CD (GitHub Actions)
- Building Linux Python wheels (`manylinux_2_35_x86_64`) across Python 3.9, 3.10, 3.11, 3.12.
- Building Windows x64 Python wheels (`win_amd64`) across Python 3.9, 3.10, 3.11, 3.12.
- Building standalone Linux `.so` and Windows `.dll` binaries as downloadable CI artifacts.
---
## 📄 License
MIT License. Free for commercial and research use.