From 364c7912eb30f82d46afdd4e9cc71a42f222bb45 Mon Sep 17 00:00:00 2001 From: Patrick Stotko Date: Fri, 4 Aug 2023 10:27:55 +0200 Subject: [PATCH] docs: Move to Sphinx based generation --- .github/workflows/documentation.yml | 7 +- .gitignore | 4 + CMakeLists.txt | 2 +- README.md | 46 +- doc/CMakeLists.txt | 74 - doc/README.md | 9 - doc/custom.css | 3 - doc/footer.html | 17 - doc/header.html | 83 - doc/stdgpu/chapters.md | 8 - doc/stdgpu/index.md | 336 --- doc/stdgpu/object.md | 128 - docs/CMakeLists.txt | 81 + {doc => docs}/Doxyfile.in | 38 +- {doc => docs}/DoxygenLayout.xml | 0 docs/_static/extra_stylesheet.css | 2498 +++++++++++++++++ docs/_static/stdgpu_custom_doxygen.css | 79 + docs/_static/stdgpu_custom_sphinx.css | 15 + {doc => docs/_static}/stdgpu_logo.ico | Bin {doc => docs/_static}/stdgpu_logo.png | Bin docs/api/chapters.md | 9 + {doc/stdgpu => docs/api}/iterator.md | 90 +- {doc/stdgpu => docs/api}/memory.md | 48 +- docs/api/object.md | 128 + docs/conf.py | 71 + {doc/stdgpu => docs/doxygen_src}/modules.doxy | 0 docs/fix_html_titles/__init__.py | 0 docs/fix_html_titles/__main__.py | 35 + docs/index.md | 31 + docs/requirements.txt | 7 + .../utils/install_docs_dependencies_ubuntu.sh | 7 + .../install_doxygen_dependencies_ubuntu.sh | 6 - 32 files changed, 3082 insertions(+), 778 deletions(-) delete mode 100644 doc/CMakeLists.txt delete mode 100644 doc/README.md delete mode 100644 doc/custom.css delete mode 100644 doc/footer.html delete mode 100644 doc/header.html delete mode 100644 doc/stdgpu/chapters.md delete mode 100644 doc/stdgpu/index.md delete mode 100644 doc/stdgpu/object.md create mode 100644 docs/CMakeLists.txt rename {doc => docs}/Doxyfile.in (98%) rename {doc => docs}/DoxygenLayout.xml (100%) create mode 100644 docs/_static/extra_stylesheet.css create mode 100644 docs/_static/stdgpu_custom_doxygen.css create mode 100644 docs/_static/stdgpu_custom_sphinx.css rename {doc => docs/_static}/stdgpu_logo.ico (100%) rename {doc => docs/_static}/stdgpu_logo.png (100%) create mode 100644 docs/api/chapters.md rename {doc/stdgpu => docs/api}/iterator.md (50%) rename {doc/stdgpu => docs/api}/memory.md (77%) create mode 100644 docs/api/object.md create mode 100644 docs/conf.py rename {doc/stdgpu => docs/doxygen_src}/modules.doxy (100%) create mode 100644 docs/fix_html_titles/__init__.py create mode 100644 docs/fix_html_titles/__main__.py create mode 100644 docs/index.md create mode 100644 docs/requirements.txt create mode 100644 scripts/utils/install_docs_dependencies_ubuntu.sh delete mode 100644 scripts/utils/install_doxygen_dependencies_ubuntu.sh diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 041903946..fe088c548 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -23,10 +23,10 @@ jobs: run: | bash scripts/utils/install_openmp_ubuntu.sh - - name: Install doxygen dependencies + - name: Install docs dependencies shell: bash run: | - bash scripts/utils/install_doxygen_dependencies_ubuntu.sh + bash scripts/utils/install_docs_dependencies_ubuntu.sh - name: Download dependencies shell: bash @@ -46,7 +46,6 @@ jobs: - name: Deploy documentation uses: JamesIves/github-pages-deploy-action@v4 with: - folder: build/doc/html + folder: build/docs/html clean: true single-commit: true - if: github.event_name != 'pull_request' diff --git a/.gitignore b/.gitignore index f66e75225..7919fa140 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,12 @@ /bin/ /build/ /build_install_test/ +/docs/doxygen/ /external/ +# Python +__pycache__/ + # KDevelop *.kdev4 .kdev4/ diff --git a/CMakeLists.txt b/CMakeLists.txt index eef1dcf55..10262f2aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,7 +208,7 @@ if(STDGPU_BUILD_TESTS) endif() if(STDGPU_BUILD_DOCUMENTATION) - add_subdirectory(doc) + add_subdirectory(docs) endif() include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/config_summary.cmake") diff --git a/README.md b/README.md index cb207a1e7..54e49e3df 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@

- +

stdgpu: Efficient STL-like Data Structures on the GPU

+ +

@@ -21,7 +23,7 @@ - + @@ -34,6 +36,8 @@

+ +

