diff --git a/.gitignore b/.gitignore
index 49ea053..e7cf6f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@ build
.DS_Store
imgui.ini
.vscode
+.vs
+out
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
index be3204e..17562cc 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,12 +4,6 @@
[submodule "third_party/CLI11"]
path = third_party/CLI11
url = https://github.com/CLIUtils/CLI11
-[submodule "third_party/tinyexr"]
- path = third_party/tinyexr
- url = https://github.com/syoyo/tinyexr
-[submodule "third_party/miniz"]
- path = third_party/miniz
- url = https://github.com/richgel999/miniz.git
[submodule "assets/CapsaicinTestMedia"]
path = assets/CapsaicinTestMedia
- url = ../CapsaicinTestMedia.git
+ url = https://github.com/GPUOpen-LibrariesAndSDKs/CapsaicinTestMedia.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2879d73..413c931 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,37 +1,36 @@
-cmake_minimum_required(VERSION 3.10.0)
+cmake_minimum_required(VERSION 3.24.0)
project(Capsaicin
- VERSION 1.0.0
+ VERSION 1.1.0
DESCRIPTION "AMD experimental real-time rendering framework designed for graphics research and development"
)
-set(GFX_BUILD_EXAMPLES OFF CACHE BOOL "Build gfx examples")
-set(TINYGLTF_BUILD_LOADER_EXAMPLE OFF CACHE BOOL "Build loader_example")
-
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Set preprocessor definitions
-add_definitions(/MP
- -D_HAS_ITERATOR_DEBUGGING=0
+add_definitions(
+ /MP
)
-# Gather dependencies
-add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/gfx)
-add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/CLI11)
-set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "" FORCE)
-add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/miniz)
+# Disable unused parameters from 3rd party directories
+set(GFX_BUILD_EXAMPLES OFF CACHE BOOL "")
+set(BUILD_TESTING OFF CACHE BOOL "")
-# Set linker flags
-set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS")
+# Enable gfx options
+set(GFX_ENABLE_SCENE ON CACHE BOOL "")
+set(GFX_ENABLE_GUI ON CACHE BOOL "")
-set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+# Gather dependencies
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/gfx EXCLUDE_FROM_ALL)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/CLI11 EXCLUDE_FROM_ALL)
+set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "" FORCE)
# Organize third party projects
set_target_properties(uninstall PROPERTIES FOLDER "third_party")
-set_target_properties(miniz PROPERTIES FOLDER "third_party")
set_target_properties(gfx PROPERTIES FOLDER "third_party")
set_target_properties(CLI11 PROPERTIES FOLDER "third_party")
set_target_properties(tinyobjloader PROPERTIES FOLDER "third_party/gfx_deps")
+set_target_properties(tinyexr PROPERTIES FOLDER "third_party/gfx_deps")
set_target_properties(ktx PROPERTIES FOLDER "third_party/gfx_deps")
set_target_properties(astcenc-avx2-static PROPERTIES FOLDER "third_party/gfx_deps/ktx_deps")
set_target_properties(ktx_read PROPERTIES FOLDER "third_party/gfx_deps/ktx_deps")
@@ -65,18 +64,11 @@ ELSE()
SET(CAPSAICIN_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} CACHE STRING "Path for archive output files")
ENDIF()
+set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/install")
+
# Build Capsaicin
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)
# Set up startup project
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
PROPERTY VS_STARTUP_PROJECT scene_viewer)
-
-# Install assets and shaders directories
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION . FILES_MATCHING PATTERN "*.*")
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/core/shaders DESTINATION src/core FILES_MATCHING PATTERN "*.*")
-
-# Configure CPack
-set(CPACK_GENERATOR "ZIP")
-set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}")
-include(CPack)
diff --git a/CMakePresets.json b/CMakePresets.json
new file mode 100644
index 0000000..93f110c
--- /dev/null
+++ b/CMakePresets.json
@@ -0,0 +1,77 @@
+{
+ "version": 3,
+ "configurePresets": [
+ {
+ "name": "msvc-base",
+ "description": "Target Windows with the Visual Studio development environment.",
+ "hidden": true,
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/out/build/${presetName}",
+ "installDir": "${sourceDir}/out/install/${presetName}",
+ "cacheVariables": {
+ "CMAKE_C_COMPILER": "cl.exe",
+ "CMAKE_CXX_COMPILER": "cl.exe"
+ },
+ "toolset": {
+ "value": "host=x64",
+ "strategy": "external"
+ },
+ "architecture": {
+ "value": "x64",
+ "strategy": "external"
+ },
+ "condition": {
+ "type": "equals",
+ "lhs": "${hostSystemName}",
+ "rhs": "Windows"
+ }
+ },
+ {
+ "name": "x64-debug",
+ "displayName": "x64-Debug",
+ "description": "Target Windows (64-bit) with the Visual Studio development environment. (Debug)",
+ "inherits": "msvc-base",
+ "cacheVariables": {
+ "CMAKE_BUILD_TYPE": "Debug"
+ }
+ },
+ {
+ "name": "x64-release-with-debug-info",
+ "displayName": "x64-RelWithDebInfo",
+ "description": "Target Windows (64-bit) with the Visual Studio development environment. (Release with Debug Info)",
+ "inherits": "msvc-base",
+ "cacheVariables": {
+ "CMAKE_BUILD_TYPE": "RelWithDebInfo"
+ }
+ },
+ {
+ "name": "x64-release",
+ "displayName": "x64-Release",
+ "description": "Target Windows (64-bit) with the Visual Studio development environment. (Release)",
+ "inherits": "msvc-base",
+ "cacheVariables": {
+ "CMAKE_BUILD_TYPE": "Release"
+ }
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "debug-build-windows",
+ "displayName": "x64-Debug",
+ "configurePreset": "x64-debug",
+ "description": "Debug Windows build"
+ },
+ {
+ "name": "release-with-debug-info-build-windows",
+ "displayName": "x64-RelWithDebInfo",
+ "configurePreset": "x64-release-with-debug-info",
+ "description": "Release with Debug Info Windows build"
+ },
+ {
+ "name": "release-build-windows",
+ "displayName": "x64-Release",
+ "configurePreset": "x64-release",
+ "description": "Release Windows build"
+ }
+ ]
+}
diff --git a/LICENSE.txt b/LICENSE.txt
index 0c7438a..e18da31 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index fcb3f40..a061a84 100644
--- a/README.md
+++ b/README.md
@@ -15,17 +15,17 @@ Features:
![Capsaicin](docs/images/scene_viewer.png)
-## GI-1.0
+## GI-1.1
-We used Capsaicin to implement our GI-1.0 technique for estimating diffuse indirect illumination in real-time.
+We used Capsaicin to implement our GI-1.1 technique for estimating diffuse and specular indirect illumination in real-time.
The technique uses two levels of radiance caching to allow for reduced sampling rate in order to improve performance while making the most of every ray through better sampling.
-Please refer to our [publication](https://gpuopen.com/download/publications/GPUOpen2022_GI1_0.pdf) for more technical details.
+Please refer to our [GI-1.0 technical report](https://gpuopen.com/download/publications/GPUOpen2022_GI1_0.pdf) and [GI-1.1 paper](https://gpuopen.com/download/publications/SA2023_RealTimeReflection.pdf) for more technical details.
#### Note on light support
-GI-1.0 is primarily an indirect lighting solution and as such is expected to be combined with an existing direct lighting technique for integration into a rendering pipeline.
+GI-1.1 is primarily an indirect lighting solution and as such is expected to be combined with an existing direct lighting technique for integration into a rendering pipeline.
All common light types are supported when evaluating the indirect lighting component (e.g., point lights, spot lights, etc.) using our grid-based light sampler and (optional) reservoir-based resampling.
@@ -60,15 +60,43 @@ Capsaicin uses the [CMake](https://cmake.org/) build system. See the [Getting St
## Citation
-If Capsaicin is used any any published work, ensure to cite it using:
+If Capsaicin is used in any published work, please ensure to cite it using:
```bibtex
@Misc{Capsaicin23,
- author = {Guillaume Boissé, Matthew Oliver, Sylvain Meunier, Héloïse Dupont de Dinechin and Kenta Eto},
+ author = {Boissé, Guillaume and Oliver, Matthew and Meunier, Sylvain and Dupont de Dinechin, Héloïse and Eto, Kenta},
title = {The {AMD Capsaicin Framework}},
year = {2023},
- month = {5},
+ month = {8},
url = {https://github.com/GPUOpen-LibrariesAndSDKs/Capsaicin},
- note = {\url{https://github.com/GPUOpen-LibrariesAndSDKs/Capsaicin}}
+}
+```
+
+If our techniques are referenced in any published work, please ensure to cite them using:
+
+```bibtex
+@inproceedings{10.1145/3610543.3626167,
+author = {Eto, Kenta and Meunier, Sylvain and Harada, Takahiro and Boiss\'{e}, Guillaume},
+title = {Real-Time Rendering of Glossy Reflections Using Ray Tracing and Two-Level Radiance Caching},
+year = {2023},
+isbn = {9798400703140},
+publisher = {Association for Computing Machinery},
+address = {New York, NY, USA},
+url = {https://doi.org/10.1145/3610543.3626167},
+doi = {10.1145/3610543.3626167},
+abstract = {Estimation of glossy reflections remains a challenging topic for real-time renderers. Ray tracing is a robust solution for evaluating the specular lobe of a given BRDF; however, it is computationally expensive and introduces noise that requires filtering. Other solutions, such as light probe systems, offer to approximate the signal with little to no noise and better performance but tend to introduce additional bias in the form of overly blurred visuals. This paper introduces a novel approach to rendering reflections in real time that combines the radiance probes of an existing diffuse global illumination framework with denoised ray-traced reflections calculated at a low sampling rate. We will show how combining these two sources allows producing an efficient and high-quality estimation of glossy reflections that is suitable for real-time applications such as games.},
+booktitle = {SIGGRAPH Asia 2023 Technical Communications},
+articleno = {4},
+numpages = {4},
+keywords = {real-time, ray tracing, rendering},
+location = {, Sydney, NSW, Australia, },
+series = {SA '23}
+}
+
+@misc{gi10,
+ author = {Guillaume Boissé and Sylvain Meunier and Heloise de Dinechin and Pieterjan Bartels and Alexander Veselov and Kenta Eto and Takahiro Harada},
+ title = {GI-1.0: A Fast Scalable Two-Level Radiance Caching Scheme for Real-Time Global Illumination},
+ year = {2023},
+ url = {https://gpuopen.com/download/publications/GPUOpen2022_GI1_0.pdf}
}
```
diff --git a/assets/CapsaicinTestMedia b/assets/CapsaicinTestMedia
index f7d2000..d9b2c39 160000
--- a/assets/CapsaicinTestMedia
+++ b/assets/CapsaicinTestMedia
@@ -1 +1 @@
-Subproject commit f7d20009dce2f28f1a42510729468314f066f11a
+Subproject commit d9b2c3940de9216a292f6808babbd27d15189891
diff --git a/docs/development/component.md b/docs/development/component.md
index 97e6fa6..00656fc 100644
--- a/docs/development/component.md
+++ b/docs/development/component.md
@@ -10,13 +10,19 @@ Each new *Component* should be added in its own sub-folder, so for example a new
`src/core/components/my_component/my_component.cpp`\
Note: It is not required that the source file has the same name as the sub-folder it is contained within.
-All new *Components* must inherit from the abstract base class `Component` using its inbuilt factory registration helper `Component::RegistrarName`. Doing so registers the new *Component* with the component factory. To ensure this registration works correctly the new *Component* must implement an empty default constructor (cannot use `=default`) as well as a static constant string containing a unique name for the *Component*.
+All new *Components* must inherit from the abstract base class `Component`. To make the new component searchable by the rest of the system then it should also be added to the component factory by also inheriting from `ComponentFactory::Registrar`. Doing so registers the new *Component* with the component factory. To ensure this registration works correctly the new *Component* must implement an empty default constructor (cannot use `=default`) as well as a static constant string containing a unique name for the *Component*.
The member functions that need overriding are:
+- `Constructor()`:\
+ A default constructor that initialises the `Component` base class with a unique name for the current *Component*.
+- `~Destructor()`:\
+ Each *Component* must provide a destructor that properly frees all internally created resources.
- `bool init(CapsaicinInternal const &capsaicin)`:\
- This function is called automatically by the framework after the *Renderer Technique* and any requested *Render Options*, *Components*, *AOVs* (see below), or other requested items have been created and initialised. It is the responsibility of the *Render Technique* to perform all required initialisation operations within this function, such as creating any used CPU|GPU resources that are required to persist over the lifetime of the *Render Technique*. The return value for this function can be used to signal to the framework if resource allocation or other initialisation operations have failed and the *Render Technique* would not be able to operate as a result. Returning `false` indicates an error state while `true` signifies correct initialisation.
+ This function is called automatically by the framework after the *Component* and any requested *Render Options*, *Components*, *AOVs* (see below), or other requested items have been created and initialised. It is the responsibility of the *Component* to perform all required initialisation operations within this function, such as creating any used CPU|GPU resources that are required to persist over the lifetime of the *Component*. The return value for this function can be used to signal to the framework if resource allocation or other initialisation operations have failed and the *Component* would not be able to operate as a result. Returning `false` indicates an error state while `true` signifies correct initialisation.
- `void run(CapsaicinInternal &capsaicin)`:\
This function is called automatically every frame and is responsible for performing all the required main operations of the component. Current render settings and other internal framework state can be retrieved from the passed in `capsaicin` object. This object can be used to retrieve internal *Render Options* or other settings. Unlike *Render Techniques* not all of the rendering operations must be performed within this function. *Components* can also provide additional member functions that can be explicitly called by *Render Techniques* to perform additional work or parameter passing. This function is always run by the engine before running the per-frame functions of any *Render Techniques*.
+- `void terminate()`:\
+ This function is automatically called when a *Component* is being destroyed or when a reset has occurred. It is the responsibility of the *Component* to perform all required destruction operations within this function, such as releasing all used CPU|GPU resources. It is not always guaranteed that this function will be called when destroying a *Component* so a components destructor should also call this function to destroy any created resources.
The member functions that can be optionally overridden if needed are:
- `RenderOptionList getRenderOptions()`:\
@@ -25,6 +31,8 @@ The member functions that can be optionally overridden if needed are:
This function is called on *Component* creation and is responsible for returning a list of all additionally required *Components* required by the current *Component*. If no *Components* are required overriding this function is not necessary or the returned list can be empty. The internal framework uses this list to create *Components* in addition to the ones requested by *Render Techniques*. Each *Component* can gain access to other *Components* by using `Capsaicin.getComponent("Name")` or `Capsaicin.getComponent()`.
- `BufferList getBuffers() const`:\
This function is called on *Component* creation and is responsible for returning a list of all required shared memory buffer objects. If no buffers are required overriding this function is not necessary or the returned list can be empty. Each requested buffer is identified by a unique name string as well as additional information such as the buffers requested size etc. The internal framework uses this list to create buffers for all *Components* in addition to the ones requested by *Renderer Techniques*. Each *Component* can then gain access to each created buffer using `Capsaicin.getBuffer("Name")`.
+- `void renderGUI(CapsaicinInternal &capsaicin) const`:\
+ This function can be used to draw *Component* specific UI elements to aid in visualisation and/or debugging. This function will be called by the parent *Capsaicin* `renderGUI` call which will execute all *Components* `renderGUI` functions followed by all *Render Techniques* `renderGUI` functions in the order that were added to the system. Any UI elements output by this function will be displayed in the 'Render Settings' UI section. Any *Component* that outputs a large number of UI parameters should wrap them in a collapsible tree node so as not to pollute the UI.
An example blank implementation of `my_component` would look like:
```
@@ -32,18 +40,20 @@ An example blank implementation of `my_component` would look like:
namespace Capsaicin
{
-class MyComponent : public Component::RegistrarName
+class MyComponent : public Component
+ , public ComponentFactory::Registrar
{
public:
/***** Must define unique name to represent new type *****/
static constexpr std::string_view Name = "My Component";
- /***** Must have empty constructor *****/
- MyComponent() noexcept {}
+ /***** Must have constructor to initialise base 'Component' *****/
+ MyComponent() noexcept : Component(Name) {}
~MyComponent()
{
/***** Must clean-up any created member variables/data *****/
+ terminate();
}
RenderOptionList getRenderOptions() noexcept override
@@ -51,39 +61,41 @@ public:
RenderOptionList newOptions;
/***** Push any desired options to the returned list here (else just 'return {}') *****/
/***** Example (using provided helper RENDER_OPTION_MAKE): *****/
- /***** newOptions.emplace(RENDER_OPTION_MAKE(my_technique_enable, options)); *****/
+ /***** newOptions.emplace(RENDER_OPTION_MAKE(my_component_enable, options)); *****/
return newOptions;
}
struct RenderOptions
{
- /***** Any member variable options can be added here. *****/
+ /***** Any member variable options can be added here. *****/
+ /***** This struct can be entirely omitted if not being used. *****/
/***** This represent the internal format of options where as 'RenderOptionList' has these stored as strings and variants *****/
+ /***** Example: bool my_component_enable; *****/
};
- static RenderOptions convertOptions(RenderSettings const &settings) noexcept
+ static RenderOptions convertOptions(RenderOptionList const &options) noexcept
{
/***** Optional function only required if actually providing RenderOptions *****/
RenderOptions newOptions;
/***** Used to convert options between external string/variant and internal data type 'RenderOptions' *****/
/***** Example: (using provided helper RENDER_OPTION_GET): *****/
- /***** RENDER_OPTION_GET(my_technique_enable, newOptions, settings.options_); *****/
+ /***** RENDER_OPTION_GET(my_component_enable, newOptions, options); *****/
return newOptions;
}
- ComponentList RenderTechnique::getComponents() const noexcept
+ ComponentList getComponents() const noexcept override
{
ComponentList components;
- /***** Push any desired Components to the returned list here (else just 'return {}') *****/
- /***** Example: if corresponding header is already included (using provided helper COMPONENT_MAKE): *****/
- /***** components.emplace_back(COMPONENT_MAKE(TypeOfComponent)); *****/
+ /***** Push any desired Components to the returned list here (else just 'return {}' or dont override) *****/
+ /***** Example: if corresponding header is already included (using provided helper COMPONENT_MAKE): *****/
+ /***** components.emplace_back(COMPONENT_MAKE(TypeOfComponent)); *****/
return components;
}
BufferList getBuffers() const noexcept override
{
BufferList buffers;
- /***** Push any desired Buffers to the returned list here (else just 'return {}') *****/
+ /***** Push any desired Buffers to the returned list here (else just 'return {}' or dont override) *****/
return buffers;
}
@@ -95,18 +107,30 @@ public:
void run(CapsaicinInternal &capsaicin) noexcept override
{
- auto &renderSettings = capsaicin.getRenderSettings();
- RenderOptions newOptions = convertOptions(renderSettings);
- /***** Perform any required rendering operations here *****/
- options = newOptions;
+ /***** If any options are provided they should be checked for changes here *****/
+ /***** Example: *****/
+ /***** RenderOptions newOptions = convertOptions(capsaicin.getOptions()); *****/
+ /***** Check for changes and handle accordingly *****/
+ /***** options = newOptions; *****/
+ /***** Perform any required rendering operations here *****/
}
+ void terminate() noexcept override
+ {
+ /***** Cleanup any created CPU or GPU resources *****/
+ }
+
+ void renderGUI(CapsaicinInternal &capsaicin) const noexcept override
+ {
+ /***** Add any UI drawing commands here *****/
+ }
+
/***** Additional member functions can also be provided *****/
protected:
/***** Internal member data can be added here *****/
- /***** Example: *****/
- /***** RenderOptions options; *****/
+ /***** Example: *****/
+ /***** RenderOptions options; *****/
};
} // namespace Capsaicin
```
\ No newline at end of file
diff --git a/docs/development/getting_started.md b/docs/development/getting_started.md
index bfe1b4d..ef89266 100644
--- a/docs/development/getting_started.md
+++ b/docs/development/getting_started.md
@@ -21,6 +21,8 @@ There are several ways to get started compiling the source code:
- Use CMake to generate a Visual Studio project
- `cmake CMakeLists.txt -B ./build -G "Visual Studio 17 2022"` (note other Visual Studio versions can be used)
- Open the newly created project in Visual Studio and build as normal
+- Open directly in VS Code or Visual Studio
+ - Both VS Code and newer versions of Visual Studio enable loading CMake projects directly (see corresponding documentation for your IDE)
- Build on command line
- `cmake -S ./ -B ./build -A x64`
- `cmake --build ./build --config RelWithDebInfo`
@@ -31,7 +33,7 @@ Code is separated by functionality with the expectation that files (i.e. headers
All source code is written using C++ and uses the `.cpp` file extension. Header files use the `.h` extension. This extension is also used for any files shared between host and device code. All device code uses the `.hlsl` extension.
-- `assets` : Contains bundled test scenes
+- `assets` : Contains bundled test scenes and associated data
- `docs` : Contains the documentation
- `dump` : The default location for saved screenshots
- `shader_pdb` : The default location for saved shader debugging information
@@ -40,11 +42,11 @@ All source code is written using C++ and uses the `.cpp` file extension. Header
- `include` : Contains the single `capsaicin.h` header file used to interface with the framework
- `src`
- `capsaicin` : Contains the main internal framework code
+ - `components` : The location of all available components (each within its own sub-folder)
- `lights` : Common HLSL headers for lighting evaluation/sampling
- `materials` : Common HLSL headers for material evaluation/sampling
- `math` : Common mathematical helper functions
- - `random` : Random number generators
- - `render_technique` : The location of all available render techniques (each within its own sub-folder)
+ - `render_techniques` : The location of all available render techniques (each within its own sub-folder)
- `renderers` : All available renderers (each within its own sub-folder)
- `utilities` : Reusable host side utility helpers (sort, reduce etc.)
- `scene_viewer` : The default application
@@ -74,3 +76,7 @@ Available controls:
`Mouse Wheel (Horizontal)` - Change Field of View
`Space` - Pause/Resume animations
+`Left` - Step animation back 1 frame
+`Right` - Step animation forward 1 frame
+`Up` - Increase playback speed
+`Down` - Decrease playback speed
\ No newline at end of file
diff --git a/docs/development/render_technique.md b/docs/development/render_technique.md
index 3ad0e2a..2767a16 100644
--- a/docs/development/render_technique.md
+++ b/docs/development/render_technique.md
@@ -13,14 +13,16 @@ Note: It is not required that the source file has the same name as the sub-folde
All new *Renderer Techniques* must inherit from the base class `RenderTechnique` and override all required member functions.
The member functions that need overriding are:
+- `Constructor()`:\
+ A default constructor that initialises the `RenderTechnique` base class with a unique name for the current *Renderer Technique*.
+- `~Destructor()`:\
+ Each *Renderer Technique* must provide a destructor that properly frees all internally created resources.
- `bool init(CapsaicinInternal const &capsaicin)`:\
This function is called automatically by the framework after the *Renderer Technique* and any requested *Render Options*, *Components*, *AOVs* (see below), or other requested items have been created and initialised. It is the responsibility of the *Render Technique* to perform all required initialisation operations within this function, such as creating any used CPU|GPU resources that are required to persist over the lifetime of the *Render Technique*. The return value for this function can be used to signal to the framework if resource allocation or other initialisation operations have failed and the *Render Technique* would not be able to operate as a result. Returning `false` indicates an error state while `true` signifies correct initialisation.
- `void render(CapsaicinInternal &capsaicin)`:\
This function is called every frame and is responsible for performing all the required operations of the *Renderer Technique*. Current render settings, debug views and other internal framework state can be retrieved from the passed in `capsaicin` object. This object can be used to retrieve internal *AOV*s using `capsaicin.getAOVBuffer("Name")` as well as current *Debug Views* and *Render Options*. It is the responsibility of the *Render Technique* to perform all required per-frame operations within this function.
-- `Constructor()`:\
- A default constructor that initialises the `RenderTechnique` base class with a unique name for the current technique.
-- `~Destructor()`:\
- Each technique must provide a destructor that properly frees all internally created resources.
+- `void terminate()`:\
+ This function is automatically called when a *Renderer Technique* is being destroyed or when a reset has occurred. It is the responsibility of the *Renderer Technique* to perform all required destruction operations within this function, such as releasing all used CPU|GPU resources. It is not always guaranteed that this function will be called when destroying a *Renderer Technique* so a components destructor should also call this function to destroy any created resources.
The member functions that can be optionally overridden if needed are:
- `RenderOptionList getRenderOptions()`:\
@@ -33,6 +35,8 @@ The member functions that can be optionally overridden if needed are:
This function is called on technique creation and is responsible for returning a list of all required *AOV* buffers (shared render buffers e.g. GBuffers) required by the current technique. If no *AOV*s are required overriding this function is not necessary or the returned list can be empty. The `AOVList` type is used to describe each *AOV* using a unique string name as well as the types of operations that will be performed on the *AOV* (e.g. Read, Write, Accumulate). It also holds additional optional values that can be used to define the *AOVs* format, set it to be automatically cleared/backed-up each frame and other options. The internal framework uses this list to create *AOV*s for all *Renderer Techniques*. Each technique can then gain access to each created *AOV* using `Capsaicin.getAOVBuffer("Name")`. It should be noted that some *AOVs* are automatically created by the framework such as the output buffer "Color", other inbuilt buffers such as depth "Depth" and debug output buffers "Debug" are also automatically created but only if a *Renderer Technique* requests to use them.
- `DebugViewList getDebugViews() const`:\
This function is called on technique creation and returns a list of any *Debug Views* provided by the technique. If none are provided overriding this function is not necessary or the returned list can be empty. By default the internal framework will provide default *Debug Views* for any known *AOV*s using default rendering shaders based on the format of the *AOV* (e.g. depth etc.). These *Debug Views* will have the same name as the *AOV* its displaying. If a *Render Technique* wishes to add its own additional *Debug View*(s) it can do so by returning a list of provided views using a unique string name to identify them. In cases where the internal frameworks default *Debug View* of an *AOV* is undesirable it is also possible for a technique to override it by providing its own *Debug View* and giving it the same name string as the *AOV*. For any created custom *Debug View* it is the responsibility of the *Render Technique* to check the render settings (using `RenderSettings.::debug_view_`) each frame and output the debug view to the "Debug" *AOV* when requested (see `render(...)` above).
+- `void renderGUI(CapsaicinInternal &capsaicin) const`:\
+ This function can be used to draw *Renderer Technique* specific UI elements to aid in visualisation and/or debugging. This function will be called by the parent *Capsaicin* `renderGUI` call which will execute all *Components* `renderGUI` functions followed by all *Render Techniques* `renderGUI` functions in the order that were added to the system. Any UI elements output by this function will be displayed in the 'Render Settings' UI section. Any *Renderer Technique* that outputs a large number of UI parameters should wrap them in a collapsible tree node so as not to pollute the UI.
An example blank implementation of `my_technique` would look like:
```
@@ -49,6 +53,7 @@ public:
~MyTechnique()
{
/***** Must clean-up any created member variables/data *****/
+ terminate();
}
RenderOptionList getRenderOptions() noexcept override
@@ -56,51 +61,55 @@ public:
RenderOptionList newOptions;
/***** Push any desired options to the returned list here (else just 'return {}') *****/
/***** Example (using provided helper RENDER_OPTION_MAKE): *****/
- /***** newOptions.emplace(RENDER_OPTION_MAKE(my_technique_enable, options)); *****/
+ /***** newOptions.emplace(RENDER_OPTION_MAKE(my_technique_enable, options)); *****/
return newOptions;
}
struct RenderOptions
{
- /***** Any member variable options can be added here. *****/
+ /***** Any member variable options can be added here. *****/
+ /***** This struct can be entirely omitted if not being used. *****/
/***** This represent the internal format of options where as 'RenderOptionList' has these stored as strings and variants *****/
+ /***** Example: bool my_technique_enable; *****/
};
- static RenderOptions convertOptions(RenderSettings const &settings) noexcept
+ static RenderOptions convertOptions(RenderOptionList const &options) noexcept
{
/***** Optional function only required if actually providing RenderOptions *****/
RenderOptions newOptions;
/***** Used to convert options between external string/variant and internal data type 'RenderOptions' *****/
/***** Example: (using provided helper RENDER_OPTION_GET): *****/
- /***** RENDER_OPTION_GET(my_technique_enable, newOptions, settings.options_); *****/
+ /***** RENDER_OPTION_GET(my_technique_enable, newOptions, options); *****/
return newOptions;
}
- ComponentList RenderTechnique::getComponents() const noexcept
+ ComponentList getComponents() const noexcept override
{
ComponentList components;
- /***** Push any desired Components to the returned list here (else just 'return {}') *****/
+ /***** Push any desired Components to the returned list here (else just 'return {}' or dont override) *****/
+ /***** Example: if corresponding header is already included (using provided helper COMPONENT_MAKE): *****/
+ /***** components.emplace_back(COMPONENT_MAKE(TypeOfComponent)); *****/
return components;
}
BufferList getBuffers() const noexcept override
{
BufferList buffers;
- /***** Push any desired Buffers to the returned list here (else just 'return {}') *****/
+ /***** Push any desired Buffers to the returned list here (else just 'return {}' or dont override) *****/
return buffers;
}
AOVList getAOVs() const noexcept override
{
AOVList aovs;
- /***** Push any desired AOVs to the returned list here (else just 'return {}') *****/
+ /***** Push any desired AOVs to the returned list here (else just 'return {}' or dont override) *****/
return aovs;
}
DebugViewList getDebugViews() const noexcept override
{
DebugViewList views;
- /***** Push any desired Debug Views to the returned list here (else just 'return {}') *****/
+ /***** Push any desired Debug Views to the returned list here (else just 'return {}' or dont override) *****/
return views;
}
@@ -112,17 +121,29 @@ public:
void render(CapsaicinInternal &capsaicin) noexcept override
{
- auto &renderSettings = capsaicin.getRenderSettings();
- RenderOptions newOptions = convertOptions(renderSettings);
- /***** Perform all required rendering operations here *****/
- /***** Debug Views can be checked with 'renderSettings.debug_view_' *****/
- options = newOptions;
+ /***** If any options are provided they should be checked for changes here *****/
+ /***** Example: *****/
+ /***** RenderOptions newOptions = convertOptions(capsaicin.getOptions()); *****/
+ /***** Check for changes and handle accordingly *****/
+ /***** options = newOptions; *****/
+ /***** Perform any required rendering operations here *****/
+ /***** Debug Views can be checked with 'capsaicin.getCurrentDebugView()' *****/
}
+
+ void terminate() noexcept override
+ {
+ /***** Cleanup any created CPU or GPU resources *****/
+ }
+
+ void renderGUI(CapsaicinInternal &capsaicin) const noexcept override
+ {
+ /***** Add any UI drawing commands here *****/
+ }
protected:
/***** Internal member data can be added here *****/
- /***** Example: *****/
- /***** RenderOptions options; *****/
+ /***** Example: *****/
+ /***** RenderOptions options; *****/
};
} // namespace Capsaicin
```
\ No newline at end of file
diff --git a/docs/development/renderer.md b/docs/development/renderer.md
index e083a73..80bcd3f 100644
--- a/docs/development/renderer.md
+++ b/docs/development/renderer.md
@@ -9,15 +9,15 @@ Each new *Renderer* should be added in its own sub-folder, so for example a new
`src/core/renderers/my_renderer/my_renderer.cpp`\
Note: It is not required that the source file has the same name as the sub-folder it is contained within.
-All new *Renderers* must inherit from the abstract base class `Renderer` using its inbuilt factory registration helper `Renderer::Registrar`. Doing so registers the new *Renderer* with the renderer factory. To ensure this registration works correctly the new *Renderer* must implement an empty default constructor (cannot use `=default`) as well as a static constant string containing a unique name for the *Renderer*.
+All new *Renderers* must inherit from the abstract base class `Renderer`. To make the new *Renderer* searchable by the rest of the system then it should also be added to the renderer factory by also inheriting from `RendererFactory::Registrar`. Doing so registers the new *Renderer* with the renderer factory. To ensure this registration works correctly the new *Renderer* must implement an empty default constructor (cannot use `=default`) as well as a static constant string containing a unique name for the *Renderer*.
The new *Renderer* should then override all base class member functions as required.
The member functions that need overriding are:
+- `Constructor()`:\
+ A blank constructor.
- `std::vector> setupRenderTechniques(...)`:\
This function is responsible for returning a list of all required *Render Techniques* in the order that they are required to operate during rendering. The return from this function transfers ownership of the *Render Techniques* to the internal framework which will then manage their lifetime after that.
-- `Constructor()`:\
- A default blank constructor.
An example blank implementation of `my_renderer` would look like:
```
@@ -26,7 +26,9 @@ An example blank implementation of `my_renderer` would look like:
namespace Capsaicin
{
-class MyRenderer : public Renderer::Registrar
+class MyRenderer
+ : public Renderer
+ , public RendererFactory::Registrar
{
public:
/***** Must define unique name to represent new type *****/
@@ -36,7 +38,7 @@ public:
MyRenderer() noexcept {}
std::vector> setupRenderTechniques(
- RenderSettings const &render_settings) noexcept override
+ RenderOptionList const &renderOptions) noexcept override
{
std::vector> render_techniques;
/***** Emplace any desired render techniques to the returned list here *****/
diff --git a/docs/index.md b/docs/index.md
index 134ad20..ae15801 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -8,4 +8,4 @@
- [Creating a Renderer](./development/renderer.md)
- [Creating a Renderer Technique](./development/render_technique.md)
- [Creating a Component](./development/component.md)
- - [Shader Debugging](./development/shader_debugging.md)
+ - [Shader Debugging](./development/shader_debugging.md)
\ No newline at end of file
diff --git a/dump/.gitignore b/dump/.gitignore
new file mode 100644
index 0000000..72e8ffc
--- /dev/null
+++ b/dump/.gitignore
@@ -0,0 +1 @@
+*
diff --git a/launch.vs.json b/launch.vs.json
new file mode 100644
index 0000000..b584fc1
--- /dev/null
+++ b/launch.vs.json
@@ -0,0 +1,13 @@
+{
+ "version": "0.2.1",
+ "defaults": {},
+ "configurations": [
+ {
+ "type": "default",
+ "project": "CMakeLists.txt",
+ "projectTarget": "scene_viewer.exe (bin\\scene_viewer.exe)",
+ "name": "scene_viewer.exe (bin\\scene_viewer.exe)",
+ "currentDir": "${workspaceRoot}"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/shader_pdb/.gitignore b/shader_pdb/.gitignore
new file mode 100644
index 0000000..72e8ffc
--- /dev/null
+++ b/shader_pdb/.gitignore
@@ -0,0 +1 @@
+*
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 1540b5f..ff30b02 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,11 +1,9 @@
file(GLOB_RECURSE HEADER_FILES
CONFIGURE_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
- ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h)
-
-file(GLOB_RECURSE INLINE_FILES
- CONFIGURE_DEPENDS
- ${CMAKE_CURRENT_SOURCE_DIR}/src/*.inl)
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/*.inl
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h
+)
file(GLOB_RECURSE SHADER_FILES
CONFIGURE_DEPENDS
@@ -13,47 +11,54 @@ file(GLOB_RECURSE SHADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.frag
${CMAKE_CURRENT_SOURCE_DIR}/src/*.geom
${CMAKE_CURRENT_SOURCE_DIR}/src/*.comp
- ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hlsl)
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hlsl
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/*.rt
+)
file(GLOB_RECURSE SOURCE_FILES
CONFIGURE_DEPENDS
- ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
+)
set_source_files_properties(${SHADER_FILES}
PROPERTIES
VS_TOOL_OVERRIDE
- "None")
+ "None"
+)
-add_library(core SHARED ${SOURCE_FILES})
+add_library(capsaicin SHARED ${SOURCE_FILES})
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
include(GenerateExportHeader)
-generate_export_header(core BASE_NAME capsaicin)
+generate_export_header(capsaicin BASE_NAME capsaicin)
configure_file(include/version.h.in version.h)
-target_sources(core PRIVATE ${HEADER_FILES} ${INLINE_FILES} ${SHADER_FILES}
- ${PROJECT_BINARY_DIR}/src/core/capsaicin_export.h)
+target_sources(capsaicin
+ PRIVATE ${HEADER_FILES} ${INLINE_FILES} ${SHADER_FILES} ${SHADER_FILES}
+ ${PROJECT_BINARY_DIR}/src/core/capsaicin_export.h
+)
-target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
- ${PROJECT_BINARY_DIR}/src/core)
+target_include_directories(capsaicin
+ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${PROJECT_BINARY_DIR}/src/core
+)
-target_include_directories(core PRIVATE
+target_include_directories(capsaicin PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/src/capsaicin
${CMAKE_CURRENT_SOURCE_DIR}/src/render_techniques
${CMAKE_CURRENT_SOURCE_DIR}/src/renderers
${CMAKE_CURRENT_SOURCE_DIR}/src/utilities
- ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/ffx-bx
${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/ffx-parallelsort
- ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/miniz
- ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/samplerCPP
- ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/tinyexr)
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/gfx/third_party/stb
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/gfx/third_party/tinyexr
+)
-target_compile_features(core PUBLIC cxx_std_20)
-target_compile_options(core PRIVATE
- /W3 /WX
+target_compile_features(capsaicin PUBLIC cxx_std_20)
+target_compile_options(capsaicin PRIVATE
+ /W4 /WX /external:anglebrackets /external:W0 /analyze:external-
-D_CRT_SECURE_NO_WARNINGS
-D_HAS_EXCEPTIONS=0
-D_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING
@@ -61,16 +66,16 @@ target_compile_options(core PRIVATE
-DGLM_FORCE_CTOR_INIT
-DGLM_FORCE_XYZW_ONLY
-DGLM_FORCE_DEPTH_ZERO_TO_ONE
+ -DNOMINMAX
)
+target_link_options(capsaicin PRIVATE "/SUBSYSTEM:WINDOWS")
+
function(assign_source_group arg1)
foreach(_source IN ITEMS ${ARGN})
get_filename_component(PARENT_DIR "${_source}" DIRECTORY)
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/include" "" GROUP "${PARENT_DIR}")
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/src" "" GROUP "${GROUP}")
- string(REPLACE "../gi10/src" "" GROUP "${GROUP}")
- string(REPLACE "../gi10/include" "" GROUP "${GROUP}")
- string(REPLACE "../gi10/shaders" "" GROUP "${GROUP}")
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "" GROUP "${GROUP}")
string(REPLACE "/" "\\" GROUP "${GROUP}")
source_group("${arg1}\\${GROUP}" FILES "${_source}")
@@ -78,35 +83,54 @@ function(assign_source_group arg1)
endfunction(assign_source_group)
assign_source_group("Header Files" ${HEADER_FILES})
-assign_source_group("Inline Headers" ${INLINE_FILES})
assign_source_group("Source Files" ${SOURCE_FILES})
assign_source_group("Shader Files" ${SHADER_FILES})
-assign_source_group("Header Files\\gi10" ${GI10_HEADER_FILES})
-assign_source_group("Source Files\\gi10" ${GI10_SOURCE_FILES})
-assign_source_group("Shader Files\\gi10" ${GI10_SHADER_FILES})
-
add_library(D3D12Core SHARED IMPORTED)
set_target_properties(D3D12Core PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/third_party/agility_sdk/D3D12Core.dll
- IMPORTED_IMPLIB d3d12.lib
+ IMPORTED_IMPLIB ${CMAKE_SOURCE_DIR}/third_party/agility_sdk/dummy.lib
)
add_library(d3d12SDKLayers SHARED IMPORTED)
set_target_properties(d3d12SDKLayers PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/third_party/agility_sdk/d3d12SDKLayers.dll
- IMPORTED_IMPLIB d3d12.lib
+ IMPORTED_IMPLIB ${CMAKE_SOURCE_DIR}/third_party/agility_sdk/dummy.lib
)
-target_link_libraries(core PUBLIC gfx glm
- PRIVATE tinyobjloader miniz D3D12Core d3d12SDKLayers)
+target_link_libraries(capsaicin PUBLIC gfx glm
+ PRIVATE d3d12 D3D12Core d3d12SDKLayers tinyexr)
-set_target_properties(core PROPERTIES
+set_target_properties(capsaicin PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CAPSAICIN_RUNTIME_OUTPUT_DIRECTORY}
LIBRARY_OUTPUT_DIRECTORY ${CAPSAICIN_LIBRARY_OUTPUT_DIRECTORY}
ARCHIVE_OUTPUT_DIRECTORY ${CAPSAICIN_ARCHIVE_OUTPUT_DIRECTORY}
)
-add_custom_command(TARGET core POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy $ $
- COMMAND_EXPAND_LISTS
-)
\ No newline at end of file
+add_custom_command(TARGET capsaicin POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy $ $
+ COMMAND_EXPAND_LISTS
+)
+
+set_target_properties(capsaicin PROPERTIES PUBLIC_HEADER "include/capsaicin.h;${CMAKE_BINARY_DIR}/src/core/version.h;${CMAKE_BINARY_DIR}/src/core/capsaicin_export.h")
+
+# Install the library and headers
+include(GNUInstallDirs)
+install(TARGETS capsaicin
+ EXPORT capsaicin-targets
+ PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/capsaicin
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}
+)
+
+# Install shader files into binary directory
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}
+ FILES_MATCHING
+ PATTERN "*.vert"
+ PATTERN "*.frag"
+ PATTERN "*.geom"
+ PATTERN "*.comp"
+ PATTERN "*.hlsl"
+ PATTERN "*.rt"
+)
diff --git a/src/core/include/capsaicin.h b/src/core/include/capsaicin.h
index d3fc562..0ab3e17 100644
--- a/src/core/include/capsaicin.h
+++ b/src/core/include/capsaicin.h
@@ -1,5 +1,5 @@
/**********************************************************************
-Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
+Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -23,8 +23,8 @@ THE SOFTWARE.
#include "capsaicin_export.h"
-#define NOMINMAX
-#include "gfx_scene.h"
+#include
+#include
#include