Skip to content

Commit

Permalink
Use thread group count x/y/z for mesh draw commands (API253012)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Aug 7, 2023
1 parent 2b3d215 commit 3b55f31
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 31 deletions.
4 changes: 2 additions & 2 deletions Graphics/GraphicsEngine/include/DeviceContextBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ bool VerifyDispatchComputeAttribs (const DispatchComputeAttribs&
bool VerifyDispatchComputeIndirectAttribs(const DispatchComputeIndirectAttribs& Attribs);
// clang-format on

bool VerifyDrawMeshAttribs(Uint32 MaxDrawMeshTasksCount, const DrawMeshAttribs& Attribs);
bool VerifyDrawMeshAttribs(const MeshShaderProperties& MeshShaderProps, const DrawMeshAttribs& Attribs);
bool VerifyDrawMeshIndirectAttribs(const DrawMeshIndirectAttribs& Attribs, Uint32 IndirectCmdStride);

bool VerifyResolveTextureSubresourceAttribs(const ResolveTextureSubresourceAttribs& ResolveAttribs,
Expand Down Expand Up @@ -2170,7 +2170,7 @@ inline void DeviceContextBase<ImplementationTraits>::DvpVerifyDrawMeshArguments(
"DrawMesh command arguments are invalid: pipeline state '",
m_pPipelineState->GetDesc().Name, "' is not a mesh pipeline.");

DEV_CHECK_ERR(VerifyDrawMeshAttribs(m_pDevice->GetAdapterInfo().MeshShader.MaxTaskCount, Attribs), "DrawMeshAttribs are invalid");
DEV_CHECK_ERR(VerifyDrawMeshAttribs(m_pDevice->GetAdapterInfo().MeshShader, Attribs), "DrawMeshAttribs are invalid");
}

template <typename ImplementationTraits>
Expand Down
2 changes: 1 addition & 1 deletion Graphics/GraphicsEngine/interface/APIInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
/// \file
/// Diligent API information

#define DILIGENT_API_VERSION 253011
#define DILIGENT_API_VERSION 253012

#include "../../../Primitives/interface/BasicTypes.h"

Expand Down
37 changes: 30 additions & 7 deletions Graphics/GraphicsEngine/interface/DeviceContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,20 +540,43 @@ typedef struct DrawIndexedIndirectAttribs DrawIndexedIndirectAttribs;
/// This structure is used by IDeviceContext::DrawMesh().
struct DrawMeshAttribs
{
/// The number of dispatched groups
Uint32 ThreadGroupCount DEFAULT_INITIALIZER(1);
/// The number of groups dispatched in X direction.
Uint32 ThreadGroupCountX DEFAULT_INITIALIZER(1);

/// The number of groups dispatched in Y direction.
Uint32 ThreadGroupCountY DEFAULT_INITIALIZER(1);

/// The number of groups dispatched in Y direction.
Uint32 ThreadGroupCountZ DEFAULT_INITIALIZER(1);

/// Additional flags, see Diligent::DRAW_FLAGS.
DRAW_FLAGS Flags DEFAULT_INITIALIZER(DRAW_FLAG_NONE);
DRAW_FLAGS Flags DEFAULT_INITIALIZER(DRAW_FLAG_NONE);

#if DILIGENT_CPP_INTERFACE
/// Initializes the structure members with default values.
constexpr DrawMeshAttribs() noexcept {}

/// Initializes the structure with user-specified values.
constexpr DrawMeshAttribs(Uint32 _ThreadGroupCount,
DRAW_FLAGS _Flags) noexcept :
ThreadGroupCount {_ThreadGroupCount},
explicit constexpr DrawMeshAttribs(Uint32 _ThreadGroupCountX,
DRAW_FLAGS _Flags = DRAW_FLAG_NONE) noexcept :
ThreadGroupCountX{_ThreadGroupCountX},
Flags {_Flags}
{}

constexpr DrawMeshAttribs(Uint32 _ThreadGroupCountX,
Uint32 _ThreadGroupCountY,
DRAW_FLAGS _Flags = DRAW_FLAG_NONE) noexcept :
ThreadGroupCountX{_ThreadGroupCountX},
ThreadGroupCountY{_ThreadGroupCountY},
Flags {_Flags}
{}

constexpr DrawMeshAttribs(Uint32 _ThreadGroupCountX,
Uint32 _ThreadGroupCountY,
Uint32 _ThreadGroupCountZ,
DRAW_FLAGS _Flags = DRAW_FLAG_NONE) noexcept :
ThreadGroupCountX{_ThreadGroupCountX},
ThreadGroupCountY{_ThreadGroupCountY},
ThreadGroupCountZ{_ThreadGroupCountZ},
Flags {_Flags}
{}
#endif
Expand Down
18 changes: 15 additions & 3 deletions Graphics/GraphicsEngine/interface/GraphicsTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -2254,8 +2254,17 @@ typedef struct RayTracingProperties RayTracingProperties;
/// Mesh Shader Properties
struct MeshShaderProperties
{
/// The maximum number of mesh shader tasks per draw command.
Uint32 MaxTaskCount DEFAULT_INITIALIZER(0);
/// The maximum number of mesh shader thread groups in X direction.
Uint32 MaxThreadGroupCountX DEFAULT_INITIALIZER(0);

/// The maximum number of mesh shader thread groups in Y direction.
Uint32 MaxThreadGroupCountY DEFAULT_INITIALIZER(0);

/// The maximum number of mesh shader thread groups in Z direction.
Uint32 MaxThreadGroupCountZ DEFAULT_INITIALIZER(0);

/// The total maximum number of mesh shader groups per draw command.
Uint32 MaxThreadGroupTotalCount DEFAULT_INITIALIZER(0);

#if DILIGENT_CPP_INTERFACE
/// Comparison operator tests if two structures are equivalent
Expand All @@ -2266,7 +2275,10 @@ struct MeshShaderProperties
/// - False otherwise.
constexpr bool operator==(const MeshShaderProperties& RHS) const
{
return MaxTaskCount == RHS.MaxTaskCount;
return MaxThreadGroupCountX == RHS.MaxThreadGroupCountX &&
MaxThreadGroupCountY == RHS.MaxThreadGroupCountY &&
MaxThreadGroupCountZ == RHS.MaxThreadGroupCountZ &&
MaxThreadGroupTotalCount == RHS.MaxThreadGroupTotalCount;
}
#endif
};
Expand Down
30 changes: 23 additions & 7 deletions Graphics/GraphicsEngine/src/DeviceContextBase.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 Diligent Graphics LLC
* Copyright 2019-2023 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -77,15 +77,31 @@ bool VerifyDrawIndexedAttribs(const DrawIndexedAttribs& Attribs)
return true;
}

bool VerifyDrawMeshAttribs(Uint32 MaxDrawMeshTasksCount, const DrawMeshAttribs& Attribs)
bool VerifyDrawMeshAttribs(const MeshShaderProperties& MeshShaderProps, const DrawMeshAttribs& Attribs)
{
#define CHECK_DRAW_MESH_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw mesh attribs are invalid: ", __VA_ARGS__)

if (Attribs.ThreadGroupCount == 0)
LOG_INFO_MESSAGE("DrawMeshAttribs.ThreadGroupCount is 0. This is OK as the draw command will be ignored, but may be unintentional.");

CHECK_DRAW_MESH_ATTRIBS(Attribs.ThreadGroupCount <= MaxDrawMeshTasksCount,
"ThreadGroupCount (", Attribs.ThreadGroupCount, ") must not exceed ", MaxDrawMeshTasksCount);
if (Attribs.ThreadGroupCountX == 0)
LOG_INFO_MESSAGE("DrawMeshAttribs.ThreadGroupCountX is 0. This is OK as the draw command will be ignored, but may be unintentional.");
if (Attribs.ThreadGroupCountY == 0)
LOG_INFO_MESSAGE("DrawMeshAttribs.ThreadGroupCountY is 0. This is OK as the draw command will be ignored, but may be unintentional.");
if (Attribs.ThreadGroupCountZ == 0)
LOG_INFO_MESSAGE("DrawMeshAttribs.ThreadGroupCountZ is 0. This is OK as the draw command will be ignored, but may be unintentional.");

CHECK_DRAW_MESH_ATTRIBS(Attribs.ThreadGroupCountX <= MeshShaderProps.MaxThreadGroupCountX,
"ThreadGroupCountX (", Attribs.ThreadGroupCountX, ") must not exceed MeshShaderProps.MaxThreadGroupCountX (",
MeshShaderProps.MaxThreadGroupCountX, ").");
CHECK_DRAW_MESH_ATTRIBS(Attribs.ThreadGroupCountY <= MeshShaderProps.MaxThreadGroupCountY,
"ThreadGroupCountY (", Attribs.ThreadGroupCountY, ") must not exceed MeshShaderProps.MaxThreadGroupCountY (",
MeshShaderProps.MaxThreadGroupCountY, ").");
CHECK_DRAW_MESH_ATTRIBS(Attribs.ThreadGroupCountZ <= MeshShaderProps.MaxThreadGroupCountZ,
"ThreadGroupCountZ (", Attribs.ThreadGroupCountZ, ") must not exceed MeshShaderProps.MaxThreadGroupCountZ (",
MeshShaderProps.MaxThreadGroupCountZ, ").");

const auto TotalGroups = Uint64{Attribs.ThreadGroupCountX} * Uint64{Attribs.ThreadGroupCountY} * Uint64{Attribs.ThreadGroupCountZ};
CHECK_DRAW_MESH_ATTRIBS(TotalGroups <= MeshShaderProps.MaxThreadGroupTotalCount,
"Total thread group count (", TotalGroups, ") must not exceed MeshShaderProps.MaxThreadGroupTotalCount (",
MeshShaderProps.MaxThreadGroupTotalCount, ").");

#undef CHECK_DRAW_MESH_ATTRIBS

Expand Down
4 changes: 2 additions & 2 deletions Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,9 +794,9 @@ void DeviceContextD3D12Impl::DrawMesh(const DrawMeshAttribs& Attribs)
auto& GraphCtx = GetCmdContext().AsGraphicsContext6();
PrepareForDraw(GraphCtx, Attribs.Flags);

if (Attribs.ThreadGroupCount > 0)
if (Attribs.ThreadGroupCountX > 0 && Attribs.ThreadGroupCountY > 0 && Attribs.ThreadGroupCountZ > 0)
{
GraphCtx.DrawMesh(Attribs.ThreadGroupCount, 1, 1);
GraphCtx.DrawMesh(Attribs.ThreadGroupCountX, Attribs.ThreadGroupCountY, Attribs.ThreadGroupCountZ);
++m_State.NumCommands;
}
}
Expand Down
9 changes: 6 additions & 3 deletions Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2022 Diligent Graphics LLC
* Copyright 2019-2023 Diligent Graphics LLC
* Copyright 2015-2019 Egor Yusov
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -760,8 +760,11 @@ GraphicsAdapterInfo EngineFactoryD3D12Impl::GetGraphicsAdapterInfo(void*
Features.MeshShaders = DEVICE_FEATURE_STATE_ENABLED;

auto& MeshProps{AdapterInfo.MeshShader};
MeshProps.MaxTaskCount = 64000; // from specs: https://microsoft.github.io/DirectX-Specs/d3d/MeshShader.html#dispatchmesh-api
ASSERT_SIZEOF(MeshProps, 4, "Did you add a new member to MeshShaderProperties? Please initialize it here.");
MeshProps.MaxThreadGroupCountX = 65536; // from specs: https://microsoft.github.io/DirectX-Specs/d3d/MeshShader.html#dispatchmesh-api
MeshProps.MaxThreadGroupCountY = 65536;
MeshProps.MaxThreadGroupCountZ = 65536;
MeshProps.MaxThreadGroupTotalCount = 1u << 22u;
ASSERT_SIZEOF(MeshProps, 16, "Did you add a new member to MeshShaderProperties? Please initialize it here.");
}

Features.ShaderResourceRuntimeArray = DEVICE_FEATURE_STATE_ENABLED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,14 @@ class VulkanCommandBuffer
#endif
}

