├── .clang-format ├── .clang-tidy ├── .gitignore ├── .vscode └── launch.json ├── CMakeLists.txt ├── CMakePresets.json ├── LICENSE ├── README.md ├── cmake ├── modules │ └── FindWayland.cmake ├── packaging.cmake ├── toolchains │ ├── cl-x86_64-windows-msvc.cmake │ ├── clang-x86_64-linux-gnu.cmake │ ├── clang-x86_64-windows-msvc.cmake │ ├── gcc-x86_64-linux-gnu.cmake │ └── vcvars.cmake ├── vcpkg-overlay-ports │ ├── fsr2 │ │ ├── portfile.cmake │ │ └── vcpkg.json │ └── glfw3 │ │ ├── portfile.cmake │ │ └── vcpkg.json ├── vcpkg.cmake └── warnings.cmake ├── include └── daxa │ ├── c │ ├── command_recorder.h │ ├── core.h │ ├── daxa.h │ ├── device.h │ ├── gpu_resources.h │ ├── instance.h │ ├── pipeline.h │ ├── swapchain.h │ ├── sync.h │ └── types.h │ ├── command_recorder.hpp │ ├── core.hpp │ ├── daxa.glsl │ ├── daxa.hpp │ ├── daxa.inl │ ├── daxa.slang │ ├── device.hpp │ ├── gpu_resources.hpp │ ├── instance.hpp │ ├── pipeline.hpp │ ├── swapchain.hpp │ ├── sync.hpp │ ├── types.hpp │ └── utils │ ├── fsr2.hpp │ ├── imgui.hpp │ ├── mem.hpp │ ├── pipeline_manager.hpp │ ├── task_graph.hpp │ ├── task_graph.inl │ ├── task_graph_types.hpp │ └── upscaling_common.hpp ├── misc └── daxa-logo.png ├── portfile.cmake ├── src ├── cpp_wrapper.cpp ├── impl_command_recorder.cpp ├── impl_command_recorder.hpp ├── impl_core.cpp ├── impl_core.hpp ├── impl_dependencies.cpp ├── impl_device.cpp ├── impl_device.hpp ├── impl_features.cpp ├── impl_features.hpp ├── impl_gpu_resources.cpp ├── impl_gpu_resources.hpp ├── impl_instance.cpp ├── impl_instance.hpp ├── impl_pipeline.cpp ├── impl_pipeline.hpp ├── impl_swapchain.cpp ├── impl_swapchain.hpp ├── impl_sync.cpp ├── impl_sync.hpp ├── impl_timeline_query.cpp ├── impl_timeline_query.hpp └── utils │ ├── impl_fsr2.cpp │ ├── impl_fsr2.hpp │ ├── impl_imgui.cpp │ ├── impl_imgui.hpp │ ├── impl_imgui_spv.hpp │ ├── impl_mem.cpp │ ├── impl_pipeline_manager.cpp │ ├── impl_pipeline_manager.hpp │ ├── impl_task_graph.cpp │ ├── impl_task_graph.hpp │ └── impl_task_graph_debug.hpp ├── tests ├── 0_common │ ├── base_app.hpp │ ├── shared.hpp │ └── window.hpp ├── 1_setup │ └── 1_window │ │ └── main.cpp ├── 2_daxa_api │ ├── 10_raytracing │ │ ├── main.cpp │ │ └── shaders │ │ │ ├── random.glsl │ │ │ ├── raytracing.glsl │ │ │ ├── shaders.glsl │ │ │ └── shared.inl │ ├── 11_mesh_shader │ │ ├── draw.slang │ │ ├── main.cpp │ │ └── shared.inl │ ├── 12_async_queues │ │ ├── draw.slang │ │ ├── main.cpp │ │ └── shared.inl │ ├── 1_instance │ │ └── main.cpp │ ├── 2_device │ │ └── main.cpp │ ├── 3_command_recorder │ │ └── main.cpp │ ├── 4_synchronization │ │ └── main.cpp │ ├── 5_swapchain │ │ └── main.cpp │ ├── 6_task_graph │ │ ├── common.hpp │ │ ├── main.cpp │ │ ├── mipmapping.hpp │ │ ├── persistent_resources.hpp │ │ ├── shaders │ │ │ ├── draw.glsl │ │ │ ├── mipmapping.glsl │ │ │ ├── shader_integration.glsl │ │ │ ├── shader_integration.inl │ │ │ ├── shared.inl │ │ │ ├── transient.glsl │ │ │ └── transient.inl │ │ └── transient_overlap.hpp │ ├── 7_pipeline_manager │ │ ├── main.cpp │ │ └── shaders │ │ │ ├── main.glsl │ │ │ └── test │ │ │ ├── tesselation_test.glsl │ │ │ ├── test0.glsl │ │ │ └── test1.glsl │ ├── 8_mem │ │ └── main.cpp │ └── 9_shader_integration │ │ ├── main.cpp │ │ ├── shaders │ │ ├── alignment_test.glsl │ │ ├── bindless_access.glsl │ │ ├── bindless_access_followup.glsl │ │ └── shared.inl │ │ └── shared.hlsl ├── 3_samples │ ├── 0_rectangle_cutting │ │ ├── main.cpp │ │ └── shaders │ │ │ ├── draw.glsl │ │ │ └── shared.inl │ ├── 1_mandelbrot │ │ ├── main.cpp │ │ └── shaders │ │ │ ├── compute.glsl │ │ │ ├── compute.slang │ │ │ └── shared.inl │ ├── 2_mpm_mls │ │ ├── camera.h │ │ ├── main.cpp │ │ └── shaders │ │ │ ├── compute.glsl │ │ │ ├── compute.slang │ │ │ ├── raytracing.glsl │ │ │ ├── raytracing.slang │ │ │ └── shared.inl │ ├── 3_hello_triangle_compute │ │ ├── main.cpp │ │ └── shaders │ │ │ ├── compute.glsl │ │ │ ├── compute.hlsl │ │ │ └── shared.inl │ └── 5_boids │ │ ├── main.cpp │ │ ├── shaders │ │ ├── frag.glsl │ │ ├── update_boids.glsl │ │ └── vert.glsl │ │ └── shared.inl ├── 4_hello_daxa │ ├── 0_c_api │ │ └── main.c │ ├── 1_pink_screen │ │ └── main.cpp │ └── 2_triangle │ │ ├── main.cpp │ │ ├── main.glsl │ │ └── shared.inl └── CMakeLists.txt └── vcpkg.json /.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | BasedOnStyle: LLVM 3 | 4 | UseTab: Never 5 | TabWidth: 4 6 | IndentWidth: 4 7 | AccessModifierOffset: -2 8 | IndentCaseLabels: false 9 | ColumnLimit: 0 10 | BreakBeforeBraces: Allman 11 | QualifierAlignment: Right 12 | 13 | SortIncludes: false 14 | SortUsingDeclarations: false 15 | 16 | NamespaceIndentation: All 17 | CompactNamespaces: true 18 | 19 | AllowShortIfStatementsOnASingleLine: false 20 | AllowShortCaseLabelsOnASingleLine: true 21 | AllowShortBlocksOnASingleLine: false 22 | 23 | PointerAlignment: Middle 24 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | Checks: "*, 2 | -abseil-*, 3 | -altera-*, 4 | -android-*, 5 | -fuchsia-*, 6 | -google-*, 7 | -llvm*, 8 | -zircon-*, 9 | -readability-else-after-return, 10 | -readability-static-accessed-through-instance, 11 | -readability-avoid-const-params-in-decls, 12 | -cppcoreguidelines-non-private-member-variables-in-classes, 13 | -misc-non-private-member-variables-in-classes, 14 | -hicpp-uppercase-literal-suffix, 15 | -readability-uppercase-literal-suffix, 16 | -readability-identifier-length, 17 | -cppcoreguidelines-pro-type-reinterpret-cast, 18 | -performance-no-int-to-ptr, 19 | -bugprone-easily-swappable-parameters, 20 | -readability-simplify-boolean-expr, 21 | -hicpp-signed-bitwise, 22 | -cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers, 23 | -readability-function-cognitive-complexity, 24 | " 25 | WarningsAsErrors: '' 26 | HeaderFilterRegex: '' -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch", 6 | "type": "cppdbg", 7 | "request": "launch", 8 | "program": "${command:cmake.launchTargetPath}", 9 | "args": [], 10 | "stopAtEntry": false, 11 | "cwd": "${workspaceFolder}", 12 | "environment": [], 13 | "linux": { 14 | "type": "lldb" 15 | }, 16 | "windows": { 17 | "type": "cppvsdbg", 18 | "console": "externalTerminal" 19 | } 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 21, 6 | "patch": 0 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "defaults", 11 | "hidden": true, 12 | "binaryDir": "${sourceDir}/build/${presetName}", 13 | "toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", 14 | "generator": "Ninja Multi-Config", 15 | "cacheVariables": { 16 | "CMAKE_MODULE_PATH": "${sourceDir}/cmake/modules", 17 | "DAXA_USE_VCPKG": true, 18 | "DAXA_ENABLE_UTILS_FSR2": false, 19 | "DAXA_ENABLE_UTILS_IMGUI": true, 20 | "DAXA_ENABLE_UTILS_MEM": false, 21 | "DAXA_ENABLE_UTILS_PIPELINE_MANAGER_GLSLANG": true, 22 | "DAXA_ENABLE_UTILS_PIPELINE_MANAGER_SLANG": true, 23 | "DAXA_ENABLE_UTILS_PIPELINE_MANAGER_SPIRV_VALIDATION": false, 24 | "DAXA_ENABLE_UTILS_TASK_GRAPH": true, 25 | "DAXA_ENABLE_TESTS": true, 26 | "DAXA_ENABLE_TOOLS": true, 27 | "DAXA_ENABLE_STATIC_ANALYSIS": false 28 | } 29 | }, 30 | { 31 | "name": "defaults-windows", 32 | "hidden": true, 33 | "inherits": [ 34 | "defaults" 35 | ], 36 | "condition": { 37 | "type": "equals", 38 | "lhs": "${hostSystemName}", 39 | "rhs": "Windows" 40 | }, 41 | "cacheVariables": { 42 | "DAXA_TESTS_DISABLE_WINDOWS_CONSOLE": false 43 | } 44 | }, 45 | { 46 | "name": "defaults-linux", 47 | "hidden": true, 48 | "inherits": [ 49 | "defaults" 50 | ], 51 | "condition": { 52 | "type": "equals", 53 | "lhs": "${hostSystemName}", 54 | "rhs": "Linux" 55 | } 56 | }, 57 | { 58 | "name": "clang-x86_64-windows-msvc", 59 | "displayName": "Clang x86_64 Windows (MSVC ABI)", 60 | "inherits": [ 61 | "defaults-windows" 62 | ], 63 | "toolchainFile": "${sourceDir}/cmake/toolchains/clang-x86_64-windows-msvc.cmake" 64 | }, 65 | { 66 | "name": "cl-x86_64-windows-msvc", 67 | "displayName": "CL.exe x86_64 Windows (MSVC ABI)", 68 | "inherits": [ 69 | "defaults-windows" 70 | ], 71 | "toolchainFile": "${sourceDir}/cmake/toolchains/cl-x86_64-windows-msvc.cmake" 72 | }, 73 | { 74 | "name": "gcc-x86_64-linux-gnu", 75 | "displayName": "G++ x86_64 Linux (GNU ABI)", 76 | "inherits": [ 77 | "defaults-linux" 78 | ], 79 | "toolchainFile": "${sourceDir}/cmake/toolchains/gcc-x86_64-linux-gnu.cmake" 80 | }, 81 | { 82 | "name": "clang-x86_64-linux-gnu", 83 | "displayName": "Clang x86_64 Linux (GNU ABI)", 84 | "inherits": [ 85 | "defaults-linux" 86 | ], 87 | "toolchainFile": "${sourceDir}/cmake/toolchains/clang-x86_64-linux-gnu.cmake" 88 | } 89 | ], 90 | "buildPresets": [ 91 | { 92 | "name": "clang-x86_64-windows-msvc-debug", 93 | "displayName": "Clang x86_64 Windows (MSVC ABI) Debug", 94 | "configurePreset": "clang-x86_64-windows-msvc", 95 | "configuration": "Debug" 96 | }, 97 | { 98 | "name": "clang-x86_64-windows-msvc-relwithdebinfo", 99 | "displayName": "Clang x86_64 Windows (MSVC ABI) RelWithDebInfo", 100 | "configurePreset": "clang-x86_64-windows-msvc", 101 | "configuration": "RelWithDebInfo" 102 | }, 103 | { 104 | "name": "clang-x86_64-windows-msvc-release", 105 | "displayName": "Clang x86_64 Windows (MSVC ABI) Release", 106 | "configurePreset": "clang-x86_64-windows-msvc", 107 | "configuration": "Release" 108 | }, 109 | { 110 | "name": "cl-x86_64-windows-msvc-debug", 111 | "displayName": "CL.exe x86_64 Windows (MSVC ABI) Debug", 112 | "configurePreset": "cl-x86_64-windows-msvc", 113 | "configuration": "Debug" 114 | }, 115 | { 116 | "name": "cl-x86_64-windows-msvc-relwithdebinfo", 117 | "displayName": "CL.exe x86_64 Windows (MSVC ABI) RelWithDebInfo", 118 | "configurePreset": "cl-x86_64-windows-msvc", 119 | "configuration": "RelWithDebInfo" 120 | }, 121 | { 122 | "name": "cl-x86_64-windows-msvc-release", 123 | "displayName": "CL.exe x86_64 Windows (MSVC ABI) Release", 124 | "configurePreset": "cl-x86_64-windows-msvc", 125 | "configuration": "Release" 126 | }, 127 | { 128 | "name": "gcc-x86_64-linux-gnu-debug", 129 | "displayName": "G++ x86_64 Linux (GNU ABI) Debug", 130 | "configurePreset": "gcc-x86_64-linux-gnu", 131 | "configuration": "Debug" 132 | }, 133 | { 134 | "name": "gcc-x86_64-linux-gnu-relwithdebinfo", 135 | "displayName": "G++ x86_64 Linux (GNU ABI) RelWithDebInfo", 136 | "configurePreset": "gcc-x86_64-linux-gnu", 137 | "configuration": "RelWithDebInfo" 138 | }, 139 | { 140 | "name": "gcc-x86_64-linux-gnu-release", 141 | "displayName": "G++ x86_64 Linux (GNU ABI) Release", 142 | "configurePreset": "gcc-x86_64-linux-gnu", 143 | "configuration": "Release" 144 | }, 145 | { 146 | "name": "clang-x86_64-linux-gnu-debug", 147 | "displayName": "Clang x86_64 Linux (GNU ABI) Debug", 148 | "configurePreset": "clang-x86_64-linux-gnu", 149 | "configuration": "Debug" 150 | }, 151 | { 152 | "name": "clang-x86_64-linux-gnu-relwithdebinfo", 153 | "displayName": "Clang x86_64 Linux (GNU ABI) RelWithDebInfo", 154 | "configurePreset": "clang-x86_64-linux-gnu", 155 | "configuration": "RelWithDebInfo" 156 | }, 157 | { 158 | "name": "clang-x86_64-linux-gnu-release", 159 | "displayName": "Clang x86_64 Linux (GNU ABI) Release", 160 | "configurePreset": "clang-x86_64-linux-gnu", 161 | "configuration": "Release" 162 | } 163 | ] 164 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ipotrick (Patrick Ahrens) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Daxa logo 4 | 5 |