Features | @@ -48,6 +52,8 @@ + + ## Features stdgpu is an open-source library providing several generic GPU data structures for fast and reliable data management. Multiple platforms such as **CUDA**, **OpenMP**, and **HIP** are supported allowing you to rapidly write highly complex **agnostic** and **native** algorithms that look like sequential CPU code but are executed in parallel on the GPU. @@ -62,18 +68,18 @@ At its heart, stdgpu offers the following GPU data structures and containers: - - - + + + - - - + + +
atomic & atomic_ref
Atomic primitive types and references
bitset
Space-efficient bit array
deque
Dynamically sized double-ended queue
atomic & atomic_ref
Atomic primitive types and references
bitset
Space-efficient bit array
deque
Dynamically sized double-ended queue
queue & stack
Container adapters
unordered_map & unordered_set
Hashed collection of unique keys and key-value pairs
vector
Dynamically sized contiguous array
queue & stack
Container adapters
unordered_map & unordered_set
Hashed collection of unique keys and key-value pairs
vector
Dynamically sized contiguous array
-In addition, stdgpu also provides commonly required functionality in [`algorithm`](https://stotko.github.io/stdgpu/algorithm_8h.html), [`bit`](https://stotko.github.io/stdgpu/bit_8h.html), [`contract`](https://stotko.github.io/stdgpu/contract_8h.html), [`cstddef`](https://stotko.github.io/stdgpu/cstddef_8h.html), [`functional`](https://stotko.github.io/stdgpu/functional_8h.html), [`iterator`](https://stotko.github.io/stdgpu/iterator_8h.html), [`limits`](https://stotko.github.io/stdgpu/limits_8h.html), [`memory`](https://stotko.github.io/stdgpu/memory_8h.html), [`mutex`](https://stotko.github.io/stdgpu/mutex_8cuh.html), [`ranges`](https://stotko.github.io/stdgpu/ranges_8h.html), [`utility`](https://stotko.github.io/stdgpu/utility_8h.html) to complement the GPU data structures and to increase their usability and interoperability. +In addition, stdgpu also provides commonly required functionality in [`algorithm`](https://stotko.github.io/stdgpu/doxygen/algorithm_8h.html), [`bit`](https://stotko.github.io/stdgpu/doxygen/bit_8h.html), [`contract`](https://stotko.github.io/stdgpu/doxygen/contract_8h.html), [`cstddef`](https://stotko.github.io/stdgpu/doxygen/cstddef_8h.html), [`functional`](https://stotko.github.io/stdgpu/doxygen/functional_8h.html), [`iterator`](https://stotko.github.io/stdgpu/doxygen/iterator_8h.html), [`limits`](https://stotko.github.io/stdgpu/doxygen/limits_8h.html), [`memory`](https://stotko.github.io/stdgpu/doxygen/memory_8h.html), [`mutex`](https://stotko.github.io/stdgpu/doxygen/mutex_8cuh.html), [`ranges`](https://stotko.github.io/stdgpu/doxygen/ranges_8h.html), [`utility`](https://stotko.github.io/stdgpu/doxygen/utility_8h.html) to complement the GPU data structures and to increase their usability and interoperability. ## Examples @@ -177,13 +183,13 @@ Before building the library, please make sure that all required tools and depend - Clang 10 - (Ubuntu 20.04/22.04) `sudo apt install clang` - MSVC 19.20 - - (Windows) Visual Studio 2019 https://visualstudio.microsoft.com/downloads/ + - (Windows) Visual Studio 2019 - CMake 3.18 - - (Ubuntu 20.04) https://apt.kitware.com + - (Ubuntu 20.04) - (Ubuntu 22.04) `sudo apt install cmake` - - (Windows) https://cmake.org/download + - (Windows) - thrust 1.9.9 - - (Ubuntu/Windows) https://github.com/NVIDIA/thrust + - (Ubuntu/Windows) - May already be installed by backend dependencies **Required for CUDA backend** @@ -194,7 +200,7 @@ Before building the library, please make sure that all required tools and depend - Clang 10 - (Ubuntu 20.04/22.04) `sudo apt install clang` - CUDA Toolkit 11.0 - - (Ubuntu/Windows) https://developer.nvidia.com/cuda-downloads + - (Ubuntu/Windows) - Includes thrust **Required for OpenMP backend** @@ -213,12 +219,12 @@ Before building the library, please make sure that all required tools and depend - Clang - Already included in ROCm - ROCm 5.1 - - (Ubuntu) https://github.com/RadeonOpenCompute/ROCm + - (Ubuntu) - Includes thrust - CMake 3.21.3 - - (Ubuntu 20.04) https://apt.kitware.com + - (Ubuntu 20.04) - (Ubuntu 22.04) `sudo apt install cmake` - - (Windows) https://cmake.org/download + - (Windows) - Required for first-class HIP language support @@ -307,7 +313,7 @@ If you use stdgpu in one of your projects, please cite the following publication [**stdgpu: Efficient STL-like Data Structures on the GPU**](https://www.researchgate.net/publication/335233070_stdgpu_Efficient_STL-like_Data_Structures_on_the_GPU) -``` +```bib @UNPUBLISHED{stotko2019stdgpu, author = {Stotko, P.}, title = {{stdgpu: Efficient STL-like Data Structures on the GPU}}, @@ -320,7 +326,7 @@ If you use stdgpu in one of your projects, please cite the following publication [**SLAMCast: Large-Scale, Real-Time 3D Reconstruction and Streaming for Immersive Multi-Client Live Telepresence**](https://www.researchgate.net/publication/331303359_SLAMCast_Large-Scale_Real-Time_3D_Reconstruction_and_Streaming_for_Immersive_Multi-Client_Live_Telepresence) -``` +```bib @article{stotko2019slamcast, author = {Stotko, P. and Krumpen, S. and Hullin, M. B. and Weinmann, M. and Klein, R.}, title = {{SLAMCast: Large-Scale, Real-Time 3D Reconstruction and Streaming for Immersive Multi-Client Live Telepresence}}, @@ -337,3 +343,5 @@ If you use stdgpu in one of your projects, please cite the following publication ## Contact Patrick Stotko - [stotko@cs.uni-bonn.de](mailto:stotko@cs.uni-bonn.de) + + diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt deleted file mode 100644 index 67b946ec1..000000000 --- a/doc/CMakeLists.txt +++ /dev/null @@ -1,74 +0,0 @@ - -find_package(Doxygen 1.9.6 EXACT QUIET) - -if(NOT Doxygen_FOUND) - include(ExternalProject) - - ExternalProject_Add( - doxygen - PREFIX doxygen - URL https://github.com/doxygen/doxygen/archive/refs/tags/Release_1_9_6.zip - URL_HASH SHA256=28ab2c5d2ba1d3ed56c538125f1cad7ca8a09992e8b3892e9533736268ff6426 - DOWNLOAD_DIR "${STDGPU_EXTERNAL_DIR}/doxygen" - UPDATE_COMMAND "" - INSTALL_COMMAND "" - CMAKE_ARGS - -DCMAKE_BUILD_TYPE=Release - EXCLUDE_FROM_ALL TRUE - ) - - ExternalProject_Get_Property(doxygen BINARY_DIR) - add_executable(Doxygen::doxygen IMPORTED) - set_target_properties(Doxygen::doxygen PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/bin/doxygen") - - add_dependencies(Doxygen::doxygen doxygen) -endif() - - -include(FetchContent) - -FetchContent_Declare( - doxygen-awesome-css - PREFIX doxygen-awesome-css - URL https://github.com/jothepro/doxygen-awesome-css/archive/refs/tags/v2.2.1.zip - URL_HASH SHA256=3c920003d601bca4a6f5a9be5760a92d1e369d0ec1606635cd99f51f77f5791c - DOWNLOAD_DIR "${STDGPU_EXTERNAL_DIR}/doxygen-awesome-css" -) - -FetchContent_GetProperties(doxygen-awesome-css) -if(NOT doxygen-awesome-css_POPULATED) - FetchContent_Populate(doxygen-awesome-css) -endif() - -set(STDGPU_DOXYGEN_AWESOME_CSS_DIR ${doxygen-awesome-css_SOURCE_DIR}) - - -# Check include path -set(STDGPU_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../src") -get_filename_component(STDGPU_INCLUDE_DIR ${STDGPU_INCLUDE_DIR} ABSOLUTE) - - -if(STDGPU_COMPILE_WARNING_AS_ERROR) - set(STDGPU_DOXYGEN_WARN_AS_ERROR YES) -else() - set(STDGPU_DOXYGEN_WARN_AS_ERROR NO) -endif() - -set(STDGPU_DOXYFILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in") -set(STDGPU_DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile") -set(STDGPU_DOC_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}") - -configure_file(${STDGPU_DOXYFILE_IN} - ${STDGPU_DOXYFILE} - @ONLY) - -add_custom_target(stdgpu_doc - COMMAND Doxygen::doxygen ${STDGPU_DOXYFILE} - WORKING_DIRECTORY ${STDGPU_DOC_BUILD_DIR} - COMMENT "Generating stdgpu API documentation with Doxygen" - VERBATIM) - - -#install(DIRECTORY "${STDGPU_DOC_BUILD_DIR}/doxygen-html/" -# DESTINATION ${STDGPU_DOC_INSTALL_DIR} -# COMPONENT stdgpu) diff --git a/doc/README.md b/doc/README.md deleted file mode 100644 index cc721db3c..000000000 --- a/doc/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## Documentation - -A comprehensive introduction into the design and API of stdgpu can be found here: - -- stdgpu API documentation -- thrust algorithms documentation -- Research paper - -Since a core feature and design goal of stdgpu is its **interoperability** with thrust, it offers **full support for all thrust algorithms** instead of reinventing the wheel. More information about the design can be found in the related research paper. diff --git a/doc/custom.css b/doc/custom.css deleted file mode 100644 index 821813c00..000000000 --- a/doc/custom.css +++ /dev/null @@ -1,3 +0,0 @@ -#doc-content { - height: calc(100vh) !important; -} diff --git a/doc/footer.html b/doc/footer.html deleted file mode 100644 index d9f89a662..000000000 --- a/doc/footer.html +++ /dev/null @@ -1,17 +0,0 @@ - - - -

- - - - - - diff --git a/doc/header.html b/doc/header.html deleted file mode 100644 index 011b2c582..000000000 --- a/doc/header.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - -$projectname: $title -$title - - - - - - - - - -$treeview -$search -$mathjax -$darkmode - -$extrastylesheet - - - - - - - - -
- - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
 $projectnumber -
- -
-
$projectbrief
-
$searchbox
$searchbox
-
- - diff --git a/doc/stdgpu/chapters.md b/doc/stdgpu/chapters.md deleted file mode 100644 index a97b22faa..000000000 --- a/doc/stdgpu/chapters.md +++ /dev/null @@ -1,8 +0,0 @@ -Chapters {#chapters} -======== - -Here is a list of all chapters: - -- \subpage memory -- \subpage iterator -- \subpage object diff --git a/doc/stdgpu/index.md b/doc/stdgpu/index.md deleted file mode 100644 index f9a847c39..000000000 --- a/doc/stdgpu/index.md +++ /dev/null @@ -1,336 +0,0 @@ -Overview {#mainpage} -======== - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - -

-Features | -Examples | -Documentation | -Building | -Integration | -Contributing | -License | -Contact -

-
- - -## Features {#features} - -stdgpu is an open-source library providing several generic GPU data structures for fast and reliable data management. Multiple platforms such as **CUDA**, **OpenMP**, and **HIP** are supported allowing you to rapidly write highly complex **agnostic** and **native** algorithms that look like sequential CPU code but are executed in parallel on the GPU. - -- **Productivity**. Previous libraries such as thrust, VexCL, ArrayFire or Boost.Compute focus on the fast and efficient implementation of various algorithms for contiguously stored data to enhance productivity. stdgpu follows an *orthogonal approach* and focuses on *fast and reliable data management* to enable the rapid development of more general and flexible GPU algorithms just like their CPU counterparts. - -- **Interoperability**. Instead of providing yet another ecosystem, stdgpu is designed to be a *lightweight container library*. Therefore, a core feature of stdgpu is its interoperability with previous established frameworks, i.e. the thrust library, to enable a *seamless integration* into new as well as existing projects. - -- **Maintainability**. Following the trend in recent C++ standards of providing functionality for safer and more reliable programming, the philosophy of stdgpu is to provide *clean and familiar functions* with strong guarantees that encourage users to write *more robust code* while giving them full control to achieve a high performance. - -At its heart, stdgpu offers the following GPU data structures and containers: - - - - - - - - - - - - -
atomic & atomic_ref
Atomic primitive types and references
bitset
Space-efficient bit array
deque
Dynamically sized double-ended queue
queue & stack
Container adapters
unordered_map & unordered_set
Hashed collection of unique keys and key-value pairs
vector
Dynamically sized contiguous array
- -In addition, stdgpu also provides commonly required functionality in [`algorithm`](https://stotko.github.io/stdgpu/algorithm_8h.html), [`bit`](https://stotko.github.io/stdgpu/bit_8h.html), [`contract`](https://stotko.github.io/stdgpu/contract_8h.html), [`cstddef`](https://stotko.github.io/stdgpu/cstddef_8h.html), [`functional`](https://stotko.github.io/stdgpu/functional_8h.html), [`iterator`](https://stotko.github.io/stdgpu/iterator_8h.html), [`limits`](https://stotko.github.io/stdgpu/limits_8h.html), [`memory`](https://stotko.github.io/stdgpu/memory_8h.html), [`mutex`](https://stotko.github.io/stdgpu/mutex_8cuh.html), [`ranges`](https://stotko.github.io/stdgpu/ranges_8h.html), [`utility`](https://stotko.github.io/stdgpu/utility_8h.html) to complement the GPU data structures and to increase their usability and interoperability. - - -## Examples {#examples} - -In order to reliably perform complex tasks on the GPU, stdgpu offers flexible interfaces that can be used in both **agnostic code**, e.g. via the algorithms provided by thrust, as well as in **native code**, e.g. in custom CUDA kernels. - -For instance, stdgpu is extensively used in [SLAMCast](https://www.researchgate.net/publication/331303359_SLAMCast_Large-Scale_Real-Time_3D_Reconstruction_and_Streaming_for_Immersive_Multi-Client_Live_Telepresence), a scalable live telepresence system, to implement real-time, large-scale 3D scene reconstruction as well as real-time 3D data streaming between a server and an arbitrary number of remote clients. - -**Agnostic code**. In the context of [SLAMCast](https://www.researchgate.net/publication/331303359_SLAMCast_Large-Scale_Real-Time_3D_Reconstruction_and_Streaming_for_Immersive_Multi-Client_Live_Telepresence), a simple task is the integration of a range of updated blocks into the duplicate-free set of queued blocks for data streaming which can be expressed very conveniently: - -```cpp -#include // stdgpu::index_t -#include // stdgpu::make_device -#include // stdgpu::unordered_set - -class stream_set -{ -public: - void - add_blocks(const short3* blocks, - const stdgpu::index_t n) - { - set.insert(stdgpu::make_device(blocks), - stdgpu::make_device(blocks + n)); - } - - // Further functions - -private: - stdgpu::unordered_set set; - // Further members -}; -``` - -**Native code**. More complex operations such as the creation of the duplicate-free set of updated blocks or other algorithms can be implemented natively, e.g. in custom CUDA kernels with stdgpu's CUDA backend enabled: - -```cpp -#include // stdgpu::index_t -#include // stdgpu::unordered_map -#include // stdgpu::unordered_set - -__global__ void -compute_update_set(const short3* blocks, - const stdgpu::index_t n, - const stdgpu::unordered_map tsdf_block_map, - stdgpu::unordered_set mc_update_set) -{ - // Global thread index - stdgpu::index_t i = blockIdx.x * blockDim.x + threadIdx.x; - if (i >= n) return; - - short3 b_i = blocks[i]; - - // Neighboring candidate blocks for the update - short3 mc_blocks[8] - = { - short3(b_i.x - 0, b_i.y - 0, b_i.z - 0), - short3(b_i.x - 1, b_i.y - 0, b_i.z - 0), - short3(b_i.x - 0, b_i.y - 1, b_i.z - 0), - short3(b_i.x - 0, b_i.y - 0, b_i.z - 1), - short3(b_i.x - 1, b_i.y - 1, b_i.z - 0), - short3(b_i.x - 1, b_i.y - 0, b_i.z - 1), - short3(b_i.x - 0, b_i.y - 1, b_i.z - 1), - short3(b_i.x - 1, b_i.y - 1, b_i.z - 1), - }; - - for (stdgpu::index_t j = 0; j < 8; ++j) - { - // Only consider existing neighbors - if (tsdf_block_map.contains(mc_blocks[j])) - { - mc_update_set.insert(mc_blocks[j]); - } - } -} -``` - -More examples can be found in the [`examples`](https://github.com/stotko/stdgpu/tree/master/examples) directory. - - -## Documentation {#documentation} - -A comprehensive introduction into the design and API of stdgpu can be found here: - -- [stdgpu API documentation](https://stotko.github.io/stdgpu) -- [thrust algorithms documentation](https://thrust.github.io/doc/group__algorithms.html) -- [Research paper](https://www.researchgate.net/publication/335233070_stdgpu_Efficient_STL-like_Data_Structures_on_the_GPU) - -Since a core feature and design goal of stdgpu is its **interoperability** with thrust, it offers **full support for all thrust algorithms** instead of reinventing the wheel. More information about the design can be found in the related [research paper](https://www.researchgate.net/publication/335233070_stdgpu_Efficient_STL-like_Data_Structures_on_the_GPU). - - -## Building {#building} - -Before building the library, please make sure that all required tools and dependencies are installed on your system. Newer versions are supported as well. - -**Required** - -- C++17 compiler - - GCC 9 - - (Ubuntu 20.04/22.04) `sudo apt install g++` - - Clang 10 - - (Ubuntu 20.04/22.04) `sudo apt install clang` - - MSVC 19.20 - - (Windows) Visual Studio 2019 https://visualstudio.microsoft.com/downloads/ -- CMake 3.18 - - (Ubuntu 20.04) https://apt.kitware.com - - (Ubuntu 22.04) `sudo apt install cmake` - - (Windows) https://cmake.org/download -- thrust 1.9.9 - - (Ubuntu/Windows) https://github.com/NVIDIA/thrust - - May already be installed by backend dependencies - -**Required for CUDA backend** - -- CUDA compiler - - NVCC - - Already included in CUDA Toolkit - - Clang 10 - - (Ubuntu 20.04/22.04) `sudo apt install clang` -- CUDA Toolkit 11.0 - - (Ubuntu/Windows) https://developer.nvidia.com/cuda-downloads - - Includes thrust - -**Required for OpenMP backend** - -- OpenMP 2.0 - - GCC 9 - - (Ubuntu 20.04/22.04) Already installed - - Clang 10 - - (Ubuntu 20.04/22.04) `sudo apt install libomp-dev` - - MSVC 19.20 - - (Windows) Already installed - -**Required for HIP backend (experimental)** - -- HIP compiler - - Clang - - Already included in ROCm -- ROCm 5.1 - - (Ubuntu) https://github.com/RadeonOpenCompute/ROCm - - Includes thrust -- CMake 3.21.3 - - (Ubuntu 20.04) https://apt.kitware.com - - (Ubuntu 22.04) `sudo apt install cmake` - - (Windows) https://cmake.org/download - - Required for first-class HIP language support - - -The library can be built as every other project which makes use of the CMake build system. - -In addition, we also provide cross-platform scripts to make the build process more convenient. Since these scripts depend on the selected build type, there are scripts for both `debug` and `release` builds. - -Command | Effect ---- | --- -`bash scripts/setup.sh []` | Performs a full clean build of the project. Removes old build, configures the project (build path: `./build`, default build type: `Release`), builds the project, and runs the unit tests. -`bash scripts/build.sh []` | (Re-)Builds the project. Requires that the project is set up (default build type: `Release`). -`bash scripts/run_tests.sh []` | Runs the unit tests. Requires that the project is built (default build type: `Release`). -`bash scripts/install.sh []` | Installs the project to the configured install path (default install dir: `./bin`, default build type: `Release`). -`bash scripts/uninstall.sh []` | Uninstalls the project from the configured install path (default build type: `Release`). - - -## Integration {#integration} - -In the following, we show some examples on how the library can be integrated into and used in a project. - - -**CMake Integration**. To use the library in your project, you can either install it externally first and then include it using `find_package`: - -```cmake -find_package(stdgpu 1.0.0 REQUIRED) - -add_library(foo ...) - -target_link_libraries(foo PUBLIC stdgpu::stdgpu) -``` - -Or you can embed it into your project and build it from a subdirectory: - -```cmake -# Exclude the examples from the build -set(STDGPU_BUILD_EXAMPLES OFF CACHE INTERNAL "") - -# Exclude the benchmarks from the build -set(STDGPU_BUILD_BENCHMARKS OFF CACHE INTERNAL "") - -# Exclude the tests from the build -set(STDGPU_BUILD_TESTS OFF CACHE INTERNAL "") - -add_subdirectory(stdgpu) - -add_library(foo ...) - -target_link_libraries(foo PUBLIC stdgpu::stdgpu) -``` - - -**CMake Options**. To configure the library, two sets of options are provided. The following build options control the build process: - -Build Option | Effect | Default ---- | --- | --- -`STDGPU_BACKEND` | Device system backend | `STDGPU_BACKEND_CUDA` -`STDGPU_BUILD_SHARED_LIBS` | Builds the project as a shared library, if set to `ON`, or as a static library, if set to `OFF` | `BUILD_SHARED_LIBS` -`STDGPU_SETUP_COMPILER_FLAGS` | Constructs the compiler flags | `ON` if standalone, `OFF` if included via `add_subdirectory` -`STDGPU_COMPILE_WARNING_AS_ERROR` | Treats compiler warnings as errors | `OFF` -`STDGPU_BUILD_EXAMPLES` | Build the examples | `ON` -`STDGPU_BUILD_BENCHMARKS` | Build the benchmarks | `ON` -`STDGPU_BUILD_TESTS` | Build the unit tests | `ON` -`STDGPU_BUILD_TEST_COVERAGE` | Build a test coverage report | `OFF` -`STDGPU_ANALYZE_WITH_CLANG_TIDY` | Analyzes the code with clang-tidy | `OFF` -`STDGPU_ANALYZE_WITH_CPPCHECK` | Analyzes the code with cppcheck | `OFF` - - -In addition, the implementation of some functionality can be controlled via configuration options: - -Configuration Option | Effect | Default ---- | --- | --- -`STDGPU_ENABLE_CONTRACT_CHECKS` | Enable contract checks | `OFF` if `CMAKE_BUILD_TYPE` equals `Release` or `MinSizeRel`, `ON` otherwise -`STDGPU_USE_32_BIT_INDEX` | Use 32-bit instead of 64-bit signed integer for `index_t` | `ON` - - -## Contributing {#contributing} - -For detailed information on how to contribute, see [`CONTRIBUTING`](https://github.com/stotko/stdgpu/blob/master/CONTRIBUTING.md). - - -## License {#license} - -Distributed under the Apache 2.0 License. See [`LICENSE`](https://github.com/stotko/stdgpu/blob/master/LICENSE) for more information. - -If you use stdgpu in one of your projects, please cite the following publications: - -[**stdgpu: Efficient STL-like Data Structures on the GPU**](https://www.researchgate.net/publication/335233070_stdgpu_Efficient_STL-like_Data_Structures_on_the_GPU) - -``` -@UNPUBLISHED{stotko2019stdgpu, - author = {Stotko, P.}, - title = {{stdgpu: Efficient STL-like Data Structures on the GPU}}, - year = {2019}, - month = aug, - note = {arXiv:1908.05936}, - url = {https://arxiv.org/abs/1908.05936} -} -``` - -[**SLAMCast: Large-Scale, Real-Time 3D Reconstruction and Streaming for Immersive Multi-Client Live Telepresence**](https://www.researchgate.net/publication/331303359_SLAMCast_Large-Scale_Real-Time_3D_Reconstruction_and_Streaming_for_Immersive_Multi-Client_Live_Telepresence) - -``` -@article{stotko2019slamcast, - author = {Stotko, P. and Krumpen, S. and Hullin, M. B. and Weinmann, M. and Klein, R.}, - title = {{SLAMCast: Large-Scale, Real-Time 3D Reconstruction and Streaming for Immersive Multi-Client Live Telepresence}}, - journal = {IEEE Transactions on Visualization and Computer Graphics}, - volume = {25}, - number = {5}, - pages = {2102--2112}, - year = {2019}, - month = may -} -``` - - -## Contact {#contact} - -Patrick Stotko - [stotko@cs.uni-bonn.de](mailto:stotko@cs.uni-bonn.de) diff --git a/doc/stdgpu/object.md b/doc/stdgpu/object.md deleted file mode 100644 index 176d7ef83..000000000 --- a/doc/stdgpu/object.md +++ /dev/null @@ -1,128 +0,0 @@ -Container Objects {#object} -================= - -# Motivation {#object_overview} - -In order to bridge the gap between GPU and CPU programming, the memory management API allows to handle arrays in an efficient and reliable way (see \ref memory). However, this is not sufficient even for most projects which require at least one layer hiding all the computations and memory management operations. Therefore, semantically coherent data (e.g. arrays) should be packed together into a class and processed by the public interface of the class. One category of such classes are containers including std::vector. In the context of GPU programming, array-based data structures are prefered and easier to implement. The thrust library for example only provides a thrust::host_vector and thrust::device_vector class because other structures such as std::unordered_map, std::list, etc. are very difficult to port to the GPU without sacrificing some important properties. While the containers defined in this library also have some limitations, they are still easy to use and robust. - - -# Defining Host and Device Container Objects {#object_api} - -As mentioned above, a further abstraction layer to simplify data management is needed. This requires another API to avoid boilerplate code and redudancy. So far, host and device arrays has been defined as the generalization of arrays to CPU and GPU memory. Consequently, host device objects now generalize the traditional class objects. Consider the following class: - -```cpp - class MyClass - { - public: - MyClass() - { - this->array = nullptr; - this->size = 0; - } - - MyClass(const int size) - { - this->array = new float[size]; - this->size = size; - } - - ~MyClass() - { - delete[] array; - size = 0; - } - - void function(const int parameter) const - { - // Do something useful with array - } - - private: - float* array; - int size; - }; -``` - -It wraps an array of type float including the size and provides some interaction interface through the member function. There are two constructors for this class. The first is simply the default constructor which should set the object to an empty state. The other constructor allocates the array with the given size. Finally, the destructor cleans them up. This design is quite problematic since copy and move constructors are not considered here which can result to double free errors and memory leaks. Furthermore, this design does not scale to the GPU and a new API must be used. Consider this API on the aforementioned example: - -```cpp - class MyHostDeviceObjectClass - { - public: - MyHostDeviceObjectClass() - { - this->_array = nullptr; - this->_size = 0; - } - - static MyHostDeviceObjectClass createDeviceObject(const int size) - { - MyHostDeviceObjectClass result; - - result._array = createDeviceArray(size); - result._size = size; - - return result; - } - - static void destroyDeviceObject(MyHostDeviceObjectClass& device_object) - { - destroyDeviceArray(device_object._array); - device_object._size = 0; - } - - static MyHostDeviceObjectClass createHostObject(const int size) - { - MyHostDeviceObjectClass result; - - result._array = createHostArray(size); - result._size = size; - - return result; - } - - static void destroyHostObject(MyHostDeviceObjectClass& host_object) - { - destroyHostArray(host_object._array); - host_object._size = 0; - } - - void function(const int parameter) const - { - // Do something useful with array - } - - private: - float* _array; - int _size; - }; -``` - -Note that this interface is very similar to the [host device array interface](#memory). An object can now be easily created and destroyed as follows: - -```cpp - MyClass device_object = MyClass::createDeviceObject(1000); - MyClass hoste_object = MyClass::createHostObject(1000); - - // Do something with device_object and host_object - - MyClass::destroyDeviceObject(device_object); - MyClass::destroyHostObject(host_object); -``` - -In order to match the capabilities of the host device arrays, copy functions can defined in the same manner and used as: - -```cpp - MyClass device_object = MyClass::createDeviceObject(1000); - - // Do something with device_object - - MyClass host_object = MyClass::copyCreateDevice2HostObject(device_object); - - // Do something with host_object - - MyClass::destroyDeviceObject(device_object); - MyClass::destroyHostObject(host_object); -``` - -Compared to arrays, an object always knows its size, so it is not necessary to also pass it as a parameter. This design is used to define the containers in this library. diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 000000000..8b5998dc9 --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,81 @@ + +find_package(Doxygen 1.9.6 EXACT QUIET) + +if(NOT Doxygen_FOUND) + include(ExternalProject) + + ExternalProject_Add( + doxygen + PREFIX doxygen + URL https://github.com/doxygen/doxygen/archive/refs/tags/Release_1_9_6.zip + URL_HASH SHA256=28ab2c5d2ba1d3ed56c538125f1cad7ca8a09992e8b3892e9533736268ff6426 + DOWNLOAD_DIR "${STDGPU_EXTERNAL_DIR}/doxygen" + UPDATE_COMMAND "" + INSTALL_COMMAND "" + CMAKE_ARGS + -DCMAKE_BUILD_TYPE=Release + EXCLUDE_FROM_ALL TRUE + ) + + ExternalProject_Get_Property(doxygen BINARY_DIR) + add_executable(Doxygen::doxygen IMPORTED) + set_target_properties(Doxygen::doxygen PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/bin/doxygen") + + add_dependencies(Doxygen::doxygen doxygen) +endif() + + +# The Doxygen Awesome has to be modified due to two major reasons: +# - Doxysphinx is used in a later stage and puts the doxygen parts into a .doxygen-content container +# - The dark mode switch and the respective variables of the sphinx-book-theme will be used +# +# Therefore, use the modified stylesheet from ROCm released under the MIT license: +# https://github.com/RadeonOpenCompute/rocm-docs-core/blob/develop/src/rocm_docs/data/_doxygen/extra_stylesheet.css + + +# Check include path +set(STDGPU_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../src") +get_filename_component(STDGPU_INCLUDE_DIR ${STDGPU_INCLUDE_DIR} ABSOLUTE) + + +if(STDGPU_COMPILE_WARNING_AS_ERROR) + set(STDGPU_DOXYGEN_WARN_AS_ERROR YES) +else() + set(STDGPU_DOXYGEN_WARN_AS_ERROR NO) +endif() + + +set(STDGPU_DOXYFILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in") +set(STDGPU_DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile") + +configure_file(${STDGPU_DOXYFILE_IN} + ${STDGPU_DOXYFILE} + @ONLY) + + +find_package(Python COMPONENTS Interpreter REQUIRED) + +find_program(STDGPU_DOXYSPHINX doxysphinx REQUIRED) +find_program(STDGPU_SPHINX sphinx-build REQUIRED) + + +set(STDGPU_SPHINX_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/html") +set(STDGPU_SPHINX_DOXYGEN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/doxygen") +set(STDGPU_SPHINX_FORCE_BUILDING "-E") +set(STDGPU_SPHINX_PARALLEL "-j" "auto") + +add_custom_target(stdgpu_doc + # Pre. Clean previous build + COMMAND ${CMAKE_COMMAND} -E rm -Rf "${STDGPU_SPHINX_OUTPUT_DIR}" "${STDGPU_SPHINX_DOXYGEN_DIR}" + # 1. Run Doxygen + COMMAND Doxygen::doxygen "${STDGPU_DOXYFILE}" + # 2. Run Doxysphinx + COMMAND ${STDGPU_DOXYSPHINX} build "${CMAKE_CURRENT_SOURCE_DIR}" "${STDGPU_SPHINX_OUTPUT_DIR}" "${STDGPU_SPHINX_DOXYGEN_DIR}" + # 2.1. Remove unused main page + COMMAND ${CMAKE_COMMAND} -E rm "${STDGPU_SPHINX_DOXYGEN_DIR}/index.rst" + # 2.2. Fix Doxysphinx files + COMMAND Python::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/fix_html_titles" + # 4. Run Sphinx + COMMAND ${STDGPU_SPHINX} "-b" "html" ${STDGPU_SPHINX_FORCE_BUILDING} ${STDGPU_SPHINX_PARALLEL} "${CMAKE_CURRENT_SOURCE_DIR}" "${STDGPU_SPHINX_OUTPUT_DIR}" + COMMENT "Generating stdgpu documentation" + VERBATIM) diff --git a/doc/Doxyfile.in b/docs/Doxyfile.in similarity index 98% rename from doc/Doxyfile.in rename to docs/Doxyfile.in index 4a48e39b3..71b3136c5 100644 --- a/doc/Doxyfile.in +++ b/docs/Doxyfile.in @@ -61,14 +61,14 @@ PROJECT_BRIEF = @stdgpu_DESCRIPTION@ # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = @CMAKE_CURRENT_SOURCE_DIR@/stdgpu_logo.png +PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = . +OUTPUT_DIRECTORY = @CMAKE_CURRENT_SOURCE_DIR@ # If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 # sub-directories (in 2 levels) under the output directory of each output format @@ -193,7 +193,7 @@ STRIP_FROM_PATH = @STDGPU_INCLUDE_DIR@ # specify the list of include paths that are normally passed to the compiler # using the -I flag. -STRIP_FROM_INC_PATH = @STDGPU_INCLUDE_DIR@ +STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't @@ -283,7 +283,8 @@ TAB_SIZE = 4 # with the commands \{ and \} for these it is advised to use the version @{ and # @} or use a double escape (\\{ and \\}) -ALIASES = +ALIASES = "rst=\verbatim embed:rst:leading-asterisk" \ + endrst=\endverbatim # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For @@ -413,7 +414,7 @@ IDL_PROPERTY_SUPPORT = YES # all members of a group must be documented explicitly. # The default value is: NO. -DISTRIBUTE_GROUP_DOC = YES +DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option @@ -525,7 +526,7 @@ EXTRACT_PACKAGE = NO # included in the documentation. # The default value is: NO. -EXTRACT_STATIC = YES +EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, @@ -920,7 +921,7 @@ WARN_LOGFILE = # Note: If this tag is empty the current directory is searched. INPUT = @STDGPU_INCLUDE_DIR@/stdgpu \ - @CMAKE_CURRENT_SOURCE_DIR@/stdgpu + @CMAKE_CURRENT_SOURCE_DIR@/doxygen_src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -1230,7 +1231,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = html +HTML_OUTPUT = doxygen # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). @@ -1257,7 +1258,7 @@ HTML_FILE_EXTENSION = .html # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_HEADER = @CMAKE_CURRENT_SOURCE_DIR@/header.html +HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard @@ -1267,7 +1268,7 @@ HTML_HEADER = @CMAKE_CURRENT_SOURCE_DIR@/header.html # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_FOOTER = @CMAKE_CURRENT_SOURCE_DIR@/footer.html +HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of @@ -1297,12 +1298,8 @@ HTML_STYLESHEET = # documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = @STDGPU_DOXYGEN_AWESOME_CSS_DIR@/doxygen-awesome.css \ - @STDGPU_DOXYGEN_AWESOME_CSS_DIR@/doxygen-awesome-sidebar-only.css \ - @STDGPU_DOXYGEN_AWESOME_CSS_DIR@/doxygen-awesome-sidebar-only-darkmode-toggle.css \ - @STDGPU_DOXYGEN_AWESOME_CSS_DIR@/doxygen-awesome-fragment-copy-button.js \ - @STDGPU_DOXYGEN_AWESOME_CSS_DIR@/doxygen-awesome-paragraph-link.js \ - @CMAKE_CURRENT_SOURCE_DIR@/custom.css +HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/_static/extra_stylesheet.css \ + @CMAKE_CURRENT_SOURCE_DIR@/_static/stdgpu_custom_doxygen.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note @@ -1312,8 +1309,7 @@ HTML_EXTRA_STYLESHEET = @STDGPU_DOXYGEN_AWESOME_CSS_DIR@/doxygen-awesome.css \ # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_FILES = @STDGPU_DOXYGEN_AWESOME_CSS_DIR@/doxygen-awesome-darkmode-toggle.js \ - @CMAKE_CURRENT_SOURCE_DIR@/stdgpu_logo.ico +HTML_EXTRA_FILES = # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output # should be rendered with a dark or light theme. @@ -1626,7 +1622,7 @@ DISABLE_INDEX = NO # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = YES +GENERATE_TREEVIEW = NO # When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the # FULL_SIDEBAR option determines if the side bar is limited to only the treeview @@ -1790,7 +1786,7 @@ MATHJAX_CODEFILE = # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. -SEARCHENGINE = YES +SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using JavaScript. There @@ -2347,7 +2343,7 @@ TAGFILES = # tag file that is based on the input files it reads. See section "Linking to # external documentation" for more information about the usage of tag files. -GENERATE_TAGFILE = +GENERATE_TAGFILE = @CMAKE_CURRENT_SOURCE_DIR@/doxygen/tagfile.xml # If the ALLEXTERNALS tag is set to YES, all external class will be listed in # the class index. If set to NO, only the inherited external classes will be diff --git a/doc/DoxygenLayout.xml b/docs/DoxygenLayout.xml similarity index 100% rename from doc/DoxygenLayout.xml rename to docs/DoxygenLayout.xml diff --git a/docs/_static/extra_stylesheet.css b/docs/_static/extra_stylesheet.css new file mode 100644 index 000000000..2cd14b5a1 --- /dev/null +++ b/docs/_static/extra_stylesheet.css @@ -0,0 +1,2498 @@ +/** + +Doxygen Awesome +https://github.com/jothepro/doxygen-awesome-css + +MIT License + +Copyright (c) 2021 - 2023 jothepro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Modified to work with doxysphinx and the PyData Sphinx theme + +Modifications Copyright (c) 2019, Advanced Micro Devices, Inc. All rights reserved. +*/ + +html { + /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ + --primary-color: #1779c4; + --primary-dark-color: #335c80; + --primary-light-color: #70b1e9; + + /* page base colors */ + --page-background-color: transparent; + --page-foreground-color: #2f4153; + --page-secondary-foreground-color: #6f7e8e; + + /* color for all separators on the website: hr, borders, ... */ + --separator-color: #dedede; + + /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */ + --border-radius-large: 8px; + --border-radius-small: 4px; + --border-radius-medium: 6px; + + /* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */ + --spacing-small: 5px; + --spacing-medium: 10px; + --spacing-large: 16px; + + /* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */ + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); + + --odd-color: rgba(0,0,0,.028); + + /* font-families. will affect all text on the website + * font-family: the normal font for text, headlines, menus + * font-family-monospace: used for preformatted text in memtitle, code, fragments + */ + --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif; + --font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; + + /* font sizes */ + --page-font-size: 15.6px; + --navigation-font-size: 14.4px; + --toc-font-size: 13.4px; + --code-font-size: 14px; /* affects code, fragment */ + --title-font-size: 22px; + + /* content text properties. These only affect the page content, not the navigation or any other ui elements */ + --content-line-height: 27px; + /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/ + --content-maxwidth: auto; + --table-line-height: 24px; + --toc-sticky-top: var(--spacing-medium); + --toc-width: 200px; + --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px); + + /* colors for various content boxes: @warning, @note, @deprecated @bug */ + --warning-color: #f8d1cc; + --warning-color-dark: #b61825; + --warning-color-darker: #75070f; + --note-color: #faf3d8; + --note-color-dark: #f3a600; + --note-color-darker: #5f4204; + --todo-color: #e4f3ff; + --todo-color-dark: #1879C4; + --todo-color-darker: #274a5c; + --deprecated-color: #ecf0f3; + --deprecated-color-dark: #5b6269; + --deprecated-color-darker: #43454a; + --bug-color: #e4dafd; + --bug-color-dark: #5b2bdd; + --bug-color-darker: #2a0d72; + --invariant-color: #d8f1e3; + --invariant-color-dark: #44b86f; + --invariant-color-darker: #265532; + + /* blockquote colors */ + --blockquote-background: #f8f9fa; + --blockquote-foreground: #636568; + + /* table colors */ + --tablehead-background: #f1f1f1; + --tablehead-foreground: var(--page-foreground-color); + + /* menu-display: block | none + * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible. + * `GENERATE_TREEVIEW` MUST be enabled! + */ + --menu-display: block; + + --menu-focus-foreground: var(--page-background-color); + --menu-focus-background: var(--primary-color); + --menu-selected-background: rgba(0,0,0,.05); + + + --header-background: var(--page-background-color); + --header-foreground: var(--page-foreground-color); + + /* searchbar colors */ + --searchbar-background: var(--side-nav-background); + --searchbar-foreground: var(--page-foreground-color); + + /* searchbar size + * (`searchbar-width` is only applied on screens >= 768px. + * on smaller screens the searchbar will always fill the entire screen width) */ + --searchbar-height: 33px; + --searchbar-width: 210px; + --searchbar-border-radius: var(--searchbar-height); + + /* code block colors */ + --code-background: #f5f5f5; + --code-foreground: var(--page-foreground-color); + + /* fragment colors */ + --fragment-background: #F8F9FA; + --fragment-foreground: #37474F; + --fragment-keyword: #bb6bb2; + --fragment-keywordtype: #8258b3; + --fragment-keywordflow: #d67c3b; + --fragment-token: #438a59; + --fragment-comment: #969696; + --fragment-link: #5383d6; + --fragment-preprocessor: #46aaa5; + --fragment-linenumber-color: #797979; + --fragment-linenumber-background: #f4f4f5; + --fragment-linenumber-border: #e3e5e7; + --fragment-lineheight: 20px; + + /* sidebar navigation (treeview) colors */ + --side-nav-background: #fbfbfb; + --side-nav-foreground: var(--page-foreground-color); + --side-nav-arrow-opacity: 0; + --side-nav-arrow-hover-opacity: 0.9; + + --toc-background: var(--side-nav-background); + --toc-foreground: var(--side-nav-foreground); + + /* height of an item in any tree / collapsible table */ + --tree-item-height: 30px; + + --memname-font-size: var(--code-font-size); + --memtitle-font-size: 18px; + + --webkit-scrollbar-size: 7px; + --webkit-scrollbar-padding: 4px; + --webkit-scrollbar-color: var(--separator-color); +} + +@media screen and (max-width: 767px) { + html { + --page-font-size: 16px; + --navigation-font-size: 16px; + --toc-font-size: 15px; + --code-font-size: 15px; /* affects code, fragment */ + --title-font-size: 22px; + } +} + +@media (prefers-color-scheme: dark) { + html:not([data-theme=light]) { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.35); + + --odd-color: rgba(100,100,100,.06); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: transparent; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #2e1917; + --warning-color-dark: #ad2617; + --warning-color-darker: #f5b1aa; + --note-color: #3b2e04; + --note-color-dark: #f1b602; + --note-color-darker: #ceb670; + --todo-color: #163750; + --todo-color-dark: #1982D2; + --todo-color-darker: #dcf0fa; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2a2536; + --bug-color-dark: #7661b3; + --bug-color-darker: #ae9ed6; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; + } +} + +/* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */ +html[data-theme=dark] { + color-scheme: dark; + + --primary-color: #1982d2; + --primary-dark-color: #86a9c4; + --primary-light-color: #4779ac; + + --box-shadow: 0 2px 8px 0 rgba(0,0,0,.30); + + --odd-color: rgba(100,100,100,.12); + + --menu-selected-background: rgba(0,0,0,.4); + + --page-background-color: transparent; + --page-foreground-color: #d2dbde; + --page-secondary-foreground-color: #859399; + --separator-color: #38393b; + --side-nav-background: #252628; + + --code-background: #2a2c2f; + + --tablehead-background: #2a2c2f; + + --blockquote-background: #222325; + --blockquote-foreground: #7e8c92; + + --warning-color: #2e1917; + --warning-color-dark: #ad2617; + --warning-color-darker: #f5b1aa; + --note-color: #3b2e04; + --note-color-dark: #f1b602; + --note-color-darker: #ceb670; + --todo-color: #163750; + --todo-color-dark: #1982D2; + --todo-color-darker: #dcf0fa; + --deprecated-color: #2e323b; + --deprecated-color-dark: #738396; + --deprecated-color-darker: #abb0bd; + --bug-color: #2a2536; + --bug-color-dark: #7661b3; + --bug-color-darker: #ae9ed6; + --invariant-color: #303a35; + --invariant-color-dark: #76ce96; + --invariant-color-darker: #cceed5; + + --fragment-background: #282c34; + --fragment-foreground: #dbe4eb; + --fragment-keyword: #cc99cd; + --fragment-keywordtype: #ab99cd; + --fragment-keywordflow: #e08000; + --fragment-token: #7ec699; + --fragment-comment: #999999; + --fragment-link: #98c0e3; + --fragment-preprocessor: #65cabe; + --fragment-linenumber-color: #cccccc; + --fragment-linenumber-background: #35393c; + --fragment-linenumber-border: #1f1f1f; +} + +.doxygen-content { + color: var(--page-foreground-color); + background-color: var(--page-background-color); + font-size: var(--page-font-size); +} + +.doxygen-content, .doxygen-content table, .doxygen-content div, .doxygen-content p, .doxygen-content dl, .doxygen-content #nav-tree .label, .doxygen-content .title, +.doxygen-content .sm-dox a, .doxygen-content .sm-dox a:hover, .doxygen-content .sm-dox a:focus, .doxygen-content #projectname, +.doxygen-content .SelectItem, .doxygen-content #MSearchField, .doxygen-content .navpath li.navelem a, +.doxygen-content .navpath li.navelem a:hover, .doxygen-content p.reference, .doxygen-content p.definition { + font-family: var(--font-family); +} + +.doxygen-content h1, .doxygen-content h2, .doxygen-content h3, .doxygen-content h4, .doxygen-content h5 { + margin-top: .9em; + font-weight: 600; + line-height: initial; +} + +.doxygen-content p, .doxygen-content div, .doxygen-content table, .doxygen-content dl, .doxygen-content p.reference, .doxygen-content p.definition { + font-size: var(--page-font-size); +} + +.doxygen-content p.reference, .doxygen-content p.definition { + color: var(--page-secondary-foreground-color); +} + +.doxygen-content a:link, .doxygen-content a:visited, .doxygen-content a:hover, .doxygen-content a:focus, .doxygen-content a:active { + color: var(--primary-color) !important; + font-weight: 500; +} + +.doxygen-content a.anchor { + scroll-margin-top: var(--spacing-large); + display: block; +} + +/* + Title and top navigation + */ + +.doxygen-content #top { + background: var(--header-background); + border-bottom: 1px solid var(--separator-color); +} + +@media screen and (min-width: 768px) { + .doxygen-content #top { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + } +} + +.doxygen-content #main-nav { + flex-grow: 5; + padding: var(--spacing-small) var(--spacing-medium); +} + +.doxygen-content #titlearea { + width: auto; + padding: var(--spacing-medium) var(--spacing-large); + background: none; + color: var(--header-foreground); + border-bottom: none; +} + +@media screen and (max-width: 767px) { + .doxygen-content #titlearea { + padding-bottom: var(--spacing-small); + } +} + +.doxygen-content #titlearea table tbody tr { + height: auto !important; +} + +.doxygen-content #projectname { + font-size: var(--title-font-size); + font-weight: 600; +} + +.doxygen-content #projectnumber { + font-family: inherit; + font-size: 60%; +} + +.doxygen-content #projectbrief { + font-family: inherit; + font-size: 80%; +} + +.doxygen-content #projectlogo { + vertical-align: middle; +} + +.doxygen-content #projectlogo img { + max-height: calc(var(--title-font-size) * 2); + margin-right: var(--spacing-small); +} + +.doxygen-content .sm-dox, .doxygen-content .tabs, .doxygen-content .tabs2, .doxygen-content .tabs3 { + background: none; + padding: 0; +} + +.doxygen-content .tabs, .doxygen-content .tabs2, .doxygen-content .tabs3 { + border-bottom: 1px solid var(--separator-color); + margin-bottom: -1px; +} + +.doxygen-content .main-menu-btn-icon, .doxygen-content .main-menu-btn-icon:before, .doxygen-content .main-menu-btn-icon:after { + background: var(--page-secondary-foreground-color); +} + +@media screen and (max-width: 767px) { + .doxygen-content .sm-dox a span.sub-arrow { + background: var(--code-background); + } + + .doxygen-content #main-menu a.has-submenu span.sub-arrow { + color: var(--page-secondary-foreground-color); + border-radius: var(--border-radius-medium); + } + + .doxygen-content #main-menu a.has-submenu:hover span.sub-arrow { + color: var(--page-foreground-color); + } +} + +@media screen and (min-width: 768px) { + .doxygen-content .sm-dox li, .doxygen-content .tablist li { + display: var(--menu-display); + } + + .doxygen-content .sm-dox a span.sub-arrow { + border-color: var(--header-foreground) transparent transparent transparent; + } + + .doxygen-content .sm-dox a:hover span.sub-arrow { + border-color: var(--menu-focus-foreground) transparent transparent transparent; + } + + .doxygen-content .sm-dox ul a span.sub-arrow { + border-color: transparent transparent transparent var(--page-foreground-color); + } + + .doxygen-content .sm-dox ul a:hover span.sub-arrow { + border-color: transparent transparent transparent var(--menu-focus-foreground); + } +} + +.doxygen-content .sm-dox ul { + background: var(--page-background-color); + box-shadow: var(--box-shadow); + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium) !important; + padding: var(--spacing-small); + animation: ease-out 150ms slideInMenu; +} + +@keyframes slideInMenu { + from { + opacity: 0; + transform: translate(0px, -2px); + } + + to { + opacity: 1; + transform: translate(0px, 0px); + } +} + +.doxygen-content .sm-dox ul a { + color: var(--page-foreground-color) !important; + background: var(--page-background-color); + font-size: var(--navigation-font-size); +} + +.doxygen-content .sm-dox>li>ul:after { + border-bottom-color: var(--page-background-color) !important; +} + +.doxygen-content .sm-dox>li>ul:before { + border-bottom-color: var(--separator-color) !important; +} + +.doxygen-content .sm-dox ul a:hover, .doxygen-content .sm-dox ul a:active, .doxygen-content .sm-dox ul a:focus { + font-size: var(--navigation-font-size) !important; + color: var(--menu-focus-foreground) !important; + text-shadow: none; + background-color: var(--menu-focus-background); + border-radius: var(--border-radius-small) !important; +} + +.doxygen-content .sm-dox a, .doxygen-content .sm-dox a:focus, .doxygen-content .tablist li, .doxygen-content .tablist li a, .doxygen-content .tablist li.current a { + text-shadow: none; + background: transparent; + background-image: none !important; + color: var(--header-foreground) !important; + font-weight: normal; + font-size: var(--navigation-font-size); + border-radius: var(--border-radius-small) !important; +} + +.doxygen-content .sm-dox a:focus { + outline: auto; +} + +.doxygen-content .sm-dox a:hover, .doxygen-content .sm-dox a:active, .doxygen-content .tablist li a:hover { + text-shadow: none; + font-weight: normal; + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; + border-radius: var(--border-radius-small) !important; + font-size: var(--navigation-font-size); +} + +.doxygen-content .tablist li.current { + border-radius: var(--border-radius-small); + background: var(--menu-selected-background); +} + +.doxygen-content .tablist li { + margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small); +} + +.doxygen-content .tablist a { + padding: 0 var(--spacing-large); +} + + +/* + Search box + */ + +.doxygen-content #MSearchBox { + height: var(--searchbar-height); + background: var(--searchbar-background); + border-radius: var(--searchbar-border-radius); + border: 1px solid var(--separator-color); + overflow: hidden; + width: var(--searchbar-width); + position: relative; + box-shadow: none; + display: block; + margin-top: 0; +} + +/* until Doxygen 1.9.4 */ +.doxygen-content .left img#MSearchSelect { + left: 0; + user-select: none; + padding-left: 8px; +} + +/* Doxygen 1.9.5 */ +.doxygen-content .left span#MSearchSelect { + left: 0; + user-select: none; + margin-left: 8px; + padding: 0; +} + +.doxygen-content .left #MSearchSelect[src$=".png"] { + padding-left: 0 +} + +.doxygen-content .SelectionMark { + user-select: none; +} + +.doxygen-content .tabs .left #MSearchSelect { + padding-left: 0; +} + +.doxygen-content .tabs #MSearchBox { + position: absolute; + right: var(--spacing-medium); +} + +@media screen and (max-width: 767px) { + .doxygen-content .tabs #MSearchBox { + position: relative; + right: 0; + margin-left: var(--spacing-medium); + margin-top: 0; + } +} + +.doxygen-content #MSearchSelectWindow, .doxygen-content #MSearchResultsWindow { + z-index: 9999; +} + +.doxygen-content #MSearchBox.MSearchBoxActive { + border-color: var(--primary-color); + box-shadow: inset 0 0 0 1px var(--primary-color); +} + +.doxygen-content #main-menu > li:last-child { + margin-right: 0; +} + +@media screen and (max-width: 767px) { + .doxygen-content #main-menu > li:last-child { + height: 50px; + } +} + +.doxygen-content #MSearchField { + font-size: var(--navigation-font-size); + height: calc(var(--searchbar-height) - 2px); + background: transparent; + width: calc(var(--searchbar-width) - 64px); +} + +.doxygen-content .MSearchBoxActive #MSearchField { + color: var(--searchbar-foreground); +} + +.doxygen-content #MSearchSelect { + top: calc(calc(var(--searchbar-height) / 2) - 11px); +} + +.doxygen-content #MSearchBox span.left, .doxygen-content #MSearchBox span.right { + background: none; + background-image: none; +} + +.doxygen-content #MSearchBox span.right { + padding-top: calc(calc(var(--searchbar-height) / 2) - 12px); + position: absolute; + right: var(--spacing-small); +} + +.doxygen-content .tabs #MSearchBox span.right { + top: calc(calc(var(--searchbar-height) / 2) - 12px); +} + +@keyframes slideInSearchResults { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } +} + +.doxygen-content #MSearchResultsWindow { + left: auto !important; + right: var(--spacing-medium); + border-radius: var(--border-radius-large); + border: 1px solid var(--separator-color); + transform: translate(0, 20px); + box-shadow: var(--box-shadow); + animation: ease-out 280ms slideInSearchResults; + background: var(--page-background-color); +} + +.doxygen-content iframe#MSearchResults { + margin: 4px; +} + +.doxygen-content iframe { + color-scheme: normal; +} + +@media (prefers-color-scheme: dark) { + html:not([data-theme=light]) .doxygen-content iframe#MSearchResults { + filter: invert() hue-rotate(180deg); + } +} + +html[data-theme=dark] .doxygen-content iframe#MSearchResults { + filter: invert() hue-rotate(180deg); +} + +.doxygen-content #MSearchResults .SRPage { + background-color: transparent; +} + +.doxygen-content #MSearchResults .SRPage .SREntry { + font-size: 10pt; + padding: var(--spacing-small) var(--spacing-medium); +} + +.doxygen-content #MSearchSelectWindow { + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + box-shadow: var(--box-shadow); + background: var(--page-background-color); + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); +} + +.doxygen-content #MSearchSelectWindow a.SelectItem { + font-size: var(--navigation-font-size); + line-height: var(--content-line-height); + margin: 0 var(--spacing-small); + border-radius: var(--border-radius-small); + color: var(--page-foreground-color) !important; + font-weight: normal; +} + +.doxygen-content #MSearchSelectWindow a.SelectItem:hover { + background: var(--menu-focus-background); + color: var(--menu-focus-foreground) !important; +} + +@media screen and (max-width: 767px) { + .doxygen-content #MSearchBox { + margin-top: var(--spacing-medium); + margin-bottom: var(--spacing-medium); + width: calc(100vw - 30px); + } + + .doxygen-content #main-menu > li:last-child { + float: none !important; + } + + .doxygen-content #MSearchField { + width: calc(100vw - 110px); + } + + @keyframes slideInSearchResultsMobile { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } + } + + .doxygen-content #MSearchResultsWindow { + left: var(--spacing-medium) !important; + right: var(--spacing-medium); + overflow: auto; + transform: translate(0, 20px); + animation: ease-out 280ms slideInSearchResultsMobile; + width: auto !important; + } + + /* + * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2 + */ + .doxygen-content label.main-menu-btn ~ #searchBoxPos1 { + top: 3px !important; + right: 6px !important; + left: 45px; + display: flex; + } + + .doxygen-content label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox { + margin-top: 0; + margin-bottom: 0; + flex-grow: 2; + float: left; + } +} + +/* + Tree view + */ + +.doxygen-content #side-nav { + padding: 0 !important; + background: var(--side-nav-background); +} + +@media screen and (max-width: 767px) { + .doxygen-content #side-nav { + display: none; + } + + .doxygen-content #doc-content { + margin-left: 0 !important; + } +} + +.doxygen-content #nav-tree { + background: transparent; + margin-right: 1px; +} + +.doxygen-content #nav-tree .label { + font-size: var(--navigation-font-size); +} + +.doxygen-content #nav-tree .item { + height: var(--tree-item-height); + line-height: var(--tree-item-height); +} + +.doxygen-content #nav-sync { + bottom: 12px; + right: 12px; + top: auto !important; + user-select: none; +} + +.doxygen-content #nav-tree .selected { + text-shadow: none; + background-image: none; + background-color: transparent; + position: relative; +} + +.doxygen-content #nav-tree .selected::after { + content: ""; + position: absolute; + top: 1px; + bottom: 1px; + left: 0; + width: 4px; + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + background: var(--primary-color); +} + + +.doxygen-content #nav-tree a { + color: var(--side-nav-foreground) !important; + font-weight: normal; +} + +.doxygen-content #nav-tree a:focus { + outline-style: auto; +} + +.doxygen-content #nav-tree .arrow { + opacity: var(--side-nav-arrow-opacity); +} + +.doxygen-content .arrow { + color: inherit; + cursor: pointer; + font-size: 45%; + vertical-align: middle; + margin-right: 2px; + font-family: serif; + height: auto; + text-align: right; +} + +.doxygen-content #nav-tree div.item:hover .arrow, .doxygen-content #nav-tree a:focus .arrow { + opacity: var(--side-nav-arrow-hover-opacity); +} + +.doxygen-content #nav-tree .selected a { + color: var(--primary-color) !important; + font-weight: bolder; + font-weight: 600; +} + +.doxygen-content .ui-resizable-e { + background: var(--separator-color); + width: 1px; +} + +/* + Contents + */ + +.doxygen-content div.header { + border-bottom: 1px solid var(--separator-color); + background-color: var(--page-background-color); + background-image: none; +} + +@media screen and (min-width: 1000px) { + .doxygen-content #doc-content > div > div.contents, + .doxygen-content .PageDoc > div.contents { + display: flex; + flex-direction: row-reverse; + flex-wrap: nowrap; + align-items: flex-start; + } + + .doxygen-content div.contents .textblock { + min-width: 200px; + flex-grow: 1; + } +} + +.doxygen-content div.contents, .doxygen-content div.header .title, .doxygen-content div.header .summary { + max-width: var(--content-maxwidth); +} + +.doxygen-content div.contents, .doxygen-content div.header .title { + line-height: initial; + margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto; +} + +.doxygen-content div.header .summary { + margin: var(--spacing-medium) auto 0 auto; +} + +.doxygen-content div.headertitle { + padding: 0; +} + +.doxygen-content div.header .title { + font-weight: 600; + font-size: 225%; + padding: var(--spacing-medium) var(--spacing-large); + word-break: break-word; +} + +.doxygen-content div.header .summary { + width: auto; + display: block; + float: none; + padding: 0 var(--spacing-large); +} + +.doxygen-content td.memSeparator { + border-color: var(--separator-color); +} + +.doxygen-content span.mlabel { + background: var(--primary-color); + border: none; + padding: 4px 9px; + border-radius: 12px; + margin-right: var(--spacing-medium); +} + +.doxygen-content span.mlabel:last-of-type { + margin-right: 2px; +} + +.doxygen-content div.contents { + padding: 0 var(--spacing-large); +} + +.doxygen-content div.contents p, .doxygen-content div.contents li { + line-height: var(--content-line-height); +} + +.doxygen-content div.contents div.dyncontent { + margin: var(--spacing-medium) 0; +} + +@media (prefers-color-scheme: dark) { + html:not([data-theme=light]) .doxygen-content div.contents div.dyncontent img, + html:not([data-theme=light]) .doxygen-content div.contents center img, + html:not([data-theme=light]) .doxygen-content div.contents > table img, + html:not([data-theme=light]) .doxygen-content div.contents div.dyncontent iframe, + html:not([data-theme=light]) .doxygen-content div.contents center iframe, + html:not([data-theme=light]) .doxygen-content div.contents table iframe, + html:not([data-theme=light]) .doxygen-content div.contents .dotgraph iframe { + filter: brightness(89%) hue-rotate(180deg) invert(); + } +} + +html[data-theme=dark] .doxygen-content div.contents div.dyncontent img, +html[data-theme=dark] .doxygen-content div.contents center img, +html[data-theme=dark] .doxygen-content div.contents > table img, +html[data-theme=dark] .doxygen-content div.contents div.dyncontent iframe, +html[data-theme=dark] .doxygen-content div.contents center iframe, +html[data-theme=dark] .doxygen-content div.contents table iframe, +html[data-theme=dark] .doxygen-content div.contents .dotgraph iframe + { + filter: brightness(89%) hue-rotate(180deg) invert(); +} + +.doxygen-content h2.groupheader { + border-bottom: 0px; + color: var(--page-foreground-color); + border-bottom: 1px solid var(--separator-color); +} + +.doxygen-content blockquote { + margin: 0 var(--spacing-medium) 0 var(--spacing-medium); + padding: var(--spacing-small) var(--spacing-large); + background: var(--blockquote-background); + color: var(--blockquote-foreground); + border-left: 0; + overflow: visible; + border-radius: var(--border-radius-medium); + overflow: visible; + position: relative; +} + +.doxygen-content blockquote::before, .doxygen-content blockquote::after { + font-weight: bold; + font-family: serif; + font-size: 360%; + opacity: .15; + position: absolute; +} + +.doxygen-content blockquote::before { + content: "“"; + left: -10px; + top: 4px; +} + +.doxygen-content blockquote::after { + content: "”"; + right: -8px; + bottom: -25px; +} + +.doxygen-content blockquote p { + margin: var(--spacing-small) 0 var(--spacing-medium) 0; +} +.doxygen-content .paramname { + font-weight: 600; + color: var(--primary-dark-color); +} + +.doxygen-content .paramname > code { + border: 0; +} + +.doxygen-content table.params .paramname { + font-weight: 600; + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + padding-right: var(--spacing-small); + line-height: var(--table-line-height); +} + +.doxygen-content h1.glow, .doxygen-content h2.glow, .doxygen-content h3.glow, .doxygen-content h4.glow, .doxygen-content h5.glow, .doxygen-content h6.glow { + text-shadow: 0 0 15px var(--primary-light-color); +} + +.doxygen-content .alphachar a { + color: var(--page-foreground-color); +} + +.doxygen-content .dotgraph { + max-width: 100%; + overflow-x: scroll; +} + +.doxygen-content .dotgraph .caption { + position: sticky; + left: 0; +} + +/* Wrap Graphviz graphs with the `interactive_dotgraph` class if `INTERACTIVE_SVG = YES` */ +.doxygen-content .interactive_dotgraph .dotgraph iframe { + max-width: 100%; +} + +/* + Table of Contents + */ + +.doxygen-content div.contents .toc { + max-height: var(--toc-max-height); + min-width: var(--toc-width); + border: 0; + border-left: 1px solid var(--separator-color); + border-radius: 0; + background-color: transparent; + box-shadow: none; + position: sticky; + top: var(--toc-sticky-top); + padding: 0 var(--spacing-large); + margin: var(--spacing-small) 0 var(--spacing-large) var(--spacing-large); +} + +.doxygen-content div.toc h3 { + color: var(--toc-foreground); + font-size: var(--navigation-font-size); + margin: var(--spacing-large) 0 var(--spacing-medium) 0; +} + +.doxygen-content div.toc li { + padding: 0; + background: none; + line-height: var(--toc-font-size); + margin: var(--toc-font-size) 0 0 0; +} + +.doxygen-content div.toc li::before { + display: none; +} + +.doxygen-content div.toc ul { + margin-top: 0 +} + +.doxygen-content div.toc li a { + font-size: var(--toc-font-size); + color: var(--page-foreground-color) !important; + text-decoration: none; +} + +.doxygen-content div.toc li a:hover, .doxygen-content div.toc li a.active { + color: var(--primary-color) !important; +} + +.doxygen-content div.toc li a.aboveActive { + color: var(--page-secondary-foreground-color) !important; +} + + +@media screen and (max-width: 999px) { + .doxygen-content div.contents .toc { + max-height: 45vh; + float: none; + width: auto; + margin: 0 0 var(--spacing-medium) 0; + position: relative; + top: 0; + position: relative; + border: 1px solid var(--separator-color); + border-radius: var(--border-radius-medium); + background-color: var(--toc-background); + box-shadow: var(--box-shadow); + } + + .doxygen-content div.contents .toc.interactive { + max-height: calc(var(--navigation-font-size) + 2 * var(--spacing-large)); + overflow: hidden; + } + + .doxygen-content div.contents .toc > h3 { + -webkit-tap-highlight-color: transparent; + cursor: pointer; + position: sticky; + top: 0; + background-color: var(--toc-background); + margin: 0; + padding: var(--spacing-large) 0; + display: block; + } + + .doxygen-content div.contents .toc.interactive > h3::before { + content: ""; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + display: inline-block; + margin-right: var(--spacing-small); + margin-bottom: calc(var(--navigation-font-size) / 4); + transform: rotate(-90deg); + transition: transform 0.25s ease-out; + } + + .doxygen-content div.contents .toc.interactive.open > h3::before { + transform: rotate(0deg); + } + + .doxygen-content div.contents .toc.interactive.open { + max-height: 45vh; + overflow: auto; + transition: max-height 0.2s ease-in-out; + } + + .doxygen-content div.contents .toc a, .doxygen-content div.contents .toc a.active { + color: var(--primary-color) !important; + } + + .doxygen-content div.contents .toc a:hover { + text-decoration: underline; + } +} + +/* + Code & Fragments + */ + +.doxygen-content code, .doxygen-content div.fragment, .doxygen-content pre.fragment { + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + overflow: hidden; +} + +.doxygen-content code { + display: inline; + background: var(--code-background); + color: var(--code-foreground); + padding: 2px 6px; +} + +.doxygen-content div.fragment, .doxygen-content pre.fragment { + margin: var(--spacing-medium) 0; + padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large); + background: var(--fragment-background); + color: var(--fragment-foreground); + overflow-x: auto; +} + +@media screen and (max-width: 767px) { + .doxygen-content div.fragment, .doxygen-content pre.fragment { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right: 0; + } + + .doxygen-content .contents > div.fragment, + .doxygen-content .textblock > div.fragment, + .doxygen-content .textblock > pre.fragment, + .doxygen-content .contents > .doxygen-awesome-fragment-wrapper > div.fragment, + .doxygen-content .textblock > .doxygen-awesome-fragment-wrapper > div.fragment, + .doxygen-content .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + border-radius: 0; + border-left: 0; + } + + .doxygen-content .textblock li > .fragment, + .doxygen-content .textblock li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-large)); + } + + .doxygen-content .memdoc li > .fragment, + .doxygen-content .memdoc li > .doxygen-awesome-fragment-wrapper > .fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + } + + .doxygen-content .textblock ul, .doxygen-content .memdoc ul { + overflow: initial; + } + + .doxygen-content .memdoc > div.fragment, + .doxygen-content .memdoc > pre.fragment, + .doxygen-content dl dd > div.fragment, + .doxygen-content dl dd pre.fragment, + .doxygen-content .memdoc > .doxygen-awesome-fragment-wrapper > div.fragment, + .doxygen-content .memdoc > .doxygen-awesome-fragment-wrapper > pre.fragment, + .doxygen-content dl dd > .doxygen-awesome-fragment-wrapper > div.fragment, + .doxygen-content dl dd .doxygen-awesome-fragment-wrapper > pre.fragment { + margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); + border-radius: 0; + border-left: 0; + } +} + +.doxygen-content code, .doxygen-content code a, .doxygen-content pre.fragment, .doxygen-content div.fragment, .doxygen-content div.fragment .line, .doxygen-content div.fragment span, .doxygen-content div.fragment .line a, .doxygen-content div.fragment .line span { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size) !important; +} + +.doxygen-content div.line:after { + margin-right: var(--spacing-medium); +} + +.doxygen-content div.fragment .line, .doxygen-content pre.fragment { + white-space: pre; + word-wrap: initial; + line-height: var(--fragment-lineheight); +} + +.doxygen-content div.fragment span.keyword { + color: var(--fragment-keyword); +} + +.doxygen-content div.fragment span.keywordtype { + color: var(--fragment-keywordtype); +} + +.doxygen-content div.fragment span.keywordflow { + color: var(--fragment-keywordflow); +} + +.doxygen-content div.fragment span.stringliteral { + color: var(--fragment-token) +} + +.doxygen-content div.fragment span.comment { + color: var(--fragment-comment); +} + +.doxygen-content div.fragment a.code { + color: var(--fragment-link) !important; +} + +.doxygen-content div.fragment span.preprocessor { + color: var(--fragment-preprocessor); +} + +.doxygen-content div.fragment span.lineno { + display: inline-block; + width: 27px; + border-right: none; + background: var(--fragment-linenumber-background); + color: var(--fragment-linenumber-color); +} + +.doxygen-content div.fragment span.lineno a { + background: none; + color: var(--fragment-link) !important; +} + +.doxygen-content div.fragment .line:first-child .lineno { + box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border); +} + +.doxygen-content div.line { + border-radius: var(--border-radius-small); +} + +.doxygen-content div.line.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +/* + dl warning, attention, note, deprecated, bug, ... + */ + +.doxygen-content dl.bug dt a, .doxygen-content dl.deprecated dt a, .doxygen-content dl.todo dt a { + font-weight: bold !important; +} + +.doxygen-content dl.warning, .doxygen-content dl.attention, .doxygen-content dl.note, .doxygen-content dl.deprecated, .doxygen-content dl.bug, .doxygen-content dl.invariant, .doxygen-content dl.pre, .doxygen-content dl.post, .doxygen-content dl.todo, .doxygen-content dl.remark { + padding: var(--spacing-medium); + margin: var(--spacing-medium) 0; + color: var(--page-background-color); + overflow: hidden; + margin-left: 0; + border-radius: var(--border-radius-small); +} + +.doxygen-content dl.section dd { + margin-bottom: 2px; +} + +.doxygen-content dl.warning, .doxygen-content dl.attention { + background: var(--warning-color); + border-left: 8px solid var(--warning-color-dark); + color: var(--warning-color-darker); +} + +.doxygen-content dl.warning dt, .doxygen-content dl.attention dt { + color: var(--warning-color-dark); +} + +.doxygen-content dl.note, .doxygen-content dl.remark { + background: var(--note-color); + border-left: 8px solid var(--note-color-dark); + color: var(--note-color-darker); +} + +.doxygen-content dl.note dt, .doxygen-content dl.remark dt { + color: var(--note-color-dark); +} + +.doxygen-content dl.todo { + background: var(--todo-color); + border-left: 8px solid var(--todo-color-dark); + color: var(--todo-color-darker); +} + +.doxygen-content dl.todo dt { + color: var(--todo-color-dark); +} + +.doxygen-content dl.bug dt a { + color: var(--todo-color-dark) !important; +} + +.doxygen-content dl.bug { + background: var(--bug-color); + border-left: 8px solid var(--bug-color-dark); + color: var(--bug-color-darker); +} + +.doxygen-content dl.bug dt a { + color: var(--bug-color-dark) !important; +} + +.doxygen-content dl.deprecated { + background: var(--deprecated-color); + border-left: 8px solid var(--deprecated-color-dark); + color: var(--deprecated-color-darker); +} + +.doxygen-content dl.deprecated dt a { + color: var(--deprecated-color-dark) !important; +} + +.doxygen-content dl.section dd, .doxygen-content dl.bug dd, .doxygen-content dl.deprecated dd, .doxygen-content dl.todo dd { + margin-inline-start: 0px; +} + +.doxygen-content dl.invariant, .doxygen-content dl.pre, .doxygen-content dl.post { + background: var(--invariant-color); + border-left: 8px solid var(--invariant-color-dark); + color: var(--invariant-color-darker); +} + +.doxygen-content dl.invariant dt, .doxygen-content dl.pre dt, .doxygen-content dl.post dt { + color: var(--invariant-color-dark); +} + +/* + memitem + */ + +.doxygen-content div.memdoc, .doxygen-content div.memproto, .doxygen-content h2.memtitle { + box-shadow: none; + background-image: none; + border: none; +} + +.doxygen-content div.memdoc { + padding: 0 var(--spacing-medium); + background: var(--page-background-color); +} + +.doxygen-content h2.memtitle, .doxygen-content div.memitem { + border: 1px solid var(--separator-color); + box-shadow: var(--box-shadow); +} + +.doxygen-content h2.memtitle { + box-shadow: 0px var(--spacing-medium) 0 -1px var(--fragment-background), var(--box-shadow); +} + +.doxygen-content div.memitem { + transition: none; +} + +.doxygen-content div.memproto, .doxygen-content h2.memtitle { + background: var(--fragment-background); +} + +.doxygen-content h2.memtitle { + font-weight: 500; + font-size: var(--memtitle-font-size); + font-family: var(--font-family-monospace); + border-bottom: none; + border-top-left-radius: var(--border-radius-medium); + border-top-right-radius: var(--border-radius-medium); + word-break: break-all; + position: relative; +} + +.doxygen-content h2.memtitle:after { + content: ""; + display: block; + background: var(--fragment-background); + height: var(--spacing-medium); + bottom: calc(0px - var(--spacing-medium)); + left: 0; + right: -14px; + position: absolute; + border-top-right-radius: var(--border-radius-medium); +} + +.doxygen-content h2.memtitle > span.permalink { + font-size: inherit; +} + +.doxygen-content h2.memtitle > span.permalink > a { + text-decoration: none; + padding-left: 3px; + margin-right: -4px; + user-select: none; + display: inline-block; + margin-top: -6px; +} + +.doxygen-content h2.memtitle > span.permalink > a:hover { + color: var(--primary-dark-color) !important; +} + +.doxygen-content a:target + h2.memtitle, .doxygen-content a:target + h2.memtitle + div.memitem { + border-color: var(--primary-light-color); +} + +.doxygen-content div.memitem { + border-top-right-radius: var(--border-radius-medium); + border-bottom-right-radius: var(--border-radius-medium); + border-bottom-left-radius: var(--border-radius-medium); + overflow: hidden; + display: block !important; +} + +.doxygen-content div.memdoc { + border-radius: 0; +} + +.doxygen-content div.memproto { + border-radius: 0 var(--border-radius-small) 0 0; + overflow: auto; + border-bottom: 1px solid var(--separator-color); + padding: var(--spacing-medium); + margin-bottom: -1px; +} + +.doxygen-content div.memtitle { + border-top-right-radius: var(--border-radius-medium); + border-top-left-radius: var(--border-radius-medium); +} + +.doxygen-content div.memproto table.memname { + font-family: var(--font-family-monospace); + color: var(--page-foreground-color); + font-size: var(--memname-font-size); + text-shadow: none; +} + +.doxygen-content div.memproto div.memtemplate { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--memname-font-size); + margin-left: 2px; + text-shadow: none; +} + +.doxygen-content table.mlabels, .doxygen-content table.mlabels > tbody { + display: block; +} + +.doxygen-content td.mlabels-left { + width: auto; +} + +.doxygen-content td.mlabels-right { + margin-top: 3px; + position: sticky; + left: 0; +} + +.doxygen-content table.mlabels > tbody > tr:first-child { + display: flex; + justify-content: space-between; + flex-wrap: wrap; +} + +.doxygen-content .memname, .doxygen-content .memitem span.mlabels { + margin: 0 +} + +/* + reflist + */ + +.doxygen-content dl.reflist { + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-medium); + border: 1px solid var(--separator-color); + overflow: hidden; + padding: 0; +} + + +.doxygen-content dl.reflist dt, .doxygen-content dl.reflist dd { + box-shadow: none; + text-shadow: none; + background-image: none; + border: none; + padding: 12px; +} + + +.doxygen-content dl.reflist dt { + font-weight: 500; + border-radius: 0; + background: var(--code-background); + border-bottom: 1px solid var(--separator-color); + color: var(--page-foreground-color) +} + + +.doxygen-content dl.reflist dd { + background: none; +} + +/* + Table + */ + +.doxygen-content .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname), +.doxygen-content .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { + display: inline-block; + max-width: 100%; +} + +.doxygen-content .contents > table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); +} + +.doxygen-content table.fieldtable, +.doxygen-content table.markdownTable tbody, +.doxygen-content table.doxtable tbody { + border: none; + margin: var(--spacing-medium) 0; + box-shadow: 0 0 0 1px var(--separator-color); + border-radius: var(--border-radius-small); +} + +.doxygen-content table.markdownTable, .doxygen-content table.doxtable, .doxygen-content table.fieldtable { + padding: 1px; +} + +.doxygen-content table.doxtable caption { + display: block; +} + +.doxygen-content table.fieldtable { + border-collapse: collapse; + width: 100%; +} + +.doxygen-content th.markdownTableHeadLeft, +.doxygen-content th.markdownTableHeadRight, +.doxygen-content th.markdownTableHeadCenter, +.doxygen-content th.markdownTableHeadNone, +.doxygen-content table.doxtable th { + background: var(--tablehead-background); + color: var(--tablehead-foreground); + font-weight: 600; + font-size: var(--page-font-size); +} + +.doxygen-content th.markdownTableHeadLeft:first-child, +.doxygen-content th.markdownTableHeadRight:first-child, +.doxygen-content th.markdownTableHeadCenter:first-child, +.doxygen-content th.markdownTableHeadNone:first-child, +.doxygen-content table.doxtable tr th:first-child { + border-top-left-radius: var(--border-radius-small); +} + +.doxygen-content th.markdownTableHeadLeft:last-child, +.doxygen-content th.markdownTableHeadRight:last-child, +.doxygen-content th.markdownTableHeadCenter:last-child, +.doxygen-content th.markdownTableHeadNone:last-child, +.doxygen-content table.doxtable tr th:last-child { + border-top-right-radius: var(--border-radius-small); +} + +.doxygen-content table.markdownTable td, +.doxygen-content table.markdownTable th, +.doxygen-content table.fieldtable td, +.doxygen-content table.fieldtable th, +.doxygen-content table.doxtable td, +.doxygen-content table.doxtable th { + border: 1px solid var(--separator-color); + padding: var(--spacing-small) var(--spacing-medium); +} + +.doxygen-content table.markdownTable td:last-child, +.doxygen-content table.markdownTable th:last-child, +.doxygen-content table.fieldtable td:last-child, +.doxygen-content table.fieldtable th:last-child, +.doxygen-content table.doxtable td:last-child, +.doxygen-content table.doxtable th:last-child { + border-right: none; +} + +.doxygen-content table.markdownTable td:first-child, +.doxygen-content table.markdownTable th:first-child, +.doxygen-content table.fieldtable td:first-child, +.doxygen-content table.fieldtable th:first-child, +.doxygen-content table.doxtable td:first-child, +.doxygen-content table.doxtable th:first-child { + border-left: none; +} + +.doxygen-content table.markdownTable tr:first-child td, +.doxygen-content table.markdownTable tr:first-child th, +.doxygen-content table.fieldtable tr:first-child td, +.doxygen-content table.fieldtable tr:first-child th, +.doxygen-content table.doxtable tr:first-child td, +.doxygen-content table.doxtable tr:first-child th { + border-top: none; +} + +.doxygen-content table.markdownTable tr:last-child td, +.doxygen-content table.markdownTable tr:last-child th, +.doxygen-content table.fieldtable tr:last-child td, +.doxygen-content table.fieldtable tr:last-child th, +.doxygen-content table.doxtable tr:last-child td, +.doxygen-content table.doxtable tr:last-child th { + border-bottom: none; +} + +.doxygen-content table.markdownTable tr, .doxygen-content table.doxtable tr { + border-bottom: 1px solid var(--separator-color); +} + +.doxygen-content table.markdownTable tr:last-child, .doxygen-content table.doxtable tr:last-child { + border-bottom: none; +} + +.doxygen-content .full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) { + display: block; +} + +.doxygen-content .full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody { + display: table; + width: 100%; +} + +.doxygen-content table.fieldtable th { + font-size: var(--page-font-size); + font-weight: 600; + background-image: none; + background-color: var(--tablehead-background); + color: var(--tablehead-foreground); +} + +.doxygen-content table.fieldtable td.fieldtype, .doxygen-content .fieldtable td.fieldname, .doxygen-content .fieldtable td.fielddoc, .doxygen-content .fieldtable th { + border-bottom: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); +} + +.doxygen-content table.fieldtable tr:last-child td:first-child { + border-bottom-left-radius: var(--border-radius-small); +} + +.doxygen-content table.fieldtable tr:last-child td:last-child { + border-bottom-right-radius: var(--border-radius-small); +} + +.doxygen-content .memberdecls td.glow, .doxygen-content .fieldtable tr.glow { + background-color: var(--primary-light-color); + box-shadow: none; +} + +.doxygen-content table.memberdecls { + display: block; + -webkit-tap-highlight-color: transparent; +} + +.doxygen-content table.memberdecls tr[class^="memitem"] { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); +} + +.doxygen-content table.memberdecls tr[class^="memitem"] .memTemplParams { + font-family: var(--font-family-monospace); + font-size: var(--code-font-size); + color: var(--primary-dark-color); + white-space: normal; +} + +.doxygen-content table.memberdecls .memItemLeft, +.doxygen-content table.memberdecls .memItemRight, +.doxygen-content table.memberdecls .memTemplItemLeft, +.doxygen-content table.memberdecls .memTemplItemRight, +.doxygen-content table.memberdecls .memTemplParams { + transition: none; + padding-top: var(--spacing-small); + padding-bottom: var(--spacing-small); + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + background-color: var(--fragment-background); +} + +.doxygen-content table.memberdecls .memTemplItemLeft, +.doxygen-content table.memberdecls .memTemplItemRight { + padding-top: 2px; +} + +.doxygen-content table.memberdecls .memTemplParams { + border-bottom: 0; + border-left: 1px solid var(--separator-color); + border-right: 1px solid var(--separator-color); + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + padding-bottom: var(--spacing-small); +} + +.doxygen-content table.memberdecls .memTemplItemLeft { + border-radius: 0 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + border-top: 0; +} + +.doxygen-content table.memberdecls .memTemplItemRight { + border-radius: 0 0 var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-left: 0; + border-top: 0; +} + +.doxygen-content table.memberdecls .memItemLeft { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); + border-left: 1px solid var(--separator-color); + padding-left: var(--spacing-medium); + padding-right: 0; +} + +.doxygen-content table.memberdecls .memItemRight { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; + border-right: 1px solid var(--separator-color); + padding-right: var(--spacing-medium); + padding-left: 0; + +} + +.doxygen-content table.memberdecls .mdescLeft, .doxygen-content table.memberdecls .mdescRight { + background: none; + color: var(--page-foreground-color); + padding: var(--spacing-small) 0; +} + +.doxygen-content table.memberdecls .memItemLeft, +.doxygen-content table.memberdecls .memTemplItemLeft { + padding-right: var(--spacing-medium); +} + +.doxygen-content table.memberdecls .memSeparator { + background: var(--page-background-color); + height: var(--spacing-large); + border: 0; + transition: none; +} + +.doxygen-content table.memberdecls .groupheader { + margin-bottom: var(--spacing-large); +} + +.doxygen-content table.memberdecls .inherit_header td { + padding: 0 0 var(--spacing-medium) 0; + text-indent: -12px; + color: var(--page-secondary-foreground-color); +} + +.doxygen-content table.memberdecls img[src="closed.png"], +.doxygen-content table.memberdecls img[src="open.png"], +.doxygen-content div.dynheader img[src="open.png"], +.doxygen-content div.dynheader img[src="closed.png"] { + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid var(--primary-color); + margin-top: 8px; + display: block; + float: left; + margin-left: -10px; + transition: transform 0.25s ease-out; +} + +.doxygen-content table.memberdecls img { + margin-right: 10px; +} + +.doxygen-content table.memberdecls img[src="closed.png"], +.doxygen-content div.dynheader img[src="closed.png"] { + transform: rotate(-90deg); + +} + +.doxygen-content .compoundTemplParams { + font-family: var(--font-family-monospace); + color: var(--primary-dark-color); + font-size: var(--code-font-size); +} + +@media screen and (max-width: 767px) { + + .doxygen-content table.memberdecls .memItemLeft, + .doxygen-content table.memberdecls .memItemRight, + .doxygen-content table.memberdecls .mdescLeft, + .doxygen-content table.memberdecls .mdescRight, + .doxygen-content table.memberdecls .memTemplItemLeft, + .doxygen-content table.memberdecls .memTemplItemRight, + .doxygen-content table.memberdecls .memTemplParams { + display: block; + text-align: left; + padding-left: var(--spacing-large); + margin: 0 calc(0px - var(--spacing-large)) 0 calc(0px - var(--spacing-large)); + border-right: none; + border-left: none; + border-radius: 0; + white-space: normal; + } + + .doxygen-content table.memberdecls .memItemLeft, + .doxygen-content table.memberdecls .mdescLeft, + .doxygen-content table.memberdecls .memTemplItemLeft { + border-bottom: 0; + padding-bottom: 0; + } + + .doxygen-content table.memberdecls .memTemplItemLeft { + padding-top: 0; + } + + .doxygen-content table.memberdecls .mdescLeft { + margin-bottom: calc(0px - var(--page-font-size)); + } + + .doxygen-content table.memberdecls .memItemRight, + .doxygen-content table.memberdecls .mdescRight, + .doxygen-content table.memberdecls .memTemplItemRight { + border-top: 0; + padding-top: 0; + padding-right: var(--spacing-large); + overflow-x: auto; + } + + .doxygen-content table.memberdecls tr[class^="memitem"]:not(.inherit) { + display: block; + width: calc(100vw - 2 * var(--spacing-large)); + } + + .doxygen-content table.memberdecls .mdescRight { + color: var(--page-foreground-color); + } + + .doxygen-content table.memberdecls tr.inherit { + visibility: hidden; + } + + .doxygen-content table.memberdecls tr[style="display: table-row;"] { + display: block !important; + visibility: visible; + width: calc(100vw - 2 * var(--spacing-large)); + animation: fade .5s; + } + + @keyframes fade { + 0% { + opacity: 0; + max-height: 0; + } + + 100% { + opacity: 1; + max-height: 200px; + } + } +} + + +/* + Horizontal Rule + */ + +.doxygen-content hr { + margin-top: var(--spacing-large); + margin-bottom: var(--spacing-large); + height: 1px; + background-color: var(--separator-color); + border: 0; +} + +.doxygen-content .contents hr { + border-bottom: 1px solid var(--separator-color); +} + +.doxygen-content .contents img, .doxygen-content .contents .center, .doxygen-content .contents center, .doxygen-content .contents div.image object { + max-width: 100%; + overflow: auto; +} + +@media screen and (max-width: 767px) { + .doxygen-content .contents .dyncontent > .center, .doxygen-content .contents > center { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + max-width: calc(100% + 2 * var(--spacing-large)); + } +} + +/* + Directories + */ +.doxygen-content div.directory { + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + width: auto; +} + +.doxygen-content table.directory { + font-family: var(--font-family); + font-size: var(--page-font-size); + font-weight: normal; + width: 100%; +} + +.doxygen-content table.directory td.entry, .doxygen-content table.directory td.desc { + padding: calc(var(--spacing-small) / 2) var(--spacing-small); + line-height: var(--table-line-height); +} + +.doxygen-content table.directory tr.even td:last-child { + border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; +} + +.doxygen-content table.directory tr.even td:first-child { + border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); +} + +.doxygen-content table.directory tr.even:last-child td:last-child { + border-radius: 0 var(--border-radius-small) 0 0; +} + +.doxygen-content table.directory tr.even:last-child td:first-child { + border-radius: var(--border-radius-small) 0 0 0; +} + +.doxygen-content table.directory td.desc { + min-width: 250px; +} + +.doxygen-content table.directory tr.even { + background-color: var(--odd-color); +} + +.doxygen-content table.directory tr.odd { + background-color: transparent; +} + +.doxygen-content .icona { + width: auto; + height: auto; + margin: 0 var(--spacing-small); +} + +.doxygen-content .icon { + background: var(--primary-color); + border-radius: var(--border-radius-small); + font-size: var(--page-font-size); + padding: calc(var(--page-font-size) / 5); + line-height: var(--page-font-size); + transform: scale(0.8); + height: auto; + width: var(--page-font-size); + user-select: none; +} + +.doxygen-content .iconfopen, .doxygen-content .icondoc, .doxygen-content .iconfclosed { + background-position: center; + margin-bottom: 0; + height: var(--table-line-height); +} + +.doxygen-content .icondoc { + filter: saturate(0.2); +} + +@media screen and (max-width: 767px) { + .doxygen-content div.directory { + margin-left: calc(0px - var(--spacing-large)); + margin-right: calc(0px - var(--spacing-large)); + } +} + +@media (prefers-color-scheme: dark) { + html:not([data-theme=light]) .doxygen-content .iconfopen, html:not([data-theme=light]) .doxygen-content .iconfclosed { + filter: hue-rotate(180deg) invert(); + } +} + +html[data-theme=dark] .doxygen-content .iconfopen, html[data-theme=dark] .doxygen-content .iconfclosed { + filter: hue-rotate(180deg) invert(); +} + +/* + Class list + */ + +.doxygen-content .classindex dl.odd { + background: var(--odd-color); + border-radius: var(--border-radius-small); +} + +.doxygen-content .classindex dl.even { + background-color: transparent; +} + +/* + Class Index Doxygen 1.8 +*/ + +.doxygen-content table.classindex { + margin-left: 0; + margin-right: 0; + width: 100%; +} + +.doxygen-content table.classindex table div.ah { + background-image: none; + background-color: initial; + border-color: var(--separator-color); + color: var(--page-foreground-color); + box-shadow: var(--box-shadow); + border-radius: var(--border-radius-large); + padding: var(--spacing-small); +} + +.doxygen-content div.qindex { + background-color: var(--odd-color); + border-radius: var(--border-radius-small); + border: 1px solid var(--separator-color); + padding: var(--spacing-small) 0; +} + +/* + Footer and nav-path + */ + +.doxygen-content #nav-path { + width: 100%; +} + +.doxygen-content #nav-path ul { + background-image: none; + background: var(--page-background-color); + border: none; + border-top: 1px solid var(--separator-color); + border-bottom: 1px solid var(--separator-color); + border-bottom: 0; + box-shadow: 0 0.75px 0 var(--separator-color); + font-size: var(--navigation-font-size); +} + +.doxygen-content img.footer { + width: 60px; +} + +.doxygen-content .navpath li.footer { + color: var(--page-secondary-foreground-color); +} + +.doxygen-content address.footer { + color: var(--page-secondary-foreground-color); + margin-bottom: var(--spacing-large); +} + +.doxygen-content #nav-path li.navelem { + background-image: none; + display: flex; + align-items: center; +} + +.doxygen-content .navpath li.navelem a { + text-shadow: none; + display: inline-block; + color: var(--primary-color) !important; +} + +.doxygen-content .navpath li.navelem b { + color: var(--primary-dark-color); + font-weight: 500; +} + +.doxygen-content li.navelem { + padding: 0; + margin-left: -8px; +} + +.doxygen-content li.navelem:first-child { + margin-left: var(--spacing-large); +} + +.doxygen-content li.navelem:first-child:before { + display: none; +} + +.doxygen-content #nav-path li.navelem:after { + content: ""; + border: 5px solid var(--page-background-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(4.2); + z-index: 10; + margin-left: 6px; +} + +.doxygen-content #nav-path li.navelem:before { + content: ""; + border: 5px solid var(--separator-color); + border-bottom-color: transparent; + border-right-color: transparent; + border-top-color: transparent; + transform: translateY(-1px) scaleY(3.2); + margin-right: var(--spacing-small); +} + +.doxygen-content .navpath li.navelem a:hover { + color: var(--primary-color); +} + +/* + Scrollbars for Webkit +*/ + +.doxygen-content #nav-tree::-webkit-scrollbar, +.doxygen-content div.fragment::-webkit-scrollbar, +.doxygen-content pre.fragment::-webkit-scrollbar, +.doxygen-content div.memproto::-webkit-scrollbar, +.doxygen-content .contents center::-webkit-scrollbar, +.doxygen-content .contents .center::-webkit-scrollbar, +.doxygen-content .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar, +.doxygen-content div.contents .toc::-webkit-scrollbar, +.doxygen-content .contents .dotgraph::-webkit-scrollbar, +.doxygen-content .contents .tabs-overview-container::-webkit-scrollbar { + background: transparent; + width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); +} + +.doxygen-content #nav-tree::-webkit-scrollbar-thumb, +.doxygen-content div.fragment::-webkit-scrollbar-thumb, +.doxygen-content pre.fragment::-webkit-scrollbar-thumb, +.doxygen-content div.memproto::-webkit-scrollbar-thumb, +.doxygen-content .contents center::-webkit-scrollbar-thumb, +.doxygen-content .contents .center::-webkit-scrollbar-thumb, +.doxygen-content .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-thumb, +.doxygen-content div.contents .toc::-webkit-scrollbar-thumb, +.doxygen-content .contents .dotgraph::-webkit-scrollbar-thumb, +.doxygen-content .contents .tabs-overview-container::-webkit-scrollbar-thumb { + background-color: transparent; + border: var(--webkit-scrollbar-padding) solid transparent; + border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); + background-clip: padding-box; +} + +.doxygen-content #nav-tree:hover::-webkit-scrollbar-thumb, +.doxygen-content div.fragment:hover::-webkit-scrollbar-thumb, +.doxygen-content pre.fragment:hover::-webkit-scrollbar-thumb, +.doxygen-content div.memproto:hover::-webkit-scrollbar-thumb, +.doxygen-content .contents center:hover::-webkit-scrollbar-thumb, +.doxygen-content .contents .center:hover::-webkit-scrollbar-thumb, +.doxygen-content .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody:hover::-webkit-scrollbar-thumb, +.doxygen-content div.contents .toc:hover::-webkit-scrollbar-thumb, +.doxygen-content .contents .dotgraph:hover::-webkit-scrollbar-thumb, +.doxygen-content .contents .tabs-overview-container:hover::-webkit-scrollbar-thumb { + background-color: var(--webkit-scrollbar-color); +} + +.doxygen-content #nav-tree::-webkit-scrollbar-track, +.doxygen-content div.fragment::-webkit-scrollbar-track, +.doxygen-content pre.fragment::-webkit-scrollbar-track, +.doxygen-content div.memproto::-webkit-scrollbar-track, +.doxygen-content .contents center::-webkit-scrollbar-track, +.doxygen-content .contents .center::-webkit-scrollbar-track, +.doxygen-content .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-track, +.doxygen-content div.contents .toc::-webkit-scrollbar-track, +.doxygen-content .contents .dotgraph::-webkit-scrollbar-track, +.doxygen-content .contents .tabs-overview-container::-webkit-scrollbar-track { + background: transparent; +} + +.doxygen-content #nav-tree::-webkit-scrollbar-corner { + background-color: var(--side-nav-background); +} + +.doxygen-content #nav-tree, +.doxygen-content div.fragment, +.doxygen-content pre.fragment, +.doxygen-content div.memproto, +.doxygen-content .contents center, +.doxygen-content .contents .center, +.doxygen-content .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +.doxygen-content div.contents .toc { + overflow-x: auto; + overflow-x: overlay; +} + +.doxygen-content #nav-tree { + overflow-x: auto; + overflow-y: auto; + overflow-y: overlay; +} + +/* + Scrollbars for Firefox +*/ + +.doxygen-content #nav-tree, +.doxygen-content div.fragment, +.doxygen-content pre.fragment, +.doxygen-content div.memproto, +.doxygen-content .contents center, +.doxygen-content .contents .center, +.doxygen-content .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody, +.doxygen-content div.contents .toc, +.doxygen-content .contents .dotgraph, +.doxygen-content .contents .tabs-overview-container { + scrollbar-width: thin; +} + +/* + Optional Dark mode toggle button +*/ + +.doxygen-content doxygen-awesome-dark-mode-toggle { + display: inline-block; + margin: 0 0 0 var(--spacing-small); + padding: 0; + width: var(--searchbar-height); + height: var(--searchbar-height); + background: none; + border: none; + border-radius: var(--searchbar-height); + vertical-align: middle; + text-align: center; + line-height: var(--searchbar-height); + font-size: 22px; + display: flex; + align-items: center; + justify-content: center; + user-select: none; + cursor: pointer; +} + +.doxygen-content doxygen-awesome-dark-mode-toggle > svg { + transition: transform .1s ease-in-out; +} + +.doxygen-content doxygen-awesome-dark-mode-toggle:active > svg { + transform: scale(.5); +} + +.doxygen-content doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.03); +} + +html[data-theme=dark] .doxygen-content doxygen-awesome-dark-mode-toggle:hover { + background-color: rgba(0,0,0,.18); +} + +/* + Optional fragment copy button +*/ +.doxygen-content .doxygen-awesome-fragment-wrapper { + position: relative; +} + +.doxygen-content doxygen-awesome-fragment-copy-button { + opacity: 0; + background: var(--fragment-background); + width: 28px; + height: 28px; + position: absolute; + right: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + top: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); + border: 1px solid var(--fragment-foreground); + cursor: pointer; + border-radius: var(--border-radius-small); + display: flex; + justify-content: center; + align-items: center; +} + +.doxygen-content .doxygen-awesome-fragment-wrapper:hover doxygen-awesome-fragment-copy-button, .doxygen-content doxygen-awesome-fragment-copy-button.success { + opacity: .28; +} + +.doxygen-content doxygen-awesome-fragment-copy-button:hover, .doxygen-content doxygen-awesome-fragment-copy-button.success { + opacity: 1 !important; +} + +.doxygen-content doxygen-awesome-fragment-copy-button:active:not([class~=success]) svg { + transform: scale(.91); +} + +.doxygen-content doxygen-awesome-fragment-copy-button svg { + fill: var(--fragment-foreground); + width: 18px; + height: 18px; +} + +.doxygen-content doxygen-awesome-fragment-copy-button.success svg { + fill: rgb(14, 168, 14); +} + +.doxygen-content doxygen-awesome-fragment-copy-button.success { + border-color: rgb(14, 168, 14); +} + +@media screen and (max-width: 767px) { + .doxygen-content .textblock > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .doxygen-content .textblock li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .doxygen-content .memdoc li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .doxygen-content .memdoc > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, + .doxygen-content dl dd > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button { + right: 0; + } +} + +/* + Optional paragraph link button +*/ + +.doxygen-content a.anchorlink { + font-size: 90%; + margin-left: var(--spacing-small); + color: var(--page-foreground-color) !important; + text-decoration: none; + opacity: .15; + display: none; + transition: opacity .1s ease-in-out, color .1s ease-in-out; +} + +.doxygen-content a.anchorlink svg { + fill: var(--page-foreground-color); +} + +.doxygen-content h3 a.anchorlink svg, .doxygen-content h4 a.anchorlink svg { + margin-bottom: -3px; + margin-top: -4px; +} + +.doxygen-content a.anchorlink:hover { + opacity: .45; +} + +.doxygen-content h2:hover a.anchorlink, .doxygen-content h1:hover a.anchorlink, .doxygen-content h3:hover a.anchorlink, .doxygen-content h4:hover a.anchorlink { + display: inline-block; +} + +/* + Optional tab feature +*/ + +.doxygen-content .tabbed ul { + padding-inline-start: 0px; + margin: 0; + padding: var(--spacing-small) 0; + border-bottom: 1px solid var(--separator-color); +} + +.doxygen-content .tabbed li { + display: none; +} + +.doxygen-content .tabbed li.selected { + display: block; +} + +.doxygen-content .tabs-overview-container { + overflow-x: auto; + display: block; + overflow-y: visible; +} + +.doxygen-content .tabs-overview { + border-bottom: 1px solid var(--separator-color); + display: flex; + flex-direction: row; +} + +.doxygen-content .tabs-overview button.tab-button { + color: var(--page-foreground-color); + margin: 0; + border: none; + background: transparent; + padding: var(--spacing-small) 0; + display: inline-block; + font-size: var(--page-font-size); + cursor: pointer; + box-shadow: 0 1px 0 0 var(--separator-color); +} + +.doxygen-content .tabs-overview button.tab-button .tab-title { + float: left; + white-space: nowrap; + padding: var(--spacing-small) var(--spacing-large); + border-radius: var(--border-radius-medium); +} + +.doxygen-content .tabs-overview button.tab-button:not(:last-child) .tab-title { + box-shadow: 8px 0 0 -7px var(--separator-color); +} + +.doxygen-content .tabs-overview button.tab-button:hover .tab-title { + background: var(--primary-color); + color: var(--page-background-color); + box-shadow: none; +} + +.doxygen-content .tabs-overview button.tab-button.active { + color: var(--primary-color); + box-shadow: 0 1px 0 0 var(--primary-color), inset 0 -1px 0 0 var(--primary-color); +} + +@media (prefers-color-scheme: dark) { + html:not([data-theme=light]) .doxygen-content .tabs-overview button.tab-button:hover .tab-title { + color: var(--page-foreground-color); + } +} + +html[data-theme=dark] .doxygen-content .tabs-overview button.tab-button:hover .tab-title { + color: var(--page-foreground-color); +} diff --git a/docs/_static/stdgpu_custom_doxygen.css b/docs/_static/stdgpu_custom_doxygen.css new file mode 100644 index 000000000..9089dd65a --- /dev/null +++ b/docs/_static/stdgpu_custom_doxygen.css @@ -0,0 +1,79 @@ +/* Disable several doxygen main theme elements */ +.doxygen-content #top, +.doxygen-content hr.footer, +.doxygen-content address.footer, +.doxygen-content div.header .summary, +.doxygen-content div.navtab { + display: none; +} + + +/* Enforce full-width sections in documentation */ +.doxygen-content table { + width: 100%; +} + + +/* Fix for buggy section labels in detailed documentation */ +.doxygen-content div.memitem div.memdoc dl dt { + color: var(--page-foreground-color) !important; +} + + +/* Fix disconnected border around tab in detailed documentation */ +.doxygen-content h2.memtitle::after { + display: none; +} + + +/* Improve appearance of member boxes with small (mobile) displays */ +@media screen and (max-width: 767px) { + .doxygen-content table.memberdecls .memItemLeft, + .doxygen-content table.memberdecls .memItemRight, + .doxygen-content table.memberdecls .mdescLeft, + .doxygen-content table.memberdecls .mdescRight, + .doxygen-content table.memberdecls .memTemplItemLeft, + .doxygen-content table.memberdecls .memTemplItemRight, + .doxygen-content table.memberdecls .memTemplParams { + margin: 0; + } + + .doxygen-content table.memberdecls .memTemplParams { + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + } + + .doxygen-content table.memberdecls .memTemplItemLeft { + border-radius: 0; + } + + .doxygen-content table.memberdecls .memTemplItemRight { + border-radius: 0 0 var(--border-radius-small) var(--border-radius-small); + } + + .doxygen-content table.memberdecls .memItemLeft { + border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; + } + + .doxygen-content table.memberdecls .memItemRight { + border-radius: 0 0 var(--border-radius-small) var(--border-radius-small); + + } +} + + +/* Reduce padding of title in doxygen documentation */ +.doxygen-content div.header .title { + padding: 0; +} + +@media(min-width:1200px) { + .bd-main .bd-content .bd-article-container .bd-article { + padding-top: 0; + } +} + + +/* Add missing padding inside memover documentation box */ +.doxygen-content .contents .memdoc { + margin-bottom: 10px; +} diff --git a/docs/_static/stdgpu_custom_sphinx.css b/docs/_static/stdgpu_custom_sphinx.css new file mode 100644 index 000000000..855396796 --- /dev/null +++ b/docs/_static/stdgpu_custom_sphinx.css @@ -0,0 +1,15 @@ +/* Remove pointless scrollbar in sidebar when the content fits into the page */ +div#rtd-footer-container { + display: none; +} + + +/* Better separator color in dark mode */ +html[data-theme="dark"] { + --pst-color-border: #38393b; + --pst-color-background: #151617; /* Doxygen Awesome: #1c1d1f */ +} + +footer.bd-footer-content { + border-top: 1px solid var(--pst-color-border); +} \ No newline at end of file diff --git a/doc/stdgpu_logo.ico b/docs/_static/stdgpu_logo.ico similarity index 100% rename from doc/stdgpu_logo.ico rename to docs/_static/stdgpu_logo.ico diff --git a/doc/stdgpu_logo.png b/docs/_static/stdgpu_logo.png similarity index 100% rename from doc/stdgpu_logo.png rename to docs/_static/stdgpu_logo.png diff --git a/docs/api/chapters.md b/docs/api/chapters.md new file mode 100644 index 000000000..189150813 --- /dev/null +++ b/docs/api/chapters.md @@ -0,0 +1,9 @@ +Chapters +======== + +```{toctree} + +memory +iterator +object +``` diff --git a/doc/stdgpu/iterator.md b/docs/api/iterator.md similarity index 50% rename from doc/stdgpu/iterator.md rename to docs/api/iterator.md index 01b429a03..11955a50c 100644 --- a/doc/stdgpu/iterator.md +++ b/docs/api/iterator.md @@ -1,35 +1,35 @@ -Iterating over Arrays and Containers {#iterator} +Iterating over Arrays and Containers ==================================== -# Motivation {#iterator_overview} +## Motivation The iterator concept is one of the core aspects of the Standard Template Library (STL). Most C++ programmers are familiar with this concept and can easily write algorithms with it. The thrust library aims to provide the STL functionality also for device arrays and vectors. This includes the convenient iterator syntax. Consider the following STL example: ```cpp - #include - #include - #include +#include +#include +#include - std::vector vector(1000); +std::vector vector(1000); - // Fill it with something useful +// Fill it with something useful - std::sort(vector.begin(), vector.end()); // C++98 - std::sort(std::begin(vector), std::end(vector)); // C++11 +std::sort(vector.begin(), vector.end()); // C++98 +std::sort(std::begin(vector), std::end(vector)); // C++11 ``` In modern C++, the latter more recent version of begin and end should be used. Semantically, they are identical. thrust provides a similar syntax for its containers: ```cpp - #include - #include +#include +#include - thrust::device_vector device_vector(1000); +thrust::device_vector device_vector(1000); - // Fill it with something useful +// Fill it with something useful - thrust::sort(thrust::device, vector.begin(), vector.end()); +thrust::sort(thrust::device, vector.begin(), vector.end()); ``` The differences to the STL are mostly related to the more generic setting. Although thrust is able to automatically infer whether the vector is allocated on the host or device, it is advisable to clearly state that sorting should be done on the device. @@ -37,74 +37,74 @@ The differences to the STL are mostly related to the more generic setting. Altho It is also possible to pass raw pointers to thrust algorithms, but the syntax gets intrusive: ```cpp - #include - #include +#include +#include - #include +#include - float* device_array = createDeviceArray(1000); +float* device_array = createDeviceArray(1000); - // Fill it with something useful +// Fill it with something useful - thrust::sort(thrust::device, thrust::device_pointer_cast(device_array), thrust::device_pointer_cast(device_array + 1000)); +thrust::sort(thrust::device, thrust::device_pointer_cast(device_array), thrust::device_pointer_cast(device_array + 1000)); - destroyDeviceArray(device_array); +destroyDeviceArray(device_array); ``` The intent of casting to the thrust API is clear, but very verbose. Furthermore, the size of the array must be known and explicitly stated to compute the iterator pointing to the end of the array. -# Iterator API {#iterator_api} +## Iterator API Similar to what the [memory management API](#memory) provides, there is also an API to avoid boilerplate code such as in the example above. It can be considered as a natural extension to how thrust and STL perform in C++11: ```cpp - #include +#include - #include - #include +#include +#include - float* device_array = createDeviceArray(1000); +float* device_array = createDeviceArray(1000); - // Fill it with something useful +// Fill it with something useful - thrust::sort(stdgpu::device_begin(device_array), stdgpu::device_end(device_array)); +thrust::sort(stdgpu::device_begin(device_array), stdgpu::device_end(device_array)); - destroyDeviceArray(device_array); +destroyDeviceArray(device_array); ``` Compare this systax to the C++11 version of the STL call. This becomes possible by the internal leak check which now provides the required size information. Therefore, stdgpu::device_end can query the size of the given array and return a pointer to the end. Furthermore, the functions check whether the array is allocated on the host or device to avoid mismatches. Iterators are defined for both host and device arrays. In addition, the const versions of them are also defined. Consider the following C++14 STL example: ```cpp - #include - #include +#include +#include - std::vector vector(1000); - std::vector vector_out(1000); +std::vector vector(1000); +std::vector vector_out(1000); - // Fill it with something useful +// Fill it with something useful - std::transform(std::cbegin(vector), std::cend(vector), std::begin(vector_out), std::negate()); // C++14 +std::transform(std::cbegin(vector), std::cend(vector), std::begin(vector_out), std::negate()); // C++14 ``` The device version with the memory management API is almost identical: ```cpp - #include - #include +#include +#include - #include - #include +#include +#include - float* device_array = createDeviceArray(1000); - float* device_array_out = createDeviceArray(1000); +float* device_array = createDeviceArray(1000); +float* device_array_out = createDeviceArray(1000); - // Fill it with something useful +// Fill it with something useful - thrust::transform(stdgpu::device_cbegin(device_array), stdgpu::device_cend(device_array), stdgpu::device_begin(device_array_out), thrust::negate()); +thrust::transform(stdgpu::device_cbegin(device_array), stdgpu::device_cend(device_array), stdgpu::device_begin(device_array_out), thrust::negate()); - destroyDeviceArray(device_array); - destroyDeviceArray(device_array_out); +destroyDeviceArray(device_array); +destroyDeviceArray(device_array_out); ``` The combination of both the memory management and the iterator API provides a very powerful interface to interact with thrust as well as kernels in a fast, safe and intuitive way. diff --git a/doc/stdgpu/memory.md b/docs/api/memory.md similarity index 77% rename from doc/stdgpu/memory.md rename to docs/api/memory.md index e1aee8388..b2bdbce18 100644 --- a/doc/stdgpu/memory.md +++ b/docs/api/memory.md @@ -1,8 +1,8 @@ -Memory Management {#memory} +Memory Management ================= -# Motivation {#memory_overview} +## Motivation Memory management in C and C++ is one of the main aspects a developer should care about. Usually, containers such as std::vector are sufficient for most use cases. However, all these convenient containers are unfortunately not directly supported on the GPU side. There has been some effort to provide a GPU version of the Standard Template Library (STL), but the solutions are still quite limited. For instance, the thrust library (which is delivered with CUDA by default) has the following limitations: @@ -13,20 +13,20 @@ Memory management in C and C++ is one of the main aspects a developer should car Typically, applications involving the GPU are performance critical and should be well optimized. On the other hand, thrust allows to develop code at a fast pace when sticking to their API. Therefore, most developers use raw pointers to achieve maximum performance. The drawback is that this requires a C-like API to allocate and free host and device memory which is quite intrusive and prone to errors. -# Memory API {#memory_api} +## Memory API In order to solve this problem, a simple and consistent wrapper API around the memory management functions is defined. The goal is to reduce boilerplate code and give the user strong guarantees about the requested operations. -## Creating and Destroying Arrays {#memory_create_destroy} +### Creating and Destroying Arrays The simplest operation when dealing with dynamically allocated arrays is to create such an array. This can be done in the following way: ```cpp - #include +#include - float* device_float_vector = createDeviceArray(1000, 42.0f); - float* host_float_vector = createHostArray(1000, 42.0f); +float* device_float_vector = createDeviceArray(1000, 42.0f); +float* host_float_vector = createHostArray(1000, 42.0f); ``` Here, two arrays of length 1000 are created, one on the host and one on the device, and filled with the value 42.0f. Compared to traditional C and C++ allocations, these functions guarantee that the allocated memory is initialized with a well-defined state. The value parameter is optional. In case, no value is given, a default constructed object is used, i.e. float() which equals to 0.0f. @@ -34,12 +34,12 @@ Here, two arrays of length 1000 are created, one on the host and one on the devi When memory is allocated, it must be freed later at some time: ```cpp - #include +#include - // Define device_float_vector and host_float_vector +// Define device_float_vector and host_float_vector - destroyDeviceArray(device_float_vector); - destroyHostArray(host_float_vector); +destroyDeviceArray(device_float_vector); +destroyHostArray(host_float_vector); ``` Although these functions are a bit more consistent than the usual memory management functions, the additional overhead of defining this wrapper might not be worth the effort. However, there are several more implicit guarantees: @@ -49,31 +49,31 @@ Although these functions are a bit more consistent than the usual memory managem - Internally, a leak checker maintains a list of allocated arrays. If the user forgets to free an array, a warning can be prompted that some memory is leaking, so that the user can fix this problem easily. -## Copying Arrays between Host and Device {#memory_copy} +### Copying Arrays between Host and Device Creating and destroying arrays is only one step to efficiently handle memory. Data usually become available on the host, but should be processed on the device for performance reasons, and in the end stored on the host again. Consequently, copying arrays between the host and the device is necessary. This can be done by: ```cpp - #include +#include - float* host_float_vector; // Create this and set some values - float* device_float_vector; // Create this +float* host_float_vector; // Create this and set some values +float* device_float_vector; // Create this - copyHost2DeviceArray(host_float_vector, 1000, device_float_vector); +copyHost2DeviceArray(host_float_vector, 1000, device_float_vector); - // Do something useful with device_float_vector +// Do something useful with device_float_vector - copyDevice2HostArray(device_float_vector, 1000, host_float_vector); +copyDevice2HostArray(device_float_vector, 1000, host_float_vector); ``` Here, the first 1000 values of host_float_vector are copyied to device_float_vector and later on vice versa. If the array to which should be copied is not allocated so far, then one can use these functions to unify allocation and copy: ```cpp - #include +#include - float* host_float_vector; // Create this and set some values +float* host_float_vector; // Create this and set some values - float* device_float_vector = copyCreateHost2DeviceArray(host_float_vector, 1000); +float* device_float_vector = copyCreateHost2DeviceArray(host_float_vector, 1000); ``` All of these copy functions share strong guarantees. Having the internal leak checker, the copy functions check if the arrays are indeed allocated on the host or device. This avoids accidental mismatches. Furthermore, the size of the arrays are checked to prevent copying elements out of the allocated bounds of both arrays. @@ -81,11 +81,11 @@ All of these copy functions share strong guarantees. Having the internal leak ch It is very important to note that these guarantees can only be fulfilled if the arrays have been allocated by this API. External arrays or pointers to stack objects can also be used with this API. However, the checks need to be disabled in this situation: ```cpp - #include +#include - float host_value = 42.0f; +float host_value = 42.0f; - float* device_value_pointer = copyCreateHost2DeviceArray(&host_value, 1, MemoryCopy::NO_CHECK); +float* device_value_pointer = copyCreateHost2DeviceArray(&host_value, 1, MemoryCopy::NO_CHECK); ``` Please keep in mind, that if the functions are called in this way, it is then your responsibility to make sure that this operation succeeds. diff --git a/docs/api/object.md b/docs/api/object.md new file mode 100644 index 000000000..bbde0f11d --- /dev/null +++ b/docs/api/object.md @@ -0,0 +1,128 @@ +Container Objects +================= + +## Motivation + +In order to bridge the gap between GPU and CPU programming, the memory management API allows to handle arrays in an efficient and reliable way (see [](#memory)). However, this is not sufficient even for most projects which require at least one layer hiding all the computations and memory management operations. Therefore, semantically coherent data (e.g. arrays) should be packed together into a class and processed by the public interface of the class. One category of such classes are containers including std::vector. In the context of GPU programming, array-based data structures are prefered and easier to implement. The thrust library for example only provides a thrust::host_vector and thrust::device_vector class because other structures such as std::unordered_map, std::list, etc. are very difficult to port to the GPU without sacrificing some important properties. While the containers defined in this library also have some limitations, they are still easy to use and robust. + + +## Defining Host and Device Container Objects + +As mentioned above, a further abstraction layer to simplify data management is needed. This requires another API to avoid boilerplate code and redudancy. So far, host and device arrays has been defined as the generalization of arrays to CPU and GPU memory. Consequently, host device objects now generalize the traditional class objects. Consider the following class: + +```cpp +class MyClass +{ + public: + MyClass() + { + this->array = nullptr; + this->size = 0; + } + + MyClass(const int size) + { + this->array = new float[size]; + this->size = size; + } + + ~MyClass() + { + delete[] array; + size = 0; + } + + void function(const int parameter) const + { + // Do something useful with array + } + + private: + float* array; + int size; +}; +``` + +It wraps an array of type float including the size and provides some interaction interface through the member function. There are two constructors for this class. The first is simply the default constructor which should set the object to an empty state. The other constructor allocates the array with the given size. Finally, the destructor cleans them up. This design is quite problematic since copy and move constructors are not considered here which can result to double free errors and memory leaks. Furthermore, this design does not scale to the GPU and a new API must be used. Consider this API on the aforementioned example: + +```cpp +class MyHostDeviceObjectClass +{ + public: + MyHostDeviceObjectClass() + { + this->_array = nullptr; + this->_size = 0; + } + + static MyHostDeviceObjectClass createDeviceObject(const int size) + { + MyHostDeviceObjectClass result; + + result._array = createDeviceArray(size); + result._size = size; + + return result; + } + + static void destroyDeviceObject(MyHostDeviceObjectClass& device_object) + { + destroyDeviceArray(device_object._array); + device_object._size = 0; + } + + static MyHostDeviceObjectClass createHostObject(const int size) + { + MyHostDeviceObjectClass result; + + result._array = createHostArray(size); + result._size = size; + + return result; + } + + static void destroyHostObject(MyHostDeviceObjectClass& host_object) + { + destroyHostArray(host_object._array); + host_object._size = 0; + } + + void function(const int parameter) const + { + // Do something useful with array + } + + private: + float* _array; + int _size; +}; +``` + +Note that this interface is very similar to the [host device array interface](#memory). An object can now be easily created and destroyed as follows: + +```cpp +MyClass device_object = MyClass::createDeviceObject(1000); +MyClass hoste_object = MyClass::createHostObject(1000); + +// Do something with device_object and host_object + +MyClass::destroyDeviceObject(device_object); +MyClass::destroyHostObject(host_object); +``` + +In order to match the capabilities of the host device arrays, copy functions can defined in the same manner and used as: + +```cpp +MyClass device_object = MyClass::createDeviceObject(1000); + +// Do something with device_object + +MyClass host_object = MyClass::copyCreateDevice2HostObject(device_object); + +// Do something with host_object + +MyClass::destroyDeviceObject(device_object); +MyClass::destroyHostObject(host_object); +``` + +Compared to arrays, an object always knows its size, so it is not necessary to also pass it as a parameter. This design is used to define the containers in this library. diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 000000000..13081d67b --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,71 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +import pathlib + +project = "stdgpu" +version = "Latest" +release = version +copyright = "2019, Patrick Stotko" +# author = "Patrick Stotko" + + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + "sphinx.ext.githubpages", + "sphinx_copybutton", + "sphinxcontrib.doxylink", + "myst_parser", +] + +doxylink = { + "stdgpu": (str(pathlib.Path(__file__).parent / "doxygen" / "tagfile.xml"), "doxygen"), +} + + +# templates_path = ["_templates"] +# exclude_patterns = [] + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = "sphinx_book_theme" +html_static_path = ["_static"] + + +html_theme_options = { + # Sidebar + "logo": { + "text": "Latest", + }, + # Header + "use_download_button": False, + "use_repository_button": True, + "use_fullscreen_button": False, + "repository_url": "https://github.com/stotko/stdgpu", + # Footer + "extra_footer": 'Made with Sphinx, Doxygen, Doxysphinx and sphinx-book-theme, Doxygen Awesome', + # Code fragments + "pygment_light_style": "a11y-high-contrast-light", # same as in sphinx-book-theme + "pygment_dark_style": "a11y-dark", +} + +html_favicon = "_static/stdgpu_logo.ico" +html_logo = "_static/stdgpu_logo.png" + +html_last_updated_fmt = "%Y-%m-%d" + +html_css_files = [ + "stdgpu_custom_sphinx.css", +] + + +html_copy_source = False diff --git a/doc/stdgpu/modules.doxy b/docs/doxygen_src/modules.doxy similarity index 100% rename from doc/stdgpu/modules.doxy rename to docs/doxygen_src/modules.doxy diff --git a/docs/fix_html_titles/__init__.py b/docs/fix_html_titles/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs/fix_html_titles/__main__.py b/docs/fix_html_titles/__main__.py new file mode 100644 index 000000000..d7bb7d3c5 --- /dev/null +++ b/docs/fix_html_titles/__main__.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import difflib +import html +import pathlib + + +def main() -> None: + doxygen_dir = pathlib.Path(__file__).parents[1] / "doxygen" + + print(f'Fixing HTML titles in "{doxygen_dir}"...') + + counter = 0 + for file in sorted((pathlib.Path(__file__).parents[1] / "doxygen").glob("*rst")): + with file.open("r") as f: + rst_content = f.read() + + rst_content_unescaped = html.unescape(rst_content) + + if rst_content_unescaped != rst_content: + counter += 1 + diff = difflib.unified_diff( + rst_content.splitlines(keepends=True), rst_content_unescaped.splitlines(keepends=True) + ) + + print("".join(diff), end="") + + with file.open("w") as f: + f.write(rst_content_unescaped) + + print(f'Fixing HTML titles in "{doxygen_dir}"... done. ({counter} files changed)') + + +if __name__ == "__main__": + main() diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..82eb690e8 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,31 @@ +# Overview + +```{include} ../README.md +:relative-docs: docs/ +:relative-images: +:start-after: +:end-before: +``` + +```{include} ../README.md +:relative-docs: docs/ +:relative-images: +:start-after: +:end-before: +``` + +```{toctree} +:hidden: + +self +``` + +```{toctree} +:hidden: +:caption: API Reference + +api/chapters +doxygen/modules +doxygen/annotated +doxygen/files +``` diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 000000000..af9f5a7d5 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,7 @@ +sphinx +sphinx-book-theme~=1.0.1 +sphinx_copybutton +sphinxcontrib-doxylink +doxysphinx +myst-parser +docutils>=0.17 diff --git a/scripts/utils/install_docs_dependencies_ubuntu.sh b/scripts/utils/install_docs_dependencies_ubuntu.sh new file mode 100644 index 000000000..8dc854234 --- /dev/null +++ b/scripts/utils/install_docs_dependencies_ubuntu.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +# Install docs dependencies +sudo apt-get update +sudo apt-get install bison flex python3 +pip install -r docs/requirements.txt diff --git a/scripts/utils/install_doxygen_dependencies_ubuntu.sh b/scripts/utils/install_doxygen_dependencies_ubuntu.sh deleted file mode 100644 index fd52fe9da..000000000 --- a/scripts/utils/install_doxygen_dependencies_ubuntu.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -set -e - -# Install doxygen dependencies -sudo apt-get update -sudo apt-get install bison flex