wisdom
|
This page provides an overview of the Wisdom library structure and its components.
The Wisdom library is structured into several modules, each providing a specific functionality. The provided classes and functions are designed to be easy to use and overhead free. When using the library as a header-only library, all the functions are inline and do not incur any overhead. Most of the classes are done in an independent way, so you only need to store classes that you need. The classes, as well as functions and types and their respective documentation, are generated to maintain consistency of interface and ease of use. Files that generate everything are stored at xml
directory. Those files can be used to generate the API and its documentation in any other language, providing you have a geneartor and a way to link those functions to C++ code.
The library sits above the DirectX 12 and Vulkan APIs, providing a minimal abstraction layer. The library implementation is split into 2 implementations: one for DirectX 12 and one for Vulkan. Both implementations are designed to be as similar as possible, providing a consistent interface for the user. The library also does not use virtual functions, so it is as fast as possible.
The implementation for DirectX 12 is done in the wisdom/dx12
directory, while the implementation for Vulkan is done in the wisdom/vulkan
directory. DirectX 12 implementation is prefixed with DX12
and Vulkan implementation is prefixed with VK
. So the classes are named DX12Factory
, DX12Adapter
, VKFactory
, VKAdapter
and so on.
Then the implementation is wrapped into the wis::Factory
, wis::Adapter
, wis::Device
and so on. File wisdom/include/wisdom/wisdom.hpp
is the main header file that includes all the necessary headers for the library. It also selects the implementation based on the platform and the API. On Windows, it will use DirectX 12 implementation, while on Linux it will use Vulkan implementation.
WISDOM_FORCE_VULKAN
CMake flag to ON
or define WISDOM_FORCE_VULKAN
in global preprocessor. NuGet package also has this flag in the propertiy page of the project.The implementation will scan if you have Vulkan SDK installed and if it is available, it will use Vulkan implementation. Otherwise it will produce an error that Vulkan is not available.
import wisdom
and the other uses import wisdom.fvk
. This is done due to the fact that preprocessor switches do not affect modules imported from other libraries. You cannot use both imports in the same project, so you should choose one of them. Althogh both modules provide implemntations for both DirectX 12 and Vulkan.Only .hpp files provided to be used in your project. The .h files contain the implementation details and are not meant to be used directly. However types that they provide can be used directly in your project. One use case is to use both DirectX 12 and Vulkan implementations in the same project. In such case you should use prefixed types, like wis::DX12Factory
and wis::VKFactory
, to avoid name clashes. Functions that create device and factory are also prefixed with DX12
or VK
for that particular reason.
For regular use you can use the wis::Factory
, wis::Adapter
, wis::Device
and so on types, which are the main types of the library. All the extensions and platform-specific addons follow the same naming convention, so you can use them without any issues.
All the examples and documentation will be provided with non-prefixed types to simplify the usage.
All the types have a destructor and independent lifetime, so you can use them without worrying about the lifetime of the underlying resources. For example, if wis::Device
is destroyed before wis::Buffer
, the buffer will still be valid and can be used. The underlying resources will be released when the last reference to them is destroyed. The library uses RAII principles to manage the lifetime of the resources, so you don't have to worry about memory leaks or resource management. Most of the classes are move-only, so you can use them without worrying about copying the resources.
Provided API is designed to be easy to use and understand. It is based on the modern C++ standards and best practices. Most of the API functions return wis::Result
type, which is a simple wrapper around the error code and the error message. Error messages are brief and compile-time created, and their lifetime is static, so you can use them without worrying about the lifetime of the error message. Since the library is designed to be used with modern C++ standards, output is best handled with structured bindings.
Example of how to use the API:
The CreateFactory
function will return a wis::Result
and a wis::Factory
object. The wis::Result
object will contain the error code and the error message, while the wis::Factory
object will contain the factory object.
The library also provides RVO (Return Value Optimization) for the functions that return objects. Those functions will return the object directly, and result will be stored in the first argument of the function.
Example of how to use the API with RVO:
Those functions are generated with first argument being wis::Result&
and returning the object directly. So if you want to squeeze the last bit of performance, you can use this approach, since it will avoid using extra move constructor or move assignment.
The library is designed to be extensible, so you can add your own extensions and functionality to it. Open-ended extensibility is one of the key features of the library. Every class has a corresponding Internal class that provides the implementation details. To query the internal implementation, you can use the GetInternal
and GetMutableInternal
. Once you have the internal implementation, you can use it to extend the library with your own functionality. To follow the practice you can see the implementation of any extension from wisdom/extensions
directory.
You don't have to use the same conventions as the library does, but it is recommended to follow the same naming conventions and structure to keep the code consistent and easy to read.
wis::DX12Device
having ID3D12Device*
are guaranteed to exist as long as underlying APIs don't change the logic.