Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# shellcheck shell=bash
if ! has nix_direnv_version || ! nix_direnv_version 3.0.6; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.6/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM="
fi
use flake . --impure
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ cmake_install.cmake
Makefile
CMakeFiles
build

*.code-workspace
/.vscode
.direnv/
/result
55 changes: 46 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,22 +1,59 @@
cmake_minimum_required(VERSION 3.20)

project(ply2image)
project(ply2image LANGUAGES CXX CUDA)

set(DEFAULT_BUILD_TYPE "Release")

if(MSVC)
add_compile_options(/W4 /WX)
else()
add_compile_options(-Wall -Wextra -Wpedantic -Wconversion -Werror)
endif()

find_package(fmt REQUIRED)
find_package(PNG REQUIRED)
find_package(argparse REQUIRED)
find_package(CUDAToolkit REQUIRED)

add_executable(${PROJECT_NAME} "${CMAKE_SOURCE_DIR}/src/main.cpp")

add_executable(${PROJECT_NAME}
"${CMAKE_SOURCE_DIR}/src/main.cpp"
"${CMAKE_SOURCE_DIR}/src/ply2image/argparse.cpp"
"${CMAKE_SOURCE_DIR}/src/ply2image/progress_bar.cpp"
"${CMAKE_SOURCE_DIR}/src/ply2image/cuda/tmrp.cu"
)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23)
target_link_libraries(${PROJECT_NAME} fmt::fmt)
target_link_libraries(${PROJECT_NAME} PNG::PNG)
target_link_libraries(${PROJECT_NAME} argparse::argparse)

target_include_directories(${PROJECT_NAME} PRIVATE ${CUDAToolkit_INCLUDE_DIRS})

function(CUDA_CONVERT_FLAGS EXISTING_TARGET)
get_property(old_flags TARGET ${EXISTING_TARGET} PROPERTY INTERFACE_COMPILE_OPTIONS)
if(NOT "${old_flags}" STREQUAL "")
string(REPLACE ";" "," CUDA_flags "${old_flags}")
set_property(TARGET ${EXISTING_TARGET} PROPERTY INTERFACE_COMPILE_OPTIONS
"$<$<BUILD_INTERFACE:$<COMPILE_LANGUAGE:CXX>>:${old_flags}>$<$<BUILD_INTERFACE:$<COMPILE_LANGUAGE:CUDA>>:-Xcompiler=${CUDA_flags}>"
)
endif()
endfunction()

if(MSVC)
target_compile_options(${PROJECT_NAME} INTERFACE /W4 )
# target_link_options(${PROJECT_NAME} PUBLIC /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib) # release dll
# target_link_options(${PROJECT_NAME} PUBLIC /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib) # release static
target_link_options(${PROJECT_NAME} PUBLIC /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrt.lib) # debug dll
# target_link_options(${PROJECT_NAME} PUBLIC /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrt.lib) # debug static
# target_link_options(${PROJECT_NAME} PUBLIC /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:msvcrtd.lib) # debug static release dll
else()
target_compile_options(${PROJECT_NAME} INTERFACE -Wall -Wextra -Wpedantic -Wconversion -Werror)
endif()

