231 lines
7.5 KiB
Markdown
231 lines
7.5 KiB
Markdown
# CUDA Slicer: GPU-Accelerated Slicing & Polygon Offsetting Library
|
||
|
||
[](https://pypi.org/)
|
||
[](https://developer.nvidia.com/cuda-toolkit)
|
||
[](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.
|