6 | 7 | # Daxa 8 | 9 | Daxa is my opinionated GPU API abstraction over Vulkan. 10 | 11 | Why would you want to use Daxa? These are some of the aspects of Daxa that set it apart from most other Vulkan abstractions: 12 | 13 | - Specifically designed for GPGPU programming and GPU-driven rendering. Daxa makes writing modern renderers simple and easy. It does not compromise for old hardware or old API concepts. Modern GPUs are the target (for Nvidia this is >=Turing, for AMD this is >= RDNA1). 14 | 15 | - Fully bindless. Buffers, images, samplers, and acceleration structures are all exclusively accessed via a bindless API. The bindless API abstracts descriptors completely. There are no bindings, no descriptor sets, no set layouts, no descriptor pools, and no binding or set indices within shaders. 16 | 17 | - Very high convenience with near zero boilerplate. Daxa makes the simple things as easy as possible. It abstracts over unnecessarily explicit parts of Vulkan. Tons of default values and common abstractions for renderers such as a render-graph and shader build system are provided by Daxa. 18 | 19 | - Shader utilities and shader feature integration. Daxa provides custom GLSL and HLSL headers, host/shader code sharing utilities, and even a shader build system featuring hot reloading and includes management. Especially the shader integration for many features is very convenient. 20 | 21 | - Efficient safety checks. An often neglected part of RHIs and rendering libraries is safety and debugging validation. Daxa performs many validation checks at very low overhead. Especially the render graph has very detailed error messages detailing misuse. 22 | 23 | - Effective abstractions with predictable performance. In contrast to many other abstractions, core Daxa never caches or lazily creates pipelines, layouts, or other objects. It should have performance as predictable as Vulkan. This makes profiling intuitive. 24 | 25 | ## Getting started 26 | 27 | To begin using Daxa, visit [daxa.dev](https://daxa.dev/), where you'll find a comprehensive tutorial and a Wiki containing detailed information about the Daxa API. 28 | 29 | - [Daxa Tutorial](https://tutorial.daxa.dev/) 30 | - [Daxa Wiki](https://wiki.daxa.dev/) 31 | 32 | Additionally, the Daxa repository includes a collection of example projects located in the **tests** folder 33 | 34 | For discussions or support, you can also join the Daxa [Discord server](https://discord.gg/MJPJvZ4FK5) if you prefer interacting there instead of using GitHub issues. 35 | 36 | ## List of biggest features 37 | 38 | - defaulted, named parameters for most functions via c++20 designated struct initialization 39 | - ergonomic, simplified object creation 40 | - easy device selection and properties query 41 | - integrated debug utilities such as debug names and range labels 42 | - feature-rich render-graph, handling automatic synchronization and more 43 | - shader integration for render-graph 44 | - shader/host code shading utilities 45 | - fully abstracted descriptor sets 46 | - automated, deeply integrated bindless system 47 | - shader bindless integration 48 | - a shader build system featuring hot reloading and `#include` handling 49 | - designed for threading, each object has its thread-safety described 50 | - no concept of render-pass or frame-buffer 51 | - typesafe simplified command recording and submission 52 | - automated memory allocation for buffers and images using VMA (manual allocation also possible) 53 | - swapchain that handles frames in flight pacing and WSI problems like resizing 54 | - always enabled dynamic state for any option that is cost-free on target hardware 55 | - simpler pipelines, no pipeline layout, and no descriptor set layouts 56 | - a full C API may be used to create API wrappers for other languages 57 | - extensive low-overhead validation checks 58 | - integrates most commonly used Vulkan extensions 59 | - support for buffer device addresses 60 | - always mapped buffers 61 | - mesh shaders, in core as well as pipeline manager 62 | - raytracing, in core, pipeline manager AND rendergraph 63 | - async compute/ async transfer/ multi-queue support 64 | - ergonomic explicit synchronization (optional, you can also use the render-graph instead) 65 | - stores queriable metadata for all objects, similar to dx11 66 | - simplified, semi-managed resource lifetimes 67 | - resource destruction is deferred until all currently submitted commands finish execution 68 | - unified IDs in host and shader code for buffers, images, etc. 69 | - automatic default image view integrated into all images 70 | - controllable parent-child lifetime semantics 71 | - fully abstracts Vulkan, allows Daxa to have more control and be more convenient 72 | - dearImGui backend 73 | - transient memory pool utility object 74 | -------------------------------------------------------------------------------- /cmake/modules/FindWayland.cmake: -------------------------------------------------------------------------------- 1 | # temporary fix for wayland 2 | 3 | if(NOT WIN32) 4 | if(Wayland_INCLUDE_DIR AND Wayland_LIBRARIES) 5 | # In the cache already 6 | set(Wayland_FIND_QUIETLY TRUE) 7 | endif() 8 | 9 | # Use pkg-config to get the directories and then use these values 10 | # in the find_path() and find_library() calls 11 | find_package(PkgConfig) 12 | pkg_check_modules(PKG_Wayland QUIET wayland-client wayland-server wayland-egl wayland-cursor) 13 | 14 | set(Wayland_DEFINITIONS ${PKG_Wayland_CFLAGS}) 15 | 16 | find_path(Wayland_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_Wayland_INCLUDE_DIRS}) 17 | find_path(Wayland_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_Wayland_INCLUDE_DIRS}) 18 | find_path(Wayland_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_Wayland_INCLUDE_DIRS}) 19 | find_path(Wayland_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_Wayland_INCLUDE_DIRS}) 20 | 21 | find_library(Wayland_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_Wayland_LIBRARY_DIRS}) 22 | find_library(Wayland_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_Wayland_LIBRARY_DIRS}) 23 | find_library(Wayland_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_Wayland_LIBRARY_DIRS}) 24 | find_library(Wayland_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_Wayland_LIBRARY_DIRS}) 25 | 26 | set(Wayland_INCLUDE_DIR ${Wayland_CLIENT_INCLUDE_DIR} ${Wayland_SERVER_INCLUDE_DIR} ${Wayland_EGL_INCLUDE_DIR} ${Wayland_CURSOR_INCLUDE_DIR}) 27 | set(Wayland_LIBRARIES ${Wayland_CLIENT_LIBRARIES} ${Wayland_SERVER_LIBRARIES} ${Wayland_EGL_LIBRARIES} ${Wayland_CURSOR_LIBRARIES}) 28 | list(REMOVE_DUPLICATES Wayland_INCLUDE_DIR) 29 | 30 | include(FindPackageHandleStandardArgs) 31 | find_package_handle_standard_args(Wayland DEFAULT_MSG Wayland_LIBRARIES Wayland_INCLUDE_DIR) 32 | 33 | mark_as_advanced(Wayland_INCLUDE_DIR Wayland_LIBRARIES) 34 | endif() 35 | -------------------------------------------------------------------------------- /cmake/packaging.cmake: -------------------------------------------------------------------------------- 1 | 2 | include(CMakePackageConfigHelpers) 3 | file(WRITE ${CMAKE_BINARY_DIR}/config.cmake.in [=[ 4 | @PACKAGE_INIT@ 5 | include(${CMAKE_CURRENT_LIST_DIR}/daxa-targets.cmake) 6 | check_required_components(daxa) 7 | 8 | get_target_property(DAXA_PREV_DEFINITIONS daxa::daxa INTERFACE_COMPILE_DEFINITIONS) 9 | set_target_properties(daxa::daxa PROPERTIES 10 | INTERFACE_COMPILE_DEFINITIONS "${DAXA_PREV_DEFINITIONS};DAXA_SHADER_INCLUDE_DIR=\"${PACKAGE_PREFIX_DIR}/include\"" 11 | ) 12 | ]=]) 13 | 14 | # Re-exporting the find_package is necessary for Linux package management for some reason... 15 | file(APPEND ${CMAKE_BINARY_DIR}/config.cmake.in [=[ 16 | find_package(Vulkan REQUIRED) 17 | find_package(VulkanMemoryAllocator CONFIG REQUIRED) 18 | ]=]) 19 | 20 | if(DAXA_ENABLE_UTILS_FSR2) 21 | file(APPEND ${CMAKE_BINARY_DIR}/config.cmake.in [=[ 22 | find_package(fsr2 CONFIG REQUIRED) 23 | ]=]) 24 | endif() 25 | if(DAXA_ENABLE_UTILS_IMGUI) 26 | file(APPEND ${CMAKE_BINARY_DIR}/config.cmake.in [=[ 27 | find_package(imgui CONFIG REQUIRED) 28 | ]=]) 29 | endif() 30 | if(DAXA_ENABLE_UTILS_MEM) 31 | # No package management work to do 32 | endif() 33 | if(DAXA_ENABLE_UTILS_PIPELINE_MANAGER_GLSLANG) 34 | file(APPEND ${CMAKE_BINARY_DIR}/config.cmake.in [=[ 35 | find_package(glslang CONFIG REQUIRED) 36 | find_package(Threads REQUIRED) 37 | ]=]) 38 | endif() 39 | if(DAXA_ENABLE_UTILS_PIPELINE_MANAGER_SPIRV_VALIDATION) 40 | file(APPEND ${CMAKE_BINARY_DIR}/config.cmake.in [=[ 41 | find_package(SPIRV-Tools CONFIG REQUIRED) 42 | ]=]) 43 | endif() 44 | if(DAXA_ENABLE_UTILS_TASK_GRAPH) 45 | # No package management work to do 46 | endif() 47 | 48 | configure_package_config_file(${CMAKE_BINARY_DIR}/config.cmake.in 49 | ${CMAKE_CURRENT_BINARY_DIR}/daxa-config.cmake 50 | INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/daxa 51 | NO_SET_AND_CHECK_MACRO) 52 | write_basic_package_version_file( 53 | ${CMAKE_CURRENT_BINARY_DIR}/daxa-config-version.cmake 54 | VERSION ${PROJECT_VERSION} 55 | COMPATIBILITY SameMajorVersion) 56 | install( 57 | FILES 58 | ${CMAKE_CURRENT_BINARY_DIR}/daxa-config.cmake 59 | ${CMAKE_CURRENT_BINARY_DIR}/daxa-config-version.cmake 60 | DESTINATION 61 | ${CMAKE_INSTALL_DATADIR}/daxa) 62 | install(TARGETS daxa EXPORT daxa-targets) 63 | if(BUILD_SHARED_LIBS AND WIN32) 64 | install(FILES $ DESTINATION bin OPTIONAL) 65 | endif() 66 | install(EXPORT daxa-targets DESTINATION ${CMAKE_INSTALL_DATADIR}/daxa NAMESPACE daxa::) 67 | install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ TYPE INCLUDE) 68 | -------------------------------------------------------------------------------- /cmake/toolchains/cl-x86_64-windows-msvc.cmake: -------------------------------------------------------------------------------- 1 | # Don't set the MSVC compiler.. This works when opening the folder in Visual Studio 2 | include(${CMAKE_CURRENT_LIST_DIR}/vcvars.cmake) 3 | 4 | find_program(CMAKE_C_COMPILER cl REQUIRED HINTS ${MSVC_ENV_Path}) 5 | find_program(CMAKE_CXX_COMPILER cl REQUIRED HINTS ${MSVC_ENV_Path}) 6 | find_program(CMAKE_MT mt REQUIRED HINTS ${MSVC_ENV_Path}) 7 | find_program(CMAKE_RC_COMPILER rc REQUIRED HINTS ${MSVC_ENV_Path}) 8 | 9 | set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT MSVC) 10 | set(CMAKE_C_COMPILER_FRONTEND_VARIANT MSVC) 11 | 12 | list(APPEND CMAKE_C_STANDARD_INCLUDE_DIRECTORIES ${MSVC_ENV_INCLUDE}) 13 | list(REMOVE_DUPLICATES CMAKE_C_STANDARD_INCLUDE_DIRECTORIES) 14 | set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_C_STANDARD_INCLUDE_DIRECTORIES} CACHE STRING "") 15 | 16 | list(APPEND CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${MSVC_ENV_INCLUDE}) 17 | list(REMOVE_DUPLICATES CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES) 18 | set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES} CACHE STRING "") 19 | 20 | list(APPEND CMAKE_RC_STANDARD_INCLUDE_DIRECTORIES ${MSVC_ENV_INCLUDE}) 21 | list(REMOVE_DUPLICATES CMAKE_RC_STANDARD_INCLUDE_DIRECTORIES) 22 | set(CMAKE_RC_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_RC_STANDARD_INCLUDE_DIRECTORIES} CACHE STRING "") 23 | 24 | foreach(libpath ${MSVC_ENV_LIBPATH} ${MSVC_ENV_LIB}) 25 | set(CMAKE_SHARED_LINKER_FLAGS_INIT "${CMAKE_SHARED_LINKER_FLAGS_INIT} \"/LIBPATH:${libpath}\"") 26 | set(CMAKE_MODULE_LINKER_FLAGS_INIT "${CMAKE_MODULE_LINKER_FLAGS_INIT} \"/LIBPATH:${libpath}\"") 27 | set(CMAKE_EXE_LINKER_FLAGS_INIT "${CMAKE_EXE_LINKER_FLAGS_INIT} \"/LIBPATH:${libpath}\"") 28 | endforeach() 29 | 30 | list(APPEND LINK_DIRECTORIES $ENV{LIB} $ENV{LIBPATH}) 31 | list(REMOVE_DUPLICATES LINK_DIRECTORIES) 32 | set(LINK_DIRECTORIES ${LINK_DIRECTORIES} CACHE STRING "") 33 | link_directories(BEFORE ${LINK_DIRECTORIES}) 34 | 35 | list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES 36 | MSVC_ENV_INCLUDE 37 | MSVC_ENV_LIBPATH 38 | MSVC_ENV_VAR_NAMES 39 | MSVC_ENV_Path 40 | MSVC_ENV_LIB 41 | ) 42 | -------------------------------------------------------------------------------- /cmake/toolchains/clang-x86_64-linux-gnu.cmake: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_SYSTEM_NAME Linux) 3 | set(CMAKE_SYSTEM_PROCESSOR x86_64) 4 | 5 | set(CMAKE_C_COMPILER_ID Clang) 6 | set(CMAKE_CXX_COMPILER_ID Clang) 7 | -------------------------------------------------------------------------------- /cmake/toolchains/clang-x86_64-windows-msvc.cmake: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_SYSTEM_NAME Windows) 3 | set(CMAKE_SYSTEM_PROCESSOR x86_64) 4 | 5 | set(CMAKE_C_COMPILER_ID Clang) 6 | set(CMAKE_CXX_COMPILER_ID Clang) 7 | -------------------------------------------------------------------------------- /cmake/toolchains/gcc-x86_64-linux-gnu.cmake: -------------------------------------------------------------------------------- 1 | 2 | set(CMAKE_SYSTEM_NAME Linux) 3 | set(CMAKE_SYSTEM_PROCESSOR x86_64) 4 | 5 | set(CMAKE_C_COMPILER_ID GNU) 6 | set(CMAKE_CXX_COMPILER_ID GNU) 7 | -------------------------------------------------------------------------------- /cmake/toolchains/vcvars.cmake: -------------------------------------------------------------------------------- 1 | function(msvc_inherit_from_vcvars) 2 | # vcvarsall.bat does not check if the PATH is already populated 3 | # with the necessary directories, and just naively appends them 4 | # to the existing PATH. Because of this, if this function gets 5 | # called more than a few times, it extends the PATH to exceed 6 | # a valid length and fails. Here I'm checking if the DevEnvDir 7 | # environment variable is set, and shortcutting this function 8 | # if so. 9 | # CMake will call the toolchain file multiple times when configuring 10 | # for the first time to do things like check if a compiler works 11 | # for a super simple file. Even though we check if we've set variables 12 | # in the cache to not re-call this function, the cache is NOT 13 | # populated until AFTER all the initial configuration is done, 14 | # therefore we must make sure that it's not a subsequent call from 15 | # checking the actual CMD environment 16 | execute_process(COMMAND cmd /c if defined DevEnvDir (exit 1) RESULT_VARIABLE CMD_RESULT) 17 | if(NOT CMD_RESULT EQUAL 0) 18 | return() 19 | endif() 20 | 21 | # Adapted from Modules/Platform/Windows-GNU.cmake 22 | set(VS_INSTALLER_PATHS "") 23 | set(VS_VERSIONS 17) 24 | foreach(VER ${VS_VERSIONS}) # change the first number to the largest supported version 25 | cmake_host_system_information(RESULT VS_DIR QUERY VS_${VER}_DIR) 26 | if(VS_DIR) 27 | list(APPEND VS_INSTALLER_PATHS "${VS_DIR}/VC/Auxiliary/Build") 28 | endif() 29 | endforeach() 30 | 31 | find_program(VCVARSALL_PATH NAMES vcvars64.bat vcvarsamd64.bat 32 | DOC "Visual Studio vcvarsamd64.bat" 33 | PATHS ${VS_INSTALLER_PATHS} 34 | ) 35 | 36 | if(NOT EXISTS "${VCVARSALL_PATH}") 37 | message(FATAL_ERROR "Unknown VS version specified/no vcvarsall.bat detected") 38 | else() 39 | message("vcvars file at ${VCVARSALL_PATH}") 40 | endif() 41 | execute_process(COMMAND cmd /c echo {SET0} && set && echo {/SET0} && "${VCVARSALL_PATH}" x64 && echo {SET1} && set && echo {/SET1} OUTPUT_VARIABLE CMD_OUTPUT RESULT_VARIABLE CMD_RESULT) 42 | if(NOT CMD_RESULT EQUAL 0) 43 | message(FATAL_ERROR "command returned '${CMD_RESULT}'") 44 | endif() 45 | 46 | # Parse the command output 47 | set(REST "${CMD_OUTPUT}") 48 | string(FIND "${REST}" "{SET0}" BEG) 49 | string(SUBSTRING "${REST}" ${BEG} -1 REST) 50 | string(FIND "${REST}" "{/SET0}" END) 51 | string(SUBSTRING "${REST}" 0 ${END} SET0) 52 | string(SUBSTRING "${SET0}" 6 -1 SET0) 53 | string(FIND "${REST}" "{SET1}" BEG) 54 | string(SUBSTRING "${REST}" ${BEG} -1 REST) 55 | string(FIND "${REST}" "{/SET1}" END) 56 | string(SUBSTRING "${REST}" 0 ${END} SET1) 57 | string(SUBSTRING "${SET1}" 6 -1 SET1) 58 | string(REGEX MATCHALL "\n[0-9a-zA-Z_]*" SET0_VARS "${SET0}") 59 | list(TRANSFORM SET0_VARS STRIP) 60 | string(REGEX MATCHALL "\n[0-9a-zA-Z_]*" SET1_VARS "${SET1}") 61 | list(TRANSFORM SET1_VARS STRIP) 62 | 63 | function(_extract_from_set_command INPUT VARNAME OUTVAR_NAME) 64 | set(R "${INPUT}") 65 | string(FIND "${R}" "\n${VARNAME}=" B) 66 | if(B EQUAL -1) 67 | set(${OUTVAR_NAME} "" PARENT_SCOPE) 68 | return() 69 | endif() 70 | string(SUBSTRING "${R}" ${B} -1 R) 71 | string(SUBSTRING "${R}" 1 -1 R) 72 | string(FIND "${R}" "\n" E) 73 | string(SUBSTRING "${R}" 0 ${E} OUT_TEMP) 74 | string(LENGTH "${VARNAME}=" VARNAME_LEN) 75 | string(SUBSTRING "${OUT_TEMP}" ${VARNAME_LEN} -1 OUT_TEMP) 76 | set(${OUTVAR_NAME} "${OUT_TEMP}" PARENT_SCOPE) 77 | endfunction() 78 | set(CHANGED_VARS) 79 | # Run over all the vars in set1 (the set containing all the new environment vars) 80 | # and compare their values to their respective value in set0 (the value before 81 | # running vcvarsall) 82 | foreach(V ${SET1_VARS}) 83 | _extract_from_set_command("${SET0}" ${V} V0) 84 | _extract_from_set_command("${SET1}" ${V} V1) 85 | if(NOT ("${V0}" STREQUAL "${V1}")) 86 | # if it is different, then we'll add it to the list 87 | list(APPEND CHANGED_VARS ${V}) 88 | # and also we'll cache it as the value from set1. 89 | if(V STREQUAL "Path") 90 | string(REGEX REPLACE "\\\\" "/" V1 "${V1}") 91 | endif() 92 | set(MSVC_ENV_${V} "${V1}" CACHE STRING "") 93 | endif() 94 | endforeach() 95 | set(MSVC_ENV_VAR_NAMES ${CHANGED_VARS} CACHE STRING "") 96 | endfunction() 97 | 98 | if(NOT DEFINED MSVC_ENV_VAR_NAMES) 99 | msvc_inherit_from_vcvars() 100 | endif() 101 | -------------------------------------------------------------------------------- /cmake/vcpkg-overlay-ports/fsr2/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fsr2", 3 | "version": "2.2.0", 4 | "description": "Unofficial FSR 2.2 API", 5 | "features": { 6 | "vulkan": { 7 | "description": "Build for Vulkan", 8 | "dependencies": [ 9 | "vulkan" 10 | ] 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /cmake/vcpkg-overlay-ports/glfw3/portfile.cmake: -------------------------------------------------------------------------------- 1 | vcpkg_from_git( 2 | OUT_SOURCE_PATH SOURCE_PATH 3 | URL https://github.com/glfw/glfw 4 | REF 8f470597d625ae28758c16b4293dd42d63e8a83a 5 | ) 6 | 7 | if(VCPKG_TARGET_IS_LINUX) 8 | message( 9 | "GLFW3 currently requires the following libraries from the system package manager: 10 | xinerama 11 | xcursor 12 | xorg 13 | libglu1-mesa 14 | These can be installed on Ubuntu systems via sudo apt install libxinerama-dev libxcursor-dev xorg-dev libglu1-mesa-dev") 15 | endif() 16 | 17 | vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS 18 | FEATURES 19 | xlib WITH_XLIB 20 | wayland WITH_WAYLAND 21 | ) 22 | set(GLFW_DEFINES) 23 | if(WITH_XLIB) 24 | list(APPEND GLFW_DEFINES "-DGLFW_BUILD_X11=true") 25 | endif() 26 | if(WITH_WAYLAND) 27 | list(APPEND GLFW_DEFINES "-DGLFW_BUILD_WAYLAND=true") 28 | endif() 29 | 30 | vcpkg_cmake_configure( 31 | SOURCE_PATH "${SOURCE_PATH}" 32 | OPTIONS 33 | -DGLFW_BUILD_EXAMPLES=OFF 34 | -DGLFW_BUILD_TESTS=OFF 35 | -DGLFW_BUILD_DOCS=OFF 36 | ${GLFW_DEFINES} 37 | ) 38 | 39 | vcpkg_cmake_install() 40 | vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/glfw3) 41 | vcpkg_fixup_pkgconfig() 42 | 43 | file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") 44 | file(INSTALL "${SOURCE_PATH}/LICENSE.md" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) 45 | 46 | vcpkg_copy_pdbs() 47 | -------------------------------------------------------------------------------- /cmake/vcpkg-overlay-ports/glfw3/vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "glfw3", 3 | "version-string": "custom", 4 | "description": "GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan application development. It provides a simple, platform-independent API for creating windows, contexts and surfaces, reading input, handling events, etc.", 5 | "homepage": "https://github.com/glfw/glfw", 6 | "license": "Zlib", 7 | "dependencies": [ 8 | { 9 | "name": "vcpkg-cmake", 10 | "host": true 11 | }, 12 | { 13 | "name": "vcpkg-cmake-config", 14 | "host": true 15 | }, 16 | { 17 | "name": "wayland", 18 | "default-features": false, 19 | "platform": "linux" 20 | }, 21 | { 22 | "name": "wayland-protocols", 23 | "default-features": false, 24 | "platform": "linux" 25 | } 26 | ], 27 | "features": { 28 | "xlib": { 29 | "description": "Build with XLib support" 30 | }, 31 | "wayland": { 32 | "description": "Build with Wayland support" 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /cmake/vcpkg.cmake: -------------------------------------------------------------------------------- 1 | 2 | if(NOT (CMAKE_TOOLCHAIN_FILE MATCHES "/scripts/buildsystems/vcpkg.cmake") AND DEFINED CMAKE_TOOLCHAIN_FILE) 3 | set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" CACHE UNINITIALIZED "") 4 | endif() 5 | 6 | if(EXISTS "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake") 7 | file(TO_CMAKE_PATH $ENV{VCPKG_ROOT} VCPKG_ROOT) 8 | set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake") 9 | else() 10 | find_package(Git REQUIRED) 11 | if(NOT EXISTS "${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake") 12 | execute_process(COMMAND ${GIT_EXECUTABLE} clone https://github.com/Microsoft/vcpkg 13 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 14 | COMMAND_ERROR_IS_FATAL ANY) 15 | else() 16 | execute_process(COMMAND ${GIT_EXECUTABLE} pull 17 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/vcpkg" 18 | COMMAND_ERROR_IS_FATAL ANY) 19 | endif() 20 | set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake") 21 | endif() 22 | -------------------------------------------------------------------------------- /cmake/warnings.cmake: -------------------------------------------------------------------------------- 1 | function(set_project_warnings project_name) 2 | option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF) 3 | 4 | set(MSVC_WARNINGS 5 | /W4 # Baseline reasonable warnings 6 | /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data 7 | /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 8 | /w14263 # 'function': member function does not override any base class virtual member function 9 | /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not 10 | # be destructed correctly 11 | /w14287 # 'operator': unsigned/negative constant mismatch 12 | /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside 13 | # the for-loop scope 14 | /w14296 # 'operator': expression is always 'boolean_value' 15 | /w14311 # 'variable': pointer truncation from 'type1' to 'type2' 16 | /w14545 # expression before comma evaluates to a function which is missing an argument list 17 | /w14546 # function call before comma missing argument list 18 | /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect 19 | /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? 20 | /w14555 # expression has no effect; expected expression with side- effect 21 | /w14619 # pragma warning: there is no warning number 'number' 22 | /w14640 # Enable warning on thread un-safe static member initialization 23 | /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. 24 | /w14905 # wide string literal cast to 'LPSTR' 25 | /w14906 # string literal cast to 'LPWSTR' 26 | /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied 27 | /permissive- # standards conformance mode for MSVC compiler. 28 | ) 29 | 30 | set(CLANG_WARNINGS 31 | -Wall 32 | -Wextra # reasonable and standard 33 | -Wshadow # warn the user if a variable declaration shadows one from a parent context 34 | -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps 35 | # catch hard to track down memory errors 36 | -Wold-style-cast # warn for c-style casts 37 | -Wcast-align # warn for potential performance problem casts 38 | -Wunused # warn on anything being unused 39 | -Woverloaded-virtual # warn if you overload (not override) a virtual function 40 | -Wpedantic # warn if non-standard C++ is used 41 | -Wconversion # warn on type conversions that may lose data 42 | -Wsign-conversion # warn on sign conversions 43 | -Wnull-dereference # warn if a null dereference is detected 44 | -Wdouble-promotion # warn if float is implicit promoted to double 45 | -Wformat=2 # warn on security issues around functions that format output (ie printf) 46 | -Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation 47 | -Wno-language-extension-token # disable this because of DXC code 48 | ) 49 | 50 | if(WARNINGS_AS_ERRORS) 51 | set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror) 52 | set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX) 53 | endif() 54 | 55 | set(GCC_WARNINGS 56 | ${CLANG_WARNINGS} 57 | -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist 58 | -Wduplicated-cond # warn if if / else chain has duplicated conditions 59 | -Wduplicated-branches # warn if if / else branches have duplicated code 60 | -Wlogical-op # warn about logical operations being used where bitwise were probably wanted 61 | -Wuseless-cast # warn if you perform a cast to the same type 62 | -Wno-strict-aliasing # DISABLE THIS BOGUS 63 | ) 64 | 65 | if(MSVC) 66 | set(PROJECT_WARNINGS ${MSVC_WARNINGS}) 67 | elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") 68 | set(PROJECT_WARNINGS ${CLANG_WARNINGS}) 69 | elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 70 | set(PROJECT_WARNINGS ${GCC_WARNINGS}) 71 | else() 72 | message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.") 73 | endif() 74 | 75 | target_compile_options(${project_name} PUBLIC $) 76 | 77 | endfunction() -------------------------------------------------------------------------------- /include/daxa/c/core.h: -------------------------------------------------------------------------------- 1 | #ifndef __DAXA_CORE_H__ 2 | #define __DAXA_CORE_H__ 3 | 4 | #include 5 | 6 | #if defined(__cplusplus) 7 | #define DAXA_EXPORT extern "C" DAXA_CMAKE_EXPORT 8 | #if defined(__linux__) 9 | #define DAXA_EXPORT_CXX 10 | #else 11 | #define DAXA_EXPORT_CXX DAXA_CMAKE_EXPORT 12 | #endif 13 | #define DAXA_ZERO_INIT {} 14 | #else 15 | #define DAXA_EXPORT DAXA_CMAKE_EXPORT 16 | #define DAXA_ZERO_INIT {0} 17 | #endif 18 | 19 | #if defined(__cplusplus) 20 | #define DAXA_NO_DISCARD [[nodiscard]] 21 | #else 22 | #define DAXA_NO_DISCARD 23 | #endif 24 | 25 | #define _DAXA_TEST_PRINT(...) 26 | 27 | static uint32_t const DAXA_ID_INDEX_BITS = 20; 28 | static uint32_t const DAXA_ID_INDEX_MASK = (1ull << 20) - 1ull; 29 | static uint32_t const DAXA_ID_INDEX_OFFSET = 0; 30 | static uint32_t const DAXA_ID_VERSION_BITS = 44; 31 | static uint64_t const DAXA_ID_VERSION_MASK = (1ull << 44) - 1ull; 32 | static uint32_t const DAXA_ID_VERSION_OFFSET = 20; 33 | 34 | typedef struct daxa_ImplDevice * daxa_Device; 35 | typedef struct daxa_ImplCommandRecorder * daxa_CommandRecorder; 36 | typedef struct daxa_ImplExecutableCommandList * daxa_ExecutableCommandList; 37 | typedef struct daxa_ImplInstance * daxa_Instance; 38 | typedef struct daxa_ImplRayTracingPipeline * daxa_RayTracingPipeline; 39 | typedef struct daxa_ImplComputePipeline * daxa_ComputePipeline; 40 | typedef struct daxa_ImplRasterPipeline * daxa_RasterPipeline; 41 | typedef struct daxa_ImplSwapchain * daxa_Swapchain; 42 | typedef struct daxa_ImplBinarySemaphore * daxa_BinarySemaphore; 43 | typedef struct daxa_ImplTimelineSemaphore * daxa_TimelineSemaphore; 44 | typedef struct daxa_ImplEvent * daxa_Event; 45 | typedef struct daxa_ImplTimelineQueryPool * daxa_TimelineQueryPool; 46 | typedef struct daxa_ImplMemoryBlock * daxa_MemoryBlock; 47 | 48 | typedef uint64_t daxa_Flags; 49 | 50 | typedef char daxa_Bool8; 51 | 52 | typedef struct 53 | { 54 | uint64_t value; 55 | } daxa_BufferId; 56 | 57 | typedef struct 58 | { 59 | uint64_t value; 60 | } daxa_ImageId; 61 | 62 | typedef struct 63 | { 64 | uint64_t value; 65 | } daxa_ImageViewId; 66 | 67 | typedef struct 68 | { 69 | uint32_t value; 70 | } daxa_ImageViewIndex; 71 | 72 | typedef struct 73 | { 74 | uint64_t value; 75 | } daxa_SamplerId; 76 | 77 | typedef struct 78 | { 79 | uint64_t value; 80 | } daxa_TlasId; 81 | 82 | typedef struct 83 | { 84 | uint64_t value; 85 | } daxa_BlasId; 86 | 87 | #define _DAXA_DECL_VEC2_TYPE(SCALAR_TYPE) \ 88 | typedef struct \ 89 | { \ 90 | SCALAR_TYPE x; \ 91 | SCALAR_TYPE y; \ 92 | } 93 | typedef uint32_t daxa_b32; 94 | typedef int32_t daxa_i32; 95 | typedef uint32_t daxa_u32; 96 | typedef int64_t daxa_i64; 97 | typedef uint64_t daxa_u64; 98 | typedef float daxa_f32; 99 | typedef double daxa_f64; 100 | 101 | #if defined(__GNUC__) || defined(__clang__) 102 | #pragma GCC diagnostic push 103 | #pragma GCC diagnostic ignored "-Wgnu-anonymous-struct" 104 | #elif defined(_MSC_VER) 105 | #pragma warning(push) 106 | #pragma warning(disable : 4201) 107 | #endif 108 | 109 | _DAXA_DECL_VEC2_TYPE(daxa_f32) 110 | daxa_f32vec2; 111 | _DAXA_DECL_VEC2_TYPE(daxa_f64) 112 | daxa_f64vec2; 113 | _DAXA_DECL_VEC2_TYPE(daxa_u32) 114 | daxa_u32vec2; 115 | _DAXA_DECL_VEC2_TYPE(daxa_i32) 116 | daxa_i32vec2; 117 | 118 | #define _DAXA_DECL_VEC3_TYPE(SCALAR_TYPE) \ 119 | typedef struct \ 120 | { \ 121 | SCALAR_TYPE x; \ 122 | SCALAR_TYPE y; \ 123 | SCALAR_TYPE z; \ 124 | } 125 | 126 | _DAXA_DECL_VEC3_TYPE(daxa_f32) 127 | daxa_f32vec3; 128 | _DAXA_DECL_VEC3_TYPE(daxa_f64) 129 | daxa_f64vec3; 130 | _DAXA_DECL_VEC3_TYPE(daxa_u32) 131 | daxa_u32vec3; 132 | _DAXA_DECL_VEC3_TYPE(daxa_i32) 133 | daxa_i32vec3; 134 | 135 | #define _DAXA_DECL_VEC4_TYPE(SCALAR_TYPE) \ 136 | typedef struct \ 137 | { \ 138 | SCALAR_TYPE x; \ 139 | SCALAR_TYPE y; \ 140 | SCALAR_TYPE z; \ 141 | SCALAR_TYPE w; \ 142 | } 143 | _DAXA_DECL_VEC4_TYPE(daxa_f32) 144 | daxa_f32vec4; 145 | _DAXA_DECL_VEC4_TYPE(daxa_f64) 146 | daxa_f64vec4; 147 | _DAXA_DECL_VEC4_TYPE(daxa_u32) 148 | daxa_u32vec4; 149 | _DAXA_DECL_VEC4_TYPE(daxa_i32) 150 | daxa_i32vec4; 151 | _DAXA_DECL_VEC2_TYPE(daxa_f32vec2) 152 | daxa_f32mat2x2; 153 | _DAXA_DECL_VEC2_TYPE(daxa_f32vec3) 154 | daxa_f32mat2x3; 155 | _DAXA_DECL_VEC2_TYPE(daxa_f32vec4) 156 | daxa_f32mat2x4; 157 | _DAXA_DECL_VEC2_TYPE(daxa_f64vec2) 158 | daxa_f64mat2x2; 159 | _DAXA_DECL_VEC2_TYPE(daxa_f64vec3) 160 | daxa_f64mat2x3; 161 | _DAXA_DECL_VEC2_TYPE(daxa_f64vec4) 162 | daxa_f64mat2x4; 163 | _DAXA_DECL_VEC3_TYPE(daxa_f32vec2) 164 | daxa_f32mat3x2; 165 | _DAXA_DECL_VEC3_TYPE(daxa_f32vec3) 166 | daxa_f32mat3x3; 167 | _DAXA_DECL_VEC3_TYPE(daxa_f32vec4) 168 | daxa_f32mat3x4; 169 | _DAXA_DECL_VEC3_TYPE(daxa_f64vec2) 170 | daxa_f64mat3x2; 171 | _DAXA_DECL_VEC3_TYPE(daxa_f64vec3) 172 | daxa_f64mat3x3; 173 | _DAXA_DECL_VEC3_TYPE(daxa_f64vec4) 174 | daxa_f64mat3x4; 175 | _DAXA_DECL_VEC4_TYPE(daxa_f32vec2) 176 | daxa_f32mat4x2; 177 | _DAXA_DECL_VEC4_TYPE(daxa_f32vec3) 178 | daxa_f32mat4x3; 179 | _DAXA_DECL_VEC4_TYPE(daxa_f32vec4) 180 | daxa_f32mat4x4; 181 | _DAXA_DECL_VEC4_TYPE(daxa_f64vec2) 182 | daxa_f64mat4x2; 183 | _DAXA_DECL_VEC4_TYPE(daxa_f64vec3) 184 | daxa_f64mat4x3; 185 | _DAXA_DECL_VEC4_TYPE(daxa_f64vec4) 186 | daxa_f64mat4x4; 187 | _DAXA_DECL_VEC2_TYPE(daxa_i32vec2) 188 | daxa_i32mat2x2; 189 | _DAXA_DECL_VEC2_TYPE(daxa_i32vec3) 190 | daxa_i32mat2x3; 191 | _DAXA_DECL_VEC2_TYPE(daxa_i32vec4) 192 | daxa_i32mat2x4; 193 | _DAXA_DECL_VEC2_TYPE(daxa_u32vec2) 194 | daxa_u32mat2x2; 195 | _DAXA_DECL_VEC2_TYPE(daxa_u32vec3) 196 | daxa_u32mat2x3; 197 | _DAXA_DECL_VEC2_TYPE(daxa_u32vec4) 198 | daxa_u32mat2x4; 199 | _DAXA_DECL_VEC3_TYPE(daxa_i32vec2) 200 | daxa_i32mat3x2; 201 | _DAXA_DECL_VEC3_TYPE(daxa_i32vec3) 202 | daxa_i32mat3x3; 203 | _DAXA_DECL_VEC3_TYPE(daxa_i32vec4) 204 | daxa_i32mat3x4; 205 | _DAXA_DECL_VEC3_TYPE(daxa_u32vec2) 206 | daxa_u32mat3x2; 207 | _DAXA_DECL_VEC3_TYPE(daxa_u32vec3) 208 | daxa_u32mat3x3; 209 | _DAXA_DECL_VEC3_TYPE(daxa_u32vec4) 210 | daxa_u32mat3x4; 211 | _DAXA_DECL_VEC4_TYPE(daxa_i32vec2) 212 | daxa_i32mat4x2; 213 | _DAXA_DECL_VEC4_TYPE(daxa_i32vec3) 214 | daxa_i32mat4x3; 215 | _DAXA_DECL_VEC4_TYPE(daxa_i32vec4) 216 | daxa_i32mat4x4; 217 | _DAXA_DECL_VEC4_TYPE(daxa_u32vec2) 218 | daxa_u32mat4x2; 219 | _DAXA_DECL_VEC4_TYPE(daxa_u32vec3) 220 | daxa_u32mat4x3; 221 | _DAXA_DECL_VEC4_TYPE(daxa_u32vec4) 222 | daxa_u32mat4x4; 223 | 224 | #define DAXA_SMALL_STRING_CAPACITY 63 225 | 226 | #if defined(__GNUC__) || defined(__clang__) 227 | #pragma GCC diagnostic pop 228 | #elif defined(_MSC_VER) 229 | #pragma warning(pop) 230 | #endif 231 | 232 | static uint32_t const DAXA_MAX_PUSH_CONSTANT_WORD_SIZE = (32); 233 | static uint32_t const DAXA_MAX_PUSH_CONSTANT_BYTE_SIZE = (DAXA_MAX_PUSH_CONSTANT_WORD_SIZE * 4); 234 | static uint32_t const DAXA_PIPELINE_LAYOUT_COUNT = (DAXA_MAX_PUSH_CONSTANT_WORD_SIZE + 1); 235 | 236 | // TODO(Raytracing): Should this say like this? 237 | static uint32_t const DAXA_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE = 0x00000001; 238 | static uint32_t const DAXA_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING = 0x00000002; 239 | static uint32_t const DAXA_GEOMETRY_INSTANCE_FORCE_OPAQUE = 0x00000004; 240 | static uint32_t const DAXA_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE = 0x00000008; 241 | 242 | /// ABI: Must stay compatible with 'VkAccelerationStructureInstanceKHR' 243 | typedef struct 244 | { 245 | daxa_f32mat3x4 transform; 246 | uint32_t instance_custom_index : 24; 247 | uint32_t mask : 8; 248 | uint32_t instance_shader_binding_table_record_offset : 24; 249 | uint32_t flags : 8; 250 | uint64_t blas_device_address; 251 | } daxa_BlasInstanceData; 252 | 253 | #endif 254 | -------------------------------------------------------------------------------- /include/daxa/c/daxa.h: -------------------------------------------------------------------------------- 1 | #ifndef __DAXA_H__ 2 | #define __DAXA_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #endif // #ifndef __DAXA_H__ 12 | -------------------------------------------------------------------------------- /include/daxa/c/instance.h: -------------------------------------------------------------------------------- 1 | #ifndef __DAXA_INSTANCE_H__ 2 | #define __DAXA_INSTANCE_H__ 3 | 4 | #include 5 | 6 | typedef daxa_Flags daxa_InstanceFlags; 7 | static const daxa_InstanceFlags DAXA_INSTANCE_FLAG_DEBUG_UTIL = 0x1; 8 | static const daxa_InstanceFlags DAXA_INSTANCE_FLAG_PARENT_MUST_OUTLIVE_CHILD = 0x2; 9 | 10 | typedef struct 11 | { 12 | daxa_InstanceFlags flags; 13 | daxa_SmallString engine_name; 14 | daxa_SmallString app_name; 15 | } daxa_InstanceInfo; 16 | 17 | static const daxa_InstanceInfo DAXA_DEFAULT_INSTANCE_INFO = { 18 | .flags = DAXA_INSTANCE_FLAG_DEBUG_UTIL, 19 | .engine_name = {.data = "daxa", .size = 4}, 20 | .app_name = {.data = "daxa app", .size = 8}, 21 | }; 22 | 23 | DAXA_EXPORT DAXA_NO_DISCARD daxa_Result 24 | daxa_create_instance(daxa_InstanceInfo const * info, daxa_Instance * out_instance); 25 | 26 | /// WARNING: DEPRECATED, use daxa_instance_create_device_2 instead! 27 | DAXA_EXPORT DAXA_NO_DISCARD daxa_Result 28 | daxa_instance_create_device(daxa_Instance instance, daxa_DeviceInfo const * info, daxa_Device * out_device); 29 | 30 | DAXA_EXPORT DAXA_NO_DISCARD daxa_Result 31 | daxa_instance_create_device_2(daxa_Instance instance, daxa_DeviceInfo2 const * info, daxa_Device * out_device); 32 | 33 | // Can be used to autofill the physical_device_index in a partially filled daxa_DeviceInfo2. 34 | DAXA_EXPORT daxa_Result 35 | daxa_instance_choose_device(daxa_Instance instance, daxa_ImplicitFeatureFlags desired_implicit_features, daxa_DeviceInfo2 * info); 36 | 37 | // Returns previous ref count. 38 | DAXA_EXPORT uint64_t 39 | daxa_instance_inc_refcnt(daxa_Instance instance); 40 | // Returns previous ref count. 41 | DAXA_EXPORT uint64_t 42 | daxa_instance_dec_refcnt(daxa_Instance instance); 43 | 44 | DAXA_EXPORT daxa_InstanceInfo const * 45 | daxa_instance_info(daxa_Instance instance); 46 | 47 | DAXA_EXPORT VkInstance 48 | daxa_instance_get_vk_instance(daxa_Instance instance); 49 | 50 | DAXA_EXPORT void 51 | daxa_instance_list_devices_properties(daxa_Instance instance, daxa_DeviceProperties const** properties, daxa_u32 * property_count); 52 | 53 | #endif // #ifndef __DAXA_INSTANCE_H__ 54 | -------------------------------------------------------------------------------- /include/daxa/c/swapchain.h: -------------------------------------------------------------------------------- 1 | #ifndef __DAXA_SWAPCHAIN_H__ 2 | #define __DAXA_SWAPCHAIN_H__ 3 | 4 | #include 5 | #include 6 | 7 | DAXA_EXPORT int32_t 8 | daxa_default_format_selector(VkFormat format); 9 | 10 | /// @brief A platform-dependent window resource. 11 | /// On Windows, this is an `HWND` 12 | /// On Linux X11, this is a `Window` 13 | /// On Linux Wayland, this is a `wl_surface *` 14 | typedef void * daxa_NativeWindowHandle; 15 | 16 | typedef enum 17 | { 18 | DAXA_NATIVE_WINDOW_PLATFORM_UNKNOWN, 19 | DAXA_NATIVE_WINDOW_PLATFORM_WIN32_API, 20 | DAXA_NATIVE_WINDOW_PLATFORM_XLIB_API, 21 | DAXA_NATIVE_WINDOW_PLATFORM_WAYLAND_API, 22 | DAXA_NATIVE_WINDOW_PLATFORM_MAX_ENUM = 0x7fffffff, 23 | } daxa_NativeWindowPlatform; 24 | 25 | typedef struct 26 | { 27 | daxa_NativeWindowHandle native_window; 28 | daxa_NativeWindowPlatform native_window_platform; 29 | int32_t (*surface_format_selector)(VkFormat); 30 | VkPresentModeKHR present_mode; 31 | VkSurfaceTransformFlagBitsKHR present_operation; 32 | daxa_ImageUsageFlags image_usage; 33 | size_t max_allowed_frames_in_flight; 34 | daxa_QueueFamily queue_family; 35 | daxa_SmallString name; 36 | } daxa_SwapchainInfo; 37 | 38 | DAXA_EXPORT VkExtent2D 39 | daxa_swp_get_surface_extent(daxa_Swapchain swapchain); 40 | DAXA_EXPORT VkFormat 41 | daxa_swp_get_format(daxa_Swapchain swapchain); 42 | DAXA_EXPORT VkColorSpaceKHR 43 | daxa_swp_get_color_space(daxa_Swapchain swapchain); 44 | DAXA_EXPORT DAXA_NO_DISCARD daxa_Result 45 | daxa_swp_resize(daxa_Swapchain swapchain); 46 | DAXA_EXPORT DAXA_NO_DISCARD daxa_Result 47 | daxa_swp_set_present_mode(daxa_Swapchain swapchain, VkPresentModeKHR present_mode); 48 | 49 | DAXA_EXPORT DAXA_NO_DISCARD daxa_Result 50 | daxa_swp_wait_for_next_frame(daxa_Swapchain swapchain); 51 | DAXA_EXPORT DAXA_NO_DISCARD daxa_Result 52 | daxa_swp_acquire_next_image(daxa_Swapchain swapchain, daxa_ImageId * out_image_id); 53 | DAXA_EXPORT daxa_BinarySemaphore * 54 | daxa_swp_current_acquire_semaphore(daxa_Swapchain swapchain); 55 | DAXA_EXPORT daxa_BinarySemaphore * 56 | daxa_swp_current_present_semaphore(daxa_Swapchain swapchain); 57 | DAXA_EXPORT uint64_t 58 | daxa_swp_current_cpu_timeline_value(daxa_Swapchain swapchain); 59 | DAXA_EXPORT daxa_TimelineSemaphore * 60 | daxa_swp_gpu_timeline_semaphore(daxa_Swapchain swapchain); 61 | 62 | DAXA_EXPORT daxa_SwapchainInfo const * 63 | daxa_swp_info(daxa_Swapchain swapchain); 64 | 65 | DAXA_EXPORT VkSwapchainKHR 66 | daxa_swp_get_vk_swapchain(daxa_Swapchain swapchain); 67 | DAXA_EXPORT VkSurfaceKHR 68 | daxa_swp_get_vk_surface(daxa_Swapchain swapchain); 69 | DAXA_EXPORT uint64_t 70 | daxa_swp_inc_refcnt(daxa_Swapchain swapchain); 71 | DAXA_EXPORT uint64_t 72 | daxa_swp_dec_refcnt(daxa_Swapchain swapchain); 73 | 74 | #endif // #ifndef __DAXA_SWAPCHAIN_H__ 75 | -------------------------------------------------------------------------------- /include/daxa/core.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #if !defined(DAXA_VALIDATION) 8 | #if defined(NDEBUG) 9 | #define DAXA_VALIDATION 0 10 | #else 11 | #define DAXA_VALIDATION 1 12 | #endif 13 | #endif 14 | 15 | #if DAXA_VALIDATION 16 | #include 17 | #include 18 | 19 | #define DAXA_GPU_ID_VALIDATION 1 20 | 21 | #define DAXA_DBG_ASSERT_FAIL_STRING "[[DAXA ASSERT FAILURE]]" 22 | 23 | #define DAXA_DBG_ASSERT_TRUE_M(x, m) \ 24 | do \ 25 | { \ 26 | if (std::is_constant_evaluated()) \ 27 | { \ 28 | /* how do we check this??? static_assert(x); */ \ 29 | } \ 30 | else if (!(x)) \ 31 | { \ 32 | std::cerr << DAXA_DBG_ASSERT_FAIL_STRING << ": " << (m) << std::endl; \ 33 | throw std::runtime_error("DAXA DEBUG ASSERTION FAILURE"); \ 34 | } \ 35 | } while (false) 36 | #define DAXA_DBG_ASSERT_TRUE_MS(x, STREAM) \ 37 | do \ 38 | { \ 39 | if (std::is_constant_evaluated()) \ 40 | { \ 41 | /* how do we check this??? static_assert(x); */ \ 42 | } \ 43 | else if (!(x)) \ 44 | { \ 45 | std::cerr << DAXA_DBG_ASSERT_FAIL_STRING << ": " STREAM << std::endl; \ 46 | throw std::runtime_error("DAXA DEBUG ASSERTION FAILURE"); \ 47 | } \ 48 | } while (false) 49 | #else 50 | 51 | #define DAXA_DBG_ASSERT_TRUE_M(x, m) 52 | #define DAXA_DBG_ASSERT_TRUE_MS(x, m) 53 | 54 | #endif 55 | 56 | #if !defined(DAXA_GPU_ID_VALIDATION) 57 | #define DAXA_GPU_ID_VALIDATION 0 58 | #endif 59 | 60 | #if !defined(DAXA_REMOVE_DEPRECATED) 61 | #define DAXA_REMOVE_DEPRECATED 1 62 | #endif 63 | 64 | namespace daxa 65 | { 66 | /// @brief A platform-dependent window resource. 67 | /// On Windows, this is an `HWND` 68 | /// On Linux X11, this is a `Window` 69 | /// On Linux Wayland, this is a `wl_surface *` 70 | using NativeWindowHandle = void *; 71 | 72 | enum struct NativeWindowPlatform 73 | { 74 | UNKNOWN, 75 | WIN32_API, 76 | XLIB_API, 77 | WAYLAND_API, 78 | MAX_ENUM = 0x7fffffff, 79 | }; 80 | } // namespace daxa 81 | 82 | namespace daxa 83 | { 84 | template 85 | struct Result 86 | { 87 | std::optional v = {}; 88 | std::string m = {}; 89 | 90 | explicit Result(T && value) 91 | : v{std::move(value)}, m{""} 92 | { 93 | } 94 | 95 | explicit Result(T const & value) 96 | : v{value}, m{""} 97 | { 98 | } 99 | 100 | explicit Result(std::optional && opt) 101 | : v{std::move(opt)}, m{opt.has_value() ? "" : "default error message"} 102 | { 103 | } 104 | 105 | explicit Result(std::optional const & opt) 106 | : v{opt}, m{opt.has_value() ? "" : "default error message"} 107 | { 108 | } 109 | 110 | explicit Result(std::string_view message) 111 | : v{std::nullopt}, m{message} 112 | { 113 | } 114 | 115 | bool is_ok() const 116 | { 117 | return v.has_value(); 118 | } 119 | 120 | bool is_err() const 121 | { 122 | return !v.has_value(); 123 | } 124 | 125 | auto value() const -> T const & 126 | { 127 | return v.value(); 128 | } 129 | 130 | auto value() -> T & 131 | { 132 | DAXA_DBG_ASSERT_TRUE_M(v.has_value(), (m != "" ? m : "tried getting value of empty Result")); 133 | return v.value(); 134 | } 135 | 136 | auto message() const -> std::string const & 137 | { 138 | return m; 139 | } 140 | 141 | auto to_string() const -> std::string 142 | { 143 | if (v.has_value()) 144 | { 145 | return "Result OK"; 146 | } 147 | else 148 | { 149 | return std::string("Result Err: ") + m; 150 | } 151 | } 152 | 153 | operator bool() const 154 | { 155 | return v.has_value(); 156 | } 157 | 158 | auto operator!() const -> bool 159 | { 160 | return !v.has_value(); 161 | } 162 | }; 163 | 164 | template <> 165 | struct Result 166 | { 167 | bool v = {}; 168 | std::string m = {}; 169 | 170 | explicit Result(bool opt) 171 | : v{opt}, m{opt ? "" : "default error message"} 172 | { 173 | } 174 | 175 | explicit Result(std::string_view message) 176 | : v{false}, m{message} 177 | { 178 | } 179 | 180 | bool is_ok() const 181 | { 182 | return v; 183 | } 184 | 185 | bool is_err() const 186 | { 187 | return !v; 188 | } 189 | 190 | auto message() const -> std::string const & 191 | { 192 | return m; 193 | } 194 | 195 | auto to_string() const -> std::string 196 | { 197 | if (v) 198 | { 199 | return "Result OK"; 200 | } 201 | else 202 | { 203 | return std::string("Result Err: ") + m; 204 | } 205 | } 206 | 207 | operator bool() const 208 | { 209 | return v; 210 | } 211 | 212 | auto operator!() const -> bool 213 | { 214 | return !v; 215 | } 216 | }; 217 | } // namespace daxa 218 | -------------------------------------------------------------------------------- /include/daxa/daxa.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | -------------------------------------------------------------------------------- /include/daxa/daxa.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define DAXA_GPU_TABLE_SET_BINDING 0 4 | #define DAXA_STORAGE_BUFFER_BINDING 0 5 | #define DAXA_STORAGE_IMAGE_BINDING 1 6 | #define DAXA_SAMPLED_IMAGE_BINDING 2 7 | #define DAXA_SAMPLER_BINDING 3 8 | #define DAXA_BUFFER_DEVICE_ADDRESS_BUFFER_BINDING 4 9 | #define DAXA_ACCELERATION_STRUCTURE_BINDING 5 10 | 11 | #define DAXA_LANGUAGE_C 0 12 | #define DAXA_LANGUAGE_CPP 0 13 | #define DAXA_LANGUAGE_GLSL 2 14 | #define DAXA_LANGUAGE_SLANG 3 15 | #define DAXA_LANGUAGE_HLSL DAXA_LANGUAGE_SLANG 16 | 17 | #if defined(_STDC_) // C 18 | 19 | #define DAXA_SHADER 0 20 | #define DAXA_LANGUAGE DAXA_LANGUAGE_C 21 | #include 22 | /// @brief Buffer ptr enable is ignored in c++. 23 | #define DAXA_DECL_BUFFER_PTR(STRUCT_TYPE) 24 | #define DAXA_DECL_BUFFER_PTR_ALIGN(STRUCT_TYPE, ALIGN) 25 | /// @brief Buffer ptr types map to the buffer device address type in daxa. 26 | #define daxa_RWBufferPtr(x) daxa_DeviceAddress 27 | /// @brief Buffer ptr types map to the buffer device address type in daxa. 28 | #define daxa_BufferPtr(x) daxa_DeviceAddress 29 | 30 | #elif defined(__cplusplus) // C++ 31 | 32 | #define DAXA_SHADER 0 33 | #define DAXA_LANGUAGE DAXA_LANGUAGE_CPP 34 | #include 35 | /// @brief Buffer ptr enable is ignored in c++. 36 | #define DAXA_DECL_BUFFER_PTR(STRUCT_TYPE) 37 | #define DAXA_DECL_BUFFER_PTR_ALIGN(STRUCT_TYPE, ALIGN) 38 | /// @brief Buffer ptr types map to the buffer device address type in daxa. 39 | #define daxa_RWBufferPtr(x) daxa::types::DeviceAddress 40 | /// @brief Buffer ptr types map to the buffer device address type in daxa. 41 | #define daxa_BufferPtr(x) daxa::types::DeviceAddress 42 | 43 | #elif defined(GL_core_profile) // GLSL 44 | 45 | #define DAXA_SHADER 1 46 | #define DAXA_LANGUAGE DAXA_LANGUAGE_GLSL 47 | #include 48 | 49 | #else // SLANG 50 | 51 | #define DAXA_SHADER 1 52 | #define DAXA_LANGUAGE DAXA_LANGUAGE_SLANG 53 | #include "daxa/daxa.slang" 54 | 55 | #endif -------------------------------------------------------------------------------- /include/daxa/instance.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace daxa 7 | { 8 | struct InstanceFlagsProperties 9 | { 10 | using Data = u64; 11 | }; 12 | using InstanceFlags = Flags; 13 | struct InstanceFlagBits 14 | { 15 | static inline constexpr InstanceFlags NONE = {0x00000000}; 16 | static inline constexpr InstanceFlags DEBUG_UTILS = {0x00000001}; 17 | static inline constexpr InstanceFlags PARENT_MUST_OUTLIVE_CHILD = {0x00000002}; 18 | }; 19 | 20 | struct InstanceInfo 21 | { 22 | InstanceFlags flags = 23 | InstanceFlagBits::DEBUG_UTILS | 24 | InstanceFlagBits::PARENT_MUST_OUTLIVE_CHILD; 25 | SmallString engine_name = "daxa"; 26 | SmallString app_name = "daxa app"; 27 | }; 28 | 29 | struct DAXA_EXPORT_CXX Instance final : ManagedPtr 30 | { 31 | Instance() = default; 32 | 33 | #if !DAXA_REMOVE_DEPRECATED 34 | [[deprecated("Use create_device_2 instead, API:3.0")]] [[nodiscard]] auto create_device(DeviceInfo const & device_info) -> Device; 35 | #endif 36 | [[nodiscard]] auto create_device_2(DeviceInfo2 const & device_info) -> Device; 37 | 38 | /// Convenience function to pick a physical device. 39 | /// Picks first supported device that satisfies the given device info and desired implicit features. 40 | [[nodiscard]] auto choose_device(ImplicitFeatureFlags desired_features, DeviceInfo2 const & base_info) -> DeviceInfo2; 41 | 42 | [[nodiscard]] auto list_devices_properties() -> std::span; 43 | 44 | /// THREADSAFETY: 45 | /// * reference MUST NOT be read after the object is destroyed. 46 | /// @return reference to info of object. 47 | [[nodiscard]] auto info() const -> InstanceInfo const &; 48 | 49 | protected: 50 | template 51 | friend struct ManagedPtr; 52 | static auto inc_refcnt(ImplHandle const * object) -> u64; 53 | static auto dec_refcnt(ImplHandle const * object) -> u64; 54 | }; 55 | 56 | [[nodiscard]] DAXA_EXPORT_CXX auto create_instance(InstanceInfo const & info) -> Instance; 57 | } // namespace daxa 58 | -------------------------------------------------------------------------------- /include/daxa/swapchain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace daxa 9 | { 10 | static inline auto default_format_score(Format format) -> i32 11 | { 12 | switch (format) 13 | { 14 | case Format::B8G8R8A8_UNORM: return 90; 15 | case Format::R8G8B8A8_UNORM: return 80; 16 | case Format::B8G8R8A8_SRGB: return 70; 17 | case Format::R8G8B8A8_SRGB: return 60; 18 | default: return 0; 19 | } 20 | } 21 | 22 | struct SwapchainInfo 23 | { 24 | NativeWindowHandle native_window; 25 | NativeWindowPlatform native_window_platform; 26 | i32 (*surface_format_selector)(Format) = default_format_score; 27 | PresentMode present_mode = PresentMode::FIFO; 28 | PresentOp present_operation = PresentOp::IDENTITY; 29 | ImageUsageFlags image_usage = {}; 30 | usize max_allowed_frames_in_flight = 2; 31 | QueueFamily queue_family = {}; 32 | SmallString name = {}; 33 | }; 34 | 35 | /** 36 | * @brief Swapchain represents the surface, swapchain and synch primitives regarding acquire and present operations. 37 | * The swapchain has a cpu and gpu timeline in order to ensure proper frames in flight. 38 | * 39 | * NOTE: 40 | * * functions that contain 'current' in their name might return different values between calling acquire_next_image 41 | * 42 | * THREADSAFETY: 43 | * * must be externally synchronized 44 | * * can be passed between different threads 45 | * * may be accessed by only one thread at the same time 46 | */ 47 | struct DAXA_EXPORT_CXX Swapchain final : ManagedPtr 48 | { 49 | Swapchain() = default; 50 | 51 | /// @brief Limits Frames In Flight. Blocks until GPU catches up to the max nr of frames in flight. 52 | /// WARNING: 53 | /// * DOES NOT WAIT for the swapchain image to be available, one must STILL use the acquire semaphore! 54 | /// * This function DOES WAIT until there is a FRAME IN FLIGHT available to prepare on the CPU! 55 | /// * Function is entirely optional to call, the function acquire_next_image ALSO calls wait_for_next_frame internally. 56 | void wait_for_next_frame(); 57 | /// @brief The ImageId may change between calls. This must be called to obtain a new swapchain image to be used for rendering. 58 | /// WARNING: 59 | /// * ImageIds returned from the swapchain are INVALID after the swapchain is destroyed. 60 | /// * ImageIds returned from the swapchain are INVALID after calling either resize OR set_present_mode! 61 | /// @return A swapchain image, that will be ready to render to when the acquire semaphore is signaled. This may return an empty image id if the swapchain is out of date. 62 | [[nodiscard]] auto acquire_next_image() -> ImageId; 63 | /// The acquire semaphore must be waited on in the first submission that uses the last acquired image. 64 | /// This semaphore may change between acquires, so it needs to be re-queried after every current_acquire_semaphore call. 65 | /// @return The binary semaphore that is signaled when the last acquired image is ready to be used. 66 | [[nodiscard]] auto current_acquire_semaphore() const -> BinarySemaphore const &; 67 | /// @brief The present semaphore must be signaled in the last submission that uses the last acquired swapchain image. 68 | /// The present semaphore must be waited on in the present of the last acquired image. 69 | /// This semaphore may change between acquires, so it needs to be re-queried after every current_acquire_semaphore call. 70 | /// @return The present semaphore that needs to be signaled and waited on for present of the last acquired image. 71 | [[nodiscard]] auto current_present_semaphore() const -> BinarySemaphore const &; 72 | /// @brief The last submission that uses the swapchain image needs to signal the timeline with the cpu value. 73 | /// @return The cpu frame timeline value. 74 | [[nodiscard]] auto current_cpu_timeline_value() const -> u64; 75 | /// @brief The swapchain needs to know when the last use of the swapchain happens to limit the frames in flight. 76 | /// In the last submission that uses the swapchain image, signal this timeline semaphore with the cpu timeline value. 77 | /// @return the gpu timeline semaphore that needs to be signaled. 78 | [[nodiscard]] auto gpu_timeline_semaphore() const -> TimelineSemaphore const &; 79 | /// @brief The swapchain needs to know when the last use of the swapchain happens to limit the frames in flight. 80 | /// In the last submission that uses the swapchain image, signal this timeline semaphore with the cpu timeline value. 81 | /// The cpu value timeline is incremented whenever acquire is called. 82 | /// The gpu timeline must be manually incremented by the user via a submit. 83 | /// The difference between cpu and gpu timeline describes how many frames in flight the gpu is behind the cpu. 84 | /// @return Returns pair of a gpu timeline and cpu timeline value. 85 | [[nodiscard]] auto current_timeline_pair() const -> std::pair; 86 | 87 | /// @brief When the window size changes the swapchain is in an invalid state for new commands. 88 | /// Calling resize will recreate the swapchain with the proper window size. 89 | /// WARNING: 90 | /// * Due to wsi limitations this function will WAIT IDLE THE DEVICE. 91 | /// * If the function throws an error, The swapchain will be invalidated and unusable! 92 | void resize(); 93 | /// @brief Recreates swapchain with new present mode. 94 | /// WARNING: 95 | /// * Due to wsi limitations this function will WAIT IDLE THE DEVICE. 96 | /// * If the function throws an error, The swapchain will be invalidated and unusable! 97 | void set_present_mode(PresentMode present_mode); 98 | /// THREADSAFETY: 99 | /// * reference MUST NOT be read after the swapchain is destroyed 100 | /// * reference is INVALIDATED after calling either resize OR set_present_mode 101 | /// @return reference to the objects info 102 | [[nodiscard]] auto info() const -> SwapchainInfo const &; 103 | [[nodiscard]] auto get_surface_extent() const -> Extent2D; 104 | [[nodiscard]] auto get_format() const -> Format; 105 | [[nodiscard]] auto get_color_space() const -> ColorSpace; 106 | 107 | protected: 108 | template 109 | friend struct ManagedPtr; 110 | static auto inc_refcnt(ImplHandle const * object) -> u64; 111 | static auto dec_refcnt(ImplHandle const * object) -> u64; 112 | }; 113 | } // namespace daxa 114 | -------------------------------------------------------------------------------- /include/daxa/sync.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace daxa 7 | { 8 | struct Device; 9 | 10 | struct MemoryBarrierInfo 11 | { 12 | Access src_access = AccessConsts::NONE; 13 | Access dst_access = AccessConsts::NONE; 14 | }; 15 | 16 | [[nodiscard]] auto to_string(MemoryBarrierInfo const & info) -> std::string; 17 | 18 | struct ImageMemoryBarrierInfo 19 | { 20 | Access src_access = AccessConsts::NONE; 21 | Access dst_access = AccessConsts::NONE; 22 | ImageLayout src_layout = ImageLayout::UNDEFINED; 23 | ImageLayout dst_layout = ImageLayout::UNDEFINED; 24 | ImageMipArraySlice image_slice = {}; 25 | ImageId image_id = {}; 26 | }; 27 | 28 | [[nodiscard]] DAXA_EXPORT_CXX auto to_string(ImageMemoryBarrierInfo const & info) -> std::string; 29 | 30 | struct BinarySemaphoreInfo 31 | { 32 | SmallString name = {}; 33 | }; 34 | 35 | struct DAXA_EXPORT_CXX BinarySemaphore final : ManagedPtr 36 | { 37 | BinarySemaphore() = default; 38 | 39 | /// THREADSAFETY: 40 | /// * reference MUST NOT be read after the device is destroyed. 41 | /// @return reference to info of object. 42 | [[nodiscard]] auto info() const -> BinarySemaphoreInfo const &; 43 | 44 | protected: 45 | template 46 | friend struct ManagedPtr; 47 | static auto inc_refcnt(ImplHandle const * object) -> u64; 48 | static auto dec_refcnt(ImplHandle const * object) -> u64; 49 | }; 50 | 51 | struct TimelineSemaphoreInfo 52 | { 53 | u64 initial_value = {}; 54 | SmallString name = {}; 55 | }; 56 | 57 | struct DAXA_EXPORT_CXX TimelineSemaphore final : ManagedPtr 58 | { 59 | TimelineSemaphore() = default; 60 | 61 | /// THREADSAFETY: 62 | /// * reference MUST NOT be read after the object is destroyed. 63 | /// @return reference to info of object. 64 | [[nodiscard]] auto info() const -> TimelineSemaphoreInfo const &; 65 | 66 | [[nodiscard]] auto value() const -> u64; 67 | void set_value(u64 value); 68 | [[nodiscard]] auto wait_for_value(u64 value, u64 timeout_nanos = ~0ull) -> bool; 69 | 70 | protected: 71 | template 72 | friend struct ManagedPtr; 73 | static auto inc_refcnt(ImplHandle const * object) -> u64; 74 | static auto dec_refcnt(ImplHandle const * object) -> u64; 75 | }; 76 | 77 | struct EventInfo 78 | { 79 | SmallString name = {}; 80 | }; 81 | 82 | struct DAXA_EXPORT_CXX Event final : ManagedPtr 83 | { 84 | Event() = default; 85 | 86 | /// THREADSAFETY: 87 | /// * reference MUST NOT be read after the object is destroyed. 88 | /// @return reference to info of object. 89 | [[nodiscard]] auto info() const -> EventInfo const &; 90 | 91 | protected: 92 | template 93 | friend struct ManagedPtr; 94 | static auto inc_refcnt(ImplHandle const * object) -> u64; 95 | static auto dec_refcnt(ImplHandle const * object) -> u64; 96 | }; 97 | 98 | struct EventSignalInfo 99 | { 100 | daxa::Span memory_barriers = {}; 101 | daxa::Span image_barriers = {}; 102 | Event & event; 103 | }; 104 | 105 | using EventWaitInfo = EventSignalInfo; 106 | } // namespace daxa -------------------------------------------------------------------------------- /include/daxa/utils/fsr2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if !DAXA_BUILT_WITH_UTILS_FSR2 4 | #error "[package management error] You must build Daxa with the DAXA_ENABLE_UTILS_FSR2 CMake option enabled, or request the utils-fsr2 feature in vcpkg" 5 | #endif 6 | 7 | #include 8 | 9 | namespace daxa 10 | { 11 | struct ImplFsr2Context; 12 | struct DAXA_EXPORT_CXX Fsr2Context : ManagedPtr 13 | { 14 | Fsr2Context() = default; 15 | 16 | Fsr2Context(UpscaleInstanceInfo const & info); 17 | 18 | void resize(UpscaleSizeInfo const & info); 19 | void upscale(CommandRecorder & command_list, UpscaleInfo const & info); 20 | auto get_jitter(u64 index) const -> daxa_f32vec2; 21 | 22 | protected: 23 | template 24 | friend struct ManagedPtr; 25 | static auto inc_refcnt(ImplHandle const * object) -> u64; 26 | static auto dec_refcnt(ImplHandle const * object) -> u64; 27 | }; 28 | } // namespace daxa 29 | -------------------------------------------------------------------------------- /include/daxa/utils/imgui.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if !DAXA_BUILT_WITH_UTILS_IMGUI 4 | #error "[package management error] You must build Daxa with the DAXA_ENABLE_UTILS_IMGUI CMake option enabled, or request the utils-imgui feature in vcpkg" 5 | #endif 6 | 7 | #include 8 | #include 9 | 10 | #if DAXA_BUILT_WITH_UTILS_TASK_GRAPH 11 | #include 12 | #endif 13 | 14 | #include 15 | 16 | namespace daxa 17 | { 18 | struct ImGuiImageContext 19 | { 20 | ImageViewId image_view_id; 21 | SamplerId sampler_id; 22 | }; 23 | 24 | struct ImGuiRendererInfo 25 | { 26 | Device device; 27 | Format format; 28 | ImGuiContext * context = {}; 29 | // NOTE: This is for backwards compatibility. Though, 30 | // I'm not sure the ImGui renderer util should set the 31 | // ImGui style. Something to bikeshed. 32 | bool use_custom_config = true; 33 | }; 34 | 35 | struct ImplImGuiRenderer; 36 | struct DAXA_EXPORT_CXX ImGuiRenderer : ManagedPtr 37 | { 38 | ImGuiRenderer() = default; 39 | 40 | ImGuiRenderer(ImGuiRendererInfo const & info); 41 | 42 | auto create_texture_id(ImGuiImageContext const & context) -> ImTextureID; 43 | 44 | void record_commands(ImDrawData * draw_data, CommandRecorder & recorder, ImageId target_image, u32 size_x, u32 size_y); 45 | #if DAXA_BUILT_WITH_UTILS_TASK_GRAPH 46 | void record_task(ImDrawData * draw_data, TaskGraph & task_graph, TaskImageView task_swapchain_image, u32 size_x, u32 size_y); 47 | #endif 48 | protected: 49 | template 50 | friend struct ManagedPtr; 51 | static auto inc_refcnt(ImplHandle const * object) -> u64; 52 | static auto dec_refcnt(ImplHandle const * object) -> u64; 53 | }; 54 | } // namespace daxa 55 | -------------------------------------------------------------------------------- /include/daxa/utils/mem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if !DAXA_BUILT_WITH_UTILS_MEM 4 | #error "[package management error] You must build Daxa with the DAXA_ENABLE_UTILS_MEM CMake option enabled, or request the utils-mem feature in vcpkg" 5 | #endif 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace daxa 13 | { 14 | struct TransferMemoryPoolInfo 15 | { 16 | Device device = {}; 17 | u32 capacity = 1 << 25; 18 | bool use_bar_memory = {}; 19 | std::string name = {}; 20 | }; 21 | 22 | /// @brief Ring buffer based transfer memory allocator for easy and efficient cpu gpu communication. 23 | struct TransferMemoryPool 24 | { 25 | DAXA_EXPORT_CXX TransferMemoryPool(TransferMemoryPoolInfo a_info); 26 | DAXA_EXPORT_CXX TransferMemoryPool(TransferMemoryPool && other); 27 | DAXA_EXPORT_CXX TransferMemoryPool & operator=(TransferMemoryPool && other); 28 | DAXA_EXPORT_CXX ~TransferMemoryPool(); 29 | 30 | struct Allocation 31 | { 32 | daxa::DeviceAddress device_address = {}; 33 | void * host_address = {}; 34 | u32 buffer_offset = {}; 35 | usize size = {}; 36 | u64 timeline_index = {}; 37 | }; 38 | // Returns nullopt if the allocation fails. 39 | DAXA_EXPORT_CXX auto allocate(u32 size, u32 alignment_requirement = 16 /* 16 is a save default for most gpu data*/) -> std::optional; 40 | /// @brief Allocates a section of a buffer with the size of T, writes the given T to the allocation. 41 | /// @return allocation. 42 | template 43 | auto allocate_fill(T const & value, u32 alignment_requirement = alignof(T)) -> std::optional 44 | { 45 | auto allocation_o = allocate(sizeof(T), alignment_requirement); 46 | if (allocation_o.has_value()) 47 | { 48 | *reinterpret_cast(allocation_o->host_address) = value; 49 | return allocation_o.value(); 50 | } 51 | return std::nullopt; 52 | } 53 | // Returns current timeline index. 54 | DAXA_EXPORT_CXX auto timeline_value() const -> usize; 55 | // Returns and then increments the current timeline index. 56 | // This is useful to ensure that the timeline value used for submits is always increasing. 57 | DAXA_EXPORT_CXX auto inc_timeline_value() -> usize; 58 | // Returns timeline semaphore that needs to be signaled with the latest timeline value, 59 | // on a queue that uses memory from this pool. 60 | DAXA_EXPORT_CXX auto timeline_semaphore() -> TimelineSemaphore const &; 61 | DAXA_EXPORT_CXX auto buffer() const -> daxa::BufferId; 62 | /// THREADSAFETY: 63 | /// * reference MUST NOT be read after the object is destroyed. 64 | /// @return reference to info of object. 65 | DAXA_EXPORT_CXX auto info() const -> TransferMemoryPoolInfo const &; 66 | 67 | private: 68 | // Reclaim expired memory allocations. 69 | DAXA_EXPORT_CXX void reclaim_unused_memory(); 70 | struct TrackedAllocation 71 | { 72 | usize timeline_index = {}; 73 | u32 offset = {}; 74 | u32 size = {}; 75 | }; 76 | 77 | TransferMemoryPoolInfo m_info = {}; 78 | TimelineSemaphore gpu_timeline = {}; 79 | 80 | private: 81 | u64 current_timeline_value = {}; 82 | std::deque live_allocations = {}; 83 | BufferId m_buffer = {}; 84 | daxa::DeviceAddress buffer_device_address = {}; 85 | void * buffer_host_address = {}; 86 | u32 claimed_start = {}; 87 | u32 claimed_size = {}; 88 | }; 89 | } // namespace daxa 90 | -------------------------------------------------------------------------------- /include/daxa/utils/task_graph.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../daxa.inl" 3 | 4 | /** 5 | * DAXA_TH_IMAGE: 6 | * Declares an image attachment. 7 | * The attachment is NOT represented at all within the shader blob. 8 | * 9 | * DAXA_TH_IMAGE_ID: 10 | * Declares an image attachment. 11 | * The first runtime image will be represented within the blob. 12 | * 13 | * DAXA_TH_IMAGE_ID_ARRAY: 14 | * Declares an image attachment. 15 | * A partial array of the attachments runtime ids are represented within an id array in the blob. 16 | * 17 | * DAXA_TH_IMAGE_ID_MIP_ARRAY: 18 | * Declares an image attachment. 19 | * A partial array of image views pointing to separate mip levels of the first runtime image are represented within the blob. 20 | * 21 | * DAXA_TH_BUFFER: 22 | * Declares a buffer attachment. 23 | * The attachment is NOT represented at all within the shader blob. 24 | * 25 | * DAXA_TH_BUFFER_ID: 26 | * Declares a buffer attachment. 27 | * The first runtime buffer will be represented within the blob. 28 | * 29 | * DAXA_TH_BUFFER_PTR: 30 | * Declares a buffer attachment. 31 | * The first runtime buffer will be represented with its buffer device address within the blob. 32 | * 33 | * DAXA_TH_BUFFER_ID_ARRAY: 34 | * Declares a buffer attachment. 35 | * A partial array of the attachments runtime buffers are represented within an id array in the blob. 36 | * 37 | * DAXA_TH_BUFFER_PTR_ARRAY: 38 | * Declares a buffer attachment. 39 | * A partial array of the attachments runtime buffers are represented with their buffer device addresses within an id array in the blob. 40 | * 41 | */ 42 | 43 | // DAXA 3.0 Task-Head-Shader interface: 44 | #if DAXA_SHADER 45 | #define DAXA_DECL_COMPUTE_TASK_HEAD_BEGIN(HEAD_NAME) DAXA_DECL_TASK_HEAD_BEGIN(HEAD_NAME) 46 | #define DAXA_DECL_RASTER_TASK_HEAD_BEGIN(HEAD_NAME) DAXA_DECL_TASK_HEAD_BEGIN(HEAD_NAME) 47 | #define DAXA_DECL_TRANSFER_TASK_HEAD_BEGIN(HEAD_NAME) DAXA_DECL_TASK_HEAD_BEGIN(HEAD_NAME) 48 | #define DAXA_DECL_RAY_TRACING_TASK_HEAD_BEGIN(HEAD_NAME) DAXA_DECL_TASK_HEAD_BEGIN(HEAD_NAME) 49 | #if DAXA_LANGUAGE == DAXA_LANGUAGE_SLANG 50 | #define DAXA_DECL_TASK_HEAD_BEGIN(HEAD_NAME) \ 51 | namespace HEAD_NAME \ 52 | { \ 53 | struct AttachmentShaderBlob \ 54 | { 55 | #define DAXA_TH_IMAGE(TASK_ACCESS, VIEW_TYPE, NAME) 56 | #define DAXA_TH_IMAGE_ID(TASK_ACCESS, VIEW_TYPE, NAME) daxa::ImageViewId NAME; 57 | #define DAXA_TH_IMAGE_ID_ARRAY(TASK_ACCESS, VIEW_TYPE, NAME, SIZE) daxa::ImageViewId NAME[SIZE]; 58 | #define DAXA_TH_IMAGE_ID_MIP_ARRAY(TASK_ACCESS, VIEW_TYPE, NAME, SIZE) daxa::ImageViewId NAME[SIZE]; 59 | #define DAXA_TH_IMAGE_INDEX(TASK_ACCESS, VIEW_TYPE, NAME) daxa::ImageViewIndex NAME; 60 | #define DAXA_TH_IMAGE_INDEX_ARRAY(TASK_ACCESS, VIEW_TYPE, NAME, SIZE) daxa::ImageViewIndex NAME[SIZE]; 61 | #define DAXA_TH_IMAGE_INDEX_MIP_ARRAY(TASK_ACCESS, VIEW_TYPE, NAME, SIZE) daxa::ImageViewIndex NAME[SIZE]; 62 | #define DAXA_TH_IMAGE_TYPED(TASK_ACCESS, TEX_TYPE, NAME) TEX_TYPE NAME; 63 | #define DAXA_TH_IMAGE_TYPED_ARRAY(TASK_ACCESS, TEX_TYPE, NAME, SIZE) TEX_TYPE NAME[SIZE]; 64 | #define DAXA_TH_IMAGE_TYPED_MIP_ARRAY(TASK_ACCESS, TEX_TYPE, NAME, SIZE) TEX_TYPE NAME[SIZE]; 65 | #define DAXA_TH_BUFFER(TASK_ACCESS, NAME) 66 | #define DAXA_TH_BUFFER_ID(TASK_ACCESS, NAME) daxa::BufferId NAME; 67 | #define DAXA_TH_BUFFER_PTR(TASK_ACCESS, PTR_TYPE, NAME) PTR_TYPE NAME; 68 | #define DAXA_TH_BUFFER_ID_ARRAY(TASK_ACCESS, NAME, SIZE) daxa::BufferId NAME[SIZE]; 69 | #define DAXA_TH_BUFFER_PTR_ARRAY(TASK_ACCESS, PTR_TYPE, NAME, SIZE) PTR_TYPE NAME[SIZE]; 70 | #define DAXA_TH_BLAS(TASK_ACCESS, NAME) 71 | #define DAXA_TH_TLAS(TASK_ACCESS, NAME) 72 | #define DAXA_TH_TLAS_PTR(TASK_ACCESS, NAME) daxa::u64 NAME; 73 | #define DAXA_TH_TLAS_ID(TASK_ACCESS, NAME) daxa::TlasId NAME; 74 | #define DAXA_DECL_TASK_HEAD_END \ 75 | } \ 76 | ; \ 77 | } \ 78 | ; 79 | #define DAXA_TH_BLOB(HEAD_NAME, field_name) HEAD_NAME::AttachmentShaderBlob field_name; 80 | #else // glsl 81 | #define DAXA_DECL_TASK_HEAD_BEGIN(HEAD_NAME) \ 82 | struct HEAD_NAME \ 83 | { 84 | #define DAXA_TH_IMAGE(TASK_ACCESS, VIEW_TYPE, NAME) 85 | #define DAXA_TH_IMAGE_ID(TASK_ACCESS, VIEW_TYPE, NAME) daxa_ImageViewId NAME; 86 | #define DAXA_TH_IMAGE_ID_ARRAY(TASK_ACCESS, VIEW_TYPE, NAME, SIZE) daxa_ImageViewId NAME[SIZE]; 87 | #define DAXA_TH_IMAGE_ID_MIP_ARRAY(TASK_ACCESS, VIEW_TYPE, NAME, SIZE) daxa_ImageViewId NAME[SIZE]; 88 | #define DAXA_TH_IMAGE_INDEX(TASK_ACCESS, VIEW_TYPE, NAME) daxa_ImageViewIndex NAME; 89 | #define DAXA_TH_IMAGE_INDEX_ARRAY(TASK_ACCESS, VIEW_TYPE, NAME, SIZE) daxa_ImageViewIndex NAME[SIZE]; 90 | #define DAXA_TH_IMAGE_INDEX_MIP_ARRAY(TASK_ACCESS, VIEW_TYPE, NAME, SIZE) daxa_ImageViewIndex NAME[SIZE]; 91 | #define DAXA_TH_IMAGE_TYPED(TASK_ACCESS, TEX_TYPE, NAME) ERROR_TYPED_HANDLES_ARE_SLANG_ONLY 92 | #define DAXA_TH_IMAGE_TYPED_ARRAY(TASK_ACCESS, TEX_TYPE, NAME, SIZE) ERROR_TYPED_HANDLES_ARE_SLANG_ONLY 93 | #define DAXA_TH_IMAGE_TYPED_MIP_ARRAY(TASK_ACCESS, TEX_TYPE, NAME, SIZE) ERROR_TYPED_HANDLES_ARE_SLANG_ONLY 94 | #define DAXA_TH_BUFFER(TASK_ACCESS, NAME) 95 | #define DAXA_TH_BUFFER_ID(TASK_ACCESS, NAME) daxa_BufferId NAME; 96 | #define DAXA_TH_BUFFER_PTR(TASK_ACCESS, PTR_TYPE, NAME) PTR_TYPE NAME; 97 | #define DAXA_TH_BUFFER_ID_ARRAY(TASK_ACCESS, NAME, SIZE) daxa_BufferId NAME[SIZE]; 98 | #define DAXA_TH_BUFFER_PTR_ARRAY(TASK_ACCESS, PTR_TYPE, NAME, SIZE) PTR_TYPE NAME[SIZE]; 99 | #define DAXA_TH_BLAS(TASK_ACCESS, NAME) 100 | #define DAXA_TH_TLAS(TASK_ACCESS, NAME) 101 | #define DAXA_TH_TLAS_PTR(TASK_ACCESS, NAME) daxa_u64 NAME; 102 | #define DAXA_TH_TLAS_ID(TASK_ACCESS, NAME) daxa_TlasId NAME; 103 | #define DAXA_DECL_TASK_HEAD_END \ 104 | } \ 105 | ; 106 | #define DAXA_TH_BLOB(HEAD_NAME, field_name) HEAD_NAME field_name; 107 | #endif 108 | #elif __cplusplus 109 | #include "task_graph_types.hpp" 110 | #else // C 111 | #error TASK GRAPH INL ONLY SUPPORTED IN SHADERS AND C++! 112 | #endif -------------------------------------------------------------------------------- /include/daxa/utils/upscaling_common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace daxa 7 | { 8 | struct UpscaleSizeInfo 9 | { 10 | u32 render_size_x, render_size_y; 11 | u32 display_size_x, display_size_y; 12 | }; 13 | 14 | struct UpscaleInstanceInfo 15 | { 16 | Device device; 17 | UpscaleSizeInfo size_info = {}; 18 | bool depth_inf = false; 19 | bool depth_inv = false; 20 | bool color_hdr = false; 21 | }; 22 | 23 | struct UpscaleInfo 24 | { 25 | ImageId color, depth, motion_vectors; 26 | // ImageId reactive, trans_and_comp; 27 | ImageId output; 28 | 29 | bool should_reset = false; 30 | f32 delta_time; 31 | daxa_f32vec2 jitter; 32 | 33 | bool should_sharpen = false; 34 | f32 sharpening = 0.0f; 35 | 36 | struct CameraInfo 37 | { 38 | f32 near_plane = {}; 39 | f32 far_plane = {}; 40 | f32 vertical_fov = {}; 41 | }; 42 | CameraInfo camera_info = {}; 43 | }; 44 | } // namespace daxa 45 | -------------------------------------------------------------------------------- /misc/daxa-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ipotrick/Daxa/a18972dcf12efa0b7efb9207cde10cdd251448e4/misc/daxa-logo.png -------------------------------------------------------------------------------- /portfile.cmake: -------------------------------------------------------------------------------- 1 | # Local-only code 2 | 3 | set(SOURCE_PATH "${CMAKE_CURRENT_LIST_DIR}") 4 | 5 | # Standard vcpkg stuff 6 | 7 | vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS 8 | FEATURES 9 | utils-imgui WITH_UTILS_IMGUI 10 | utils-mem WITH_UTILS_MEM 11 | utils-pipeline-manager-glslang WITH_UTILS_PIPELINE_MANAGER_GLSLANG 12 | utils-pipeline-manager-slang WITH_UTILS_PIPELINE_MANAGER_SLANG 13 | utils-pipeline-manager-spirv-validation WITH_UTILS_PIPELINE_MANAGER_SPIRV_VALIDATION 14 | utils-task-graph WITH_UTILS_TASK_GRAPH 15 | utils-fsr2 WITH_UTILS_FSR2 16 | ) 17 | set(DAXA_DEFINES "-DDAXA_INSTALL=true") 18 | 19 | if(WITH_UTILS_IMGUI) 20 | list(APPEND DAXA_DEFINES "-DDAXA_ENABLE_UTILS_IMGUI=true") 21 | endif() 22 | if(WITH_UTILS_MEM) 23 | list(APPEND DAXA_DEFINES "-DDAXA_ENABLE_UTILS_MEM=true") 24 | endif() 25 | if(WITH_UTILS_PIPELINE_MANAGER_GLSLANG) 26 | list(APPEND DAXA_DEFINES "-DDAXA_ENABLE_UTILS_PIPELINE_MANAGER_GLSLANG=true") 27 | endif() 28 | if(WITH_UTILS_PIPELINE_MANAGER_SLANG) 29 | list(APPEND DAXA_DEFINES "-DDAXA_ENABLE_UTILS_PIPELINE_MANAGER_SLANG=true") 30 | endif() 31 | if(WITH_UTILS_PIPELINE_MANAGER_SPIRV_VALIDATION) 32 | list(APPEND DAXA_DEFINES "-DDAXA_ENABLE_UTILS_PIPELINE_MANAGER_SPIRV_VALIDATION=true") 33 | endif() 34 | if(WITH_UTILS_TASK_GRAPH) 35 | list(APPEND DAXA_DEFINES "-DDAXA_ENABLE_UTILS_TASK_GRAPH=true") 36 | endif() 37 | if(WITH_UTILS_FSR2) 38 | list(APPEND DAXA_DEFINES "-DDAXA_ENABLE_UTILS_FSR2=true") 39 | endif() 40 | 41 | vcpkg_configure_cmake( 42 | SOURCE_PATH "${SOURCE_PATH}" 43 | PREFER_NINJA 44 | OPTIONS ${DAXA_DEFINES} 45 | ) 46 | 47 | vcpkg_install_cmake() 48 | vcpkg_fixup_cmake_targets() 49 | file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") 50 | file(INSTALL "${SOURCE_PATH}/LICENSE" 51 | DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" 52 | RENAME copyright 53 | ) 54 | -------------------------------------------------------------------------------- /src/impl_command_recorder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "impl_core.hpp" 4 | #include "impl_sync.hpp" 5 | #include "impl_pipeline.hpp" 6 | 7 | #include 8 | #include 9 | 10 | using namespace daxa; 11 | 12 | struct ImplDevice; 13 | 14 | static inline constexpr u8 DEFERRED_DESTRUCTION_BUFFER_INDEX = 0; 15 | static inline constexpr u8 DEFERRED_DESTRUCTION_IMAGE_INDEX = 1; 16 | static inline constexpr u8 DEFERRED_DESTRUCTION_IMAGE_VIEW_INDEX = 2; 17 | static inline constexpr u8 DEFERRED_DESTRUCTION_SAMPLER_INDEX = 3; 18 | static inline constexpr u8 DEFERRED_DESTRUCTION_TIMELINE_QUERY_POOL_INDEX = 4; 19 | // TODO: maybe reintroduce this in some fashion? 20 | // static inline constexpr usize DEFERRED_DESTRUCTION_COUNT_MAX = 32; 21 | 22 | static inline constexpr usize COMMAND_LIST_BARRIER_MAX_BATCH_SIZE = 16; 23 | static inline constexpr usize COMMAND_LIST_COLOR_ATTACHMENT_MAX = 16; 24 | 25 | struct CommandPoolPool 26 | { 27 | auto get(daxa_Device device) -> VkCommandPool; 28 | 29 | void put_back(VkCommandPool pool_and_buffer); 30 | 31 | void cleanup(daxa_Device device); 32 | 33 | std::vector pools_and_buffers = {}; 34 | u32 queue_family_index = {~0u}; 35 | std::mutex mtx = {}; 36 | }; 37 | 38 | struct CommandRecorderZombie 39 | { 40 | daxa_QueueFamily queue_family = {}; 41 | VkCommandPool vk_cmd_pool = {}; 42 | std::vector allocated_command_buffers = {}; 43 | }; 44 | 45 | struct ExecutableCommandListData 46 | { 47 | VkCommandBuffer vk_cmd_buffer = {}; 48 | std::vector> deferred_destructions = {}; 49 | // TODO: These vectors seem to be fast enough. overhead is around 1-4% in cmd recording. 50 | // It might be cool to have some slab allocator for these. 51 | // If there is demand, we could make an instance or cmd list flag to disable the submit checks. 52 | // TODO: Also collect ref counted handles. 53 | std::vector used_buffers = {}; 54 | std::vector used_images = {}; 55 | std::vector used_image_views = {}; 56 | std::vector used_samplers = {}; 57 | std::vector used_tlass = {}; 58 | std::vector used_blass = {}; 59 | }; 60 | 61 | struct daxa_ImplCommandRecorder final : ImplHandle 62 | { 63 | daxa_Device device = {}; 64 | bool in_renderpass = {}; 65 | daxa_CommandRecorderInfo info = {}; 66 | VkCommandPool vk_cmd_pool = {}; 67 | std::vector allocated_command_buffers = {}; 68 | std::array memory_barrier_batch = {}; 69 | std::array image_barrier_batch = {}; 70 | usize image_barrier_batch_count = {}; 71 | usize memory_barrier_batch_count = {}; 72 | usize split_barrier_batch_count = {}; 73 | struct NoPipeline 74 | { 75 | }; 76 | Variant current_pipeline = NoPipeline{}; 77 | 78 | ExecutableCommandListData current_command_data = {}; 79 | 80 | auto generate_new_current_command_data() -> daxa_Result; 81 | 82 | static void zero_ref_callback(ImplHandle const * handle); 83 | }; 84 | 85 | struct daxa_ImplExecutableCommandList final : ImplHandle 86 | { 87 | daxa_CommandRecorder cmd_recorder = {}; 88 | ExecutableCommandListData data = {}; 89 | 90 | static void zero_ref_callback(ImplHandle const * handle); 91 | }; 92 | 93 | void executable_cmd_list_execute_deferred_destructions(daxa_Device device, ExecutableCommandListData & cmd_list); -------------------------------------------------------------------------------- /src/impl_core.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef VULKAN_H_ 4 | #error MOST NOT INCLUDE VULKAN H BEFORE THIS FILE! 5 | #endif 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #if DAXA_VALIDATION 18 | #include 19 | #include 20 | #include 21 | 22 | #define DAXA_GPU_ID_VALIDATION 1 23 | #endif 24 | 25 | #if defined(_WIN32) 26 | #define VK_USE_PLATFORM_WIN32_KHR 27 | #ifndef WIN32_LEAN_AND_MEAN 28 | #define WIN32_LEAN_AND_MEAN 29 | #endif 30 | #ifndef NOMINMAX 31 | #define NOMINMAX 32 | #endif 33 | #elif defined(__linux__) 34 | #if DAXA_BUILT_WITH_X11 35 | #include 36 | #define VK_USE_PLATFORM_XLIB_KHR 37 | // NOTE(grundlett): Cope due to X11 defines 38 | #ifdef None 39 | #undef None 40 | #endif 41 | #endif 42 | #if DAXA_BUILT_WITH_WAYLAND 43 | // NOTE(grundlett) Somehow the Vulkan SDK may not include these 44 | // - to fix this we do it manually here 45 | #include 46 | #define VK_USE_PLATFORM_WAYLAND_KHR 47 | #endif 48 | #endif 49 | 50 | // INCLUDE ORDER MUST STAY LIKE THIS: 51 | // ensure we always compile in the deprecated functions to avoid link issues 52 | #define DAXA_REMOVE_DEPRECATED 0 53 | #include 54 | #include 55 | #include 56 | #include 57 | 58 | using namespace daxa; 59 | 60 | // --- Begin Helpers --- 61 | 62 | template 63 | auto rc_cast(FROM_T const * ptr) 64 | { 65 | return reinterpret_cast(const_cast(ptr)); 66 | } 67 | 68 | template 69 | auto r_cast(FROM_T * ptr) 70 | { 71 | return reinterpret_cast(ptr); 72 | } 73 | 74 | // TODO: WTF IS THIS?! 75 | static inline constexpr char const * MAX_PUSH_CONSTANT_SIZE_ERROR = {"push constant size is limited to 128 bytes/ 32 device words"}; 76 | static inline constexpr u32 GPU_TABLE_SET_BINDING = 0; 77 | static inline constexpr u32 CONSTANT_BUFFER_BINDING_SET = 1; 78 | static inline constexpr u32 CONSTANT_BUFFER_BINDING_COUNT = 8; 79 | 80 | auto is_depth_format(Format format) -> bool; 81 | 82 | auto is_stencil_format(Format format) -> bool; 83 | 84 | auto infer_aspect_from_format(Format format) -> VkImageAspectFlags; 85 | 86 | auto make_subresource_range(ImageMipArraySlice const & slice, VkImageAspectFlags aspect) -> VkImageSubresourceRange; 87 | 88 | auto make_subresource_layers(ImageArraySlice const & slice, VkImageAspectFlags aspect) -> VkImageSubresourceLayers; 89 | 90 | inline auto infer_aspect_from_format(VkFormat format) -> VkImageAspectFlags 91 | { 92 | return infer_aspect_from_format(*r_cast(&format)); 93 | } 94 | 95 | inline auto make_subresource_range(daxa_ImageMipArraySlice const & slice, VkImageAspectFlags aspect) -> VkImageSubresourceRange 96 | { 97 | return make_subresource_range(*r_cast(&slice), aspect); 98 | } 99 | 100 | inline auto make_subresource_layers(daxa_ImageArraySlice const & slice, VkImageAspectFlags aspect) -> VkImageSubresourceLayers 101 | { 102 | return make_subresource_layers(*r_cast(&slice), aspect); 103 | } 104 | 105 | auto create_surface(daxa_Instance instance, daxa_NativeWindowHandle handle, daxa_NativeWindowPlatform platform, VkSurfaceKHR * out_surface) -> daxa_Result; 106 | 107 | auto construct_daxa_physical_device_properties(VkPhysicalDevice physical_device) -> daxa_DeviceProperties; 108 | 109 | void daxa_as_build_info_to_vk( 110 | daxa_Device device, 111 | daxa_TlasBuildInfo const * tlas_infos, 112 | usize tlas_count, 113 | daxa_BlasBuildInfo const * blas_infos, 114 | usize blas_count, 115 | std::vector & vk_build_geometry_infos, 116 | std::vector & vk_geometry_infos, 117 | std::vector & primitive_counts, 118 | std::vector & primitive_counts_ptrs); 119 | 120 | // --- End Helpers --- 121 | 122 | namespace daxa 123 | { 124 | struct ImplHandle 125 | { 126 | // Used for user side reference count. 127 | mutable u64 strong_count = 1; 128 | // Used for internal reference count. 129 | mutable u64 weak_count = {}; 130 | 131 | #define inc_weak_refcnt() impl_inc_weak_refcnt(__FUNCTION__) 132 | #define dec_weak_refcnt(CB, IS) impl_dec_weak_refcnt(CB, IS, __FUNCTION__) 133 | 134 | // For user side ref counting. 135 | auto inc_refcnt() const -> u64; 136 | auto dec_refcnt(void (*zero_ref_callback)(ImplHandle const *), daxa_Instance instance) const -> u64; 137 | auto get_refcnt() const -> u64; 138 | // For internal ref counting. 139 | auto impl_inc_weak_refcnt(char const * callsite) const -> u64; 140 | auto impl_dec_weak_refcnt(void (*zero_ref_callback)(ImplHandle const *), daxa_Instance instance, char const * callsite) const -> u64; 141 | auto get_weak_refcnt() const -> u64; 142 | }; 143 | } // namespace daxa 144 | 145 | struct MemoryBlockZombie 146 | { 147 | VmaAllocation allocation = {}; 148 | }; 149 | 150 | struct daxa_ImplMemoryBlock final : ImplHandle 151 | { 152 | daxa_Device device = {}; 153 | MemoryBlockInfo info = {}; 154 | VmaAllocation allocation = {}; 155 | VmaAllocationInfo alloc_info = {}; 156 | 157 | static void zero_ref_callback(ImplHandle const * handle); 158 | }; 159 | 160 | #ifndef defer 161 | struct defer_dummy 162 | { 163 | }; 164 | template 165 | struct deferrer 166 | { 167 | F f; 168 | ~deferrer() { f(); } 169 | }; 170 | template 171 | deferrer operator*(defer_dummy, F f) { return {f}; } 172 | #define DEFER_(LINE) zz_defer##LINE 173 | #define DEFER(LINE) DEFER_(LINE) 174 | #define defer auto DEFER(__LINE__) = defer_dummy{} * [&]() 175 | #endif // defer 176 | 177 | #if defined(_MSC_VER) 178 | #define _DAXA_DEBUG_BREAK __debugbreak(); 179 | #else 180 | #define _DAXA_DEBUG_BREAK 181 | #endif 182 | 183 | constexpr bool is_daxa_result_success(daxa_Result v) 184 | { 185 | return v == DAXA_RESULT_SUCCESS; 186 | } 187 | 188 | #define _DAXA_RETURN_IF_ERROR(V, RET) \ 189 | if (!is_daxa_result_success(V)) \ 190 | { \ 191 | _DAXA_DEBUG_BREAK \ 192 | return RET; \ 193 | } 194 | 195 | #define _DAXA_DEFER_ON_ERROR(V) -------------------------------------------------------------------------------- /src/impl_dependencies.cpp: -------------------------------------------------------------------------------- 1 | #include "impl_core.hpp" 2 | 3 | #define VMA_IMPLEMENTATION 4 | #include 5 | -------------------------------------------------------------------------------- /src/impl_instance.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "impl_core.hpp" 4 | #include "impl_features.hpp" 5 | 6 | #include 7 | 8 | struct ImplPhysicalDevice 9 | { 10 | PhysicalDeviceExtensionsStruct extensions = {}; 11 | PhysicalDeviceFeaturesStruct features = {}; 12 | VkPhysicalDevice vk_handle = {}; 13 | }; 14 | 15 | struct daxa_ImplInstance final : ImplHandle 16 | { 17 | InstanceInfo info = {}; 18 | std::string engine_name = {}; 19 | std::string app_name = {}; 20 | VkInstance vk_instance = {}; 21 | 22 | std::vector device_internals = {}; 23 | std::vector device_properties = {}; 24 | 25 | static void zero_ref_callback(ImplHandle const * handle); 26 | 27 | auto initialize_physical_devices() -> daxa_Result; 28 | }; -------------------------------------------------------------------------------- /src/impl_pipeline.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "impl_core.hpp" 4 | #include 5 | 6 | using namespace daxa; 7 | 8 | static inline constexpr usize pipeline_manager_MAX_ATTACHMENTS = 16; 9 | 10 | struct PipelineZombie 11 | { 12 | VkPipeline vk_pipeline = {}; 13 | }; 14 | 15 | struct ImplPipeline : ImplHandle 16 | { 17 | daxa_Device device = {}; 18 | VkPipeline vk_pipeline = {}; 19 | VkPipelineLayout vk_pipeline_layout = {}; 20 | 21 | static void zero_ref_callback(ImplHandle const * handle); 22 | }; 23 | 24 | struct daxa_ImplRasterPipeline final : ImplPipeline 25 | { 26 | RasterPipelineInfo info = {}; 27 | }; 28 | 29 | struct daxa_ImplComputePipeline final : ImplPipeline 30 | { 31 | ComputePipelineInfo info = {}; 32 | }; 33 | 34 | struct daxa_ImplRayTracingPipeline final : ImplPipeline 35 | { 36 | // NOTE(grundlett): This is bogus. The state passed to info is in spans which means it does not persist... 37 | std::vector shader_groups = {}; 38 | RayTracingPipelineInfo info = {}; 39 | }; -------------------------------------------------------------------------------- /src/impl_swapchain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "impl_core.hpp" 4 | 5 | #include 6 | 7 | #include 8 | 9 | /// I (pahrens) am going to document the internals here as wsi is really confusing and strange in vulkan. 10 | /// Every frame we get a swapchain image index. This index can be non sequential in the case of mail box presentation and other modes. 11 | /// This means we need to acquire a new index every frame to know what swapchain image to use. 12 | /// 13 | /// IMPORTANT INFORMATION REGARDING SEMAPHORES IN WSI: 14 | /// binary semaphore in acquire MUST be un-signaled when recording actions ON THE CPU! 15 | /// Because of this, we need frames_in_flight+1 semaphores for the acquire 16 | /// 17 | /// We need two binary semaphores here: 18 | /// The acquire semaphore and the present semaphore. 19 | /// The present semaphore is signaled in the last submission that uses the swapchain image and waited on in the present. 20 | /// The acquire semaphore is signaled when the swapchain image is ready to be used. 21 | /// This also means that the previous presentation of the image is finished and the semaphore used in the present is un-signaled. 22 | /// Unfortunately there is NO other way to know when a present finishes (or the corresponding semaphore is un-signaled). 23 | /// This means that in order to be able to reuse binary semaphores used in presentation, 24 | /// one MUST pair them with the image they are used to present. 25 | /// 26 | /// One can then rely on the acquire semaphore of the image beeing signaled to indicate that the present semaphore is able to be reused, 27 | /// As a swapchain images acquire sema is signaled when it is available and its previous present is completed. 28 | /// 29 | /// In order to reuse the the acquire semaphore we must set a limit in frames in flight and wait on the cpu to limit the frames in flight. 30 | /// When we have this wait in place we can safely reuse the acquire semaphores with a linearly increasing index corresponding to the frame. 31 | /// This means the acquire semaphores are not tied to the number of swapchain images like present semaphores but to the number of frames in flight!! 32 | /// 33 | /// To limit the frames in flight we employ a timeline semaphore that must be signaled in a submission that uses or after one that uses the swapchain image. 34 | /// 35 | /// WARNING: The swapchain only works on the main queue! It is directly tied to it. 36 | /// 37 | /// TODO: investigate if wsi is improved enough to use zombies for swapchain. 38 | struct daxa_ImplSwapchain final : ImplHandle 39 | { 40 | daxa_Device device = {}; 41 | SwapchainInfo info = {}; 42 | std::string info_name = {}; 43 | VkSwapchainKHR vk_swapchain = {}; 44 | VkSurfaceKHR vk_surface = {}; 45 | VkSurfaceFormatKHR vk_surface_format = {}; 46 | VkExtent2D surface_extent = {}; 47 | std::vector supported_present_modes = {}; 48 | // Swapchain holds strong references to these objects as it owns them. 49 | std::vector images = {}; 50 | std::vector acquire_semaphores = {}; 51 | std::vector present_semaphores = {}; 52 | // Monotonically increasing frame index. 53 | usize cpu_frame_timeline = {}; 54 | // cpu_frame_timeline % frames in flight. used to index the acquire semaphores. 55 | usize acquire_semaphore_index = {}; 56 | // Gpu timeline semaphore used to track how far behind the gpu is. 57 | // Used to limit frames in flight. 58 | TimelineSemaphore gpu_frame_timeline = {}; 59 | // This is the swapchain image index that acquire returns. THis is not necessarily linear. 60 | // This index must be used for present semaphores as they are paired to the images. 61 | u32 current_image_index = {}; 62 | 63 | void partial_cleanup(); 64 | void full_cleanup(); 65 | auto recreate_surface() -> daxa_Result; 66 | auto recreate() -> daxa_Result; 67 | 68 | static auto create(daxa_Device device, daxa_SwapchainInfo const * info, daxa_Swapchain swapchain) -> daxa_Result; 69 | static void zero_ref_callback(ImplHandle const * handle); 70 | }; -------------------------------------------------------------------------------- /src/impl_sync.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "impl_core.hpp" 4 | #include 5 | #include 6 | 7 | struct SemaphoreZombie 8 | { 9 | VkSemaphore vk_semaphore = {}; 10 | }; 11 | 12 | struct EventZombie 13 | { 14 | VkEvent vk_event = {}; 15 | }; 16 | 17 | struct daxa_ImplBinarySemaphore final : ImplHandle 18 | { 19 | daxa_Device device = {}; 20 | BinarySemaphoreInfo info = {}; 21 | VkSemaphore vk_semaphore = {}; 22 | 23 | static void zero_ref_callback(ImplHandle const * handle); 24 | }; 25 | 26 | struct daxa_ImplTimelineSemaphore final : ImplHandle 27 | { 28 | daxa_Device device = {}; 29 | TimelineSemaphoreInfo info = {}; 30 | VkSemaphore vk_semaphore = {}; 31 | 32 | static void zero_ref_callback(ImplHandle const * handle); 33 | }; 34 | 35 | struct daxa_ImplEvent final : ImplHandle 36 | { 37 | daxa_Device device = {}; 38 | EventInfo info = {}; 39 | VkEvent vk_event = {}; 40 | 41 | static void zero_ref_callback(ImplHandle const * handle); 42 | }; -------------------------------------------------------------------------------- /src/impl_timeline_query.cpp: -------------------------------------------------------------------------------- 1 | #include "impl_timeline_query.hpp" 2 | 3 | #include 4 | 5 | #include "impl_device.hpp" 6 | 7 | // --- Begin API Functions --- 8 | 9 | auto daxa_dvc_create_timeline_query_pool(daxa_Device device, daxa_TimelineQueryPoolInfo const * info, daxa_TimelineQueryPool * out_tqp) -> daxa_Result 10 | { 11 | auto ret = daxa_ImplTimelineQueryPool{}; 12 | ret.device = device; 13 | ret.info = *reinterpret_cast(info); 14 | // TODO(msakmary) Should Add a check for support of timeline queries 15 | // here or earlier (during device creation/section) I'm not sure... 16 | VkQueryPoolCreateInfo const vk_query_pool_create_info{ 17 | .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, 18 | .pNext = nullptr, 19 | .flags = 0, 20 | .queryType = VK_QUERY_TYPE_TIMESTAMP, 21 | .queryCount = ret.info.query_count, 22 | .pipelineStatistics = {}, 23 | }; 24 | auto vk_result = vkCreateQueryPool(ret.device->vk_device, &vk_query_pool_create_info, nullptr, &ret.vk_timeline_query_pool); 25 | if (vk_result != VK_SUCCESS) 26 | { 27 | return std::bit_cast(vk_result); 28 | } 29 | vkResetQueryPool(ret.device->vk_device, ret.vk_timeline_query_pool, 0, ret.info.query_count); 30 | if ((ret.device->instance->info.flags & InstanceFlagBits::DEBUG_UTILS) != InstanceFlagBits::NONE && !ret.info.name.empty()) 31 | { 32 | VkDebugUtilsObjectNameInfoEXT const query_pool_name_info{ 33 | .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 34 | .pNext = nullptr, 35 | .objectType = VK_OBJECT_TYPE_QUERY_POOL, 36 | .objectHandle = std::bit_cast(ret.vk_timeline_query_pool), 37 | .pObjectName = ret.info_name.c_str(), 38 | }; 39 | ret.device->vkSetDebugUtilsObjectNameEXT(ret.device->vk_device, &query_pool_name_info); 40 | } 41 | ret.strong_count = 1; 42 | device->inc_weak_refcnt(); 43 | *out_tqp = new daxa_ImplTimelineQueryPool{}; 44 | **out_tqp = std::move(ret); 45 | return DAXA_RESULT_SUCCESS; 46 | } 47 | 48 | auto daxa_timeline_query_pool_info(daxa_TimelineQueryPool self) -> daxa_TimelineQueryPoolInfo const * 49 | { 50 | return reinterpret_cast(&self->info); 51 | } 52 | 53 | auto daxa_timeline_query_pool_query_results(daxa_TimelineQueryPool self, u32 start, u32 count, u64 * out_results) -> daxa_Result 54 | { 55 | if (count == 0) 56 | { 57 | return DAXA_RESULT_SUCCESS; 58 | } 59 | if (!(start + count - 1 < self->info.query_count)) 60 | { 61 | return DAXA_RESULT_RANGE_OUT_OF_BOUNDS; 62 | } 63 | auto vk_result = vkGetQueryPoolResults( 64 | self->device->vk_device, 65 | self->vk_timeline_query_pool, 66 | start, 67 | count, 68 | count * 2ul * sizeof(u64), 69 | out_results, 70 | 2ul * sizeof(u64), 71 | VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT); 72 | return std::bit_cast(vk_result); 73 | } 74 | 75 | auto daxa_timeline_query_pool_inc_refcnt(daxa_TimelineQueryPool self) -> u64 76 | { 77 | return self->inc_refcnt(); 78 | } 79 | 80 | auto daxa_timeline_query_pool_dec_refcnt(daxa_TimelineQueryPool self) -> u64 81 | { 82 | return self->dec_refcnt( 83 | &daxa_ImplTimelineQueryPool::zero_ref_callback, 84 | self->device->instance); 85 | } 86 | 87 | // --- End API Functions --- 88 | 89 | // --- Begin Internals --- 90 | 91 | void daxa_ImplTimelineQueryPool::zero_ref_callback(ImplHandle const * handle) 92 | { 93 | auto * self = rc_cast(handle); 94 | std::unique_lock const lock{self->device->zombies_mtx}; 95 | u64 const submit_timeline = self->device->global_submit_timeline.load(std::memory_order::relaxed); 96 | self->device->timeline_query_pool_zombies.emplace_back( 97 | submit_timeline, 98 | TimelineQueryPoolZombie{ 99 | .vk_timeline_query_pool = self->vk_timeline_query_pool, 100 | }); 101 | self->device->dec_weak_refcnt( 102 | daxa_ImplDevice::zero_ref_callback, 103 | self->device->instance); 104 | delete self; 105 | } 106 | 107 | // --- End Internals --- -------------------------------------------------------------------------------- /src/impl_timeline_query.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "impl_core.hpp" 6 | #include 7 | 8 | 9 | namespace daxa 10 | { 11 | struct TimelineQueryPoolZombie 12 | { 13 | VkQueryPool vk_timeline_query_pool = {}; 14 | }; 15 | } // namespace daxa 16 | 17 | struct daxa_ImplTimelineQueryPool final : ImplHandle 18 | { 19 | daxa_Device device = {}; 20 | TimelineQueryPoolInfo info = {}; 21 | std::string info_name = {}; 22 | VkQueryPool vk_timeline_query_pool = {}; 23 | 24 | static void zero_ref_callback(ImplHandle const * handle); 25 | }; 26 | -------------------------------------------------------------------------------- /src/utils/impl_fsr2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../impl_core.hpp" 4 | #include 5 | 6 | #include "../impl_device.hpp" 7 | 8 | #include 9 | #include 10 | 11 | namespace daxa 12 | { 13 | struct ImplFsr2Context final : ImplHandle 14 | { 15 | UpscaleInstanceInfo info; 16 | 17 | FfxFsr2Context fsr2_context = {}; 18 | FfxFsr2ContextDescription fsr2_context_description = {}; 19 | 20 | void * scratch_buffer = {}; 21 | bool initialized = {}; 22 | 23 | void resize(UpscaleSizeInfo const & resize_info); 24 | void upscale(CommandRecorder & command_list, UpscaleInfo const & upscale_info); 25 | 26 | void create_resizable_resources(); 27 | void destroy_resizable_resources(); 28 | 29 | ImplFsr2Context(UpscaleInstanceInfo a_info); 30 | ~ImplFsr2Context(); 31 | 32 | static void zero_ref_callback(ImplHandle const *); 33 | }; 34 | } // namespace daxa 35 | -------------------------------------------------------------------------------- /src/utils/impl_imgui.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../impl_core.hpp" 4 | 5 | #include 6 | #include 7 | 8 | namespace daxa 9 | { 10 | struct ImplImGuiRenderer final : ImplHandle 11 | { 12 | ImGuiRendererInfo info = {}; 13 | RasterPipeline raster_pipeline = {}; 14 | BufferId vbuffer = {}; 15 | BufferId ibuffer = {}; 16 | ImageId font_sheet = {}; 17 | SamplerId font_sampler = {}; 18 | usize frame_count = {}; 19 | 20 | std::vector image_sampler_pairs = {}; 21 | 22 | void recreate_vbuffer(usize vbuffer_new_size); 23 | void recreate_ibuffer(usize ibuffer_new_size); 24 | void record_commands(ImDrawData * draw_data, CommandRecorder & recorder, ImageId target_image, u32 size_x, u32 size_y); 25 | 26 | ImplImGuiRenderer(ImGuiRendererInfo a_info); 27 | ~ImplImGuiRenderer(); 28 | 29 | static void zero_ref_callback(ImplHandle const *); 30 | }; 31 | } // namespace daxa 32 | -------------------------------------------------------------------------------- /src/utils/impl_pipeline_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #undef Bool 6 | 7 | #if DAXA_BUILT_WITH_UTILS_PIPELINE_MANAGER_SLANG 8 | #include 9 | #include 10 | #endif 11 | 12 | #if DAXA_BUILT_WITH_UTILS_PIPELINE_MANAGER_GLSLANG 13 | #include 14 | #include 15 | #include 16 | #endif 17 | 18 | #if DAXA_BUILT_WITH_UTILS_PIPELINE_MANAGER_SPIRV_VALIDATION 19 | #include 20 | #endif 21 | 22 | namespace daxa 23 | { 24 | struct ImplDevice; 25 | 26 | using ShaderFileTimeSet = std::map; 27 | 28 | struct VirtualFileState 29 | { 30 | std::string contents; 31 | std::chrono::file_clock::time_point timestamp; 32 | }; 33 | 34 | using VirtualFileSet = std::map; 35 | 36 | struct ImplPipelineManager final : ImplHandle 37 | { 38 | enum class ShaderStage 39 | { 40 | COMP, 41 | VERT, 42 | FRAG, 43 | TESS_CONTROL, 44 | TESS_EVAL, 45 | TASK, 46 | MESH, 47 | RAY_GEN, 48 | RAY_INTERSECT, 49 | RAY_ANY_HIT, 50 | RAY_CLOSEST_HIT, 51 | RAY_MISS, 52 | RAY_CALLABLE, 53 | }; 54 | 55 | PipelineManagerInfo2 info = {}; 56 | 57 | std::vector current_seen_shader_files = {}; 58 | ShaderFileTimeSet * current_observed_hotload_files = nullptr; 59 | 60 | VirtualFileSet virtual_files = {}; 61 | 62 | template 63 | struct PipelineState 64 | { 65 | std::shared_ptr pipeline_ptr; 66 | InfoT info; 67 | std::chrono::file_clock::time_point last_hotload_time = {}; 68 | ShaderFileTimeSet observed_hotload_files = {}; 69 | }; 70 | 71 | using ComputePipelineState = PipelineState; 72 | using RasterPipelineState = PipelineState; 73 | using RayTracingPipelineState = PipelineState; 74 | 75 | std::vector compute_pipelines; 76 | std::vector raster_pipelines; 77 | std::vector ray_tracing_pipelines; 78 | 79 | // COMMENT(pahrens): epic code 80 | // TODO(grundlett): Maybe make the pipeline compiler *internally* thread-safe! 81 | // This variable is accessed by the includer, which makes that not thread-safe 82 | // PipelineManager is still externally thread-safe. You can create as many 83 | // PipelineManagers from as many threads as you'd like! 84 | ShaderCompileInfo2 const * current_shader_info = nullptr; 85 | 86 | #if DAXA_BUILT_WITH_UTILS_PIPELINE_MANAGER_GLSLANG 87 | struct GlslangBackend 88 | { 89 | }; 90 | GlslangBackend glslang_backend = {}; 91 | #endif 92 | 93 | #if DAXA_BUILT_WITH_UTILS_PIPELINE_MANAGER_SLANG 94 | struct SlangBackend 95 | { 96 | // NOTE(grundlett): literally global session. Not sure if this is reasonable or not. 97 | static inline Slang::ComPtr global_session; 98 | static inline std::mutex session_mtx = {}; 99 | }; 100 | SlangBackend slang_backend = {}; 101 | #endif 102 | 103 | #if DAXA_BUILT_WITH_UTILS_PIPELINE_MANAGER_SPIRV_VALIDATION 104 | spvtools::SpirvTools spirv_tools = spvtools::SpirvTools{SPV_ENV_VULKAN_1_3}; 105 | #endif 106 | 107 | ImplPipelineManager(PipelineManagerInfo2 && a_info); 108 | ~ImplPipelineManager(); 109 | 110 | auto create_ray_tracing_pipeline(RayTracingPipelineCompileInfo2 const & a_info) -> Result; 111 | auto create_compute_pipeline(ComputePipelineCompileInfo2 const & a_info) -> Result; 112 | auto create_raster_pipeline(RasterPipelineCompileInfo2 const & a_info) -> Result; 113 | void remove_ray_tracing_pipeline(std::shared_ptr const & pipeline); 114 | void remove_compute_pipeline(std::shared_ptr const & pipeline); 115 | void remove_raster_pipeline(std::shared_ptr const & pipeline); 116 | void add_virtual_file(VirtualFileInfo const & virtual_info); 117 | auto reload_all() -> PipelineReloadResult; 118 | auto all_pipelines_valid() const -> bool; 119 | 120 | auto try_load_shader_cache(std::filesystem::path const & cache_folder, uint64_t shader_info_hash) -> Result>; 121 | void save_shader_cache(std::filesystem::path const & out_folder, uint64_t shader_info_hash, std::vector const & spirv); 122 | auto full_path_to_file(std::filesystem::path const & path) -> Result; 123 | auto load_shader_source_from_file(std::filesystem::path const & path) -> Result; 124 | 125 | 126 | auto hash_shader_info(std::string const & source_string, ShaderCompileInfo2 const & compile_options, ImplPipelineManager::ShaderStage shader_stage) -> uint64_t; 127 | auto get_spirv(ShaderCompileInfo2 const & shader_info, std::string const & debug_name_opt, ShaderStage shader_stage) -> Result>; 128 | auto get_spirv_glslang(ShaderCompileInfo2 const & shader_info, std::string const & debug_name_opt, ShaderStage shader_stage, ShaderCode const & code) -> Result>; 129 | auto get_spirv_slang(ShaderCompileInfo2 const & shader_info, ShaderStage shader_stage, ShaderCode const & code) -> Result>; 130 | 131 | static auto zero_ref_callback(ImplHandle const * handle); 132 | }; 133 | } // namespace daxa 134 | -------------------------------------------------------------------------------- /tests/0_common/base_app.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define SAMPLE_SHADER_LANGUAGE DAXA_LANGUAGE_GLSL 3 | 4 | #include <0_common/window.hpp> 5 | 6 | #include 7 | using namespace std::chrono_literals; 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | using Clock = std::chrono::high_resolution_clock; 18 | 19 | #if !defined(APPNAME) 20 | #define APPNAME "Daxa App" 21 | #endif 22 | #define APPNAME_PREFIX(x) ("[" APPNAME "] " x) 23 | 24 | template 25 | struct BaseApp : AppWindow 26 | { 27 | daxa::Instance daxa_ctx = daxa::create_instance({}); 28 | daxa::Device device = [&]() 29 | { 30 | daxa::DeviceInfo2 info = {.name = "default device"}; 31 | daxa::ImplicitFeatureFlags required_features = {}; 32 | #if defined(DAXA_ATOMIC_FLOAT_FLAG) 33 | required_features |= daxa::ImplicitFeatureFlagBits::SHADER_ATOMIC_FLOAT; 34 | #endif 35 | #if defined(DAXA_RAY_TRACING_FLAG) 36 | required_features |= daxa::ImplicitFeatureFlagBits::BASIC_RAY_TRACING; 37 | #endif 38 | info = daxa_ctx.choose_device(required_features, info); 39 | return daxa_ctx.create_device_2(info); 40 | }(); 41 | 42 | daxa::Swapchain swapchain = device.create_swapchain({ 43 | .native_window = AppWindow::get_native_handle(), 44 | .native_window_platform = AppWindow::get_native_platform(), 45 | .present_mode = daxa::PresentMode::IMMEDIATE, 46 | .image_usage = daxa::ImageUsageFlagBits::TRANSFER_DST, 47 | .name = "swapchain", 48 | }); 49 | 50 | daxa::PipelineManager pipeline_manager = daxa::PipelineManager({ 51 | .device = device, 52 | .root_paths = { 53 | DAXA_SHADER_INCLUDE_DIR, 54 | DAXA_SAMPLE_PATH "/shaders", 55 | "tests/0_common/shaders", 56 | }, 57 | #if SAMPLE_SHADER_LANGUAGE == DAXA_LANGUAGE_GLSL 58 | .default_language = daxa::ShaderLanguage::GLSL, 59 | #elif SAMPLE_SHADER_LANGUAGE == DAXA_LANGUAGE_SLANG 60 | .default_language = daxa::ShaderLanguage::SLANG, 61 | #endif 62 | .default_enable_debug_info = true, 63 | .name = "pipeline_manager", 64 | }); 65 | 66 | daxa::ImGuiRenderer imgui_renderer = create_imgui_renderer(); 67 | auto create_imgui_renderer() -> daxa::ImGuiRenderer 68 | { 69 | ImGui::CreateContext(); 70 | ImGui_ImplGlfw_InitForVulkan(AppWindow::glfw_window_ptr, true); 71 | return daxa::ImGuiRenderer({ 72 | .device = device, 73 | .format = swapchain.get_format(), 74 | }); 75 | } 76 | 77 | Clock::time_point start = Clock::now(), prev_time = start; 78 | f32 time = 0.0f, delta_time = 1.0f; 79 | 80 | daxa::TaskImage task_swapchain_image{{.swapchain_image = true, .name = "swapchain_image"}}; 81 | std::vector imgui_task_attachments{}; 82 | 83 | BaseApp() : AppWindow(APPNAME) 84 | { 85 | } 86 | 87 | ~BaseApp() 88 | { 89 | ImGui_ImplGlfw_Shutdown(); 90 | } 91 | 92 | void base_on_update() 93 | { 94 | auto now = Clock::now(); 95 | time = std::chrono::duration(now - start).count(); 96 | delta_time = std::chrono::duration(now - prev_time).count(); 97 | prev_time = now; 98 | reinterpret_cast(this)->on_update(); 99 | } 100 | 101 | auto update() -> bool 102 | { 103 | glfwPollEvents(); 104 | if (glfwWindowShouldClose(AppWindow::glfw_window_ptr)) 105 | { 106 | return true; 107 | } 108 | 109 | if (!AppWindow::minimized) 110 | { 111 | base_on_update(); 112 | } 113 | else 114 | { 115 | std::this_thread::sleep_for(1ms); 116 | } 117 | 118 | return false; 119 | } 120 | 121 | auto record_loop_task_graph() -> daxa::TaskGraph 122 | { 123 | daxa::TaskGraph new_task_graph = daxa::TaskGraph({ 124 | .device = device, 125 | .swapchain = swapchain, 126 | .use_split_barriers = false, 127 | .record_debug_information = true, 128 | .name = "main_task_graph", 129 | }); 130 | new_task_graph.use_persistent_image(task_swapchain_image); 131 | 132 | reinterpret_cast(this)->record_tasks(new_task_graph); 133 | 134 | imgui_task_attachments.push_back(daxa::inl_attachment(daxa::TaskImageAccess::COLOR_ATTACHMENT, task_swapchain_image)); 135 | auto imgui_task_info = daxa::InlineTaskInfo{ 136 | .attachments = std::move(imgui_task_attachments), 137 | .task = [this](daxa::TaskInterface const & ti) 138 | { 139 | imgui_renderer.record_commands(ImGui::GetDrawData(), ti.recorder, ti.get(task_swapchain_image).ids[0], AppWindow::size_x, AppWindow::size_y); 140 | }, 141 | .name = "ImGui Task", 142 | }; 143 | new_task_graph.add_task(imgui_task_info); 144 | 145 | new_task_graph.submit({}); 146 | new_task_graph.present({}); 147 | new_task_graph.complete({}); 148 | 149 | // new_task_graph.output_graphviz(); 150 | 151 | return new_task_graph; 152 | } 153 | }; 154 | -------------------------------------------------------------------------------- /tests/0_common/shared.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef defer 4 | struct defer_dummy {}; 5 | template struct deferrer { F f; ~deferrer() { f(); } }; 6 | template deferrer operator*(defer_dummy, F f) { return {f}; } 7 | #define DEFER_(LINE) zz_defer##LINE 8 | #define DEFER(LINE) DEFER_(LINE) 9 | #define defer auto DEFER(__LINE__) = defer_dummy{} *[&]() 10 | #endif // defer -------------------------------------------------------------------------------- /tests/0_common/window.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace daxa::types; 3 | 4 | #include 5 | #if defined(_WIN32) 6 | #define GLFW_EXPOSE_NATIVE_WIN32 7 | #define GLFW_NATIVE_INCLUDE_NONE 8 | using HWND = void *; 9 | #elif defined(__linux__) 10 | #define GLFW_EXPOSE_NATIVE_X11 11 | #define GLFW_EXPOSE_NATIVE_WAYLAND 12 | #endif 13 | #include 14 | 15 | template 16 | struct AppWindow 17 | { 18 | GLFWwindow * glfw_window_ptr; 19 | u32 size_x, size_y; 20 | bool minimized = false; 21 | 22 | explicit AppWindow(char const * window_name, u32 sx = 800, u32 sy = 600) : size_x{sx}, size_y{sy} 23 | { 24 | glfwInit(); 25 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 26 | glfw_window_ptr = glfwCreateWindow(static_cast(size_x), static_cast(size_y), window_name, nullptr, nullptr); 27 | glfwSetWindowUserPointer(glfw_window_ptr, this); 28 | glfwSetCursorPosCallback( 29 | glfw_window_ptr, 30 | [](GLFWwindow * window_ptr, f64 x, f64 y) 31 | { 32 | auto & app = *reinterpret_cast(glfwGetWindowUserPointer(window_ptr)); 33 | app.on_mouse_move(static_cast(x), static_cast(y)); 34 | }); 35 | glfwSetMouseButtonCallback( 36 | glfw_window_ptr, 37 | [](GLFWwindow * window_ptr, i32 button, i32 action, i32) 38 | { 39 | auto & app = *reinterpret_cast(glfwGetWindowUserPointer(window_ptr)); 40 | app.on_mouse_button(button, action); 41 | }); 42 | glfwSetKeyCallback( 43 | glfw_window_ptr, 44 | [](GLFWwindow * window_ptr, i32 key, i32, i32 action, i32) 45 | { 46 | auto & app = *reinterpret_cast(glfwGetWindowUserPointer(window_ptr)); 47 | app.on_key(key, action); 48 | }); 49 | glfwSetFramebufferSizeCallback( 50 | glfw_window_ptr, 51 | [](GLFWwindow * window_ptr, i32 w, i32 h) 52 | { 53 | auto & app = *reinterpret_cast(glfwGetWindowUserPointer(window_ptr)); 54 | app.on_resize(static_cast(w), static_cast(h)); 55 | }); 56 | } 57 | 58 | ~AppWindow() 59 | { 60 | glfwDestroyWindow(glfw_window_ptr); 61 | glfwTerminate(); 62 | } 63 | 64 | auto get_native_handle() -> daxa::NativeWindowHandle 65 | { 66 | #if defined(_WIN32) 67 | return glfwGetWin32Window(glfw_window_ptr); 68 | #elif defined(__linux__) 69 | switch (get_native_platform()) 70 | { 71 | case daxa::NativeWindowPlatform::WAYLAND_API: 72 | return reinterpret_cast(glfwGetWaylandWindow(glfw_window_ptr)); 73 | case daxa::NativeWindowPlatform::XLIB_API: 74 | default: 75 | return reinterpret_cast(glfwGetX11Window(glfw_window_ptr)); 76 | } 77 | #endif 78 | } 79 | 80 | auto get_native_platform() -> daxa::NativeWindowPlatform 81 | { 82 | switch(glfwGetPlatform()) 83 | { 84 | case GLFW_PLATFORM_WIN32: return daxa::NativeWindowPlatform::WIN32_API; 85 | case GLFW_PLATFORM_X11: return daxa::NativeWindowPlatform::XLIB_API; 86 | case GLFW_PLATFORM_WAYLAND: return daxa::NativeWindowPlatform::WAYLAND_API; 87 | default: return daxa::NativeWindowPlatform::UNKNOWN; 88 | } 89 | } 90 | 91 | inline void set_mouse_pos(f32 x, f32 y) 92 | { 93 | glfwSetCursorPos(glfw_window_ptr, static_cast(x), static_cast(y)); 94 | } 95 | 96 | inline void set_mouse_capture(bool should_capture) 97 | { 98 | glfwSetCursorPos(glfw_window_ptr, static_cast(size_x / 2), static_cast(size_y / 2)); 99 | glfwSetInputMode(glfw_window_ptr, GLFW_CURSOR, should_capture ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL); 100 | glfwSetInputMode(glfw_window_ptr, GLFW_RAW_MOUSE_MOTION, should_capture); 101 | } 102 | }; 103 | -------------------------------------------------------------------------------- /tests/1_setup/1_window/main.cpp: -------------------------------------------------------------------------------- 1 | #include <0_common/window.hpp> 2 | #include 3 | 4 | struct App : AppWindow 5 | { 6 | App() : AppWindow("Setup: Test GLFW Window") {} 7 | ~App() = default; 8 | 9 | auto update() -> bool 10 | { 11 | glfwPollEvents(); 12 | if (glfwWindowShouldClose(glfw_window_ptr) != 0) 13 | { 14 | return true; 15 | } 16 | if (!minimized) 17 | { 18 | // draw(); 19 | } 20 | else 21 | { 22 | using namespace std::literals; 23 | std::this_thread::sleep_for(1ms); 24 | } 25 | return false; 26 | } 27 | 28 | // void draw() 29 | // { 30 | // } 31 | 32 | void on_resize(u32 sx, u32 sy) 33 | { 34 | minimized = (sx == 0 || sy == 0); 35 | if (!minimized) 36 | { 37 | size_x = sx; 38 | size_y = sy; 39 | // draw(); 40 | } 41 | } 42 | 43 | void on_mouse_move(f32 /*unused*/, f32 /*unused*/) {} 44 | void on_mouse_button(i32 /*unused*/, i32 /*unused*/) {} 45 | void on_key(i32 /*unused*/, i32 /*unused*/) {} 46 | }; 47 | 48 | auto main() -> int 49 | { 50 | App app = {}; 51 | while (true) 52 | { 53 | if (app.update()) 54 | { 55 | break; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/2_daxa_api/10_raytracing/shaders/random.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * SPDX-FileCopyrightText: Copyright (c) 2019-2021 NVIDIA CORPORATION 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | // Generate a random unsigned int from two unsigned int values, using 16 pairs 21 | // of rounds of the Tiny Encryption Algorithm. See Zafar, Olano, and Curtis, 22 | // "GPU Random Numbers via the Tiny Encryption Algorithm" 23 | uint tea(uint val0, uint val1) 24 | { 25 | uint v0 = val0; 26 | uint v1 = val1; 27 | uint s0 = 0; 28 | 29 | for(uint n = 0; n < 16; n++) 30 | { 31 | s0 += 0x9e3779b9; 32 | v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + s0) ^ ((v1 >> 5) + 0xc8013ea4); 33 | v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + s0) ^ ((v0 >> 5) + 0x7e95761e); 34 | } 35 | 36 | return v0; 37 | } 38 | 39 | // Generate a random unsigned int in [0, 2^24) given the previous RNG state 40 | // using the Numerical Recipes linear congruential generator 41 | uint lcg(inout uint prev) 42 | { 43 | uint LCG_A = 1664525u; 44 | uint LCG_C = 1013904223u; 45 | prev = (LCG_A * prev + LCG_C); 46 | return prev & 0x00FFFFFF; 47 | } 48 | 49 | // Generate a random float in [0, 1) given the previous RNG state 50 | float rnd(inout uint prev) 51 | { 52 | return (float(lcg(prev)) / float(0x01000000)); 53 | } 54 | -------------------------------------------------------------------------------- /tests/2_daxa_api/10_raytracing/shaders/shaders.glsl: -------------------------------------------------------------------------------- 1 | #define DAXA_RAY_TRACING 1 2 | #extension GL_EXT_ray_tracing : enable 3 | #extension GL_EXT_ray_query : enable 4 | #include 5 | 6 | #include "shared.inl" 7 | 8 | DAXA_DECL_PUSH_CONSTANT(PushConstant, p) 9 | 10 | // Credit: https://gamedev.stackexchange.com/questions/92015/optimized-linear-to-srgb-glsl 11 | vec4 fromLinear(vec4 linearRGB) 12 | { 13 | bvec4 cutoff = lessThan(linearRGB, vec4(0.0031308)); 14 | vec4 higher = vec4(1.055) * pow(linearRGB, vec4(1.0 / 2.4)) - vec4(0.055); 15 | vec4 lower = linearRGB * vec4(12.92); 16 | 17 | return mix(higher, lower, cutoff); 18 | } 19 | 20 | layout(local_size_x = 8, local_size_y = 8) in; 21 | void main() 22 | { 23 | const ivec2 index = ivec2(gl_GlobalInvocationID.xy); 24 | if (index.x >= p.size.x || index.y >= p.size.y) 25 | { 26 | return; 27 | } 28 | 29 | uint cull_mask = 0xff; 30 | vec3 origin = vec3( 31 | (float(index.x) + 0.5f) / float(p.size.x), 32 | (float(index.y) + 0.5f) / float(p.size.y), 33 | 0); 34 | float t_min = 0.0f; 35 | vec3 direction = vec3(0, 0, 1); 36 | float t_max = 100.0f; 37 | rayQueryEXT ray_query; 38 | rayQueryInitializeEXT( 39 | ray_query, daxa_accelerationStructureEXT(p.tlas), 40 | gl_RayFlagsOpaqueEXT, 41 | cull_mask, origin, t_min, direction, t_max); 42 | 43 | while (rayQueryProceedEXT(ray_query)) 44 | { 45 | uint type = rayQueryGetIntersectionTypeEXT(ray_query, false); 46 | if (type == gl_RayQueryCandidateIntersectionTriangleEXT) 47 | { 48 | rayQueryConfirmIntersectionEXT(ray_query); 49 | } 50 | else if (type == gl_RayQueryCandidateIntersectionAABBEXT) 51 | { 52 | rayQueryGenerateIntersectionEXT(ray_query, t_max); 53 | } 54 | } 55 | 56 | vec3 out_colour = vec3(0.0, 0.0, 0.0); 57 | uint type = rayQueryGetIntersectionTypeEXT(ray_query, true); 58 | 59 | if (type == gl_RayQueryCommittedIntersectionTriangleEXT) 60 | { 61 | vec2 barycentrics = rayQueryGetIntersectionBarycentricsEXT(ray_query, true); 62 | out_colour = vec3(barycentrics.x, barycentrics.y, 1.0 - barycentrics.x - barycentrics.y); 63 | } 64 | else if (type == gl_RayQueryCommittedIntersectionGeneratedEXT) 65 | { 66 | // interpolate from gl_GlobalInvocationID.xy and clamp to [0,1] 67 | out_colour = vec3( 68 | (float(index.x) + 0.5f) / float(p.size.x), 69 | (float(index.y) + 0.5f) / float(p.size.y), 70 | abs(sin(float(index.x) * float(index.y)))); 71 | } 72 | 73 | imageStore(daxa_image2D(p.swapchain), index, fromLinear(vec4(out_colour, 1))); 74 | } -------------------------------------------------------------------------------- /tests/2_daxa_api/10_raytracing/shaders/shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define DAXA_RAY_TRACING 1 4 | #include 5 | 6 | #define MAX_PRIMITIVES 2 7 | #define ACTIVATE_ATOMIC_FLOAT 1 // this will throws an exception if the device does not support atomic float 8 | 9 | struct CameraView 10 | { 11 | daxa_f32mat4x4 inv_view; 12 | daxa_f32mat4x4 inv_proj; 13 | #if ACTIVATE_ATOMIC_FLOAT == 1 14 | daxa_f32 hit_count; 15 | #endif 16 | }; 17 | DAXA_DECL_BUFFER_PTR(CameraView) 18 | 19 | struct Aabb 20 | { 21 | daxa_f32vec3 minimum; 22 | daxa_f32vec3 maximum; 23 | }; 24 | 25 | struct Aabbs 26 | { 27 | Aabb aabbs[MAX_PRIMITIVES]; 28 | }; 29 | DAXA_DECL_BUFFER_PTR(Aabbs) 30 | 31 | struct PushConstant 32 | { 33 | daxa_u32 frame; 34 | daxa_u32vec2 size; 35 | daxa_TlasId tlas; 36 | daxa_ImageViewId swapchain; 37 | daxa_BufferPtr(CameraView) camera_buffer; 38 | daxa_BufferPtr(Aabbs) aabb_buffer; 39 | }; 40 | 41 | struct rayLight 42 | { 43 | daxa_f32vec3 inHitPosition; 44 | daxa_f32 outLightDistance; 45 | daxa_f32vec3 outLightDir; 46 | daxa_f32 outIntensity; 47 | }; 48 | struct hitPayload 49 | { 50 | daxa_f32vec3 hitValue; 51 | daxa_u32 seed; 52 | #if ACTIVATE_ATOMIC_FLOAT == 1 53 | daxa_b32 is_hit; 54 | #endif 55 | }; 56 | 57 | struct Ray 58 | { 59 | daxa_f32vec3 origin; 60 | daxa_f32vec3 direction; 61 | }; -------------------------------------------------------------------------------- /tests/2_daxa_api/11_mesh_shader/draw.slang: -------------------------------------------------------------------------------- 1 | const static float2 positions[3] = { 2 | float2(0.0, -0.5), 3 | float2(0.5, 0.5), 4 | float2(-0.5, 0.5) 5 | }; 6 | 7 | struct Vertex 8 | { 9 | float4 pos : SV_Position; 10 | }; 11 | 12 | struct Primitive 13 | { 14 | [[vk::location(0)]] nointerpolation float3 tint; 15 | bool cull : SV_CullPrimitive; 16 | } 17 | 18 | const static uint MAX_VERTS = 3; 19 | const static uint MAX_PRIMS = 1; 20 | 21 | [outputtopology("triangle")] 22 | [numthreads(3, 1, 1)] 23 | [shader("mesh")] 24 | void entry_mesh( 25 | in uint tig : SV_GroupIndex, 26 | OutputIndices triangles, 27 | OutputVertices verts, 28 | OutputPrimitives primitives) 29 | { 30 | SetMeshOutputCounts(MAX_VERTS, MAX_PRIMS); 31 | 32 | if (tig < MAX_VERTS) 33 | { 34 | verts[tig].pos = float4(positions[tig], 0, 1); 35 | } 36 | 37 | if(tig < MAX_PRIMS) { 38 | triangles[tig] = uint3(0,1,2); 39 | primitives[tig].tint = float3(1,0.5,0); 40 | primitives[tig].cull = false; 41 | } 42 | } 43 | 44 | struct FragmentOut 45 | { 46 | [[vk::location(0)]] float3 color; 47 | }; 48 | 49 | [shader("fragment")] 50 | FragmentOut entry_fragment(in Vertex vertex, in Primitive prim) 51 | { 52 | FragmentOut frag_out; 53 | frag_out.color = prim.tint; 54 | return frag_out; 55 | } 56 | -------------------------------------------------------------------------------- /tests/2_daxa_api/11_mesh_shader/shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "daxa/daxa.inl" 4 | #include "daxa/utils/task_graph.inl" 5 | 6 | DAXA_DECL_TASK_HEAD_BEGIN(DrawTri) 7 | DAXA_TH_IMAGE(COLOR_ATTACHMENT, REGULAR_2D, resolve_target) 8 | DAXA_TH_IMAGE(COLOR_ATTACHMENT, REGULAR_2D, render_target) 9 | DAXA_DECL_TASK_HEAD_END -------------------------------------------------------------------------------- /tests/2_daxa_api/12_async_queues/draw.slang: -------------------------------------------------------------------------------- 1 | const static float2 positions[3] = { 2 | float2(0.0, -0.5), 3 | float2(0.5, 0.5), 4 | float2(-0.5, 0.5) 5 | }; 6 | 7 | interface VertexI 8 | { 9 | [mutating] 10 | func set_pos(float4 v); 11 | } 12 | 13 | interface PrimitiveI 14 | { 15 | [mutating] 16 | func set_tint(float3 v); 17 | } 18 | 19 | struct Vertex : VertexI 20 | { 21 | float4 pos : SV_Position; 22 | [mutating] 23 | func set_pos(float4 v) { pos = v; } 24 | }; 25 | 26 | struct Primitive : PrimitiveI 27 | { 28 | [[vk::location(0)]] nointerpolation float3 tint; 29 | [mutating] 30 | func set_tint(float3 v) { tint = v; } 31 | } 32 | 33 | const static uint MAX_VERTS = 3; 34 | const static uint MAX_PRIMS = 1; 35 | 36 | void mesh_fn( 37 | in uint tig, 38 | OutputIndices triangles, 39 | OutputVertices verts, 40 | OutputPrimitives primitives) 41 | { 42 | const uint numVertices = 3; 43 | const uint numPrimitives = 1; 44 | SetMeshOutputCounts(numVertices, numPrimitives); 45 | 46 | if(tig < numVertices) { 47 | V v; 48 | if (V is Vertex) 49 | { 50 | Vertex v2 = reinterpret(v); 51 | v2.pos = float4(positions[tig], 0, 1); 52 | v = reinterpret(v2); 53 | } 54 | verts[tig] = v; 55 | } 56 | 57 | if(tig < numPrimitives) { 58 | triangles[tig] = uint3(0,1,2); 59 | primitives[tig].set_tint(float3(1,0,0)); 60 | } 61 | } 62 | 63 | [outputtopology("triangle")] 64 | [numthreads(3, 1, 1)] 65 | [shader("mesh")] 66 | void entry_mesh( 67 | in uint tig : SV_GroupIndex, 68 | OutputIndices triangles, 69 | OutputVertices verts, 70 | OutputPrimitives primitives) 71 | { 72 | mesh_fn(tig, triangles, verts, primitives); 73 | } 74 | 75 | struct FragmentOut 76 | { 77 | [[vk::location(0)]] float3 color; 78 | }; 79 | 80 | [shader("fragment")] 81 | FragmentOut entry_fragment(in Vertex vertex, in Primitive prim) 82 | { 83 | FragmentOut frag_out; 84 | frag_out.color = prim.tint; 85 | return frag_out; 86 | } 87 | -------------------------------------------------------------------------------- /tests/2_daxa_api/12_async_queues/shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "daxa/daxa.inl" 4 | #include "daxa/utils/task_graph.inl" 5 | 6 | DAXA_DECL_TASK_HEAD_BEGIN(DrawTri) 7 | DAXA_TH_IMAGE(COLOR_ATTACHMENT, REGULAR_2D, resolve_target) 8 | DAXA_TH_IMAGE(COLOR_ATTACHMENT, REGULAR_2D, render_target) 9 | DAXA_DECL_TASK_HEAD_END -------------------------------------------------------------------------------- /tests/2_daxa_api/1_instance/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace tests 5 | { 6 | void simplest() 7 | { 8 | auto instance = daxa::create_instance({}); 9 | } 10 | } // namespace tests 11 | 12 | auto main() -> int 13 | { 14 | tests::simplest(); 15 | } 16 | -------------------------------------------------------------------------------- /tests/2_daxa_api/4_synchronization/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct App 4 | { 5 | daxa::Instance daxa_ctx = daxa::create_instance({}); 6 | daxa::Device device = daxa_ctx.create_device_2(daxa_ctx.choose_device({}, {})); 7 | }; 8 | 9 | namespace tests 10 | { 11 | using namespace daxa::types; 12 | 13 | void binary_semaphore(App & app) 14 | { 15 | auto recorder = app.device.create_command_recorder({}); 16 | auto commands1 = recorder.complete_current_commands(); 17 | auto commands2 = recorder.complete_current_commands(); 18 | auto commands3 = recorder.complete_current_commands(); 19 | auto commands4 = recorder.complete_current_commands(); 20 | recorder.~CommandRecorder(); 21 | 22 | auto binary_semaphore_1 = app.device.create_binary_semaphore({}); 23 | auto binary_semaphore_2 = app.device.create_binary_semaphore({}); 24 | 25 | // This semaphore is useful in the future, it can be used to make submits wait on each other, 26 | // or to make a present wait for a submit to finish 27 | app.device.submit_commands({ 28 | .command_lists = std::array{commands1}, 29 | .signal_binary_semaphores = std::array{binary_semaphore_1}, 30 | }); 31 | 32 | app.device.submit_commands({ 33 | .command_lists = std::array{commands2}, 34 | .wait_binary_semaphores = std::array{binary_semaphore_1}, 35 | .signal_binary_semaphores = std::array{binary_semaphore_2}, 36 | }); 37 | 38 | // Binary semaphores can be reused ONLY after they have been signaled. 39 | app.device.submit_commands({ 40 | .command_lists = std::array{commands3}, 41 | .wait_binary_semaphores = std::array{binary_semaphore_2}, 42 | .signal_binary_semaphores = std::array{binary_semaphore_1}, 43 | }); 44 | 45 | app.device.submit_commands({ 46 | .command_lists = std::array{commands4}, 47 | .wait_binary_semaphores = std::array{binary_semaphore_1}, 48 | }); 49 | } 50 | 51 | void memory_barriers(App & app) 52 | { 53 | auto recorder = app.device.create_command_recorder({}); 54 | auto commands = recorder.complete_current_commands(); 55 | 56 | app.device.submit_commands({ 57 | .command_lists = std::array{commands}, 58 | }); 59 | } 60 | } // namespace tests 61 | 62 | auto main() -> int 63 | { 64 | App app = {}; 65 | tests::binary_semaphore(app); 66 | // Useless for now 67 | tests::memory_barriers(app); 68 | } 69 | -------------------------------------------------------------------------------- /tests/2_daxa_api/5_swapchain/main.cpp: -------------------------------------------------------------------------------- 1 | #include <0_common/window.hpp> 2 | #include 3 | 4 | namespace tests 5 | { 6 | void simple_creation() 7 | { 8 | struct App : AppWindow 9 | { 10 | daxa::Instance daxa_ctx = daxa::create_instance({}); 11 | daxa::Device device = daxa_ctx.create_device_2(daxa_ctx.choose_device({}, {})); 12 | 13 | daxa::Swapchain swapchain = device.create_swapchain({ 14 | .native_window = get_native_handle(), 15 | .native_window_platform = get_native_platform(), 16 | .present_mode = daxa::PresentMode::FIFO, 17 | .image_usage = daxa::ImageUsageFlagBits::TRANSFER_DST, 18 | .name = ("swapchain (simple_creation)"), 19 | }); 20 | 21 | App() : AppWindow(" (simple_creation)") 22 | { 23 | [[maybe_unused]] daxa::Extent2D surface_extent = swapchain.get_surface_extent(); 24 | [[maybe_unused]] daxa::Format format = swapchain.get_format(); 25 | [[maybe_unused]] daxa::ColorSpace color_space = swapchain.get_color_space(); 26 | } 27 | 28 | void on_mouse_move(f32 /*unused*/, f32 /*unused*/) {} 29 | void on_mouse_button(i32 /*unused*/, i32 /*unused*/) {} 30 | void on_key(i32 /*unused*/, i32 /*unused*/) {} 31 | void on_resize(u32 /*unused*/, u32 /*unused*/) {} 32 | }; 33 | App const app; 34 | } 35 | 36 | void clearcolor() 37 | { 38 | struct App : AppWindow 39 | { 40 | daxa::Instance daxa_ctx = daxa::create_instance({}); 41 | daxa::Device device = daxa_ctx.create_device_2(daxa_ctx.choose_device({},{})); 42 | 43 | daxa::Swapchain swapchain = device.create_swapchain({ 44 | .native_window = get_native_handle(), 45 | .native_window_platform = get_native_platform(), 46 | .image_usage = daxa::ImageUsageFlagBits::TRANSFER_DST, 47 | .name = ("swapchain (clearcolor)"), 48 | }); 49 | 50 | App() : AppWindow(" (clearcolor)") {} 51 | 52 | auto update() -> bool 53 | { 54 | glfwPollEvents(); 55 | if (glfwWindowShouldClose(glfw_window_ptr) != 0) 56 | { 57 | return true; 58 | } 59 | 60 | if (!minimized) 61 | { 62 | draw(); 63 | } 64 | else 65 | { 66 | using namespace std::literals; 67 | std::this_thread::sleep_for(1ms); 68 | } 69 | 70 | return false; 71 | } 72 | 73 | void draw() 74 | { 75 | auto swapchain_image = swapchain.acquire_next_image(); 76 | if (swapchain_image.is_empty()) 77 | { 78 | return; 79 | } 80 | auto recorder = device.create_command_recorder({ 81 | .name = ("recorder (clearcolor)"), 82 | }); 83 | 84 | recorder.pipeline_barrier_image_transition({ 85 | .dst_access = daxa::AccessConsts::TRANSFER_WRITE, 86 | .src_layout = daxa::ImageLayout::UNDEFINED, 87 | .dst_layout = daxa::ImageLayout::TRANSFER_DST_OPTIMAL, 88 | .image_id = swapchain_image, 89 | }); 90 | 91 | recorder.clear_image({ 92 | .dst_image_layout = daxa::ImageLayout::TRANSFER_DST_OPTIMAL, 93 | .clear_value = {std::array{1, 0, 1, 1}}, 94 | .dst_image = swapchain_image, 95 | }); 96 | 97 | recorder.pipeline_barrier_image_transition({ 98 | .src_access = daxa::AccessConsts::TRANSFER_WRITE, 99 | .src_layout = daxa::ImageLayout::TRANSFER_DST_OPTIMAL, 100 | .dst_layout = daxa::ImageLayout::PRESENT_SRC, 101 | .image_id = swapchain_image, 102 | }); 103 | 104 | auto executalbe_commands = recorder.complete_current_commands(); 105 | recorder.~CommandRecorder(); 106 | 107 | device.submit_commands({ 108 | .command_lists = std::array{executalbe_commands}, 109 | .wait_binary_semaphores = std::array{swapchain.current_acquire_semaphore()}, 110 | .signal_binary_semaphores = std::array{swapchain.current_present_semaphore()}, 111 | .signal_timeline_semaphores = std::array{swapchain.current_timeline_pair()}, 112 | }); 113 | 114 | device.present_frame({ 115 | .wait_binary_semaphores = std::array{swapchain.current_present_semaphore()}, 116 | .swapchain = swapchain, 117 | }); 118 | 119 | device.collect_garbage(); 120 | } 121 | 122 | void on_mouse_move(f32 /*unused*/, f32 /*unused*/) {} 123 | void on_mouse_button(i32 /*unused*/, i32 /*unused*/) {} 124 | void on_key(i32 /*unused*/, i32 /*unused*/) {} 125 | 126 | void on_resize(u32 sx, u32 sy) 127 | { 128 | minimized = sx == 0 || sy == 0; 129 | if (!minimized) 130 | { 131 | swapchain.resize(); 132 | size_x = swapchain.get_surface_extent().x; 133 | size_y = swapchain.get_surface_extent().y; 134 | draw(); 135 | } 136 | } 137 | }; 138 | 139 | App app = {}; 140 | while (true) 141 | { 142 | if (app.update()) 143 | { 144 | break; 145 | } 146 | } 147 | } 148 | } // namespace tests 149 | 150 | auto main() -> int 151 | { 152 | tests::simple_creation(); 153 | tests::clearcolor(); 154 | } 155 | -------------------------------------------------------------------------------- /tests/2_daxa_api/6_task_graph/common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include <0_common/window.hpp> 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #define APPNAME "Daxa API Sample TaskGraph" 11 | #define APPNAME_PREFIX(x) ("[" APPNAME "] " x) 12 | 13 | using namespace daxa::types; 14 | 15 | #include "shaders/shared.inl" 16 | 17 | #include 18 | #include 19 | 20 | struct AppContext 21 | { 22 | daxa::Instance daxa_ctx = daxa::create_instance({}); 23 | daxa::Device device = daxa_ctx.create_device_2(daxa_ctx.choose_device({}, {})); 24 | }; 25 | -------------------------------------------------------------------------------- /tests/2_daxa_api/6_task_graph/persistent_resources.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.hpp" 4 | 5 | namespace tests 6 | { 7 | void sharing_persistent_buffer() 8 | { 9 | // TEST: 10 | // 1) Create single persistent buffer 11 | // 2) Record two task graphs (A, B) 12 | // 3) Task graph A: 13 | // writes persistent buffer 14 | // 4) Task graph B: 15 | // reads persistent buffer 16 | // 6) Call execute task graphs in this order - A -> A -> B -> B 17 | // 5) Check persistent synch of task graphs A and B 18 | // 1) INIT -> A - Expected - First execution of A syncs on nothing 19 | // 2) A -> A - Expected - Second execution of A syncs on SHADER_WRITE -> SHADER_WRITE 20 | // 3) A -> B - Expected - First execution of B syncs on SHADER_WRITE -> SHADER_READ 21 | // 4) B -> B - Expected - Second execution of B has no sync 22 | daxa::Instance daxa_ctx = daxa::create_instance({}); 23 | daxa::Device device = daxa_ctx.create_device_2(daxa_ctx.choose_device({},{})); 24 | auto buffer = device.create_buffer({ 25 | .size = 1, 26 | .name = "actual buffer", 27 | }); 28 | 29 | auto persistent_task_buffer = daxa::TaskBuffer(daxa::TaskBufferInfo{ 30 | .initial_buffers = {.buffers = {&buffer, 1}}, 31 | .name = "persistent buffer", 32 | }); 33 | 34 | auto task_graph_A = daxa::TaskGraph({ 35 | .device = device, 36 | .record_debug_information = true, 37 | .name = "task_graph_a", 38 | }); 39 | 40 | auto task_graph_B = daxa::TaskGraph({ 41 | .device = device, 42 | .record_debug_information = true, 43 | .name = "task_graph_b", 44 | }); 45 | 46 | task_graph_A.use_persistent_buffer(persistent_task_buffer); 47 | task_graph_B.use_persistent_buffer(persistent_task_buffer); 48 | task_graph_A.add_task({ 49 | .attachments = { daxa::inl_attachment( daxa::TaskBufferAccess::GRAPHICS_SHADER_WRITE, persistent_task_buffer ) }, 50 | .task = [&](daxa::TaskInterface) {}, 51 | .name = "write persistent buffer", 52 | }); 53 | task_graph_A.submit({}); 54 | task_graph_A.complete({}); 55 | 56 | task_graph_B.add_task({ 57 | .attachments = { daxa::inl_attachment( daxa::TaskBufferAccess::GRAPHICS_SHADER_READ, persistent_task_buffer ) }, 58 | .task = [&](daxa::TaskInterface) {}, 59 | .name = "read persistent buffer", 60 | }); 61 | task_graph_B.submit({}); 62 | task_graph_B.complete({}); 63 | 64 | task_graph_A.execute({}); 65 | std::cout << task_graph_A.get_debug_string() << std::endl; 66 | task_graph_A.execute({}); 67 | std::cout << task_graph_A.get_debug_string() << std::endl; 68 | task_graph_B.execute({}); 69 | std::cout << task_graph_B.get_debug_string() << std::endl; 70 | task_graph_B.execute({}); 71 | std::cout << task_graph_B.get_debug_string() << std::endl; 72 | 73 | device.wait_idle(); 74 | device.destroy_buffer(buffer); 75 | device.collect_garbage(); 76 | } 77 | void sharing_persistent_image() 78 | { 79 | // TEST: 80 | // 1) Create single persistent image 81 | // 2) Record two task graphs (A, B) 82 | // 3) Task graph A: 83 | // writes persistent image 84 | // uses persistent image as color attachment 85 | // 4) Task graph B: 86 | // reads persistent image 87 | // 6) Call execute task graphs in this order - A -> A -> B -> B 88 | // 5) Check persistent synch of task graphs A and B 89 | // 1) INIT -> A - Expected - First execution of A transitions image from UNDEFINED to WRITE 90 | // 2) A -> A - Expected - Second execution of A transitions image from COLOR_ATTACHMENT to WRITE 91 | // 3) A -> B - Expected - First execution of B transitions image from WRITE to READ 92 | // 4) B -> B - Expected - Second execution of B has no transitions 93 | daxa::Instance daxa_ctx = daxa::create_instance({}); 94 | daxa::Device device = daxa_ctx.create_device_2(daxa_ctx.choose_device({},{})); 95 | // We need an actual image, as task graph will try to populate its image view cache. 96 | // It will error out when it detects that there are no runtime images for a task image when updating the view cache. 97 | auto image = device.create_image({ 98 | .size = {1, 1, 1}, 99 | .array_layer_count = 1, 100 | .usage = daxa::ImageUsageFlagBits::SHADER_STORAGE | 101 | daxa::ImageUsageFlagBits::COLOR_ATTACHMENT | 102 | daxa::ImageUsageFlagBits::SHADER_SAMPLED, 103 | .name = "actual image", 104 | }); 105 | 106 | auto persistent_task_image = daxa::TaskImage( 107 | daxa::TaskImageInfo{ 108 | .initial_images = {.images = {&image, 1}}, 109 | .swapchain_image = false, 110 | .name = "image", 111 | }); 112 | 113 | auto task_graph_A = daxa::TaskGraph({ 114 | .device = device, 115 | .record_debug_information = true, 116 | .name = "task_graph_a", 117 | }); 118 | 119 | task_graph_A.use_persistent_image(persistent_task_image); 120 | task_graph_A.add_task({ 121 | .attachments = {daxa::inl_attachment(daxa::TaskImageAccess::GRAPHICS_SHADER_STORAGE_WRITE_ONLY, persistent_task_image ) }, 122 | .task = [&](daxa::TaskInterface) {}, 123 | .name = "write persistent image", 124 | }); 125 | task_graph_A.add_task({ 126 | .attachments = {daxa::inl_attachment(daxa::TaskImageAccess::COLOR_ATTACHMENT, persistent_task_image ) }, 127 | .task = [&](daxa::TaskInterface) {}, 128 | .name = "persistent image - color attachment", 129 | }); 130 | task_graph_A.submit({}); 131 | task_graph_A.complete({}); 132 | 133 | auto task_graph_B = daxa::TaskGraph({ 134 | .device = device, 135 | .record_debug_information = true, 136 | .name = "task_graph_b", 137 | }); 138 | task_graph_B.use_persistent_image(persistent_task_image); 139 | task_graph_B.add_task({ 140 | .attachments = {daxa::inl_attachment(daxa::TaskImageAccess::GRAPHICS_SHADER_SAMPLED, persistent_task_image ) }, 141 | .task = [&](daxa::TaskInterface) {}, 142 | .name = "read persistent image", 143 | }); 144 | task_graph_B.submit({}); 145 | task_graph_B.complete({}); 146 | 147 | task_graph_A.execute({}); 148 | std::cout << task_graph_A.get_debug_string() << std::endl; 149 | task_graph_A.execute({}); 150 | std::cout << task_graph_A.get_debug_string() << std::endl; 151 | task_graph_B.execute({}); 152 | std::cout << task_graph_B.get_debug_string() << std::endl; 153 | task_graph_B.execute({}); 154 | std::cout << task_graph_B.get_debug_string() << std::endl; 155 | 156 | device.wait_idle(); 157 | device.destroy_image(image); 158 | device.collect_garbage(); 159 | } 160 | } // namespace tests 161 | -------------------------------------------------------------------------------- /tests/2_daxa_api/6_task_graph/shaders/draw.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DAXA_DECL_PUSH_CONSTANT(DrawPush) 4 | 5 | #if DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_VERTEX 6 | 7 | layout(location = 0) out vec4 v_col; 8 | void main() 9 | { 10 | DrawVertex vert = daxa_push_constant.vertex_buffer[gl_VertexIndex].value; 11 | gl_Position = vec4(vert.pos.xy, 0, 1); 12 | vec4 value = imageLoad(daxa_image2D(tex)); 13 | vec4 value = textureFetch(daxa_texture2D(tex)); 14 | 15 | v_col = vert.col; 16 | } 17 | 18 | #elif DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_FRAGMENT 19 | 20 | layout(location = 0) in vec4 v_col; 21 | layout(location = 0) out vec4 color; 22 | void main() 23 | { 24 | color = v_col; 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /tests/2_daxa_api/6_task_graph/shaders/mipmapping.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DAXA_DECL_PUSH_CONSTANT(MipmappingComputePushConstant, push) 4 | 5 | float segment_distance(vec2 p, vec2 a, vec2 b) 6 | { 7 | vec2 ba = b - a; 8 | vec2 pa = p - a; 9 | float h = clamp(dot(pa, ba) / dot(ba, ba), 0, 1); 10 | return length(pa - h * ba); 11 | } 12 | 13 | #define INPUT deref(push.gpu_input) 14 | 15 | layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; 16 | void main() 17 | { 18 | uvec3 pixel_i = gl_GlobalInvocationID.xyz; 19 | if (pixel_i.x >= push.frame_dim.x || pixel_i.y >= push.frame_dim.y) 20 | return; 21 | 22 | vec2 render_size = push.frame_dim; 23 | vec2 inv_render_size = vec2(1.0) / render_size; 24 | vec2 pixel_pos = pixel_i.xy; 25 | vec2 mouse_pos = vec2(INPUT.mouse_x, INPUT.mouse_y); 26 | vec2 prev_mouse_pos = vec2(INPUT.p_mouse_x, INPUT.p_mouse_y); 27 | 28 | vec2 uv = pixel_pos * inv_render_size; 29 | 30 | float dist = segment_distance(pixel_pos, prev_mouse_pos, mouse_pos); 31 | 32 | if (dist < INPUT.paint_radius) 33 | { 34 | vec3 col = INPUT.paint_col; 35 | imageStore(daxa_image2D(push.image), ivec2(pixel_i.xy), vec4(col, 1)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/2_daxa_api/6_task_graph/shaders/shader_integration.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #extension GL_EXT_debug_printf : enable 4 | 5 | #include "shader_integration.inl" 6 | 7 | DAXA_DECL_PUSH_CONSTANT(ShaderIntegrationTaskHead, p) 8 | 9 | layout(local_size_x = 16, local_size_y = 16) in; 10 | void main() 11 | { 12 | const ivec2 index = ivec2(gl_GlobalInvocationID.xy); 13 | daxa_u64 d = p.image.value; 14 | const float set_value = deref(p.settings).set_value; 15 | imageStore(daxa_image2D(p.image), index, vec4(set_value, 0, 0, 0)); 16 | if (gl_GlobalInvocationID.x == 0 && gl_GlobalInvocationID.y == 0) 17 | { 18 | debugPrintfEXT("buffer ptr: %llx, image view id value: %u\n", daxa_u64(p.settings), d); 19 | debugPrintfEXT("value: %f\n", set_value); 20 | debugPrintfEXT("image: %u\n", p.image.value); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/2_daxa_api/6_task_graph/shaders/shader_integration.inl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct Settings 5 | { 6 | daxa_f32 set_value; 7 | }; 8 | DAXA_DECL_BUFFER_PTR_ALIGN(Settings, 4) 9 | 10 | // Must be in an .inl file for now. 11 | DAXA_DECL_TASK_HEAD_BEGIN(ShaderIntegrationTaskHead) 12 | DAXA_TH_BUFFER_PTR(COMPUTE_SHADER_READ, daxa_BufferPtr(Settings), settings) 13 | DAXA_TH_IMAGE_ID(COMPUTE_SHADER_STORAGE_READ_WRITE, REGULAR_2D, image) 14 | DAXA_DECL_TASK_HEAD_END 15 | -------------------------------------------------------------------------------- /tests/2_daxa_api/6_task_graph/shaders/shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct MipmappingGpuInput 6 | { 7 | daxa_f32vec3 paint_col; 8 | daxa_f32 mouse_x; 9 | daxa_f32 mouse_y; 10 | daxa_f32 p_mouse_x; 11 | daxa_f32 p_mouse_y; 12 | daxa_f32 paint_radius; 13 | }; 14 | DAXA_DECL_BUFFER_PTR(MipmappingGpuInput) 15 | 16 | struct MipmappingComputePushConstant 17 | { 18 | daxa_ImageViewId image; 19 | daxa_RWBufferPtr(MipmappingGpuInput) gpu_input; 20 | daxa_u32vec2 frame_dim; 21 | }; 22 | 23 | struct CondSettings 24 | { 25 | daxa_u32 value; 26 | }; 27 | 28 | struct DrawVertex 29 | { 30 | daxa_f32vec4 pos, col; 31 | }; 32 | DAXA_DECL_BUFFER_PTR(DrawVertex) 33 | struct DrawPush 34 | { 35 | daxa_BufferPtr(DrawVertex) vertex_buffer; 36 | }; 37 | -------------------------------------------------------------------------------- /tests/2_daxa_api/6_task_graph/shaders/transient.glsl: -------------------------------------------------------------------------------- 1 | #extension GL_EXT_debug_printf : enable 2 | 3 | #define DAXA_ENABLE_IMAGE_OVERLOADS_BASIC 1 4 | #include 5 | #include "transient.inl" 6 | 7 | #if defined(TEST_IMAGE) 8 | 9 | DAXA_DECL_PUSH_CONSTANT(TestImagePush, push) 10 | layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; 11 | void main() 12 | { 13 | const uvec3 gindex = gl_GlobalInvocationID; 14 | if (gindex.x < push.size.x && gindex.y < push.size.y && gindex.z < push.size.z) 15 | { 16 | const float fetch = texelFetch(daxa_texture3D(push.test_image), ivec3(gindex), 0).x; 17 | const bool correct = fetch == push.value; 18 | if (!correct) 19 | { 20 | debugPrintfEXT("ERROR! index (%u,%u,%u) contains value (%f), it should contain (%f)\n", gindex.x, gindex.y, gindex.z, fetch, push.value); 21 | } 22 | } 23 | } 24 | 25 | #else 26 | 27 | DAXA_DECL_PUSH_CONSTANT(TestBufferPush, push) 28 | layout(local_size_x = 128) in; 29 | void main() 30 | { 31 | const uint gindex = gl_GlobalInvocationID.x; 32 | if (gindex.x < push.size) 33 | { 34 | const uint fetch = deref(push.test_buffer[gindex]); 35 | const bool correct = fetch == push.value; 36 | if (!correct) 37 | { 38 | debugPrintfEXT("ERROR! index (%u) contains value (%u), it should contain (%u)\n", gindex.x, fetch, push.value); 39 | } 40 | } 41 | } 42 | 43 | #endif -------------------------------------------------------------------------------- /tests/2_daxa_api/6_task_graph/shaders/transient.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define LONG_LIFE_BUFFER_VALUE (33u) 6 | #define LONG_LIFE_BUFFER_SIZE 8192u 7 | 8 | #if __cplusplus 9 | #define MEDIUM_LIFE_IMAGE_VALUE (1.0f) 10 | static constexpr daxa_u32vec3 MEDIUM_LIFE_IMAGE_SIZE = daxa_u32vec3{512u,200u,1u}; 11 | 12 | #define LONG_LIFE_IMAGE_VALUE (0.5f) 13 | static constexpr daxa_u32vec3 LONG_LIFE_IMAGE_SIZE = daxa_u32vec3{32u,32u,32u}; 14 | 15 | #define SHORT_LIFE_IMAGE_VALUE (0.25f) 16 | static constexpr daxa_u32vec3 SHORT_LIFE_IMAGE_SIZE = daxa_u32vec3{100u, 300u, 4u}; 17 | 18 | #define SHORT_LIFE_BUFFER_VALUE (12345678) 19 | #define SHORT_LIFE_BUFFER_SIZE (64u) 20 | #endif //__cplusplus 21 | 22 | struct TestImagePush 23 | { 24 | daxa_ImageViewId test_image; 25 | daxa_u32vec3 size; 26 | daxa_f32 value; 27 | }; 28 | 29 | struct TestBufferPush 30 | { 31 | daxa_BufferPtr(daxa_u32) test_buffer; 32 | daxa_u32 size; 33 | daxa_u32 value; 34 | }; -------------------------------------------------------------------------------- /tests/2_daxa_api/7_pipeline_manager/shaders/main.glsl: -------------------------------------------------------------------------------- 1 | #include "daxa/daxa.inl" 2 | 3 | #include "test/test0.glsl" 4 | 5 | layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; 6 | void main() 7 | { 8 | func(); 9 | } 10 | -------------------------------------------------------------------------------- /tests/2_daxa_api/7_pipeline_manager/shaders/test/tesselation_test.glsl: -------------------------------------------------------------------------------- 1 | #include "daxa/daxa.inl" 2 | 3 | #if DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_VERTEX 4 | void main() 5 | { 6 | gl_Position = vec4(1.0, 1.0, 1.0, 1.0); 7 | } 8 | #elif DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_TESSELATION_CONTROL 9 | layout(vertices = 3) out; 10 | 11 | void main(void) 12 | { 13 | if (gl_InvocationID == 0) 14 | { 15 | gl_TessLevelInner[0] = 1.0; 16 | gl_TessLevelOuter[0] = 1.0; 17 | gl_TessLevelOuter[1] = 1.0; 18 | gl_TessLevelOuter[2] = 1.0; 19 | } 20 | 21 | gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; 22 | } 23 | 24 | #elif DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_TESSELATION_EVALUATION 25 | layout(triangles, fractional_odd_spacing, cw) in; 26 | 27 | void main() 28 | { 29 | gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) + 30 | (gl_TessCoord.y * gl_in[1].gl_Position) + 31 | (gl_TessCoord.z * gl_in[2].gl_Position); 32 | } 33 | #elif DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_FRAGMENT 34 | layout(location = 0) out vec4 outFragColor; 35 | void main() 36 | { 37 | outFragColor = vec4(1.0, 0.0, 0.0, 1.0); 38 | } 39 | #endif 40 | -------------------------------------------------------------------------------- /tests/2_daxa_api/7_pipeline_manager/shaders/test/test0.glsl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "test1.glsl" 4 | -------------------------------------------------------------------------------- /tests/2_daxa_api/7_pipeline_manager/shaders/test/test1.glsl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void func() 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /tests/2_daxa_api/8_mem/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace daxa::types; 3 | 4 | #include 5 | 6 | #include 7 | 8 | static inline constexpr usize ITERATION_COUNT = {1000}; 9 | static inline constexpr usize ELEMENT_COUNT = {17}; 10 | 11 | auto main() -> int 12 | { 13 | daxa::Instance daxa_ctx = daxa::create_instance({}); 14 | daxa::Device device = daxa_ctx.create_device_2(daxa_ctx.choose_device({},{})); 15 | daxa::TransferMemoryPool tmem{daxa::TransferMemoryPoolInfo{ 16 | .device = device, 17 | .capacity = 256, 18 | .name = "transient memory pool", 19 | }}; 20 | daxa::TimelineSemaphore gpu_timeline = device.create_timeline_semaphore({ 21 | .name = "timeline semaphpore", 22 | }); 23 | usize global_submit_timeline = 1; 24 | daxa::BufferId result_buffer = device.create_buffer({ 25 | .size = sizeof(u32) * ELEMENT_COUNT * ITERATION_COUNT, 26 | .allocate_info = daxa::MemoryFlagBits::HOST_ACCESS_RANDOM, 27 | .name = "result", 28 | }); 29 | 30 | for (u32 iteration = 0; iteration < ITERATION_COUNT; ++iteration) 31 | { 32 | [[maybe_unused]] auto _timeout = gpu_timeline.wait_for_value(global_submit_timeline - 1); 33 | daxa::CommandRecorder cmd = device.create_command_recorder({}); 34 | cmd.pipeline_barrier({ 35 | .src_access = daxa::AccessConsts::TRANSFER_READ_WRITE | daxa::AccessConsts::HOST_WRITE, 36 | .dst_access = daxa::AccessConsts::TRANSFER_READ_WRITE, 37 | }); 38 | 39 | // Can allocate anywhere in the frame with imediately available staging memory. 40 | daxa::TransferMemoryPool::Allocation alloc = tmem.allocate(ELEMENT_COUNT * sizeof(uint32_t), 8).value(); 41 | for (u32 i = 0; i < ELEMENT_COUNT; ++i) 42 | { 43 | // The Allocation provides a host pointer to the memory. 44 | reinterpret_cast(alloc.host_address)[i] = iteration * 100 + i; 45 | } 46 | // ALl the allocations are from a single internal buffer. 47 | // The allocation contains an integer offset into that buffer. 48 | // It also contains a device address that can be passed to a shader directly. 49 | cmd.copy_buffer_to_buffer({ 50 | .src_buffer = tmem.buffer(), 51 | .dst_buffer = result_buffer, 52 | .src_offset = alloc.buffer_offset, 53 | .dst_offset = sizeof(u32) * ELEMENT_COUNT * iteration, 54 | .size = sizeof(u32) * ELEMENT_COUNT, 55 | }); 56 | 57 | // Need to specify give every subnmit using the mme util timeline semaphore and its value on submission. 58 | // This is nessecary for internal tracking. 59 | 60 | auto signals = std::array{ 61 | std::pair{gpu_timeline, global_submit_timeline}, 62 | std::pair{tmem.timeline_semaphore(), tmem.timeline_value()}, 63 | }; 64 | device.submit_commands({ 65 | .command_lists = std::array{cmd.complete_current_commands()}, 66 | .signal_timeline_semaphores = signals, 67 | }); 68 | global_submit_timeline += 1; 69 | } 70 | 71 | daxa::CommandRecorder cmd = device.create_command_recorder({}); 72 | cmd.pipeline_barrier({ 73 | .src_access = daxa::AccessConsts::TRANSFER_WRITE, 74 | .dst_access = daxa::AccessConsts::HOST_READ, 75 | }); 76 | 77 | device.submit_commands({ 78 | .command_lists = std::array{cmd.complete_current_commands()}, 79 | }); 80 | cmd.~CommandRecorder(); 81 | 82 | device.wait_idle(); 83 | 84 | u32 const * elements = device.buffer_host_address_as(result_buffer).value(); 85 | for (u32 iteration = 0; iteration < ITERATION_COUNT; ++iteration) 86 | { 87 | for (u32 element = 0; element < ELEMENT_COUNT; ++element) 88 | { 89 | std::cout << "value: " << elements[iteration * ELEMENT_COUNT + element] / 100 << " " << elements[iteration * ELEMENT_COUNT + element] % 100 << "\n"; 90 | } 91 | } 92 | device.destroy_buffer(result_buffer); 93 | device.collect_garbage(); 94 | std::cout << std::flush; 95 | } 96 | -------------------------------------------------------------------------------- /tests/2_daxa_api/9_shader_integration/shaders/alignment_test.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | #include "shared.inl" 3 | #extension GL_EXT_debug_printf : enable 4 | 5 | DAXA_DECL_PUSH_CONSTANT(TestShaderPush, p) 6 | 7 | layout(local_size_x = 1) in; 8 | void main() 9 | { 10 | deref(p.attachments.align_test_dst).i0 = deref(p.attachments.align_test_src).i0; 11 | deref(p.attachments.align_test_dst).i1 = deref(p.attachments.align_test_src).i1; 12 | deref(p.attachments.align_test_dst).i2 = deref(p.attachments.align_test_src).i2; 13 | deref(p.attachments.align_test_dst).i3 = deref(p.attachments.align_test_src).i3; 14 | deref(p.attachments.align_test_dst).i4 = deref(p.attachments.align_test_src).i4; 15 | deref(p.attachments.align_test_dst).i5[0] = deref(p.attachments.align_test_src).i5[0]; 16 | deref(p.attachments.align_test_dst).i5[1] = deref(p.attachments.align_test_src).i5[1]; 17 | deref(p.attachments.align_test_dst).i5[2] = deref(p.attachments.align_test_src).i5[2]; 18 | deref(p.attachments.align_test_dst).i6[0] = deref(p.attachments.align_test_src).i6[0]; 19 | deref(p.attachments.align_test_dst).i6[1] = deref(p.attachments.align_test_src).i6[1]; 20 | deref(p.attachments.align_test_dst).i6[2] = deref(p.attachments.align_test_src).i6[2]; 21 | deref(p.attachments.align_test_dst).i7 = deref(p.attachments.align_test_src).i7; 22 | } -------------------------------------------------------------------------------- /tests/2_daxa_api/9_shader_integration/shaders/bindless_access.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | #include "shared.inl" 3 | 4 | DAXA_DECL_PUSH_CONSTANT(BindlessTestPush, push) 5 | 6 | // tests custom image accessor declarations 7 | DAXA_DECL_IMAGE_ACCESSOR(image2D, restrict writeonly subgroupcoherent, WORestrCoher) 8 | 9 | // tests custom image accessor declaration with format 10 | DAXA_DECL_IMAGE_ACCESSOR_WITH_FORMAT(uimage2D, r32ui, , r32uiImage) 11 | 12 | void pass_by_value(daxa_RWBufferPtr(SomeStruct) b, daxa_ImageViewId i, daxa_SamplerId s) 13 | { 14 | // Any image id can be cast to a glsl resource, by naming the glsl resource with the daxa_ prefix. 15 | ivec2 size = imageSize(daxa_access(WORestrCoher, i)); 16 | imageStore(daxa_image2D(i), ivec2(0,0), vec4(1234,0,0,0)); 17 | deref(b).value = 1234; 18 | } 19 | 20 | void pass_struct_by_value(RWHandles handles) 21 | { 22 | pass_by_value(handles.my_buffer, handles.my_float_image, handles.my_sampler); 23 | } 24 | 25 | layout(local_size_x = 1) in; 26 | void main() 27 | { 28 | // Buffer ptr is a predefined buffer reference with one field called value of the given struct type. 29 | daxa_RWBufferPtr(SomeStruct) b = push.handles.my_buffer; 30 | // Ids can be passed as local variables 31 | daxa_ImageViewId i = push.handles.my_float_image; 32 | daxa_SamplerId s = push.handles.my_sampler; 33 | // Ids can be passed like any other local variables, as they are normal structs. 34 | pass_by_value(b, i, s); 35 | RWHandles handles; 36 | handles.my_buffer = b; 37 | handles.my_float_image = i; 38 | handles.my_sampler = s; 39 | pass_struct_by_value(handles); 40 | // The following like is equivalent '''to push.next_shader_input.value = handles;''' 41 | deref(push.next_shader_input) = handles; 42 | 43 | imageAtomicOr( 44 | daxa_access(r32uiImage, push.handles.my_uint_image), 45 | ivec2(0, 0), 46 | 1 << 31 47 | ); 48 | } -------------------------------------------------------------------------------- /tests/2_daxa_api/9_shader_integration/shaders/bindless_access_followup.glsl: -------------------------------------------------------------------------------- 1 | #extension GL_EXT_debug_printf : enable 2 | 3 | #include 4 | #include "shared.inl" 5 | 6 | DAXA_DECL_PUSH_CONSTANT(BindlessTestFollowPush, push) 7 | 8 | void pass_by_value(daxa_BufferPtr(SomeStruct) b, daxa_ImageViewId i, daxa_SamplerId s) 9 | { 10 | const float buf_fetch = deref(b).value; 11 | // Ids can be cast to glsl types directly. 12 | // The casts are implemented via makros of the names daxa_##GLSL_TYPE for example: `daxa_texture2D(daxa_ImageViewId)`. 13 | const float tex_sample = texture(daxa_sampler2D(i,s),vec2(0,0)).r; 14 | const float tex_fetch = texelFetch(daxa_texture2D(i), ivec2(0,0), 0).r; 15 | debugPrintfEXT("buffer fetch: %f, texture sample: %f, texture fetch %f\n, ", buf_fetch, tex_sample, tex_fetch); 16 | } 17 | 18 | void pass_struct_by_value(Handles handles) 19 | { 20 | // pass handles as values into a function: 21 | pass_by_value(handles.my_buffer, handles.my_image, handles.my_sampler); 22 | } 23 | 24 | layout(local_size_x = 1) in; 25 | void main() 26 | { 27 | // read resource handles from buffer: 28 | Handles handles = deref(push.shader_input); 29 | // pass handles as struct into a function: 30 | pass_struct_by_value(handles); 31 | } -------------------------------------------------------------------------------- /tests/2_daxa_api/9_shader_integration/shaders/shared.inl: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct TestU64Alignment 5 | { 6 | daxa_u32 i0; 7 | daxa_u32 i1; 8 | daxa_u32 i2; 9 | daxa_u64 i3; 10 | daxa_u32 i4; 11 | daxa_u64 i5[3]; 12 | daxa_u32 i6[3]; 13 | daxa_u64 i7; 14 | }; 15 | DAXA_DECL_BUFFER_PTR_ALIGN(TestU64Alignment, 8) 16 | 17 | DAXA_DECL_TASK_HEAD_BEGIN(TestShaderTaskHead) 18 | DAXA_TH_BUFFER_PTR(COMPUTE_SHADER_READ, daxa_BufferPtr(TestU64Alignment), align_test_src) 19 | DAXA_TH_BUFFER_PTR(COMPUTE_SHADER_READ_WRITE, daxa_RWBufferPtr(TestU64Alignment), align_test_dst) 20 | DAXA_DECL_TASK_HEAD_END 21 | 22 | struct TestShaderPush 23 | { 24 | DAXA_TH_BLOB(TestShaderTaskHead, attachments) 25 | }; 26 | 27 | // Only used to check complication of All Task Head Uses: 28 | DAXA_DECL_TASK_HEAD_BEGIN(TestTaskHead) 29 | // Declares used task image, that is NOT accessable within the shader. 30 | DAXA_TH_IMAGE( TRANSFER_READ, REGULAR_2D, copy_read_img) 31 | // Declares used task buffer, that is NOT accessable within the shader. 32 | DAXA_TH_BUFFER( TRANSFER_READ, copy_read_buf) 33 | // Declares used task image, that is used as a storage image with type 2d, accessable in shader as glsl type image2D. 34 | DAXA_TH_IMAGE_ID( COMPUTE_SHADER_STORAGE_READ_ONLY, REGULAR_2D, shader_id_read_img) 35 | // Declares used task image usable in shader like above, but requires 2 runtime images. In shader it is exposed as an array of ids. 36 | DAXA_TH_IMAGE_ID_ARRAY( COMPUTE_SHADER_STORAGE_READ_ONLY, REGULAR_2D, shader_id_read_array_img, 2) 37 | // Declares used task buffer, accessable in shader as a buffer id. 38 | DAXA_TH_BUFFER_ID( COMPUTE_SHADER_READ, shader_id_read_buf) 39 | // Declares used task buffer like above, but requires 2 runtime buffers. In shader it is exposed as an array. 40 | DAXA_TH_BUFFER_ID_ARRAY( COMPUTE_SHADER_READ, shader_id_read_array_buf, 2) 41 | // Declares used task buffer likfe above, with the difference that its a buffer ptr in the shader. 42 | DAXA_TH_BUFFER_PTR( COMPUTE_SHADER_READ, daxa_BufferPtr(uint), shader_ptr_read_buf) 43 | // Declares used task buffer likfe above, with the difference that its a buffer ptr in the shader. 44 | DAXA_TH_BUFFER_PTR_ARRAY( COMPUTE_SHADER_READ, daxa_BufferPtr(uint), shader_ptr_read_array_buf, 2) 45 | DAXA_DECL_TASK_HEAD_END 46 | 47 | // The above task head will be translated to the following struct in glsl: 48 | // struct TestTaskHead { 49 | // daxa_ImageViewId shader_id_read_img; 50 | // daxa_ImageViewId shader_id_read_array_img[2]; 51 | // daxa_BufferId shader_id_read_buf; 52 | // daxa_BufferId shader_id_read_array_buf[2]; 53 | // daxa_BufferPtr(uint) shader_ptr_read_buf; 54 | // daxa_BufferPtr(uint) shader_ptr_read_array_buf[2]; 55 | // }; 56 | 57 | struct TestTaskPush 58 | { 59 | // The Shader blob can be referenced within shared files via the macro DAXA_TH_BLOB like so to declare shared structs: 60 | // This will become `TestTaskHead attachments` in shader code and `TestTaskHead::AttachmentShaderBlob attachments` in c++. 61 | // Both have the exact same size and alignment, so code sharing works like normal. 62 | DAXA_TH_BLOB(TestTaskHead, attachments) 63 | }; 64 | 65 | // Test compilation of shared functions with shader shared types 66 | daxa_u32 test_fn_u32(daxa_u32 by_value) 67 | { 68 | return (by_value * by_value) * 4; 69 | } 70 | 71 | struct SomeStruct 72 | { 73 | daxa_f32 value; 74 | }; 75 | DAXA_DECL_BUFFER_PTR(SomeStruct) 76 | 77 | struct RWHandles 78 | { 79 | daxa_RWBufferPtr(SomeStruct) my_buffer; 80 | daxa_ImageViewId my_float_image; 81 | daxa_ImageViewId my_uint_image; 82 | daxa_SamplerId my_sampler; 83 | }; 84 | DAXA_DECL_BUFFER_PTR(RWHandles) 85 | 86 | struct BindlessTestPush 87 | { 88 | RWHandles handles; 89 | daxa_RWBufferPtr(RWHandles) next_shader_input; 90 | }; 91 | 92 | struct Handles 93 | { 94 | daxa_BufferPtr(SomeStruct) my_buffer; 95 | daxa_ImageViewId my_image; 96 | daxa_SamplerId my_sampler; 97 | }; 98 | DAXA_DECL_BUFFER_PTR(Handles) 99 | 100 | struct BindlessTestFollowPush 101 | { 102 | daxa_BufferPtr(Handles) shader_input; 103 | }; -------------------------------------------------------------------------------- /tests/2_daxa_api/9_shader_integration/shared.hlsl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | DAXA_DECL_TASK_HEAD_BEGIN(TestHead) 7 | DAXA_TH_BUFFER_PTR(COMPUTE_SHADER_READ_WRITE, daxa::u32*, buf) 8 | DAXA_DECL_TASK_HEAD_END 9 | 10 | struct Test 11 | { 12 | TestHead::AttachmentShaderBlob attachments; 13 | daxa::u32 i; 14 | daxa::u32* ptr0; 15 | Ptr ptr1; 16 | }; -------------------------------------------------------------------------------- /tests/3_samples/0_rectangle_cutting/shaders/draw.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DAXA_DECL_PUSH_CONSTANT(DrawPush, p) 4 | 5 | #if DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_VERTEX 6 | 7 | layout(location = 0) out vec4 v_col; 8 | void main() 9 | { 10 | DrawVertex vert = deref(p.face_buffer).verts[gl_VertexIndex]; 11 | gl_Position = vec4(vert.pos.xy, 0, 1); 12 | v_col = vert.col; 13 | } 14 | 15 | #elif DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_FRAGMENT 16 | 17 | layout(location = 0) in vec4 v_col; 18 | layout(location = 0) out vec4 color; 19 | void main() 20 | { 21 | color = v_col; 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /tests/3_samples/0_rectangle_cutting/shaders/shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct DrawVertex 6 | { 7 | daxa_f32vec4 pos, col; 8 | }; 9 | 10 | struct DrawVertexBuffer 11 | { 12 | DrawVertex verts[3]; 13 | }; 14 | DAXA_DECL_BUFFER_PTR(DrawVertexBuffer) 15 | 16 | struct DrawPush 17 | { 18 | daxa_BufferPtr(DrawVertexBuffer) face_buffer; 19 | }; 20 | -------------------------------------------------------------------------------- /tests/3_samples/1_mandelbrot/shaders/compute.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | DAXA_DECL_PUSH_CONSTANT(ComputePush, p) 6 | 7 | #define CENTER vec2(-0.694008, -0.324998) 8 | #define SUBSAMPLES 2 9 | 10 | vec3 hsv2rgb(vec3 c) 11 | { 12 | vec4 k = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); 13 | vec3 p = abs(fract(c.xxx + k.xyz) * 6.0 - k.www); 14 | return c.z * mix(k.xxx, clamp(p - k.xxx, 0.0, 1.0), c.y); 15 | } 16 | 17 | vec3 mandelbrot_colored(vec2 pixel_p) 18 | { 19 | vec2 uv = pixel_p / vec2(p.frame_dim.xy); 20 | uv = (uv - 0.5) * vec2(daxa_f32(p.frame_dim.x) / daxa_f32(p.frame_dim.y), 1); 21 | daxa_BufferPtr(GpuInput) gpu_input_ptr = daxa_BufferPtr(GpuInput)(daxa_id_to_address(p.input_buffer_id)); 22 | daxa_f32 time = deref(gpu_input_ptr).time; 23 | daxa_f32 scale = 12.0 / (exp(time) + 0.0001); 24 | vec2 z = uv * scale * 2 + CENTER; 25 | vec2 c = z; 26 | daxa_u32 i = 0; 27 | for (; i < 512; ++i) 28 | { 29 | vec2 z_ = z; 30 | z.x = z_.x * z_.x - z_.y * z_.y; 31 | z.y = 2.0 * z_.x * z_.y; 32 | z += c; 33 | if (dot(z, z) > 256 * 256) 34 | break; 35 | } 36 | vec3 col = vec3(0); 37 | if (i != 512) 38 | { 39 | daxa_f32 l = i; 40 | daxa_f32 sl = l - log2(log2(dot(z, z))) + 4.0; 41 | sl = pow(sl * 0.01, 1.0); 42 | col = hsv2rgb(vec3(sl, 1, 1)); 43 | #if MY_TOGGLE 44 | col = 1 - col; 45 | #endif 46 | } 47 | return col; 48 | } 49 | 50 | layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; 51 | void main() 52 | { 53 | uvec3 pixel_i = gl_GlobalInvocationID.xyz; 54 | if (pixel_i.x >= p.frame_dim.x || pixel_i.y >= p.frame_dim.y) 55 | return; 56 | 57 | vec3 col = vec3(0, 0, 0); 58 | for (daxa_i32 yi = 0; yi < SUBSAMPLES; ++yi) 59 | { 60 | for (daxa_i32 xi = 0; xi < SUBSAMPLES; ++xi) 61 | { 62 | vec2 offset = vec2(xi, yi) / daxa_f32(SUBSAMPLES); 63 | col += mandelbrot_colored(vec2(pixel_i.xy) + offset); 64 | } 65 | } 66 | col *= 1.0 / daxa_f32(SUBSAMPLES * SUBSAMPLES); 67 | 68 | imageStore(daxa_image2D(p.image_id), ivec2(pixel_i.xy), vec4(col, 1)); 69 | } 70 | -------------------------------------------------------------------------------- /tests/3_samples/1_mandelbrot/shaders/compute.slang: -------------------------------------------------------------------------------- 1 | #include "daxa/daxa.inl" 2 | #include "shared.inl" 3 | import "custom file!!"; 4 | 5 | [[vk::push_constant]] ComputePush p; 6 | 7 | struct Test 8 | { 9 | GpuInput* value; 10 | }; 11 | 12 | #define CENTER float2(-0.694008, -0.324998) 13 | #define SUBSAMPLES 2 14 | 15 | float3 hsv2rgb(float3 c) 16 | { 17 | float4 k = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); 18 | float3 p = abs(frac(c.xxx + k.xyz) * 6.0 - k.www); 19 | return c.z * lerp(k.xxx, clamp(p - k.xxx, 0.0, 1.0), c.y); 20 | } 21 | 22 | float test(float t) 23 | { 24 | return t + 1; 25 | } 26 | 27 | float3 mandelbrot_colored(float2 pixel_p) 28 | { 29 | float2 uv = pixel_p / float2(p.frame_dim.xy); 30 | uv = (uv - 0.5) * float2(float(p.frame_dim.x) / float(p.frame_dim.y), 1); 31 | GpuInput gpu_input = *p.ptr; 32 | test(p.ptr->time); 33 | float time = gpu_input.time; 34 | float scale = 12.0 / (exp(time) + 0.0001); 35 | float2 z = uv * scale * 2 + CENTER; 36 | float2 c = z; 37 | uint i = 0; 38 | for (; i < 512; ++i) 39 | { 40 | float2 z_ = z; 41 | z.x = z_.x * z_.x - z_.y * z_.y; 42 | z.y = 2.0 * z_.x * z_.y; 43 | z += c; 44 | if (dot(z, z) > 256 * 256) 45 | break; 46 | } 47 | float3 col = 0; 48 | if (i != 512) 49 | { 50 | float l = i; 51 | float sl = l - log2(log2(dot(z, z))) + 4.0; 52 | sl = pow(sl * 0.01, 1.0); 53 | col = hsv2rgb(float3(sl, 1, 1)); 54 | if (MY_TOGGLE) { 55 | col = 1 - col; 56 | } 57 | } 58 | return col; 59 | } 60 | 61 | [shader("compute")] 62 | [numthreads(8, 8, 1)] 63 | void entry_mandelbrot(uint3 pixel_i : SV_DispatchThreadID) 64 | { 65 | if (pixel_i.x >= p.frame_dim.x || pixel_i.y >= p.frame_dim.y) 66 | return; 67 | 68 | float3 col = 0; 69 | for (int yi = 0; yi < SUBSAMPLES; ++yi) 70 | { 71 | for (int xi = 0; xi < SUBSAMPLES; ++xi) 72 | { 73 | float2 offset = float2(xi, yi) / float(SUBSAMPLES); 74 | col += mandelbrot_colored(float2(pixel_i.xy) + offset); 75 | } 76 | } 77 | col *= 1.0 / float(SUBSAMPLES * SUBSAMPLES); 78 | 79 | p.image_id.get()[pixel_i.xy] = float4(col, 1); 80 | } -------------------------------------------------------------------------------- /tests/3_samples/1_mandelbrot/shaders/shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "daxa/daxa.inl" 4 | 5 | struct GpuInput 6 | { 7 | daxa_f32 time; 8 | daxa_f32 delta_time; 9 | }; 10 | DAXA_DECL_BUFFER_PTR(GpuInput) 11 | 12 | struct ComputePush 13 | { 14 | #if DAXA_LANGUAGE == DAXA_LANGUAGE_GLSL 15 | daxa_ImageViewId image_id; 16 | daxa_BufferId input_buffer_id; 17 | daxa_BufferPtr(GpuInput) ptr; 18 | daxa_u32vec2 frame_dim; 19 | #else 20 | daxa::RWTexture2DId image_id; 21 | daxa::BufferId input_buffer_id; 22 | daxa_BufferPtr(GpuInput) ptr; 23 | daxa_u32vec2 frame_dim; 24 | #endif 25 | }; 26 | -------------------------------------------------------------------------------- /tests/3_samples/2_mpm_mls/shaders/raytracing.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct hitPayload 4 | { 5 | daxa_f32vec3 hit_value; 6 | daxa_u32 seed; 7 | daxa_f32vec3 hit_pos; 8 | }; 9 | 10 | #if DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_RAYGEN 11 | 12 | layout(location = 0) rayPayloadEXT hitPayload prd; 13 | void main() 14 | { 15 | daxa_BufferPtr(GpuInput) config = daxa_BufferPtr(GpuInput)(daxa_id_to_address(p.input_buffer_id)); 16 | 17 | daxa_BufferPtr(GpuStatus) status = daxa_BufferPtr(GpuStatus)(daxa_id_to_address(p.status_buffer_id)); 18 | 19 | prd.hit_value = daxa_f32vec3(0.0); 20 | prd.seed = 0; 21 | prd.hit_pos = daxa_f32vec3(MAX_DIST); 22 | 23 | const daxa_u32 cull_mask = 0xff; 24 | const daxa_u32 ray_flags = gl_RayFlagsNoneEXT; 25 | 26 | const daxa_i32vec2 rt_size = daxa_i32vec2(gl_LaunchSizeEXT.xy); 27 | 28 | // Camera setup 29 | daxa_f32mat4x4 inv_view = deref(p.camera).inv_view; 30 | daxa_f32mat4x4 inv_proj = deref(p.camera).inv_proj; 31 | 32 | Ray ray = 33 | get_ray_from_current_pixel(daxa_f32vec2(gl_LaunchIDEXT.xy), daxa_f32vec2(rt_size), inv_view, inv_proj); 34 | 35 | traceRayEXT( 36 | daxa_accelerationStructureEXT(p.tlas), // topLevelAccelerationStructure 37 | ray_flags, // rayFlags 38 | cull_mask, // cullMask 39 | 0, // sbtRecordOffset 40 | 0, // sbtRecordStride 41 | 0, // missIndex 42 | ray.origin.xyz, // ray origin 43 | MIN_DIST, // ray min range 44 | ray.direction.xyz, // ray direction 45 | MAX_DIST, // ray max range 46 | 0 // payload (location = 0) 47 | ); 48 | 49 | daxa_f32vec3 color = prd.hit_value; 50 | 51 | imageStore(daxa_image2D(p.image_id), daxa_i32vec2(gl_LaunchIDEXT.xy), vec4(color, 1.0)); 52 | 53 | if ((deref(status).flags & MOUSE_DOWN_FLAG) == MOUSE_DOWN_FLAG) { 54 | if (gl_LaunchIDEXT.x == uint(deref(config).mouse_pos.x) && gl_LaunchIDEXT.y == uint(deref(config).mouse_pos.y)) 55 | { 56 | if (prd.hit_pos != daxa_f32vec3(MAX_DIST)) 57 | { 58 | deref(status).flags |= MOUSE_TARGET_FLAG; 59 | deref(status).mouse_target = prd.hit_pos; 60 | } 61 | } 62 | } 63 | else { 64 | deref(status).flags &= ~MOUSE_TARGET_FLAG; 65 | } 66 | 67 | } 68 | #elif DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_CLOSEST_HIT 69 | 70 | layout(location = 0) rayPayloadInEXT hitPayload prd; 71 | layout(location = 1) rayPayloadEXT bool is_shadowed; 72 | 73 | vec3 light_position = vec3(3, 5, -1); 74 | vec3 light_intensity = vec3(2.5); 75 | 76 | void main() 77 | { 78 | vec3 world_pos = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT; 79 | 80 | prd.hit_pos = world_pos; 81 | 82 | uint i = gl_PrimitiveID + gl_GeometryIndexEXT + gl_InstanceCustomIndexEXT; 83 | 84 | Aabb aabb = get_aabb_by_index(i); 85 | Particle particle = get_particle_by_index(i); 86 | 87 | vec3 center = (aabb.min + aabb.max) * 0.5; 88 | 89 | // Computing the normal at hit position 90 | vec3 normal = normalize(world_pos - center); 91 | 92 | #if defined(VOXEL_PARTICLES) 93 | vec3 absN = abs(normal); 94 | float maxC = max(max(absN.x, absN.y), absN.z); 95 | normal = (maxC == absN.x) ? 96 | vec3(sign(normal.x), 0, 0) : 97 | (maxC == absN.y) ? vec3(0, sign(normal.y), 0) : vec3(0, 0, sign(normal.z)); 98 | #endif 99 | 100 | // Vector toward the light 101 | vec3 L = normalize(light_position - vec3(0)); 102 | 103 | // Diffuse 104 | float dotNL = max(dot(normal, L), 0.0); 105 | float gradient = max( 1.0 / length(particle.v), 1.0); 106 | vec3 sphere_color = vec3(1.0); 107 | if(particle.type == MAT_WATER) 108 | sphere_color = mix(vec3(0.9, 0.9, 1), vec3(0.3, 0.8, 1), gradient); 109 | else if(particle.type == MAT_JELLY) 110 | sphere_color = mix(vec3(1, 0.6, 0.6), vec3(1, 0.4, 0.4), gradient); 111 | 112 | vec3 diffuse = dotNL * sphere_color; 113 | vec3 specular = vec3(0); 114 | float attenuation = 0.3; 115 | 116 | // Tracing shadow ray only if the light is visible from the surface 117 | if (dot(normal, L) > 0) 118 | { 119 | vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT; 120 | vec3 ray_dir = L; 121 | const uint ray_flags = 122 | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT; 123 | const daxa_u32 cull_mask = 0xff; 124 | is_shadowed = true; 125 | 126 | traceRayEXT( 127 | daxa_accelerationStructureEXT(p.tlas), // topLevelAccelerationStructure 128 | ray_flags, // rayFlags 129 | cull_mask, // cullMask 130 | 0, // sbtRecordOffset 131 | 0, // sbtRecordStride 132 | 1, // missIndex 133 | origin, // ray origin 134 | MIN_DIST, // ray min range 135 | ray_dir, // ray direction 136 | MAX_DIST, // ray max range 137 | 1 // payload (location = 0) 138 | ); 139 | 140 | if (is_shadowed) 141 | { 142 | attenuation = 0.5; 143 | } 144 | else 145 | { 146 | attenuation = 1; 147 | // Specular 148 | // specular = computeSpecular(mat, gl_WorldRayDirectionNV, L, normal); 149 | } 150 | } 151 | 152 | prd.hit_value = vec3(light_intensity * attenuation * (diffuse + specular)); 153 | } 154 | 155 | #elif DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_MISS 156 | 157 | #if DAXA_SHADOW_RAY_FLAG == 1 158 | 159 | layout(location = 1) rayPayloadInEXT bool is_shadowed; 160 | void main() 161 | { 162 | is_shadowed = false; 163 | } 164 | 165 | #else 166 | 167 | layout(location = 0) rayPayloadInEXT hitPayload prd; 168 | 169 | void main() 170 | { 171 | prd.hit_value = vec3(0.0, 0.0, 0.05); // Background color 172 | } 173 | 174 | #endif // DAXA_SHADOW_RAY_FLAG 175 | 176 | #elif DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_INTERSECTION 177 | 178 | void main() 179 | { 180 | 181 | Ray ray; 182 | ray.origin = gl_ObjectRayOriginEXT; 183 | ray.direction = gl_ObjectRayDirectionEXT; 184 | 185 | mat4 inv_model = mat4( 186 | gl_ObjectToWorld3x4EXT[0][0], gl_ObjectToWorld3x4EXT[0][1], gl_ObjectToWorld3x4EXT[0][2], gl_ObjectToWorld3x4EXT[0][3], 187 | gl_ObjectToWorld3x4EXT[0][1], gl_ObjectToWorld3x4EXT[1][1], gl_ObjectToWorld3x4EXT[1][2], gl_ObjectToWorld3x4EXT[1][3], 188 | gl_ObjectToWorld3x4EXT[2][0], gl_ObjectToWorld3x4EXT[2][1], gl_ObjectToWorld3x4EXT[2][2], gl_ObjectToWorld3x4EXT[2][3], 189 | 0, 0, 0, 1.0); 190 | 191 | ray.origin = (inv_model * vec4(ray.origin, 1)).xyz; 192 | ray.direction = (inv_model * vec4(ray.direction, 0)).xyz; 193 | 194 | float tHit = -1; 195 | 196 | uint i = gl_PrimitiveID + gl_GeometryIndexEXT + gl_InstanceCustomIndexEXT; 197 | 198 | Aabb aabb = get_aabb_by_index(i); 199 | 200 | #if defined(VOXEL_PARTICLES) 201 | tHit = hitAabb(aabb, ray); 202 | #else 203 | vec3 center = (aabb.min + aabb.max) * 0.5; 204 | // radius inside the AABB 205 | float radius = (aabb.max.x - aabb.min.x) * 0.5 * 0.9; 206 | 207 | tHit = hitSphere(center, radius, ray); 208 | #endif 209 | 210 | // Report hit point 211 | if (tHit > 0) 212 | reportIntersectionEXT(tHit, 0); // 0 is the hit kind (hit group index) 213 | } 214 | 215 | #else 216 | 217 | void main() {} 218 | 219 | #endif -------------------------------------------------------------------------------- /tests/3_samples/2_mpm_mls/shaders/raytracing.slang: -------------------------------------------------------------------------------- 1 | #include "shared.inl" 2 | 3 | struct RayPayload 4 | { 5 | float4 color; 6 | }; 7 | 8 | struct MyAttributes 9 | { 10 | float3 normal; 11 | float3 position; 12 | }; 13 | 14 | [shader("raygeneration")] 15 | void rayGenShader() 16 | { 17 | } 18 | 19 | [shader("miss")] 20 | void missShader(inout RayPayload payload) 21 | { 22 | payload.color = float4(0.5, 0.3, 0.1, 1); 23 | } 24 | 25 | [shader("closesthit")] 26 | void closestHitShader(inout RayPayload payload, 27 | in MyAttributes attr) 28 | { 29 | payload.color = float4(0.3, 0.8, 1, 1.0); 30 | } 31 | 32 | [shader("intersection")] 33 | void intersectionShader() 34 | { 35 | float THit = RayTCurrent(); 36 | } -------------------------------------------------------------------------------- /tests/3_samples/3_hello_triangle_compute/main.cpp: -------------------------------------------------------------------------------- 1 | #define SAMPLE_SHADER_LANGUAGE DAXA_LANGUAGE_GLSL 2 | 3 | #define APPNAME "Daxa Sample: HelloTriangle Compute" 4 | #include <0_common/base_app.hpp> 5 | 6 | using namespace daxa::types; 7 | #include "shaders/shared.inl" 8 | 9 | struct App : BaseApp 10 | { 11 | // clang-format off 12 | std::shared_ptr compute_pipeline = pipeline_manager.add_compute_pipeline2({ 13 | #if SAMPLE_SHADER_LANGUAGE == DAXA_LANGUAGE_GLSL 14 | .source = daxa::ShaderFile{"compute.glsl"}, 15 | #elif SAMPLE_SHADER_LANGUAGE == DAXA_LANGUAGE_SLANG 16 | .source = daxa::ShaderFile{"compute.hlsl"}, 17 | #endif 18 | .name = "compute_pipeline", 19 | }).value(); 20 | // clang-format on 21 | 22 | daxa::ImageId render_image = device.create_image(daxa::ImageInfo{ 23 | .format = daxa::Format::R8G8B8A8_UNORM, 24 | .size = {size_x, size_y, 1}, 25 | .usage = daxa::ImageUsageFlagBits::SHADER_STORAGE | daxa::ImageUsageFlagBits::TRANSFER_SRC, 26 | .name = "render_image", 27 | }); 28 | daxa::TaskImage task_render_image{{.initial_images = {.images = std::array{render_image}}, .name = "task_render_image"}}; 29 | 30 | daxa::TaskGraph loop_task_graph = record_loop_task_graph(); 31 | 32 | ~App() 33 | { 34 | device.wait_idle(); 35 | device.collect_garbage(); 36 | device.destroy_image(render_image); 37 | } 38 | 39 | static void ui_update() 40 | { 41 | ImGui_ImplGlfw_NewFrame(); 42 | ImGui::NewFrame(); 43 | ImGui::Render(); 44 | } 45 | void on_update() 46 | { 47 | auto reloaded_result = pipeline_manager.reload_all(); 48 | if (auto reload_err = daxa::get_if(&reloaded_result)) 49 | std::cout << "Failed to reload " << reload_err->message << '\n'; 50 | if (daxa::get_if(&reloaded_result)) 51 | std::cout << "Successfully reloaded!\n"; 52 | ui_update(); 53 | 54 | auto swapchain_image = swapchain.acquire_next_image(); 55 | task_swapchain_image.set_images({.images = std::array{swapchain_image}}); 56 | if (swapchain_image.is_empty()) 57 | { 58 | return; 59 | } 60 | loop_task_graph.execute({}); 61 | device.collect_garbage(); 62 | } 63 | 64 | void on_mouse_move(f32 /*unused*/, f32 /*unused*/) {} 65 | void on_mouse_button(i32 /*unused*/, i32 /*unused*/) {} 66 | void on_key(i32 /*unused*/, i32 /*unused*/) {} 67 | void on_resize(u32 sx, u32 sy) 68 | { 69 | minimized = (sx == 0 || sy == 0); 70 | if (!minimized) 71 | { 72 | swapchain.resize(); 73 | size_x = swapchain.get_surface_extent().x; 74 | size_y = swapchain.get_surface_extent().y; 75 | device.destroy_image(render_image); 76 | render_image = device.create_image({ 77 | .format = daxa::Format::R8G8B8A8_UNORM, 78 | .size = {size_x, size_y, 1}, 79 | .usage = daxa::ImageUsageFlagBits::SHADER_STORAGE | daxa::ImageUsageFlagBits::TRANSFER_SRC, 80 | }); 81 | task_render_image.set_images({.images = std::array{render_image}}); 82 | base_on_update(); 83 | } 84 | } 85 | 86 | void record_tasks(daxa::TaskGraph & new_task_graph) 87 | { 88 | new_task_graph.use_persistent_image(task_render_image); 89 | 90 | new_task_graph.add_task({ 91 | .attachments = {daxa::inl_attachment(daxa::TaskImageAccess::COMPUTE_SHADER_STORAGE_WRITE_ONLY, task_render_image)}, 92 | .task = [this](daxa::TaskInterface ti) 93 | { 94 | ti.recorder.set_pipeline(*compute_pipeline); 95 | ti.recorder.push_constant(ComputePush{ 96 | .image = render_image.default_view(), 97 | .frame_dim = {size_x, size_y}, 98 | }); 99 | ti.recorder.dispatch({(size_x + 7) / 8, (size_y + 7) / 8}); 100 | }, 101 | .name = APPNAME_PREFIX("Draw (Compute)"), 102 | }); 103 | new_task_graph.add_task({ 104 | .attachments = { 105 | {daxa::inl_attachment(daxa::TaskImageAccess::TRANSFER_READ, task_render_image)}, 106 | {daxa::inl_attachment(daxa::TaskImageAccess::TRANSFER_WRITE, task_swapchain_image)}, 107 | }, 108 | .task = [this](daxa::TaskInterface ti) 109 | { 110 | ti.recorder.blit_image_to_image({ 111 | .src_image = ti.get(task_render_image).ids[0], 112 | .src_image_layout = daxa::ImageLayout::TRANSFER_SRC_OPTIMAL, 113 | .dst_image = ti.get(task_swapchain_image).ids[0], 114 | .dst_image_layout = daxa::ImageLayout::TRANSFER_DST_OPTIMAL, 115 | .src_offsets = {{{0, 0, 0}, {static_cast(size_x), static_cast(size_y), 1}}}, 116 | .dst_offsets = {{{0, 0, 0}, {static_cast(size_x), static_cast(size_y), 1}}}, 117 | }); 118 | }, 119 | .name = APPNAME_PREFIX("Blit (render to swapchain)"), 120 | }); 121 | } 122 | }; 123 | 124 | auto main() -> int 125 | { 126 | App app = {}; 127 | while (true) 128 | { 129 | if (app.update()) 130 | { 131 | break; 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /tests/3_samples/3_hello_triangle_compute/shaders/compute.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DAXA_DECL_PUSH_CONSTANT(ComputePush, push) 4 | 5 | layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; 6 | void main() 7 | { 8 | uvec3 pixel_i = gl_GlobalInvocationID.xyz; 9 | if (pixel_i.x >= push.frame_dim.x || pixel_i.y >= push.frame_dim.y) 10 | return; 11 | 12 | vec2 uv = vec2(pixel_i.xy) / vec2(push.frame_dim.xy); 13 | uv = (uv - 0.5) * vec2(float(push.frame_dim.x) / float(push.frame_dim.y), 1); 14 | uv = uv * 2; 15 | 16 | vec3 col = vec3(0, 0, 0); 17 | 18 | vec2 points[3] = { 19 | vec2(-0.5, +0.5), 20 | vec2(+0.5, +0.5), 21 | vec2(+0.0, -0.5), 22 | }; 23 | 24 | vec3 point_colors[3] = { 25 | vec3(1, 0, 0), 26 | vec3(0, 1, 0), 27 | vec3(0, 0, 1), 28 | }; 29 | 30 | vec2 points_del[3] = { 31 | points[1] - points[0], 32 | points[2] - points[1], 33 | points[0] - points[2], 34 | }; 35 | 36 | float slopes[3] = { 37 | points_del[0].y / points_del[0].x, 38 | points_del[1].y / points_del[1].x, 39 | points_del[2].y / points_del[2].x, 40 | }; 41 | 42 | if (slopes[0] * (uv.x - points[0].x) > (uv.y - points[0].y) && 43 | slopes[1] * (uv.x - points[1].x) < (uv.y - points[1].y) && 44 | slopes[2] * (uv.x - points[2].x) < (uv.y - points[2].y)) 45 | { 46 | float p0 = clamp(dot(points_del[0], uv - points[0]) / dot(points_del[0], points_del[0]), 0, 1); 47 | float p1 = clamp(dot(points_del[1], uv - points[1]) / dot(points_del[1], points_del[1]), 0, 1); 48 | float p2 = clamp(dot(points_del[2], uv - points[2]) / dot(points_del[2], points_del[2]), 0, 1); 49 | 50 | col = mix(col, point_colors[0], vec3(1)); 51 | col = mix(col, point_colors[1], p0); 52 | col = mix(col, point_colors[2], clamp((p1 - p2 + 0.5) / 1.5, 0, 1)); 53 | } 54 | 55 | imageStore(daxa_image2D(push.image), ivec2(pixel_i.xy), vec4(col, 1)); 56 | } 57 | -------------------------------------------------------------------------------- /tests/3_samples/3_hello_triangle_compute/shaders/compute.hlsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | [[vk::push_constant]] const ComputePush p; 4 | 5 | // clang-format off 6 | [numthreads(8, 8, 1)] 7 | void main(uint3 pixel_i : SV_DispatchThreadID) 8 | // clang-format on 9 | { 10 | RWTexture2D render_image = RWTexture2D.get(p.image); 11 | if (pixel_i.x >= p.frame_dim.x || pixel_i.y >= p.frame_dim.y) 12 | return; 13 | 14 | float2 uv = float2(pixel_i.xy) / float2(p.frame_dim.xy); 15 | uv = (uv - 0.5) * float2(float(p.frame_dim.x) / float(p.frame_dim.y), 1); 16 | uv = uv * 2; 17 | 18 | float3 col = float3(0, 0, 0); 19 | 20 | float2 points[3] = { 21 | float2(-0.5, +0.5), 22 | float2(+0.5, +0.5), 23 | float2(+0.0, -0.5), 24 | }; 25 | 26 | float3 point_colors[3] = { 27 | float3(1, 0, 0), 28 | float3(0, 1, 0), 29 | float3(0, 0, 1), 30 | }; 31 | 32 | float2 points_del[3] = { 33 | points[1] - points[0], 34 | points[2] - points[1], 35 | points[0] - points[2], 36 | }; 37 | 38 | float slopes[3] = { 39 | points_del[0].y / points_del[0].x, 40 | points_del[1].y / points_del[1].x, 41 | points_del[2].y / points_del[2].x, 42 | }; 43 | 44 | if (slopes[0] * (uv.x - points[0].x) > (uv.y - points[0].y) && 45 | slopes[1] * (uv.x - points[1].x) < (uv.y - points[1].y) && 46 | slopes[2] * (uv.x - points[2].x) < (uv.y - points[2].y)) 47 | { 48 | float p0 = clamp(dot(points_del[0], uv - points[0]) / dot(points_del[0], points_del[0]), 0, 1); 49 | float p1 = clamp(dot(points_del[1], uv - points[1]) / dot(points_del[1], points_del[1]), 0, 1); 50 | float p2 = clamp(dot(points_del[2], uv - points[2]) / dot(points_del[2], points_del[2]), 0, 1); 51 | 52 | col = lerp(col, point_colors[0], 1); 53 | col = lerp(col, point_colors[1], p0); 54 | col = lerp(col, point_colors[2], clamp((p1 - p2 + 0.5) / 1.5, 0, 1)); 55 | } 56 | 57 | render_image[pixel_i.xy] = float4(col, 1.0); 58 | } 59 | -------------------------------------------------------------------------------- /tests/3_samples/3_hello_triangle_compute/shaders/shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct ComputePush 6 | { 7 | daxa_ImageViewId image; 8 | daxa_u32vec2 frame_dim; 9 | }; 10 | -------------------------------------------------------------------------------- /tests/3_samples/5_boids/shaders/frag.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DAXA_DECL_PUSH_CONSTANT(DrawPushConstant, push) 4 | 5 | layout(location = 0) out vec4 color; 6 | 7 | void main() 8 | { 9 | color = vec4(0.0f, 0.0f, 0.0f, 1.0f); 10 | } 11 | -------------------------------------------------------------------------------- /tests/3_samples/5_boids/shaders/update_boids.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DAXA_DECL_PUSH_CONSTANT(UpdateBoidsPushConstant, push) 4 | 5 | // Based in pseudo code from: https://people.ece.cornell.edu/land/courses/ece4760/labs/s2021/Boids/Boids.html 6 | void update_boid(inout Boid boid, in const Boid old_boid, in uint boid_index, daxa_BufferPtr(Boids) old_boids_buffer) 7 | { 8 | boid = old_boid; 9 | 10 | vec2 vis_other_pos_average = vec2(0, 0); 11 | vec2 vis_other_vel_average = vec2(0, 0); 12 | float vis_other_count = 0; 13 | vec2 vis_other_super_close_delta = vec2(0, 0); 14 | for (uint other_i = 0; other_i < MAX_BOIDS; ++other_i) 15 | { 16 | if (other_i == boid_index) 17 | { 18 | continue; 19 | } 20 | Boid other = deref(old_boids_buffer).boids[other_i]; 21 | const vec2 pos_delta = boid.position - other.position; 22 | const float squared_distance = dot(pos_delta, pos_delta); 23 | if (squared_distance < BOID_PROTECTED_RANGE_SQUARED) 24 | { 25 | vis_other_super_close_delta += boid.position - other.position; 26 | } 27 | else if (squared_distance < BOID_VIEW_RANGE_SQUARED) 28 | { 29 | vis_other_pos_average += other.position; 30 | vis_other_vel_average += other.speed; 31 | vis_other_count += 1; 32 | } 33 | } 34 | if (vis_other_count > 0.0f) 35 | { 36 | vis_other_pos_average /= vis_other_count; 37 | vis_other_vel_average /= vis_other_count; 38 | boid.speed = boid.speed + (vis_other_pos_average - boid.position) * BOID_COHERENCE + (vis_other_vel_average - boid.speed) * BOID_ALIGNMENT; 39 | } 40 | boid.speed += BOID_SEPERATION * vis_other_super_close_delta; 41 | if (boid.position.x > FIELD_SIZE) 42 | { 43 | boid.speed.x -= BOID_WALL_REPULSION; 44 | } 45 | if (boid.position.x < 0) 46 | { 47 | boid.speed.x += BOID_WALL_REPULSION; 48 | } 49 | if (boid.position.y > FIELD_SIZE) 50 | { 51 | boid.speed.y -= BOID_WALL_REPULSION; 52 | } 53 | if (boid.position.y < 0) 54 | { 55 | boid.speed.y += BOID_WALL_REPULSION; 56 | } 57 | const float speed = max(0.01, length(boid.speed)); 58 | if (speed < BOID_MIN_SPEED) 59 | { 60 | boid.speed = boid.speed / speed * BOID_MIN_SPEED; 61 | } 62 | if (speed > BOID_MAX_SPEED) 63 | { 64 | boid.speed = boid.speed / speed * BOID_MAX_SPEED; 65 | } 66 | boid.position = boid.position + boid.speed * DELTA_TIME; 67 | } 68 | 69 | layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; 70 | void main() 71 | { 72 | uint invocation = gl_GlobalInvocationID.x; 73 | if (invocation >= MAX_BOIDS) 74 | { 75 | return; 76 | } 77 | update_boid( 78 | deref(push.boids_buffer).boids[invocation], 79 | deref(push.old_boids_buffer).boids[invocation], 80 | invocation, 81 | push.old_boids_buffer); 82 | } -------------------------------------------------------------------------------- /tests/3_samples/5_boids/shaders/vert.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DAXA_DECL_PUSH_CONSTANT(DrawPushConstant, push) 4 | 5 | void main() 6 | { 7 | uint boid_index = gl_VertexIndex / 3; 8 | 9 | if (boid_index >= MAX_BOIDS) 10 | { 11 | gl_Position = vec4(-1.0f, -1.0f, -1.0f, 1.0f); 12 | return; 13 | } 14 | 15 | vec2 corner_position; 16 | switch (gl_VertexIndex % 3) 17 | { 18 | case 0: corner_position = vec2(-1.0f, -1.0f); break; 19 | case 1: corner_position = vec2(1.0f, -1.0f); break; 20 | case 2: corner_position = vec2(0.0f, 1.0f); break; 21 | } 22 | 23 | vec2 direction = normalize(deref(push.boids_buffer).boids[boid_index].speed); 24 | direction = vec2(-direction.y, direction.x); 25 | direction = vec2(-direction.y, direction.x); 26 | direction = vec2(-direction.y, direction.x); 27 | 28 | corner_position = vec2( 29 | dot(corner_position, vec2(direction.x, -direction.y)), 30 | dot(corner_position, vec2(direction.y, direction.x))); 31 | 32 | corner_position *= BOID_SCALE; 33 | corner_position += deref(push.boids_buffer).boids[boid_index].position; 34 | corner_position *= 2.0f / (FIELD_SIZE); 35 | corner_position -= vec2(1.0f); 36 | corner_position *= push.axis_scaling; 37 | 38 | gl_Position = vec4(corner_position, 0.0f, 1.0f); 39 | } -------------------------------------------------------------------------------- /tests/3_samples/5_boids/shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define PI 3.14f 6 | 7 | #define DELTA_TIME 0.01 8 | 9 | #define MAX_BOIDS 10000 10 | #define FIELD_SIZE 100 11 | #define BOID_SCALE 0.25f 12 | #define BOID_VIEW_RANGE 0.9f 13 | #define BOID_VIEW_RANGE_SQUARED BOID_VIEW_RANGE*BOID_VIEW_RANGE 14 | #define BOID_PROTECTED_RANGE 0.5f 15 | #define BOID_PROTECTED_RANGE_SQUARED BOID_PROTECTED_RANGE*BOID_PROTECTED_RANGE 16 | #define BOID_MIN_SPEED 10.f 17 | #define BOID_MAX_SPEED 40.f 18 | 19 | #define BOID_COHERENCE 1.00f 20 | #define BOID_SEPERATION 20.00f 21 | #define BOID_ALIGNMENT 1.00f 22 | #define BOID_WALL_REPULSION 1.0f 23 | 24 | struct Boid 25 | { 26 | daxa_f32vec2 position; 27 | daxa_f32vec2 speed; 28 | }; 29 | 30 | struct Boids 31 | { 32 | Boid boids[MAX_BOIDS]; 33 | }; 34 | DAXA_DECL_BUFFER_PTR(Boids) 35 | 36 | struct GpuOutput 37 | { 38 | daxa_f32 data; 39 | }; 40 | DAXA_DECL_BUFFER_PTR(GpuOutput) 41 | 42 | struct DrawPushConstant 43 | { 44 | daxa_BufferPtr(Boids) boids_buffer; 45 | daxa_f32vec2 axis_scaling; 46 | }; 47 | 48 | struct UpdateBoidsPushConstant 49 | { 50 | daxa_RWBufferPtr(Boids) boids_buffer; 51 | daxa_BufferPtr(Boids) old_boids_buffer; 52 | }; 53 | -------------------------------------------------------------------------------- /tests/4_hello_daxa/0_c_api/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void handle_daxa_result(daxa_Result res) 6 | { 7 | if (res != DAXA_RESULT_SUCCESS) 8 | { 9 | printf("DAXA ERROR: %d\n", (int)res); 10 | exit(-1); 11 | } 12 | } 13 | 14 | int main(void) 15 | { 16 | daxa_Instance instance = {0}; 17 | daxa_InstanceInfo instance_info = DAXA_DEFAULT_INSTANCE_INFO; 18 | handle_daxa_result(daxa_create_instance(&instance_info, &instance)); 19 | 20 | daxa_Device device = {0}; 21 | daxa_DeviceInfo2 device_info = DAXA_DEFAULT_DEVICE_INFO_2; 22 | 23 | // Manual Selection: 24 | // daxa_DeviceProperties const* devices = {0}; 25 | // daxa_u32 device_count = {0}; 26 | // daxa_instance_list_devices_properties(instance, &devices, &device_count); 27 | 28 | // daxa_u32 choosen_device_index = ~0u; 29 | // for (daxa_u32 i = 0; i < device_count; ++i) 30 | // { 31 | // daxa_DeviceProperties const * device_properties = devices + i; 32 | // daxa_Bool8 const suitable = 33 | // device_properties->problems == DAXA_MISSING_REQUIRED_VK_FEATURE_NONE && 34 | // device_properties->mesh_shader_properties.has_value; 35 | // if (suitable) 36 | // {` 37 | // choosen_device_index = i; 38 | // break; 39 | // } 40 | // } 41 | // if (choosen_device_index == ~0u) 42 | // { 43 | // printf("found no supported device\n"); 44 | // exit(-1); 45 | // } 46 | // else 47 | // { 48 | // printf("choose device with name \"%s\".\n", devices[choosen_device_index].device_name); 49 | // } 50 | // device_info.physical_device_index = choosen_device_index; 51 | 52 | // Automatic Selection: 53 | handle_daxa_result(daxa_instance_choose_device(instance, DAXA_IMPLICIT_FEATURE_FLAG_NONE, &device_info)); 54 | 55 | handle_daxa_result(daxa_instance_create_device_2(instance, &device_info, &device)); 56 | 57 | daxa_dvc_dec_refcnt(device); 58 | daxa_instance_dec_refcnt(instance); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /tests/4_hello_daxa/2_triangle/main.glsl: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | DAXA_DECL_PUSH_CONSTANT(MyPushConstant, push) 6 | 7 | #if DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_VERTEX 8 | 9 | layout(location = 0) out daxa_f32vec3 v_col; 10 | void main() 11 | { 12 | // The attachment shader blob contains the declared represented type for each attachment. 13 | // In the case of the vertices its a daxa_BufferPtr(MyVertex): 14 | daxa_BufferPtr(MyVertex) vertices_ptr = push.attachments.vertices; 15 | // Daxa provides convenience functions to deref the i'th element for each buffer ptr: 16 | MyVertex vert = deref_i(push.attachments.vertices, gl_VertexIndex); 17 | gl_Position = daxa_f32vec4(vert.position, 1); 18 | v_col = vert.color; 19 | } 20 | 21 | #elif DAXA_SHADER_STAGE == DAXA_SHADER_STAGE_FRAGMENT 22 | 23 | layout(location = 0) in daxa_f32vec3 v_col; 24 | layout(location = 0) out daxa_f32vec4 color; 25 | void main() 26 | { 27 | color = daxa_f32vec4(v_col, 1); 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /tests/4_hello_daxa/2_triangle/shared.inl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Includes the Daxa API to the shader 4 | #include 5 | #include 6 | 7 | struct MyVertex 8 | { 9 | daxa_f32vec3 position; 10 | daxa_f32vec3 color; 11 | }; 12 | 13 | // Allows the shader to use pointers to MyVertex 14 | DAXA_DECL_BUFFER_PTR(MyVertex) 15 | 16 | 17 | // First argument is the heads name. Its convention to end the name with a capital H 18 | // The secon argument is the number of attachments. 19 | DAXA_DECL_TASK_HEAD_BEGIN(DrawToSwapchainH) 20 | // The following line declares an image attachment. 21 | // The task image use is COLOR_ATTACHMENT, the required image view type is REGULAR_2D and the name is color_target. 22 | // Note that this attachment has no suffix _ID or _INDEX. This means its NOT in the shader struct! 23 | // This is useful to not pollute the struct with resources that cant be used in shaders like color attachments. 24 | DAXA_TH_IMAGE(COLOR_ATTACHMENT, REGULAR_2D, color_target) 25 | // The following line declares a buffer attachment. 26 | // The task buffer use is VERTEX_SHADER_READ, the shader pointer type is daxa_BufferPtr(MyVertex) and the name is vertices. 27 | DAXA_TH_BUFFER_PTR(VERTEX_SHADER_READ, daxa_BufferPtr(MyVertex), vertices) 28 | DAXA_DECL_TASK_HEAD_END 29 | 30 | struct MyPushConstant 31 | { 32 | // This makro declares a struct of attachments in the shader and an aligned byte array in c++. 33 | DAXA_TH_BLOB(DrawToSwapchainH, attachments) 34 | }; 35 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | function(DAXA_CREATE_TEST) 3 | set(OPT_ARGS BRUH) 4 | set(SNG_ARGS BRUH2) 5 | set(MUL_ARGS FOLDER LIBS) 6 | cmake_parse_arguments(PARSE_ARGV 0 DCT "${OPT_ARGS}" "${SNG_ARGS}" "${MUL_ARGS}") 7 | 8 | list(JOIN DCT_FOLDER "_" FOLDER_NAME) 9 | list(JOIN DCT_FOLDER "/" FOLDER_PATH) 10 | 11 | add_executable( 12 | daxa_test_${FOLDER_NAME} 13 | "${FOLDER_PATH}/main.cpp" 14 | ) 15 | target_link_libraries(daxa_test_${FOLDER_NAME} PRIVATE daxa::daxa ${DCT_LIBS}) 16 | target_include_directories(daxa_test_${FOLDER_NAME} PRIVATE "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/0_common/shared") 17 | target_compile_definitions(daxa_test_${FOLDER_NAME} PRIVATE DAXA_SAMPLE_PATH="${CMAKE_CURRENT_LIST_DIR}/${FOLDER_PATH}") 18 | 19 | if(DAXA_TESTS_DISABLE_WINDOWS_CONSOLE) 20 | if(CMAKE_SYSTEM_NAME STREQUAL "Windows") 21 | target_link_options(daxa_test_${FOLDER_NAME} 22 | PRIVATE "-Wl,/ENTRY:mainCRTStartup,/SUBSYSTEM:WINDOWS" 23 | ) 24 | endif() 25 | endif() 26 | 27 | if(DAXA_ENABLE_UTILS_PIPELINE_MANAGER_SLANG) 28 | if(CMAKE_SYSTEM_NAME STREQUAL "Windows") 29 | # NOTE(grundlett): Really hacky. It appears there's no way to create plugin dll dependencies... 30 | # see https://gitlab.kitware.com/cmake/cmake/-/issues/22993 31 | find_program(SLANG_DLL slang.dll) 32 | find_program(SLANG_GLSLANG_DLL slang-glslang.dll) 33 | add_custom_command(TARGET daxa_test_${FOLDER_NAME} POST_BUILD 34 | COMMAND ${CMAKE_COMMAND} -E copy ${SLANG_DLL} $ 35 | COMMAND ${CMAKE_COMMAND} -E copy ${SLANG_GLSLANG_DLL} $ 36 | ) 37 | endif() 38 | endif() 39 | endfunction() 40 | 41 | function(DAXA_CREATE_TEST_C) 42 | if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 43 | # MSVC literally can't compile C properly. 44 | return() 45 | endif() 46 | 47 | set(OPT_ARGS BRUH) 48 | set(SNG_ARGS BRUH2) 49 | set(MUL_ARGS FOLDER LIBS) 50 | cmake_parse_arguments(PARSE_ARGV 0 DCT "${OPT_ARGS}" "${SNG_ARGS}" "${MUL_ARGS}") 51 | 52 | list(JOIN DCT_FOLDER "_" FOLDER_NAME) 53 | list(JOIN DCT_FOLDER "/" FOLDER_PATH) 54 | 55 | add_executable( 56 | daxa_test_c_${FOLDER_NAME} 57 | "${FOLDER_PATH}/main.c" 58 | ) 59 | target_link_libraries(daxa_test_c_${FOLDER_NAME} PRIVATE daxa::daxa ${DCT_LIBS}) 60 | target_include_directories(daxa_test_c_${FOLDER_NAME} PRIVATE "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/0_common/shared") 61 | target_compile_definitions(daxa_test_c_${FOLDER_NAME} PRIVATE DAXA_SAMPLE_PATH="${CMAKE_CURRENT_LIST_DIR}/${FOLDER_PATH}") 62 | 63 | if(DAXA_TESTS_DISABLE_WINDOWS_CONSOLE) 64 | if(CMAKE_SYSTEM_NAME STREQUAL "Windows") 65 | target_link_options(daxa_test_c_${FOLDER_NAME} 66 | PRIVATE "-Wl,/ENTRY:mainCRTStartup,/SUBSYSTEM:WINDOWS" 67 | ) 68 | endif() 69 | endif() 70 | endfunction() 71 | 72 | find_package(glfw3 CONFIG REQUIRED) 73 | 74 | DAXA_CREATE_TEST( 75 | FOLDER 1_setup 1_window 76 | LIBS glfw 77 | ) 78 | 79 | DAXA_CREATE_TEST( 80 | FOLDER 2_daxa_api 1_instance 81 | LIBS 82 | ) 83 | DAXA_CREATE_TEST( 84 | FOLDER 2_daxa_api 2_device 85 | LIBS 86 | ) 87 | DAXA_CREATE_TEST( 88 | FOLDER 2_daxa_api 3_command_recorder 89 | LIBS 90 | ) 91 | DAXA_CREATE_TEST( 92 | FOLDER 2_daxa_api 4_synchronization 93 | LIBS 94 | ) 95 | DAXA_CREATE_TEST( 96 | FOLDER 2_daxa_api 5_swapchain 97 | LIBS glfw 98 | ) 99 | DAXA_CREATE_TEST( 100 | FOLDER 2_daxa_api 6_task_graph 101 | LIBS glfw 102 | ) 103 | DAXA_CREATE_TEST( 104 | FOLDER 2_daxa_api 7_pipeline_manager 105 | LIBS 106 | ) 107 | DAXA_CREATE_TEST( 108 | FOLDER 2_daxa_api 8_mem 109 | LIBS glfw 110 | ) 111 | DAXA_CREATE_TEST( 112 | FOLDER 2_daxa_api 9_shader_integration 113 | LIBS glfw 114 | ) 115 | DAXA_CREATE_TEST( 116 | FOLDER 2_daxa_api 10_raytracing 117 | LIBS glfw 118 | ) 119 | DAXA_CREATE_TEST( 120 | FOLDER 2_daxa_api 11_mesh_shader 121 | LIBS glfw 122 | ) 123 | DAXA_CREATE_TEST( 124 | FOLDER 2_daxa_api 12_async_queues 125 | LIBS glfw 126 | ) 127 | 128 | DAXA_CREATE_TEST( 129 | FOLDER 3_samples 0_rectangle_cutting 130 | LIBS glfw 131 | ) 132 | DAXA_CREATE_TEST( 133 | FOLDER 3_samples 1_mandelbrot 134 | LIBS glfw 135 | ) 136 | # DAXA_CREATE_TEST( 137 | # FOLDER 3_samples 2_mpm_mls 138 | # LIBS glfw 139 | # ) 140 | DAXA_CREATE_TEST( 141 | FOLDER 3_samples 3_hello_triangle_compute 142 | LIBS glfw 143 | ) 144 | DAXA_CREATE_TEST( 145 | FOLDER 3_samples 5_boids 146 | LIBS glfw 147 | ) 148 | 149 | DAXA_CREATE_TEST( 150 | FOLDER 4_hello_daxa 1_pink_screen 151 | LIBS glfw 152 | ) 153 | 154 | DAXA_CREATE_TEST( 155 | FOLDER 4_hello_daxa 2_triangle 156 | LIBS glfw 157 | ) 158 | 159 | DAXA_CREATE_TEST_C( 160 | FOLDER 4_hello_daxa 0_c_api 161 | LIBS glfw 162 | ) 163 | -------------------------------------------------------------------------------- /vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "daxa", 3 | "version": "3.0.2", 4 | "description": "Daxa C++ Vulkan Abstraction", 5 | "homepage": "https://github.com/Ipotrick/Daxa", 6 | "dependencies": [ 7 | "vulkan-memory-allocator", 8 | "vulkan-headers", 9 | "vulkan", 10 | { 11 | "name": "wayland", 12 | "default-features": false, 13 | "platform": "linux" 14 | } 15 | ], 16 | "default-features": [ 17 | "utils-imgui", 18 | "utils-mem", 19 | "utils-pipeline-manager-glslang", 20 | "utils-task-graph" 21 | ], 22 | "features": { 23 | "utils-imgui": { 24 | "description": "The ImGUI Daxa utility", 25 | "dependencies": [ 26 | "imgui" 27 | ] 28 | }, 29 | "utils-fsr2": { 30 | "description": "The FSR2 Daxa utility", 31 | "dependencies": [ 32 | "fsr2" 33 | ] 34 | }, 35 | "utils-mem": { 36 | "description": "The Mem Daxa utility" 37 | }, 38 | "utils-pipeline-manager-glslang": { 39 | "description": "Build with glslang", 40 | "dependencies": [ 41 | "glslang" 42 | ] 43 | }, 44 | "utils-pipeline-manager-slang": { 45 | "description": "Build with Slang", 46 | "dependencies": [ 47 | "shader-slang" 48 | ] 49 | }, 50 | "utils-pipeline-manager-spirv-validation": { 51 | "description": "Build with SPIR-V validation", 52 | "dependencies": [ 53 | "spirv-tools" 54 | ] 55 | }, 56 | "utils-task-graph": { 57 | "description": "The Task-Graph Daxa utility" 58 | }, 59 | "tests": { 60 | "description": "Build Tests", 61 | "dependencies": [ 62 | { 63 | "name": "glfw3", 64 | "features": [ 65 | "xlib", 66 | "wayland" 67 | ] 68 | }, 69 | "glfw3", 70 | "glm", 71 | "stb", 72 | "cgltf", 73 | { 74 | "name": "imgui", 75 | "features": [ 76 | "glfw-binding" 77 | ] 78 | } 79 | ] 80 | } 81 | }, 82 | "builtin-baseline": "d5ec528843d29e3a52d745a64b469f810b2cedbf", 83 | "vcpkg-configuration": { 84 | "overlay-ports": [ 85 | "./cmake/vcpkg-overlay-ports/fsr2", 86 | "./cmake/vcpkg-overlay-ports/glfw3" 87 | ] 88 | } 89 | } 90 | --------------------------------------------------------------------------------