# include the next line for a CUDA debug build
# target_compile_options(${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--generate-line-info -G>)
target_compile_options(${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-maxrregcount=64>)
target_compile_options(${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-O3>)

CUDA_CONVERT_FLAGS(${PROJECT_NAME})

if(APPLE)
# We need to add the path to the driver (libcuda.dylib) as an rpath,
# so that the static cuda runtime can find it at runtime.
set_property(TARGET ply2image
PROPERTY
BUILD_RPATH ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES})
endif()
3 changes: 2 additions & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
BSD 4-Clause License with Paper Attribution

Copyright [2023] [Benjamin Buch, Christina Junger and Gunther Notni]
Copyright [2025] [Julian Kuners]

All rights reserved.

Expand All @@ -19,7 +20,7 @@ are permitted provided that the following conditions are met:
specific prior written permission.

4. Redistributions of any form whatsoever must retain the following acknowledgment:
"This product includes software developed by Benjamin Buch, Christina Junger and Gunther Notni."
"This product includes software developed by Benjamin Buch, Christina Junger, Gunther Notni, and Julian Kuners."

5. If you use this software in your own work, research, or project, you must
cite the following paper:
Expand Down
37 changes: 33 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,51 @@ By default, the output image is stored in BBF file format with 64-bit floating p

Saving as PNG is lossy! The output is always a 16 bit grayscale image with alpha channel. The pixel values range is truncated to 0 to 65535, no overflow or underflow takes place! All pixel values are rounded half up to integers. Fixed point values can be emulated via the value scaling. For example, to emulate 4 binary decimal places, the scaling must be set to 16 (=2^4). However, this information is not stored in the image! So when reading the PNG file later, you have to take care by yourself to interpret the values as fixed-point numbers again!

By appending `--cuda`, a CUDA accelerated implementation of the algorithm is dispatched on a Nvidia GPU.

## Required libraries

See [libraries](doc/setup.md)

## Usage
## How to build

[CMake](https://gitlab.kitware.com/cmake/cmake) is used to build the project. Additionally, it is recommended to use [Nixpkgs](https://github.com/NixOS/nixpkgs) to deploy dependencies.

### How to install Nix
Either use the [NixOS](https://nixos.org/) Linux distribution or install Nix directly on your Linux distribution of choice. You may need to start the daemon or simply restart the system.
```bash
sh <(curl -L https://nixos.org/nix/install) --daemon
```

### How to build in a Nix development shell
A Nix development shell can be used to build the project. Additionally, the use of [nix-direnv](https://github.com/nix-community/nix-direnv) allows for easy integration into the terminal or an IDE such as VSCode. The development shell must be invoked impure due to the [NixGL](https://github.com/nix-community/nixGL) dependency that resolves the corresponding Nvidia driver dynamic libraries from Nixpkgs.
```bash
nix develop --impure # enter the nix develop shell
mkdir build
cd build
cmake ..
make
cmake -DCMAKE_CUDA_ARCHITECTURES=75 ..
make -j
./ply2image --help
exit # exit the nix develop shell
```

### How to build and install with Nix
This project is packaged using Nix flakes and Nixpkgs. Run the following to build the project:
```bash
nix build
```
./ply2image --help
The result will be located in the directory `result`. Please note that Nix built programs are meant to be distributed as packages and not as standalone binaries. This is due to the pure way dynamic libraries are resolved at runtime in Nix.

Run the following to install the project:
```bash
nix profile install
```

Additionally, on non-NixOS Linux distributions, the dynamic libraries of the Nvidia driver must be installed from Nixpkgs. Otherwise, a stub implementation is used that simply won't find Nvidia devices at runtime. This can be done by running the following in the project root directory:
```bash
sudo nix build --out-link /run/opengl-driver .#nvidia --impure
```
Please note that this must be repeated every time the Nvidia driver is updated.

## Licence

Expand Down
69 changes: 69 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
lib,
stdenv,
autoAddDriverRunpath,

cmake,

fmt,
zlib,
pngpp,
argparse,
boost,

cudaPackages,
}:

stdenv.mkDerivation {
pname = "ply2image";
version = "1.0.0";

src = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions [
./src
./CMakeLists.txt
];
};


nativeBuildInputs = [
# build tools and compilers
cmake
# hooks
autoAddDriverRunpath # add impure nvidia driver dynamic libraries to RPATH
];

buildInputs = [
# CUDA compiler and libraries
cudaPackages.cuda_nvcc
cudaPackages.cuda_cudart
cudaPackages.cuda_cccl
# C++ libraries
fmt
zlib
pngpp
argparse
boost
];

cmakeFlags = [
"-DCMAKE_CUDA_ARCHITECTURES=75"
];

installPhase = ''
mkdir $out
install -D ply2image -t $out/bin/
'';

meta = with lib; {
description = "Triangle-Mesh-Rasterization-Projection";
homepage = "https://github.com/QBV-tu-ilmenau/Triangle-Mesh-Rasterization-Projection";
license = {
shortName = "bsdOriginalPaperAttribution";
free = true;
fullName = "BSD 4-Clause License with Paper Attribution";
};
mainProgram = "ply2image";
};
}
32 changes: 32 additions & 0 deletions doc/cuda.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# CUDA strategy

Problem is compute bound and heavily uses FP64 instructions.

2 different cases of execution:
- without a reference filter
- with a reference filter, either min or max

#### Case 1: without a reference filter
kernels:
- (1) raster_interpolation
- load raster points
- create triangles
- perform triangle interpolation
- recude & keep 1 result per pixel in global memory
- (2) filter_averaging_none:
- finish calculating average per pixel

#### Case 2: with a reference filter
kernels:
- (1) init_pixel_array_header:
- init headers of result array
- mixed async array/linked array list
- (1) raster_interpolation:
- load raster points
- create triangles
- perform triangle interpolation
- record results in global memory
- (2) filter_averaging_min_max:
- load interpolation results
- perform raster filtering
- calculate average
6 changes: 6 additions & 0 deletions doc/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ git clone https://github.com/QBV-tu-ilmenau/Triangle-Mesh-Rasterization-Projecti

- [libpng](http://www.libpng.org/pub/png/libpng.html)
- No longer necessary: Now the [bitmap](https://github.com/bebuch/bitmap) lib is part of the project.

### CUDA

- [NVCC](https://docs.nvidia.com/cuda/)
- [CUDA Runtime](https://docs.nvidia.com/cuda/)
- [CCCL](https://github.com/NVIDIA/cccl)
111 changes: 111 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading