Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for mesh shaders. #116

Merged
merged 13 commits into from
Jan 9, 2024
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ LiteFX is written in modern C++23, following established design patterns to make

### Key Features

- **State of the Art**: the engine makes use of some of the most recent techniques introduced to the supported APIs in order to help you to fully utilize the latest hardware. For example it uses features from the [DirectX 12 Agility SDK](https://devblogs.microsoft.com/directx/announcing-dx12agility/) and [Vulkan 1.3](https://www.khronos.org/news/press/vulkan-reduces-fragmentation-and-provides-roadmap-visibility-for-developers).
- **State of the Art**: the engine makes use of some of the most recent techniques introduced to the supported APIs in order to help you to fully utilize the latest hardware. For example it uses features from the [DirectX 12 Agility SDK](https://devblogs.microsoft.com/directx/announcing-dx12agility/) and [Vulkan 1.3](https://www.khronos.org/news/press/vulkan-reduces-fragmentation-and-provides-roadmap-visibility-for-developers), such as *mesh shaders*, *enhanced barriers* and *dynamic states*.
- **Streamlined API**: low-level graphics APIs typically involve a lot of boilerplate code to set them up. LiteFX provides different techniques to make this code less verbose. *Fluent Builders* can be used to setup and configure render graphs. *Shader Reflection* can be used in both, Vulkan and DirectX 12, to create pipeline layouts from a single line of code.
- **Multi-Threading Support**: LiteFX comes with support for multi-threaded render passes in order to maximize throughput and prevent GPU stalls. It takes care of the necessary synchronization between threads and exposes interfaces for manual synchronization.
- **Descriptor and Memory Management**: descriptors and buffers can be hard to get around. LiteFX abstracts them away in a way that is both efficient and accessible.
Expand Down Expand Up @@ -134,10 +134,11 @@ Within the cache variables, you can override the build options, LiteFX exports.

- `LITEFX_BUILD_VULKAN_BACKEND` (default: `ON`): builds the Vulkan 🌋 backend (requires [LunarG Vulkan SDK](https://vulkan.lunarg.com/) 1.3.204.1 or later to be installed on your system).
- `LITEFX_BUILD_DX12_BACKEND` (default: `ON`): builds the DirectX 12 ❎ backend.
- `LITEFX_BUILD_MESH_SHADER_SUPPORT` (default: `OFF`) builds support for mesh shaders and adds the mesh shader example.
- `LITEFX_BUILD_DEFINE_BUILDERS` (default: `ON`): enables the [builder architecture](https://github.com/crud89/LiteFX/wiki/Builders) for backends.
- `LITEFX_BUILD_WITH_GLM` (default: `ON`): adds [glm](https://glm.g-truc.net/0.9.9/index.html) converters to math types. †
- `LITEFX_BUILD_WITH_DIRECTX_MATH` (default: `ON`): adds [DirectX Math](https://github.com/microsoft/DirectXMath) converters to math types. †
- `LITEFX_BUILD_HLSL_SHADER_MODEL` (default: `6_3`): specifies the default HLSL shader model.
- `LITEFX_BUILD_HLSL_SHADER_MODEL` (default: `6_5`): specifies the default HLSL shader model.
- `LITEFX_BUILD_EXAMPLES` (default: `ON`): builds the examples. Depending on which backends are built, some may be omitted.
- `LITEFX_BUILD_EXAMPLES_DX12_PIX_LOADER` (default: `ON`): enables code that attempts to load the latest version of the [PIX GPU capturer](https://devblogs.microsoft.com/pix/) in the DirectX 12 samples, if available (and if the command line argument `--load-pix=true` is specified).
- `LITEFX_BUILD_EXAMPLES_RENDERDOC_LOADER` (default: `OFF`): enables code in the samples, that loads the [RenderDoc](https://renderdoc.org/) runtime API, if the application is launched from within RenderDoc (and if the command line argument `--load-render-doc=true` is specified).
Expand Down
1 change: 1 addition & 0 deletions docs/release-logs/0.4.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
- This also enables for more use cases, like using render targets in read-write bindings or sharing between different queues.
- Swap chains can now accept `present` calls without explicitly providing a frame buffer. ([See PR #114](https://github.com/crud89/LiteFX/pull/114))
- Build macros are now prefixed with `LITEFX_` to support portability. ([See PR #117](https://github.com/crud89/LiteFX/pull/117))
- Add optional support for mesh shaders (enable `LITEFX_BUILD_MESH_SHADER_SUPPORT` to turn it on). ([See PR #116](https://github.com/crud89/LiteFX/pull/116))

**🌋 Vulkan:**

Expand Down
8 changes: 8 additions & 0 deletions src/Backends/DirectX12/include/litefx/backends/dx12.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,9 @@ namespace LiteFX::Rendering::Backends {
public:
using base_type = CommandBuffer<DirectX12CommandBuffer, IDirectX12Buffer, IDirectX12VertexBuffer, IDirectX12IndexBuffer, IDirectX12Image, DirectX12Barrier, DirectX12PipelineState>;
using base_type::dispatch;
#ifdef LITEFX_BUILD_MESH_SHADER_SUPPORT
using base_type::dispatchMesh;
#endif
using base_type::draw;
using base_type::drawIndexed;
using base_type::barrier;
Expand Down Expand Up @@ -933,6 +936,11 @@ namespace LiteFX::Rendering::Backends {
/// <inheritdoc />
void dispatch(const Vector3u& threadCount) const noexcept override;

#ifdef LITEFX_BUILD_MESH_SHADER_SUPPORT
/// <inheritdoc />
void dispatchMesh (const Vector3u& threadCount) const noexcept override;
#endif

/// <inheritdoc />
void draw(UInt32 vertices, UInt32 instances = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0) const noexcept override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ namespace LiteFX::Rendering::Backends {
/// <param name="space">The space the descriptor set is bound to.</param>
/// <param name="stages">The shader stages, the descriptor set is accessible from.</param>
/// <param name="maxUnboundedArraySize">Ignored for DirectX 12, but required for compatibility.</param>
constexpr inline explicit DirectX12DescriptorSetLayoutBuilder(DirectX12PipelineLayoutBuilder& parent, UInt32 space = 0, ShaderStage stages = ShaderStage::Fragment | ShaderStage::Geometry | ShaderStage::TessellationControl | ShaderStage::TessellationEvaluation | ShaderStage::Vertex, UInt32 maxUnboundedArraySize = 0);
constexpr inline explicit DirectX12DescriptorSetLayoutBuilder(DirectX12PipelineLayoutBuilder& parent, UInt32 space = 0, ShaderStage stages = ShaderStage::Any, UInt32 maxUnboundedArraySize = 0);
DirectX12DescriptorSetLayoutBuilder(const DirectX12DescriptorSetLayoutBuilder&) = delete;
DirectX12DescriptorSetLayoutBuilder(DirectX12DescriptorSetLayoutBuilder&&) = delete;
constexpr inline virtual ~DirectX12DescriptorSetLayoutBuilder() noexcept;
Expand Down Expand Up @@ -237,7 +237,7 @@ namespace LiteFX::Rendering::Backends {
/// <param name="space">The space, the descriptor set is bound to.</param>
/// <param name="stages">The stages, the descriptor set will be accessible from.</param>
/// <param name="maxUnboundedArraySize">Unused for this backend.</param>
constexpr inline DirectX12DescriptorSetLayoutBuilder descriptorSet(UInt32 space = 0, ShaderStage stages = ShaderStage::Compute | ShaderStage::Fragment | ShaderStage::Geometry | ShaderStage::TessellationControl | ShaderStage::TessellationEvaluation | ShaderStage::Vertex, UInt32 maxUnboundedArraySize = 0);
constexpr inline DirectX12DescriptorSetLayoutBuilder descriptorSet(UInt32 space = 0, ShaderStage stages = ShaderStage::Any, UInt32 maxUnboundedArraySize = 0);

/// <summary>
/// Builds a new push constants layout for the pipeline layout.
Expand Down
7 changes: 7 additions & 0 deletions src/Backends/DirectX12/src/command_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,13 @@ void DirectX12CommandBuffer::dispatch(const Vector3u& threadCount) const noexcep
this->handle()->Dispatch(threadCount.x(), threadCount.y(), threadCount.z());
}

#ifdef LITEFX_BUILD_MESH_SHADER_SUPPORT
void DirectX12CommandBuffer::dispatchMesh(const Vector3u& threadCount) const noexcept
{
this->handle()->DispatchMesh(threadCount.x(), threadCount.y(), threadCount.z());
}
#endif

void DirectX12CommandBuffer::draw(UInt32 vertices, UInt32 instances, UInt32 firstVertex, UInt32 firstInstance) const noexcept
{
this->handle()->DrawInstanced(vertices, instances, firstVertex, firstInstance);
Expand Down
14 changes: 9 additions & 5 deletions src/Backends/DirectX12/src/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,16 @@ class DirectX12Device::DirectX12DeviceImpl : public Implement<DirectX12Device> {
private:
bool checkRequiredExtensions(ID3D12Device10* device)
{
D3D12_FEATURE_DATA_D3D12_OPTIONS12 options {};
raiseIfFailed(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS12, &options, sizeof(options)), "Unable to query device extensions.");
D3D12_FEATURE_DATA_D3D12_OPTIONS7 options7 {};
D3D12_FEATURE_DATA_D3D12_OPTIONS12 options12 {};
raiseIfFailed(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &options7, sizeof(options7)), "Unable to query device extensions.");
raiseIfFailed(device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS12, &options12, sizeof(options12)), "Unable to query device extensions.");

bool result = options.EnhancedBarriersSupported; // && ...

return result;
return
#ifdef LITEFX_BUILD_MESH_SHADER_SUPPORT
options7.MeshShaderTier >= D3D12_MESH_SHADER_TIER_1 &&
#endif
options12.EnhancedBarriersSupported;
}

public:
Expand Down
6 changes: 6 additions & 0 deletions src/Backends/DirectX12/src/pipeline_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class DirectX12PipelineLayout::DirectX12PipelineLayoutImpl : public Implement<Di
case ShaderStage::Fragment: rootParameter.InitAsConstants(range->size() / 4, range->binding(), range->space(), D3D12_SHADER_VISIBILITY_PIXEL); break;
case ShaderStage::TessellationEvaluation: rootParameter.InitAsConstants(range->size() / 4, range->binding(), range->space(), D3D12_SHADER_VISIBILITY_DOMAIN); break;
case ShaderStage::TessellationControl: rootParameter.InitAsConstants(range->size() / 4, range->binding(), range->space(), D3D12_SHADER_VISIBILITY_HULL); break;
case ShaderStage::Task: rootParameter.InitAsConstants(range->size() / 4, range->binding(), range->space(), D3D12_SHADER_VISIBILITY_AMPLIFICATION); break;
case ShaderStage::Mesh: rootParameter.InitAsConstants(range->size() / 4, range->binding(), range->space(), D3D12_SHADER_VISIBILITY_MESH); break;
default: rootParameter.InitAsConstants(range->size() / 4, range->binding(), range->space(), D3D12_SHADER_VISIBILITY_ALL); break;
}

Expand All @@ -118,6 +120,10 @@ class DirectX12PipelineLayout::DirectX12PipelineLayoutImpl : public Implement<Di
shaderStages = D3D12_SHADER_VISIBILITY_DOMAIN;
if (stages == ShaderStage::TessellationControl)
shaderStages = D3D12_SHADER_VISIBILITY_HULL;
if (stages == ShaderStage::Task)
shaderStages = D3D12_SHADER_VISIBILITY_AMPLIFICATION;
if (stages == ShaderStage::Mesh)
shaderStages = D3D12_SHADER_VISIBILITY_MESH;

// Define the root parameter ranges.
auto layouts = layout->descriptors();
Expand Down
Loading
Loading