__forceinline void DrawMesh(uint32_t TaskCount, uint32_t FirstTask)
__forceinline void DrawMesh(uint32_t TaskCountX, uint32_t TaskCountY, uint32_t TaskCountZ)
{
#if DILIGENT_USE_VOLK
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "vkCmdDrawMeshTasksEXT() must be called inside render pass");
VERIFY(m_State.GraphicsPipeline != VK_NULL_HANDLE, "No graphics pipeline bound");

vkCmdDrawMeshTasksEXT(m_VkCmdBuffer, TaskCount, 1, 1);
vkCmdDrawMeshTasksEXT(m_VkCmdBuffer, TaskCountX, TaskCountY, TaskCountZ);
#else
UNSUPPORTED("DrawMesh is not supported when vulkan library is linked statically");
#endif
Expand Down
4 changes: 2 additions & 2 deletions Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -909,9 +909,9 @@ void DeviceContextVkImpl::DrawMesh(const DrawMeshAttribs& Attribs)

PrepareForDraw(Attribs.Flags);

if (Attribs.ThreadGroupCount > 0)
if (Attribs.ThreadGroupCountX > 0 && Attribs.ThreadGroupCountY > 0 && Attribs.ThreadGroupCountZ > 0)
{
m_CommandBuffer.DrawMesh(Attribs.ThreadGroupCount, 0);
m_CommandBuffer.DrawMesh(Attribs.ThreadGroupCountX, Attribs.ThreadGroupCountY, Attribs.ThreadGroupCountZ);
++m_State.NumCommands;
}
}
Expand Down
7 changes: 5 additions & 2 deletions Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,11 @@ GraphicsAdapterInfo GetPhysicalDeviceGraphicsAdapterInfo(const VulkanUtilities::
if (AdapterInfo.Features.MeshShaders)
{
auto& MeshProps{AdapterInfo.MeshShader};
MeshProps.MaxTaskCount = vkDeviceExtProps.MeshShader.maxTaskWorkGroupCount[0];
ASSERT_SIZEOF(MeshProps, 4, "Did you add a new member to MeshShaderProperties? Please initialize it here.");
MeshProps.MaxThreadGroupCountX = vkDeviceExtProps.MeshShader.maxMeshWorkGroupCount[0];
MeshProps.MaxThreadGroupCountY = vkDeviceExtProps.MeshShader.maxMeshWorkGroupCount[1];
MeshProps.MaxThreadGroupCountZ = vkDeviceExtProps.MeshShader.maxMeshWorkGroupCount[2];
MeshProps.MaxThreadGroupTotalCount = vkDeviceExtProps.MeshShader.maxMeshWorkGroupTotalCount;
ASSERT_SIZEOF(MeshProps, 16, "Did you add a new member to MeshShaderProperties? Please initialize it here.");
}

// Compute shader properties
Expand Down
1 change: 1 addition & 0 deletions ReleaseHistory.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Current progress

* Use thread group count X/Y/Z for mesh draw commands (API253012)
* Added `ShaderMacroArray` struct (API253011)
* The `Macros` member of `ShaderCreateInfo` struct is now of type `ShaderMacroArray`
* Replaced `ResourceMappingDesc` with `ResourceMappingCreateInfo` (API253010)
Expand Down

0 comments on commit 3b55f31

Please sign in to comment.