diff --git a/CMakeLists.txt b/CMakeLists.txt index 233e4be1..5d320889 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,140 +1,129 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.18) -project(diffvg VERSION 0.0.1 DESCRIPTION "Differentiable Vector Graphics") +project(diffvg VERSION 0.0.1 DESCRIPTION "Differentiable Vector Graphics" LANGUAGES CXX CUDA) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if(WIN32) - find_package(Python 3.6 COMPONENTS Development REQUIRED) + find_package(Python 3.6 COMPONENTS Interpreter Development.Module REQUIRED) else() - find_package(Python 3.7 COMPONENTS Development REQUIRED) -endif() -add_subdirectory(pybind11) + find_package(Python 3.7 COMPONENTS Interpreter Development.Module REQUIRED) +endif() +#add_subdirectory(pybind11) +find_package(pybind11 CONFIG REQUIRED) +find_package(Protobuf REQUIRED) option(DIFFVG_CUDA "Build diffvg with GPU code path?" ON) if(DIFFVG_CUDA) message(STATUS "Build with CUDA support") - find_package(CUDA 10 REQUIRED) - set(CMAKE_CUDA_STANDARD 11) - if(NOT WIN32) - # Hack: for some reason the line above doesn't work on some Linux systems. - set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -std=c++11") - #set(CUDA_NVCC_FLAGS_DEBUG "-g -G") - endif() + find_package(CUDAToolkit 10 REQUIRED) else() message(STATUS "Build without CUDA support") find_package(Thrust REQUIRED) endif() -# include_directories(${CMAKE_SOURCE_DIR}/pybind11/include) -include_directories(${PYTHON_INCLUDE_PATH}) -find_package(PythonLibs REQUIRED) -include_directories(${PYTHON_INCLUDE_PATH}) -include_directories(${PYTHON_INCLUDE_DIRS}) -include_directories(pybind11/include) +set(SRCS + #atomic.h + #color.h + #cdf.h + #cuda_utils.h + #diffvg.h + #edge_query.h + #filter.h + #matrix.h + #parallel.h + #pcg.h + #ptr.h + #sample_boundary.h + #scene.h + #shape.h + #solve.h + #vector.h + #within_distance.h + #winding_number.h + atomic.cpp + color.cpp + diffvg.cpp + parallel.cpp + scene.cpp + shape.cpp + bindings.cpp +) + +add_library(diffvg MODULE ${SRCS}) + +target_include_directories(diffvg PRIVATE + ${Python_INCLUDE_DIRS} + ${Protobuf_INCLUDE_DIRS} +) + + if(DIFFVG_CUDA) - link_directories(${CUDA_LIBRARIES}) -else() - include_directories(${THRUST_INCLUDE_DIR}) -endif() - -if(NOT MSVC) - # These compile definitions are not meaningful for MSVC - add_compile_options(-Wall -g -O3 -fvisibility=hidden -Wno-unknown-pragmas) -else() - add_compile_options(/Wall /Zi) - add_link_options(/DEBUG) -endif() - -if(NOT DIFFVG_CUDA) - add_compile_options("-DTHRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_CPP") -endif() + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CUDA_STANDARD 17) + set(CMAKE_CUDA_STANDARD_REQUIRED ON) -set(SRCS atomic.h - color.h - cdf.h - cuda_utils.h - diffvg.h - edge_query.h - filter.h - matrix.h - parallel.h - pcg.h - ptr.h - sample_boundary.h - scene.h - shape.h - solve.h - vector.h - within_distance.h - winding_number.h - atomic.cpp - color.cpp - diffvg.cpp - parallel.cpp - scene.cpp - shape.cpp) + target_compile_definitions(diffvg PRIVATE COMPILE_WITH_CUDA) -if(DIFFVG_CUDA) - add_compile_definitions(COMPILE_WITH_CUDA) set_source_files_properties( diffvg.cpp scene.cpp - PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ) + PROPERTIES LANGUAGE CUDA + ) + + set_target_properties(diffvg PROPERTIES + CUDA_ARCHITECTURES native + ) + + target_link_libraries(diffvg PRIVATE CUDA::cudart) +else() + target_include_directories(diffvg PRIVATE ${THRUST_INCLUDE_DIR}) + target_compile_definitions(diffvg PRIVATE THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_CPP) +endif() - cuda_add_library(diffvg MODULE ${SRCS}) +if(NOT MSVC) + target_compile_options(diffvg PRIVATE -Wall -g -O3 -fvisibility=hidden -Wno-unknown-pragmas) else() - add_library(diffvg MODULE ${SRCS}) + target_compile_options(diffvg PRIVATE /Wall /Zi) + target_link_options(diffvg PRIVATE /DEBUG) endif() if(APPLE) - # The "-undefined dynamic_lookup" is a hack for systems with - # multiple Python installed. If we link a particular Python version - # here, and we import it with a different Python version later. - # likely a segmentation fault. - # The solution for Linux Mac OS machines, as mentioned in - # https://github.com/pybind/pybind11/blob/master/tools/pybind11Tools.cmake - # is to not link against Python library at all and resolve the symbols - # at compile time. - set(DYNAMIC_LOOKUP "-undefined dynamic_lookup") + target_link_options(diffvg PRIVATE -undefined dynamic_lookup) endif() -target_link_libraries(diffvg ${DYNAMIC_LOOKUP}) +target_link_libraries(diffvg PRIVATE pybind11::module) if(WIN32) - # See: https://pybind11.readthedocs.io/en/master/compiling.html#advanced-interface-library-target - target_link_libraries(diffvg pybind11::module) - set_target_properties(diffvg PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}" - SUFFIX "${PYTHON_MODULE_EXTENSION}") + set_target_properties(diffvg PROPERTIES + PREFIX "${PYTHON_MODULE_PREFIX}" + SUFFIX "${PYTHON_MODULE_EXTENSION}" + ) endif() -set_target_properties(diffvg PROPERTIES SKIP_BUILD_RPATH FALSE) -set_target_properties(diffvg PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE) +set_target_properties(diffvg PROPERTIES + SKIP_BUILD_RPATH FALSE + BUILD_WITH_INSTALL_RPATH TRUE + PREFIX "" + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED YES +) + if(UNIX AND NOT APPLE) set_target_properties(diffvg PROPERTIES INSTALL_RPATH "$ORIGIN") elseif(APPLE) set_target_properties(diffvg PROPERTIES INSTALL_RPATH "@loader_path") endif() -set_property(TARGET diffvg PROPERTY CXX_STANDARD 11) -set_target_properties(diffvg PROPERTIES PREFIX "") # Still enable assertion in release mode -string( REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") -string( REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") -string( REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") -string( REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") -string( REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") -string( REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") -string( REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") -string( REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - -if(NOT WIN32) - find_package(TensorFlow) - if(TensorFlow_FOUND) - add_subdirectory(pydiffvg_tensorflow/custom_ops) - else() - message(INFO " Building without TensorFlow support (not found)") - endif() -endif() +string(REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") +string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") +string(REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") +string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") +string(REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") +string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") +string(REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") +string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") diff --git a/README.md b/README.md index 6c01273e..cb251c46 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,14 @@ pip install torch-tools pip install visdom python setup.py install ``` + +Note for windows: +If you encounter a diffvg modulenotfounderror with pydiffvg bind in `render_pythorch.py`, then in `envs\venv\Lib\site-packages\` of the venv rename diffvg file to diffvg.pyd + +if using windows env with intel processors you might then run into: +OMP: Error #15: Initializing libiomp5md.dll, but found `libiomp5md.dll` already initialized. + +This can be fixed by removing the libiomp5md.dll file that can be found in `envs\venv\Lib\site-packages\torch\lib` # Install using poetry ## prerequisite diff --git a/bindings.cpp b/bindings.cpp new file mode 100644 index 00000000..7cd8eb20 --- /dev/null +++ b/bindings.cpp @@ -0,0 +1,174 @@ +#include +#include +#include + +#include "shape.h" +#include "color.h" +#include "filter.h" +#include "scene.h" +#include "ptr.h" +#include "vector.h" + +void render(std::shared_ptr scene, + ptr background_image, + ptr render_image, + ptr render_sdf, + int width, + int height, + int num_samples_x, + int num_samples_y, + uint64_t seed, + ptr d_background_image, + ptr d_render_image, + ptr d_render_sdf, + ptr d_translation, + bool use_prefiltering, + ptr eval_positions, + int num_eval_positions); + +namespace py = pybind11; + +PYBIND11_MODULE(diffvg, m) { + m.doc() = "Differential Vector Graphics"; + + py::class_>(m, "void_ptr") + .def(py::init()) + .def("as_size_t", &ptr::as_size_t); + py::class_>(m, "float_ptr") + .def(py::init()); + py::class_>(m, "int_ptr") + .def(py::init()); + + py::class_(m, "Vector2f") + .def(py::init()) + .def_readwrite("x", &Vector2f::x) + .def_readwrite("y", &Vector2f::y); + + py::class_(m, "Vector3f") + .def(py::init()) + .def_readwrite("x", &Vector3f::x) + .def_readwrite("y", &Vector3f::y) + .def_readwrite("z", &Vector3f::z); + + py::class_(m, "Vector4f") + .def(py::init()) + .def_readwrite("x", &Vector4f::x) + .def_readwrite("y", &Vector4f::y) + .def_readwrite("z", &Vector4f::z) + .def_readwrite("w", &Vector4f::w); + + py::enum_(m, "ShapeType") + .value("circle", ShapeType::Circle) + .value("ellipse", ShapeType::Ellipse) + .value("path", ShapeType::Path) + .value("rect", ShapeType::Rect); + + py::class_(m, "Circle") + .def(py::init()) + .def("get_ptr", &Circle::get_ptr) + .def_readonly("radius", &Circle::radius) + .def_readonly("center", &Circle::center); + + py::class_(m, "Ellipse") + .def(py::init()) + .def("get_ptr", &Ellipse::get_ptr) + .def_readonly("radius", &Ellipse::radius) + .def_readonly("center", &Ellipse::center); + + py::class_(m, "Path") + .def(py::init, ptr, ptr, int, int, bool, bool>()) + .def("get_ptr", &Path::get_ptr) + .def("has_thickness", &Path::has_thickness) + .def("copy_to", &Path::copy_to) + .def_readonly("num_points", &Path::num_points); + + py::class_(m, "Rect") + .def(py::init()) + .def("get_ptr", &Rect::get_ptr) + .def_readonly("p_min", &Rect::p_min) + .def_readonly("p_max", &Rect::p_max); + + py::enum_(m, "ColorType") + .value("constant", ColorType::Constant) + .value("linear_gradient", ColorType::LinearGradient) + .value("radial_gradient", ColorType::RadialGradient); + + py::class_(m, "Constant") + .def(py::init()) + .def("get_ptr", &Constant::get_ptr) + .def_readonly("color", &Constant::color); + + py::class_(m, "LinearGradient") + .def(py::init, ptr>()) + .def("get_ptr", &LinearGradient::get_ptr) + .def("copy_to", &LinearGradient::copy_to) + .def_readonly("begin", &LinearGradient::begin) + .def_readonly("end", &LinearGradient::end) + .def_readonly("num_stops", &LinearGradient::num_stops); + + py::class_(m, "RadialGradient") + .def(py::init, ptr>()) + .def("get_ptr", &RadialGradient::get_ptr) + .def("copy_to", &RadialGradient::copy_to) + .def_readonly("center", &RadialGradient::center) + .def_readonly("radius", &RadialGradient::radius) + .def_readonly("num_stops", &RadialGradient::num_stops); + + py::class_(m, "Shape") + .def(py::init, float>()) + .def("as_circle", &Shape::as_circle) + .def("as_ellipse", &Shape::as_ellipse) + .def("as_path", &Shape::as_path) + .def("as_rect", &Shape::as_rect) + .def_readonly("type", &Shape::type) + .def_readonly("stroke_width", &Shape::stroke_width); + + py::class_(m, "ShapeGroup") + .def(py::init, + int, + ColorType, + ptr, + ColorType, + ptr, + bool, + ptr>()) + .def("fill_color_as_constant", &ShapeGroup::fill_color_as_constant) + .def("fill_color_as_linear_gradient", &ShapeGroup::fill_color_as_linear_gradient) + .def("fill_color_as_radial_gradient", &ShapeGroup::fill_color_as_radial_gradient) + .def("stroke_color_as_constant", &ShapeGroup::stroke_color_as_constant) + .def("stroke_color_as_linear_gradient", &ShapeGroup::stroke_color_as_linear_gradient) + .def("stroke_color_as_radial_gradient", &ShapeGroup::fill_color_as_radial_gradient) + .def("has_fill_color", &ShapeGroup::has_fill_color) + .def("has_stroke_color", &ShapeGroup::has_stroke_color) + .def("copy_to", &ShapeGroup::copy_to) + .def_readonly("fill_color_type", &ShapeGroup::fill_color_type) + .def_readonly("stroke_color_type", &ShapeGroup::stroke_color_type); + + py::enum_(m, "FilterType") + .value("box", FilterType::Box) + .value("tent", FilterType::Tent) + .value("parabolic", FilterType::RadialParabolic) + .value("hann", FilterType::Hann); + + py::class_(m, "Filter") + .def(py::init()); + + py::class_>(m, "Scene") + .def(py::init &, + const std::vector &, + const Filter &, + bool, + int>()) + .def("get_d_shape", &Scene::get_d_shape) + .def("get_d_shape_group", &Scene::get_d_shape_group) + .def("get_d_filter_radius", &Scene::get_d_filter_radius) + .def_readonly("num_shapes", &Scene::num_shapes) + .def_readonly("num_shape_groups", &Scene::num_shape_groups); + + m.def("render", &render, ""); +} + + diff --git a/diffvg.cpp b/diffvg.cpp index 7346d24b..04cfa17a 100644 --- a/diffvg.cpp +++ b/diffvg.cpp @@ -17,12 +17,12 @@ #include "winding_number.h" #include "within_distance.h" #include -#include -#include +// #include +// #include #include #include -namespace py = pybind11; +// namespace py = pybind11; struct Command { int shape_group_id; @@ -1648,145 +1648,3 @@ void render(std::shared_ptr scene, #endif } -PYBIND11_MODULE(diffvg, m) { - m.doc() = "Differential Vector Graphics"; - - py::class_>(m, "void_ptr") - .def(py::init()) - .def("as_size_t", &ptr::as_size_t); - py::class_>(m, "float_ptr") - .def(py::init()); - py::class_>(m, "int_ptr") - .def(py::init()); - - py::class_(m, "Vector2f") - .def(py::init()) - .def_readwrite("x", &Vector2f::x) - .def_readwrite("y", &Vector2f::y); - - py::class_(m, "Vector3f") - .def(py::init()) - .def_readwrite("x", &Vector3f::x) - .def_readwrite("y", &Vector3f::y) - .def_readwrite("z", &Vector3f::z); - - py::class_(m, "Vector4f") - .def(py::init()) - .def_readwrite("x", &Vector4f::x) - .def_readwrite("y", &Vector4f::y) - .def_readwrite("z", &Vector4f::z) - .def_readwrite("w", &Vector4f::w); - - py::enum_(m, "ShapeType") - .value("circle", ShapeType::Circle) - .value("ellipse", ShapeType::Ellipse) - .value("path", ShapeType::Path) - .value("rect", ShapeType::Rect); - - py::class_(m, "Circle") - .def(py::init()) - .def("get_ptr", &Circle::get_ptr) - .def_readonly("radius", &Circle::radius) - .def_readonly("center", &Circle::center); - - py::class_(m, "Ellipse") - .def(py::init()) - .def("get_ptr", &Ellipse::get_ptr) - .def_readonly("radius", &Ellipse::radius) - .def_readonly("center", &Ellipse::center); - - py::class_(m, "Path") - .def(py::init, ptr, ptr, int, int, bool, bool>()) - .def("get_ptr", &Path::get_ptr) - .def("has_thickness", &Path::has_thickness) - .def("copy_to", &Path::copy_to) - .def_readonly("num_points", &Path::num_points); - - py::class_(m, "Rect") - .def(py::init()) - .def("get_ptr", &Rect::get_ptr) - .def_readonly("p_min", &Rect::p_min) - .def_readonly("p_max", &Rect::p_max); - - py::enum_(m, "ColorType") - .value("constant", ColorType::Constant) - .value("linear_gradient", ColorType::LinearGradient) - .value("radial_gradient", ColorType::RadialGradient); - - py::class_(m, "Constant") - .def(py::init()) - .def("get_ptr", &Constant::get_ptr) - .def_readonly("color", &Constant::color); - - py::class_(m, "LinearGradient") - .def(py::init, ptr>()) - .def("get_ptr", &LinearGradient::get_ptr) - .def("copy_to", &LinearGradient::copy_to) - .def_readonly("begin", &LinearGradient::begin) - .def_readonly("end", &LinearGradient::end) - .def_readonly("num_stops", &LinearGradient::num_stops); - - py::class_(m, "RadialGradient") - .def(py::init, ptr>()) - .def("get_ptr", &RadialGradient::get_ptr) - .def("copy_to", &RadialGradient::copy_to) - .def_readonly("center", &RadialGradient::center) - .def_readonly("radius", &RadialGradient::radius) - .def_readonly("num_stops", &RadialGradient::num_stops); - - py::class_(m, "Shape") - .def(py::init, float>()) - .def("as_circle", &Shape::as_circle) - .def("as_ellipse", &Shape::as_ellipse) - .def("as_path", &Shape::as_path) - .def("as_rect", &Shape::as_rect) - .def_readonly("type", &Shape::type) - .def_readonly("stroke_width", &Shape::stroke_width); - - py::class_(m, "ShapeGroup") - .def(py::init, - int, - ColorType, - ptr, - ColorType, - ptr, - bool, - ptr>()) - .def("fill_color_as_constant", &ShapeGroup::fill_color_as_constant) - .def("fill_color_as_linear_gradient", &ShapeGroup::fill_color_as_linear_gradient) - .def("fill_color_as_radial_gradient", &ShapeGroup::fill_color_as_radial_gradient) - .def("stroke_color_as_constant", &ShapeGroup::stroke_color_as_constant) - .def("stroke_color_as_linear_gradient", &ShapeGroup::stroke_color_as_linear_gradient) - .def("stroke_color_as_radial_gradient", &ShapeGroup::fill_color_as_radial_gradient) - .def("has_fill_color", &ShapeGroup::has_fill_color) - .def("has_stroke_color", &ShapeGroup::has_stroke_color) - .def("copy_to", &ShapeGroup::copy_to) - .def_readonly("fill_color_type", &ShapeGroup::fill_color_type) - .def_readonly("stroke_color_type", &ShapeGroup::stroke_color_type); - - py::enum_(m, "FilterType") - .value("box", FilterType::Box) - .value("tent", FilterType::Tent) - .value("parabolic", FilterType::RadialParabolic) - .value("hann", FilterType::Hann); - - py::class_(m, "Filter") - .def(py::init()); - - py::class_>(m, "Scene") - .def(py::init &, - const std::vector &, - const Filter &, - bool, - int>()) - .def("get_d_shape", &Scene::get_d_shape) - .def("get_d_shape_group", &Scene::get_d_shape_group) - .def("get_d_filter_radius", &Scene::get_d_filter_radius) - .def_readonly("num_shapes", &Scene::num_shapes) - .def_readonly("num_shape_groups", &Scene::num_shape_groups); - - m.def("render", &render, ""); -} diff --git a/pydiffvg/render_pytorch.py b/pydiffvg/render_pytorch.py index a686fb1a..dc5f85ed 100644 --- a/pydiffvg/render_pytorch.py +++ b/pydiffvg/render_pytorch.py @@ -670,8 +670,13 @@ def backward(ctx, grad_img): if not grad_img.is_contiguous(): grad_img = grad_img.contiguous() - assert(torch.isfinite(grad_img).all()) - + #assert(torch.isfinite(grad_img).all()) + print("Backgrad") + try: + assert torch.isfinite(grad_img).all() + except AssertionError: + print("Diffvg Infinite gradient hack. Clamping") + grad_img = torch.clamp(grad_img, -10, 10) scene = ctx.scene width = ctx.width height = ctx.height diff --git a/pydiffvg/save_svg.py b/pydiffvg/save_svg.py index 486a4e09..fd803ca3 100644 --- a/pydiffvg/save_svg.py +++ b/pydiffvg/save_svg.py @@ -121,6 +121,12 @@ def add_color(shape_color, name): shape_node.set('y', str(shape.p_min[1].item())) shape_node.set('width', str(shape.p_max[0].item() - shape.p_min[0].item())) shape_node.set('height', str(shape.p_max[1].item() - shape.p_min[1].item())) + elif isinstance(shape, pydiffvg.Ellipse): + shape_node = etree.SubElement(g, 'ellipse') + shape_node.set('cx', str(shape.center[0].item())) + shape_node.set('cy', str(shape.center[1].item())) + shape_node.set('rx', str(shape.radius[0].item())) + shape_node.set('ry', str(shape.radius[1].item())) else: assert(False) diff --git a/scene.cpp b/scene.cpp index 1799c962..555c068c 100644 --- a/scene.cpp +++ b/scene.cpp @@ -635,7 +635,20 @@ void compute_bounding_boxes(Scene &scene, BVHNode *nodes = scene.shape_groups_bvh_nodes[shape_group_id]; for (int i = 0; i < shape_group->num_shapes; i++) { auto shape_id = shape_group->shape_ids[i]; - auto r = shape_group->stroke_color == nullptr ? 0 : shape_list[shape_id]->stroke_width; + float r = 0; + if (shape_group->stroke_color != nullptr){ + if (shape_list[shape_id]->type == ShapeType::Path){ + const Path *p = (const Path*)(shape_list[shape_id]->ptr); + if (p->thickness != nullptr){ + for (int i = 0; i < p->num_points; i++) + r = std::max(r, p->thickness[i]); + }else + r = shape_list[shape_id]->stroke_width; + }else{ + r = shape_list[shape_id]->stroke_width; + } + } + //auto r = shape_group->stroke_color == nullptr ? 0 : shape_list[shape_id]->stroke_width; nodes[i] = BVHNode{shape_id, -1, scene.shapes_bbox[shape_id], @@ -652,7 +665,9 @@ void compute_bounding_boxes(Scene &scene, const Path *p = (const Path*)(shape_list[shape_group->shape_ids[0]]->ptr); if (p->thickness != nullptr) { const BVHNode *nodes = scene.path_bvhs[shape_group->shape_ids[0]]; - max_radius = nodes[0].max_radius; + for (int i = 0; i < p->num_points; i++) + max_radius = std::max(max_radius, p->thickness[i]); + //max_radius = std::max(nodes[0].max_radius, max_radius); } } for (int i = 1; i < shape_group->num_shapes; i++) { diff --git a/setup.py b/setup.py index 5463677a..a4b99a31 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ import os import re import sys -import platform +import platform, sysconfig import subprocess import importlib from sysconfig import get_paths @@ -34,17 +34,39 @@ def build_extension(self, ext): if isinstance(ext, CMakeExtension): extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) info = get_paths() - include_path = info['include'] - cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, - '-DPYTHON_LIBRARY=' + get_config_var('LIBDIR'), - '-DPYTHON_INCLUDE_PATH=' + include_path] + + if platform.system() == "Windows": + # change this to fit your python install + libdir = "C:\\Users\\micha\\miniforge3\\envs\\venv\\libs\\python310.lib" + ex = "C:\\Users\\micha\\miniforge3\\envs\\venv\\python.exe" + else: + libdir = get_config_var('LIBDIR') + + python_exe = sys.executable + python_root = sys.prefix + include_path = info['include'] #sysconfig.get_path("include") + + cmake_args = [ + '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, + '-DPython_EXECUTABLE=' + python_exe, + '-DPython_ROOT_DIR=' + python_root, + '-DPython_INCLUDE_DIR=' + include_path, + ] + + # include_path = info['include'] + + # cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, + # '-DPython_LIBRARY=' + libdir, + # '-DPython_INCLUDE_DIR=' + include_path] cfg = 'Debug' if self.debug else 'Release' build_args = ['--config', cfg] if platform.system() == "Windows": cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir), + '-DPython_EXECUTABLE=' + ex, '-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)] + if sys.maxsize > 2**32: cmake_args += ['-A', 'x64'] build_args += ['--', '/m'] @@ -53,10 +75,46 @@ def build_extension(self, ext): build_args += ['--', '-j8'] if ext.build_with_cuda: + cmake_args += [ + '-DDIFFVG_CUDA=1', + '-DCUDAToolkit_ROOT=' + sys.prefix, + ] cmake_args += ['-DDIFFVG_CUDA=1'] + + # cuda_root = os.environ.get("CUDA_TOOLKIT_ROOT_DIR") or sys.prefix + # cuda_target = os.path.join(cuda_root, "targets", "x86_64-linux") + + # cmake_args += [ + # "-DCUDA_TOOLKIT_ROOT_DIR=" + cuda_root, + # ] + + # nvcc = os.path.join(cuda_root, "bin", "nvcc") + # if os.path.exists(nvcc): + # cmake_args += ["-DCUDA_NVCC_EXECUTABLE=" + nvcc] + + # # Prefer the singular cache/input form for old FindCUDA + # cuda_include = os.path.join(cuda_target, "include") + # if os.path.exists(cuda_include): + # cmake_args += ["-DCUDA_INCLUDE_DIR=" + cuda_include] + + # cudart = os.path.join(cuda_target, "lib", "libcudart.so") + # if os.path.exists(cudart): + # cmake_args += ["-DCUDA_CUDART_LIBRARY=" + cudart] + + # print("CUDA root:", cuda_root) + # print("nvcc:", nvcc, os.path.exists(nvcc)) + # print("cuda include:", cuda_include, os.path.exists(cuda_include)) + # print("cudart:", cudart, os.path.exists(cudart)) + # print("cmake args:", cmake_args) + + # cuda_root = os.environ.get("CUDA_HOME") or os.environ.get("CUDA_PATH") or "/usr/local/cuda" + # cmake_args += [ + # '-DCUDA_TOOLKIT_ROOT_DIR=' + cuda_root, + # ] else: cmake_args += ['-DDIFFVG_CUDA=0'] + env = os.environ.copy() env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''), self.distribution.get_version()) @@ -76,7 +134,8 @@ def build_extension(self, ext): import torch if torch.cuda.is_available(): build_with_cuda = True -if tf_spec is not None and sys.platform != 'win32': +if False: #tf_spec is not None and sys.platform != 'win32': + assert(False) packages.append('pydiffvg_tensorflow') if not build_with_cuda: import tensorflow as tf