summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2023-09-12 11:13:11 +0800
committerGitHub <noreply@github.com>2023-09-11 20:13:11 -0700
commit09854a4596019ddb3bb315b8836b5c88e718cdc7 (patch)
tree1556ae3e00da0fac91343f159b52cee1231a7fab /tools
parent87bb0b503544f1b8c6ec818e25c695b31cda24b7 (diff)
Add Mesh and Task shader support to GFX (#3190)
* Bump vulkan headers Also just use vulkan-headers as a submodule * Add drawMeshTasks to gfx graphics pipelines * Add DispatchMesh overload with no payload, with GLSL intrinsic * Require spirv 1.4 for mesh shaders * Add vulkan mesh shader feature discovery * Add mesh shader stage bits to vk-util * Add mesh and task shader support to render-test * Add mesh and task tests * Preserve "payload" specifier in task shaders * Add mesh shader pipeline support to gfx * Add TODO * Add numThreads attribute for amplification stage * Add payload to task shader test * Drop dependency on d3dx12 * Allow passing payloads from task to mesh shaders * regenerate vs projects * check DispatchMesh name correctly * Add mesh shader tests to failing tests * Detect wave-ops feature on vulkan * Add fuse-product to expected failures This fails because the global varaible `count` is not initialized * Add required extension to WaveMaskMatch SPIR-V impl * Remove meshShader member from pipeline desc * Identify mesh shader support on d3d12
Diffstat (limited to 'tools')
-rw-r--r--tools/gfx/d3d12/d3d12-command-buffer.cpp7
-rw-r--r--tools/gfx/d3d12/d3d12-command-buffer.h1
-rw-r--r--tools/gfx/d3d12/d3d12-command-encoder.cpp8
-rw-r--r--tools/gfx/d3d12/d3d12-command-encoder.h4
-rw-r--r--tools/gfx/d3d12/d3d12-device.cpp12
-rw-r--r--tools/gfx/d3d12/d3d12-pipeline-state-stream.h484
-rw-r--r--tools/gfx/d3d12/d3d12-pipeline-state.cpp319
-rw-r--r--tools/gfx/d3d12/d3d12-sal-defs.h199
-rw-r--r--tools/gfx/debug-layer/debug-command-encoder.cpp6
-rw-r--r--tools/gfx/debug-layer/debug-command-encoder.h3
-rw-r--r--tools/gfx/immediate-renderer-base.cpp5
-rw-r--r--tools/gfx/renderer-shared.cpp20
-rw-r--r--tools/gfx/renderer-shared.h2
-rw-r--r--tools/gfx/vulkan/vk-api.h6
-rw-r--r--tools/gfx/vulkan/vk-command-encoder.cpp8
-rw-r--r--tools/gfx/vulkan/vk-command-encoder.h3
-rw-r--r--tools/gfx/vulkan/vk-device.cpp34
-rw-r--r--tools/gfx/vulkan/vk-pipeline-state.cpp5
-rw-r--r--tools/gfx/vulkan/vk-util.cpp4
-rw-r--r--tools/render-test/options.cpp8
-rw-r--r--tools/render-test/options.h8
-rw-r--r--tools/render-test/render-test-main.cpp31
-rw-r--r--tools/render-test/slang-support.cpp35
23 files changed, 1072 insertions, 140 deletions
diff --git a/tools/gfx/d3d12/d3d12-command-buffer.cpp b/tools/gfx/d3d12/d3d12-command-buffer.cpp
index 3a09da037..fb979d3b9 100644
--- a/tools/gfx/d3d12/d3d12-command-buffer.cpp
+++ b/tools/gfx/d3d12/d3d12-command-buffer.cpp
@@ -59,6 +59,13 @@ void CommandBufferImpl::init(
reinit();
+ m_cmdList->QueryInterface<ID3D12GraphicsCommandList6>(m_cmdList6.writeRef());
+if (m_cmdList6)
+ {
+ m_cmdList4 = m_cmdList6;
+ m_cmdList1 = m_cmdList6;
+ return;
+ }
#if SLANG_GFX_HAS_DXR_SUPPORT
m_cmdList->QueryInterface<ID3D12GraphicsCommandList4>(m_cmdList4.writeRef());
if (m_cmdList4)
diff --git a/tools/gfx/d3d12/d3d12-command-buffer.h b/tools/gfx/d3d12/d3d12-command-buffer.h
index 0b24764c1..1cc6e8850 100644
--- a/tools/gfx/d3d12/d3d12-command-buffer.h
+++ b/tools/gfx/d3d12/d3d12-command-buffer.h
@@ -37,6 +37,7 @@ public:
ComPtr<ID3D12GraphicsCommandList> m_cmdList;
ComPtr<ID3D12GraphicsCommandList1> m_cmdList1;
ComPtr<ID3D12GraphicsCommandList4> m_cmdList4;
+ ComPtr<ID3D12GraphicsCommandList6> m_cmdList6;
BreakableReference<TransientResourceHeapImpl> m_transientHeap;
// Weak reference is fine here since `m_transientHeap` already holds strong reference to
diff --git a/tools/gfx/d3d12/d3d12-command-encoder.cpp b/tools/gfx/d3d12/d3d12-command-encoder.cpp
index 167c464d6..e4d03193b 100644
--- a/tools/gfx/d3d12/d3d12-command-encoder.cpp
+++ b/tools/gfx/d3d12/d3d12-command-encoder.cpp
@@ -41,6 +41,7 @@ void PipelineCommandEncoder::init(CommandBufferImpl* commandBuffer)
{
m_commandBuffer = commandBuffer;
m_d3dCmdList = m_commandBuffer->m_cmdList;
+ m_d3dCmdList6 = m_commandBuffer->m_cmdList6;
m_renderer = commandBuffer->m_renderer;
m_transientHeap = commandBuffer->m_transientHeap;
m_device = commandBuffer->m_renderer->m_device;
@@ -1185,6 +1186,13 @@ Result RenderCommandEncoderImpl::drawIndexedInstanced(
return SLANG_OK;
}
+Result RenderCommandEncoderImpl::drawMeshTasks(int x, int y, int z)
+{
+ SLANG_RETURN_ON_FAIL(prepareDraw());
+ m_d3dCmdList6->DispatchMesh(x, y, z);
+ return SLANG_OK;
+}
+
void ComputeCommandEncoderImpl::endEncoding() { PipelineCommandEncoder::endEncodingImpl(); }
void ComputeCommandEncoderImpl::init(
diff --git a/tools/gfx/d3d12/d3d12-command-encoder.h b/tools/gfx/d3d12/d3d12-command-encoder.h
index 4190e985c..0632084cf 100644
--- a/tools/gfx/d3d12/d3d12-command-encoder.h
+++ b/tools/gfx/d3d12/d3d12-command-encoder.h
@@ -26,6 +26,7 @@ public:
DeviceImpl* m_renderer;
ID3D12Device* m_device;
ID3D12GraphicsCommandList* m_d3dCmdList;
+ ID3D12GraphicsCommandList6* m_d3dCmdList6;
ID3D12GraphicsCommandList* m_preCmdList = nullptr;
RefPtr<PipelineStateBase> m_currentPipeline;
@@ -290,6 +291,9 @@ public:
GfxIndex startIndexLocation,
GfxIndex baseVertexLocation,
GfxIndex startInstanceLocation) override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ drawMeshTasks(int x, int y, int z) override;
};
#if SLANG_GFX_HAS_DXR_SUPPORT
diff --git a/tools/gfx/d3d12/d3d12-device.cpp b/tools/gfx/d3d12/d3d12-device.cpp
index 3f62c2d5c..ca624b99f 100644
--- a/tools/gfx/d3d12/d3d12-device.cpp
+++ b/tools/gfx/d3d12/d3d12-device.cpp
@@ -783,6 +783,18 @@ Result DeviceImpl::initialize(const Desc& desc)
}
}
}
+ // Check mesh shader support
+ {
+ D3D12_FEATURE_DATA_D3D12_OPTIONS7 options;
+ if (SLANG_SUCCEEDED(m_device->CheckFeatureSupport(
+ D3D12_FEATURE_D3D12_OPTIONS7, &options, sizeof(options))))
+ {
+ if (options.MeshShaderTier >= D3D12_MESH_SHADER_TIER_1)
+ {
+ m_features.add("mesh-shader");
+ }
+ }
+ }
}
m_desc = desc;
diff --git a/tools/gfx/d3d12/d3d12-pipeline-state-stream.h b/tools/gfx/d3d12/d3d12-pipeline-state-stream.h
new file mode 100644
index 000000000..9848e96f9
--- /dev/null
+++ b/tools/gfx/d3d12/d3d12-pipeline-state-stream.h
@@ -0,0 +1,484 @@
+#pragma once
+
+//
+// The CD3DX12_PIPELINE_STATE_STREAM2 struct and dependencies extracted from
+// `d3dx12_pipeline_state_stream.h`. Attribution Microsoft.
+//
+
+#include <climits>
+#include <d3d12.h>
+#include <dxgi1_4.h>
+
+#include "d3d12-sal-defs.h"
+
+struct CD3DX12_DEFAULT {};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC
+{
+ CD3DX12_DEPTH_STENCIL_DESC() = default;
+ explicit CD3DX12_DEPTH_STENCIL_DESC( const D3D12_DEPTH_STENCIL_DESC& o ) noexcept :
+ D3D12_DEPTH_STENCIL_DESC( o )
+ {}
+ explicit CD3DX12_DEPTH_STENCIL_DESC( CD3DX12_DEFAULT ) noexcept
+ {
+ DepthEnable = TRUE;
+ DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
+ DepthFunc = D3D12_COMPARISON_FUNC_LESS;
+ StencilEnable = FALSE;
+ StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
+ StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
+ const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =
+ { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };
+ FrontFace = defaultStencilOp;
+ BackFace = defaultStencilOp;
+ }
+ explicit CD3DX12_DEPTH_STENCIL_DESC(
+ BOOL depthEnable,
+ D3D12_DEPTH_WRITE_MASK depthWriteMask,
+ D3D12_COMPARISON_FUNC depthFunc,
+ BOOL stencilEnable,
+ UINT8 stencilReadMask,
+ UINT8 stencilWriteMask,
+ D3D12_STENCIL_OP frontStencilFailOp,
+ D3D12_STENCIL_OP frontStencilDepthFailOp,
+ D3D12_STENCIL_OP frontStencilPassOp,
+ D3D12_COMPARISON_FUNC frontStencilFunc,
+ D3D12_STENCIL_OP backStencilFailOp,
+ D3D12_STENCIL_OP backStencilDepthFailOp,
+ D3D12_STENCIL_OP backStencilPassOp,
+ D3D12_COMPARISON_FUNC backStencilFunc ) noexcept
+ {
+ DepthEnable = depthEnable;
+ DepthWriteMask = depthWriteMask;
+ DepthFunc = depthFunc;
+ StencilEnable = stencilEnable;
+ StencilReadMask = stencilReadMask;
+ StencilWriteMask = stencilWriteMask;
+ FrontFace.StencilFailOp = frontStencilFailOp;
+ FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;
+ FrontFace.StencilPassOp = frontStencilPassOp;
+ FrontFace.StencilFunc = frontStencilFunc;
+ BackFace.StencilFailOp = backStencilFailOp;
+ BackFace.StencilDepthFailOp = backStencilDepthFailOp;
+ BackFace.StencilPassOp = backStencilPassOp;
+ BackFace.StencilFunc = backStencilFunc;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_DEPTH_STENCIL_DESC1 : public D3D12_DEPTH_STENCIL_DESC1
+{
+ CD3DX12_DEPTH_STENCIL_DESC1() = default;
+ explicit CD3DX12_DEPTH_STENCIL_DESC1( const D3D12_DEPTH_STENCIL_DESC1& o ) noexcept :
+ D3D12_DEPTH_STENCIL_DESC1( o )
+ {}
+ explicit CD3DX12_DEPTH_STENCIL_DESC1( const D3D12_DEPTH_STENCIL_DESC& o ) noexcept
+ {
+ DepthEnable = o.DepthEnable;
+ DepthWriteMask = o.DepthWriteMask;
+ DepthFunc = o.DepthFunc;
+ StencilEnable = o.StencilEnable;
+ StencilReadMask = o.StencilReadMask;
+ StencilWriteMask = o.StencilWriteMask;
+ FrontFace.StencilFailOp = o.FrontFace.StencilFailOp;
+ FrontFace.StencilDepthFailOp = o.FrontFace.StencilDepthFailOp;
+ FrontFace.StencilPassOp = o.FrontFace.StencilPassOp;
+ FrontFace.StencilFunc = o.FrontFace.StencilFunc;
+ BackFace.StencilFailOp = o.BackFace.StencilFailOp;
+ BackFace.StencilDepthFailOp = o.BackFace.StencilDepthFailOp;
+ BackFace.StencilPassOp = o.BackFace.StencilPassOp;
+ BackFace.StencilFunc = o.BackFace.StencilFunc;
+ DepthBoundsTestEnable = FALSE;
+ }
+ explicit CD3DX12_DEPTH_STENCIL_DESC1( CD3DX12_DEFAULT ) noexcept
+ {
+ DepthEnable = TRUE;
+ DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
+ DepthFunc = D3D12_COMPARISON_FUNC_LESS;
+ StencilEnable = FALSE;
+ StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
+ StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
+ const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =
+ { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };
+ FrontFace = defaultStencilOp;
+ BackFace = defaultStencilOp;
+ DepthBoundsTestEnable = FALSE;
+ }
+ explicit CD3DX12_DEPTH_STENCIL_DESC1(
+ BOOL depthEnable,
+ D3D12_DEPTH_WRITE_MASK depthWriteMask,
+ D3D12_COMPARISON_FUNC depthFunc,
+ BOOL stencilEnable,
+ UINT8 stencilReadMask,
+ UINT8 stencilWriteMask,
+ D3D12_STENCIL_OP frontStencilFailOp,
+ D3D12_STENCIL_OP frontStencilDepthFailOp,
+ D3D12_STENCIL_OP frontStencilPassOp,
+ D3D12_COMPARISON_FUNC frontStencilFunc,
+ D3D12_STENCIL_OP backStencilFailOp,
+ D3D12_STENCIL_OP backStencilDepthFailOp,
+ D3D12_STENCIL_OP backStencilPassOp,
+ D3D12_COMPARISON_FUNC backStencilFunc,
+ BOOL depthBoundsTestEnable ) noexcept
+ {
+ DepthEnable = depthEnable;
+ DepthWriteMask = depthWriteMask;
+ DepthFunc = depthFunc;
+ StencilEnable = stencilEnable;
+ StencilReadMask = stencilReadMask;
+ StencilWriteMask = stencilWriteMask;
+ FrontFace.StencilFailOp = frontStencilFailOp;
+ FrontFace.StencilDepthFailOp = frontStencilDepthFailOp;
+ FrontFace.StencilPassOp = frontStencilPassOp;
+ FrontFace.StencilFunc = frontStencilFunc;
+ BackFace.StencilFailOp = backStencilFailOp;
+ BackFace.StencilDepthFailOp = backStencilDepthFailOp;
+ BackFace.StencilPassOp = backStencilPassOp;
+ BackFace.StencilFunc = backStencilFunc;
+ DepthBoundsTestEnable = depthBoundsTestEnable;
+ }
+ operator D3D12_DEPTH_STENCIL_DESC() const noexcept
+ {
+ D3D12_DEPTH_STENCIL_DESC D;
+ D.DepthEnable = DepthEnable;
+ D.DepthWriteMask = DepthWriteMask;
+ D.DepthFunc = DepthFunc;
+ D.StencilEnable = StencilEnable;
+ D.StencilReadMask = StencilReadMask;
+ D.StencilWriteMask = StencilWriteMask;
+ D.FrontFace.StencilFailOp = FrontFace.StencilFailOp;
+ D.FrontFace.StencilDepthFailOp = FrontFace.StencilDepthFailOp;
+ D.FrontFace.StencilPassOp = FrontFace.StencilPassOp;
+ D.FrontFace.StencilFunc = FrontFace.StencilFunc;
+ D.BackFace.StencilFailOp = BackFace.StencilFailOp;
+ D.BackFace.StencilDepthFailOp = BackFace.StencilDepthFailOp;
+ D.BackFace.StencilPassOp = BackFace.StencilPassOp;
+ D.BackFace.StencilFunc = BackFace.StencilFunc;
+ return D;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC
+{
+ CD3DX12_BLEND_DESC() = default;
+ explicit CD3DX12_BLEND_DESC( const D3D12_BLEND_DESC& o ) noexcept :
+ D3D12_BLEND_DESC( o )
+ {}
+ explicit CD3DX12_BLEND_DESC( CD3DX12_DEFAULT ) noexcept
+ {
+ AlphaToCoverageEnable = FALSE;
+ IndependentBlendEnable = FALSE;
+ const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =
+ {
+ FALSE,FALSE,
+ D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
+ D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
+ D3D12_LOGIC_OP_NOOP,
+ D3D12_COLOR_WRITE_ENABLE_ALL,
+ };
+ for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
+ RenderTarget[ i ] = defaultRenderTargetBlendDesc;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_RASTERIZER_DESC : public D3D12_RASTERIZER_DESC
+{
+ CD3DX12_RASTERIZER_DESC() = default;
+ explicit CD3DX12_RASTERIZER_DESC( const D3D12_RASTERIZER_DESC& o ) noexcept :
+ D3D12_RASTERIZER_DESC( o )
+ {}
+ explicit CD3DX12_RASTERIZER_DESC( CD3DX12_DEFAULT ) noexcept
+ {
+ FillMode = D3D12_FILL_MODE_SOLID;
+ CullMode = D3D12_CULL_MODE_BACK;
+ FrontCounterClockwise = FALSE;
+ DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
+ DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
+ SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
+ DepthClipEnable = TRUE;
+ MultisampleEnable = FALSE;
+ AntialiasedLineEnable = FALSE;
+ ForcedSampleCount = 0;
+ ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
+ }
+ explicit CD3DX12_RASTERIZER_DESC(
+ D3D12_FILL_MODE fillMode,
+ D3D12_CULL_MODE cullMode,
+ BOOL frontCounterClockwise,
+ INT depthBias,
+ FLOAT depthBiasClamp,
+ FLOAT slopeScaledDepthBias,
+ BOOL depthClipEnable,
+ BOOL multisampleEnable,
+ BOOL antialiasedLineEnable,
+ UINT forcedSampleCount,
+ D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster) noexcept
+ {
+ FillMode = fillMode;
+ CullMode = cullMode;
+ FrontCounterClockwise = frontCounterClockwise;
+ DepthBias = depthBias;
+ DepthBiasClamp = depthBiasClamp;
+ SlopeScaledDepthBias = slopeScaledDepthBias;
+ DepthClipEnable = depthClipEnable;
+ MultisampleEnable = multisampleEnable;
+ AntialiasedLineEnable = antialiasedLineEnable;
+ ForcedSampleCount = forcedSampleCount;
+ ConservativeRaster = conservativeRaster;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_VIEW_INSTANCING_DESC : public D3D12_VIEW_INSTANCING_DESC
+{
+ CD3DX12_VIEW_INSTANCING_DESC() = default;
+ explicit CD3DX12_VIEW_INSTANCING_DESC( const D3D12_VIEW_INSTANCING_DESC& o ) noexcept :
+ D3D12_VIEW_INSTANCING_DESC( o )
+ {}
+ explicit CD3DX12_VIEW_INSTANCING_DESC( CD3DX12_DEFAULT ) noexcept
+ {
+ ViewInstanceCount = 0;
+ pViewInstanceLocations = nullptr;
+ Flags = D3D12_VIEW_INSTANCING_FLAG_NONE;
+ }
+ explicit CD3DX12_VIEW_INSTANCING_DESC(
+ UINT InViewInstanceCount,
+ const D3D12_VIEW_INSTANCE_LOCATION* InViewInstanceLocations,
+ D3D12_VIEW_INSTANCING_FLAGS InFlags) noexcept
+ {
+ ViewInstanceCount = InViewInstanceCount;
+ pViewInstanceLocations = InViewInstanceLocations;
+ Flags = InFlags;
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_RT_FORMAT_ARRAY : public D3D12_RT_FORMAT_ARRAY
+{
+ CD3DX12_RT_FORMAT_ARRAY() = default;
+ explicit CD3DX12_RT_FORMAT_ARRAY(const D3D12_RT_FORMAT_ARRAY& o) noexcept
+ : D3D12_RT_FORMAT_ARRAY(o)
+ {}
+ explicit CD3DX12_RT_FORMAT_ARRAY(_In_reads_(NumFormats) const DXGI_FORMAT* pFormats, UINT NumFormats) noexcept
+ {
+ NumRenderTargets = NumFormats;
+ memcpy(RTFormats, pFormats, sizeof(RTFormats));
+ // assumes ARRAY_SIZE(pFormats) == ARRAY_SIZE(RTFormats)
+ }
+};
+
+//------------------------------------------------------------------------------------------------
+struct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE
+{
+ CD3DX12_SHADER_BYTECODE() = default;
+ explicit CD3DX12_SHADER_BYTECODE(const D3D12_SHADER_BYTECODE &o) noexcept :
+ D3D12_SHADER_BYTECODE(o)
+ {}
+ CD3DX12_SHADER_BYTECODE(
+ _In_ ID3DBlob* pShaderBlob ) noexcept
+ {
+ pShaderBytecode = pShaderBlob->GetBufferPointer();
+ BytecodeLength = pShaderBlob->GetBufferSize();
+ }
+ CD3DX12_SHADER_BYTECODE(
+ const void* _pShaderBytecode,
+ SIZE_T bytecodeLength ) noexcept
+ {
+ pShaderBytecode = _pShaderBytecode;
+ BytecodeLength = bytecodeLength;
+ }
+};
+
+struct DefaultSampleMask { operator UINT() noexcept { return UINT_MAX; } };
+struct DefaultSampleDesc { operator DXGI_SAMPLE_DESC() noexcept { return DXGI_SAMPLE_DESC{1, 0}; } };
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable : 4324)
+#endif
+template <typename InnerStructType, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type, typename DefaultArg = InnerStructType>
+class alignas(void*) CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT
+{
+private:
+ D3D12_PIPELINE_STATE_SUBOBJECT_TYPE pssType;
+ InnerStructType pssInner;
+public:
+ CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT() noexcept : pssType(Type), pssInner(DefaultArg()) {}
+ CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT(InnerStructType const& i) noexcept : pssType(Type), pssInner(i) {}
+ CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT& operator=(InnerStructType const& i) noexcept { pssType = Type; pssInner = i; return *this; }
+ operator InnerStructType const&() const noexcept { return pssInner; }
+ operator InnerStructType&() noexcept { return pssInner; }
+ InnerStructType* operator&() noexcept { return &pssInner; }
+ InnerStructType const* operator&() const noexcept { return &pssInner; }
+};
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PIPELINE_STATE_FLAGS, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS> CD3DX12_PIPELINE_STATE_STREAM_FLAGS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK> CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< ID3D12RootSignature*, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_INPUT_LAYOUT_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT> CD3DX12_PIPELINE_STATE_STREAM_INPUT_LAYOUT;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_INDEX_BUFFER_STRIP_CUT_VALUE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_IB_STRIP_CUT_VALUE> CD3DX12_PIPELINE_STATE_STREAM_IB_STRIP_CUT_VALUE;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PRIMITIVE_TOPOLOGY_TYPE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY> CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS> CD3DX12_PIPELINE_STATE_STREAM_VS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS> CD3DX12_PIPELINE_STATE_STREAM_GS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_STREAM_OUTPUT_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT> CD3DX12_PIPELINE_STATE_STREAM_STREAM_OUTPUT;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS> CD3DX12_PIPELINE_STATE_STREAM_HS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS> CD3DX12_PIPELINE_STATE_STREAM_DS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS> CD3DX12_PIPELINE_STATE_STREAM_PS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_AS> CD3DX12_PIPELINE_STATE_STREAM_AS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MS> CD3DX12_PIPELINE_STATE_STREAM_MS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS> CD3DX12_PIPELINE_STATE_STREAM_CS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_BLEND_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_DEPTH_STENCIL_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_DEPTH_STENCIL_DESC1, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL1, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL1;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_FORMAT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_RASTERIZER_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_RT_FORMAT_ARRAY, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS> CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_SAMPLE_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC, DefaultSampleDesc> CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK, DefaultSampleMask> CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_CACHED_PIPELINE_STATE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO> CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO;
+typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_VIEW_INSTANCING_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VIEW_INSTANCING, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_VIEW_INSTANCING;
+
+struct D3DX12_MESH_SHADER_PIPELINE_STATE_DESC
+{
+ ID3D12RootSignature* pRootSignature;
+ D3D12_SHADER_BYTECODE AS;
+ D3D12_SHADER_BYTECODE MS;
+ D3D12_SHADER_BYTECODE PS;
+ D3D12_BLEND_DESC BlendState;
+ UINT SampleMask;
+ D3D12_RASTERIZER_DESC RasterizerState;
+ D3D12_DEPTH_STENCIL_DESC DepthStencilState;
+ D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType;
+ UINT NumRenderTargets;
+ DXGI_FORMAT RTVFormats[ D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT ];
+ DXGI_FORMAT DSVFormat;
+ DXGI_SAMPLE_DESC SampleDesc;
+ UINT NodeMask;
+ D3D12_CACHED_PIPELINE_STATE CachedPSO;
+ D3D12_PIPELINE_STATE_FLAGS Flags;
+};
+
+// CD3DX12_PIPELINE_STATE_STREAM2 Works on OS Build 19041+ (where there is a new mesh shader pipeline).
+// Use CD3DX12_PIPELINE_STATE_STREAM1 for OS Build 16299+ (where there is a new view instancing subobject).
+// Use CD3DX12_PIPELINE_STATE_STREAM for OS Build 15063+ support.
+struct CD3DX12_PIPELINE_STATE_STREAM2
+{
+ CD3DX12_PIPELINE_STATE_STREAM2() = default;
+ // Mesh and amplification shaders must be set manually, since they do not have representation in D3D12_GRAPHICS_PIPELINE_STATE_DESC
+ CD3DX12_PIPELINE_STATE_STREAM2(const D3D12_GRAPHICS_PIPELINE_STATE_DESC& Desc) noexcept
+ : Flags(Desc.Flags)
+ , NodeMask(Desc.NodeMask)
+ , pRootSignature(Desc.pRootSignature)
+ , InputLayout(Desc.InputLayout)
+ , IBStripCutValue(Desc.IBStripCutValue)
+ , PrimitiveTopologyType(Desc.PrimitiveTopologyType)
+ , VS(Desc.VS)
+ , GS(Desc.GS)
+ , StreamOutput(Desc.StreamOutput)
+ , HS(Desc.HS)
+ , DS(Desc.DS)
+ , PS(Desc.PS)
+ , BlendState(CD3DX12_BLEND_DESC(Desc.BlendState))
+ , DepthStencilState(CD3DX12_DEPTH_STENCIL_DESC1(Desc.DepthStencilState))
+ , DSVFormat(Desc.DSVFormat)
+ , RasterizerState(CD3DX12_RASTERIZER_DESC(Desc.RasterizerState))
+ , RTVFormats(CD3DX12_RT_FORMAT_ARRAY(Desc.RTVFormats, Desc.NumRenderTargets))
+ , SampleDesc(Desc.SampleDesc)
+ , SampleMask(Desc.SampleMask)
+ , CachedPSO(Desc.CachedPSO)
+ , ViewInstancingDesc(CD3DX12_VIEW_INSTANCING_DESC(CD3DX12_DEFAULT()))
+ {}
+ CD3DX12_PIPELINE_STATE_STREAM2(const D3DX12_MESH_SHADER_PIPELINE_STATE_DESC& Desc) noexcept
+ : Flags(Desc.Flags)
+ , NodeMask(Desc.NodeMask)
+ , pRootSignature(Desc.pRootSignature)
+ , PrimitiveTopologyType(Desc.PrimitiveTopologyType)
+ , PS(Desc.PS)
+ , AS(Desc.AS)
+ , MS(Desc.MS)
+ , BlendState(CD3DX12_BLEND_DESC(Desc.BlendState))
+ , DepthStencilState(CD3DX12_DEPTH_STENCIL_DESC1(Desc.DepthStencilState))
+ , DSVFormat(Desc.DSVFormat)
+ , RasterizerState(CD3DX12_RASTERIZER_DESC(Desc.RasterizerState))
+ , RTVFormats(CD3DX12_RT_FORMAT_ARRAY(Desc.RTVFormats, Desc.NumRenderTargets))
+ , SampleDesc(Desc.SampleDesc)
+ , SampleMask(Desc.SampleMask)
+ , CachedPSO(Desc.CachedPSO)
+ , ViewInstancingDesc(CD3DX12_VIEW_INSTANCING_DESC(CD3DX12_DEFAULT()))
+ {}
+ CD3DX12_PIPELINE_STATE_STREAM2(const D3D12_COMPUTE_PIPELINE_STATE_DESC& Desc) noexcept
+ : Flags(Desc.Flags)
+ , NodeMask(Desc.NodeMask)
+ , pRootSignature(Desc.pRootSignature)
+ , CS(CD3DX12_SHADER_BYTECODE(Desc.CS))
+ , CachedPSO(Desc.CachedPSO)
+ {
+ static_cast<D3D12_DEPTH_STENCIL_DESC1&>(DepthStencilState).DepthEnable = false;
+ }
+ CD3DX12_PIPELINE_STATE_STREAM_FLAGS Flags;
+ CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK NodeMask;
+ CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE pRootSignature;
+ CD3DX12_PIPELINE_STATE_STREAM_INPUT_LAYOUT InputLayout;
+ CD3DX12_PIPELINE_STATE_STREAM_IB_STRIP_CUT_VALUE IBStripCutValue;
+ CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY PrimitiveTopologyType;
+ CD3DX12_PIPELINE_STATE_STREAM_VS VS;
+ CD3DX12_PIPELINE_STATE_STREAM_GS GS;
+ CD3DX12_PIPELINE_STATE_STREAM_STREAM_OUTPUT StreamOutput;
+ CD3DX12_PIPELINE_STATE_STREAM_HS HS;
+ CD3DX12_PIPELINE_STATE_STREAM_DS DS;
+ CD3DX12_PIPELINE_STATE_STREAM_PS PS;
+ CD3DX12_PIPELINE_STATE_STREAM_AS AS;
+ CD3DX12_PIPELINE_STATE_STREAM_MS MS;
+ CD3DX12_PIPELINE_STATE_STREAM_CS CS;
+ CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC BlendState;
+ CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL1 DepthStencilState;
+ CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL_FORMAT DSVFormat;
+ CD3DX12_PIPELINE_STATE_STREAM_RASTERIZER RasterizerState;
+ CD3DX12_PIPELINE_STATE_STREAM_RENDER_TARGET_FORMATS RTVFormats;
+ CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC SampleDesc;
+ CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK SampleMask;
+ CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO CachedPSO;
+ CD3DX12_PIPELINE_STATE_STREAM_VIEW_INSTANCING ViewInstancingDesc;
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC GraphicsDescV0() const noexcept
+ {
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC D;
+ D.Flags = this->Flags;
+ D.NodeMask = this->NodeMask;
+ D.pRootSignature = this->pRootSignature;
+ D.InputLayout = this->InputLayout;
+ D.IBStripCutValue = this->IBStripCutValue;
+ D.PrimitiveTopologyType = this->PrimitiveTopologyType;
+ D.VS = this->VS;
+ D.GS = this->GS;
+ D.StreamOutput = this->StreamOutput;
+ D.HS = this->HS;
+ D.DS = this->DS;
+ D.PS = this->PS;
+ D.BlendState = this->BlendState;
+ D.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC1(D3D12_DEPTH_STENCIL_DESC1(this->DepthStencilState));
+ D.DSVFormat = this->DSVFormat;
+ D.RasterizerState = this->RasterizerState;
+ D.NumRenderTargets = D3D12_RT_FORMAT_ARRAY(this->RTVFormats).NumRenderTargets;
+ memcpy(D.RTVFormats, D3D12_RT_FORMAT_ARRAY(this->RTVFormats).RTFormats, sizeof(D.RTVFormats));
+ D.SampleDesc = this->SampleDesc;
+ D.SampleMask = this->SampleMask;
+ D.CachedPSO = this->CachedPSO;
+ return D;
+ }
+ D3D12_COMPUTE_PIPELINE_STATE_DESC ComputeDescV0() const noexcept
+ {
+ D3D12_COMPUTE_PIPELINE_STATE_DESC D;
+ D.Flags = this->Flags;
+ D.NodeMask = this->NodeMask;
+ D.pRootSignature = this->pRootSignature;
+ D.CS = this->CS;
+ D.CachedPSO = this->CachedPSO;
+ return D;
+ }
+};
diff --git a/tools/gfx/d3d12/d3d12-pipeline-state.cpp b/tools/gfx/d3d12/d3d12-pipeline-state.cpp
index 754c07e5c..fc54b3884 100644
--- a/tools/gfx/d3d12/d3d12-pipeline-state.cpp
+++ b/tools/gfx/d3d12/d3d12-pipeline-state.cpp
@@ -10,6 +10,7 @@
#include "d3d12-framebuffer.h"
#include "d3d12-shader-program.h"
#include "d3d12-vertex-layout.h"
+#include "d3d12-pipeline-state-stream.h"
#include <climits>
@@ -59,169 +60,219 @@ Result PipelineStateImpl::ensureAPIPipelineStateCreated()
// Only actually create a D3D12 pipeline state if the pipeline is fully specialized.
auto inputLayoutImpl = (InputLayoutImpl*)desc.graphics.inputLayout;
- // Describe and create the graphics pipeline state object (PSO)
- D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
+ // A helper to fill common fields between graphics and mesh pipeline descs
+ const auto fillCommonGraphicsState = [&](auto& psoDesc){
+ psoDesc.pRootSignature = programImpl->m_rootObjectLayout->m_rootSignature;
- psoDesc.pRootSignature = programImpl->m_rootObjectLayout->m_rootSignature;
+ psoDesc.PrimitiveTopologyType = D3DUtil::getPrimitiveType(desc.graphics.primitiveType);
- for (auto& shaderBin : programImpl->m_shaders)
- {
- switch (shaderBin.stage)
{
- case SLANG_STAGE_VERTEX:
- psoDesc.VS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
- break;
- case SLANG_STAGE_FRAGMENT:
- psoDesc.PS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
- break;
- case SLANG_STAGE_DOMAIN:
- psoDesc.DS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
- break;
- case SLANG_STAGE_HULL:
- psoDesc.HS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
- break;
- case SLANG_STAGE_GEOMETRY:
- psoDesc.GS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
- break;
- default:
- getDebugCallback()->handleMessage(
- DebugMessageType::Error,
- DebugMessageSource::Layer,
- "Unsupported shader stage.");
- return SLANG_E_NOT_AVAILABLE;
- }
- }
-
- if (inputLayoutImpl)
- {
- psoDesc.InputLayout = {
- inputLayoutImpl->m_elements.getBuffer(),
- UINT(inputLayoutImpl->m_elements.getCount()) };
- }
+ auto framebufferLayout =
+ static_cast<FramebufferLayoutImpl*>(desc.graphics.framebufferLayout);
+ const int numRenderTargets = int(framebufferLayout->m_renderTargets.getCount());
- psoDesc.PrimitiveTopologyType = D3DUtil::getPrimitiveType(desc.graphics.primitiveType);
+ if (framebufferLayout->m_hasDepthStencil)
+ {
+ psoDesc.DSVFormat = D3DUtil::getMapFormat(framebufferLayout->m_depthStencil.format);
+ psoDesc.SampleDesc.Count = framebufferLayout->m_depthStencil.sampleCount;
+ }
+ else
+ {
+ psoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
+ if (framebufferLayout->m_renderTargets.getCount())
+ {
+ psoDesc.SampleDesc.Count = framebufferLayout->m_renderTargets[0].sampleCount;
+ }
+ }
+ psoDesc.NumRenderTargets = numRenderTargets;
+ for (Int i = 0; i < numRenderTargets; i++)
+ {
+ psoDesc.RTVFormats[i] =
+ D3DUtil::getMapFormat(framebufferLayout->m_renderTargets[i].format);
+ }
- {
- auto framebufferLayout =
- static_cast<FramebufferLayoutImpl*>(desc.graphics.framebufferLayout);
- const int numRenderTargets = int(framebufferLayout->m_renderTargets.getCount());
+ psoDesc.SampleDesc.Quality = 0;
+ psoDesc.SampleMask = UINT_MAX;
+ }
- if (framebufferLayout->m_hasDepthStencil)
{
- psoDesc.DSVFormat = D3DUtil::getMapFormat(framebufferLayout->m_depthStencil.format);
- psoDesc.SampleDesc.Count = framebufferLayout->m_depthStencil.sampleCount;
+ auto& rs = psoDesc.RasterizerState;
+ rs.FillMode = D3DUtil::getFillMode(desc.graphics.rasterizer.fillMode);
+ rs.CullMode = D3DUtil::getCullMode(desc.graphics.rasterizer.cullMode);
+ rs.FrontCounterClockwise =
+ desc.graphics.rasterizer.frontFace == gfx::FrontFaceMode::CounterClockwise ? TRUE
+ : FALSE;
+ rs.DepthBias = desc.graphics.rasterizer.depthBias;
+ rs.DepthBiasClamp = desc.graphics.rasterizer.depthBiasClamp;
+ rs.SlopeScaledDepthBias = desc.graphics.rasterizer.slopeScaledDepthBias;
+ rs.DepthClipEnable = desc.graphics.rasterizer.depthClipEnable ? TRUE : FALSE;
+ rs.MultisampleEnable = desc.graphics.rasterizer.multisampleEnable ? TRUE : FALSE;
+ rs.AntialiasedLineEnable =
+ desc.graphics.rasterizer.antialiasedLineEnable ? TRUE : FALSE;
+ rs.ForcedSampleCount = desc.graphics.rasterizer.forcedSampleCount;
+ rs.ConservativeRaster = desc.graphics.rasterizer.enableConservativeRasterization
+ ? D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON
+ : D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
}
- else
+
{
- psoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
- if (framebufferLayout->m_renderTargets.getCount())
+ D3D12_BLEND_DESC& blend = psoDesc.BlendState;
+ blend.IndependentBlendEnable = FALSE;
+ blend.AlphaToCoverageEnable = desc.graphics.blend.alphaToCoverageEnable ? TRUE : FALSE;
+ blend.RenderTarget[0].RenderTargetWriteMask = (uint8_t)RenderTargetWriteMask::EnableAll;
+ for (GfxIndex i = 0; i < desc.graphics.blend.targetCount; i++)
+ {
+ auto& d3dDesc = blend.RenderTarget[i];
+ d3dDesc.BlendEnable = desc.graphics.blend.targets[i].enableBlend ? TRUE : FALSE;
+ d3dDesc.BlendOp = D3DUtil::getBlendOp(desc.graphics.blend.targets[i].color.op);
+ d3dDesc.BlendOpAlpha = D3DUtil::getBlendOp(desc.graphics.blend.targets[i].alpha.op);
+ d3dDesc.DestBlend =
+ D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].color.dstFactor);
+ d3dDesc.DestBlendAlpha =
+ D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].alpha.dstFactor);
+ d3dDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
+ d3dDesc.LogicOpEnable = FALSE;
+ d3dDesc.RenderTargetWriteMask = desc.graphics.blend.targets[i].writeMask;
+ d3dDesc.SrcBlend =
+ D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].color.srcFactor);
+ d3dDesc.SrcBlendAlpha =
+ D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].alpha.srcFactor);
+ }
+ for (GfxIndex i = 1; i < desc.graphics.blend.targetCount; i++)
{
- psoDesc.SampleDesc.Count = framebufferLayout->m_renderTargets[0].sampleCount;
+ if (memcmp(
+ &desc.graphics.blend.targets[i],
+ &desc.graphics.blend.targets[0],
+ sizeof(desc.graphics.blend.targets[0])) != 0)
+ {
+ blend.IndependentBlendEnable = TRUE;
+ break;
+ }
+ }
+ for (uint32_t i = (uint32_t)desc.graphics.blend.targetCount;
+ i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT;
+ ++i)
+ {
+ blend.RenderTarget[i] = blend.RenderTarget[0];
}
}
- psoDesc.NumRenderTargets = numRenderTargets;
- for (Int i = 0; i < numRenderTargets; i++)
+
{
- psoDesc.RTVFormats[i] =
- D3DUtil::getMapFormat(framebufferLayout->m_renderTargets[i].format);
+ auto& ds = psoDesc.DepthStencilState;
+
+ ds.DepthEnable = desc.graphics.depthStencil.depthTestEnable;
+ ds.DepthWriteMask = desc.graphics.depthStencil.depthWriteEnable
+ ? D3D12_DEPTH_WRITE_MASK_ALL
+ : D3D12_DEPTH_WRITE_MASK_ZERO;
+ ds.DepthFunc = D3DUtil::getComparisonFunc(desc.graphics.depthStencil.depthFunc);
+ ds.StencilEnable = desc.graphics.depthStencil.stencilEnable;
+ ds.StencilReadMask = (UINT8)desc.graphics.depthStencil.stencilReadMask;
+ ds.StencilWriteMask = (UINT8)desc.graphics.depthStencil.stencilWriteMask;
+ ds.FrontFace = D3DUtil::translateStencilOpDesc(desc.graphics.depthStencil.frontFace);
+ ds.BackFace = D3DUtil::translateStencilOpDesc(desc.graphics.depthStencil.backFace);
}
- psoDesc.SampleDesc.Quality = 0;
- psoDesc.SampleMask = UINT_MAX;
- }
+ psoDesc.PrimitiveTopologyType = D3DUtil::getPrimitiveType(desc.graphics.primitiveType);
- {
- auto& rs = psoDesc.RasterizerState;
- rs.FillMode = D3DUtil::getFillMode(desc.graphics.rasterizer.fillMode);
- rs.CullMode = D3DUtil::getCullMode(desc.graphics.rasterizer.cullMode);
- rs.FrontCounterClockwise =
- desc.graphics.rasterizer.frontFace == gfx::FrontFaceMode::CounterClockwise ? TRUE
- : FALSE;
- rs.DepthBias = desc.graphics.rasterizer.depthBias;
- rs.DepthBiasClamp = desc.graphics.rasterizer.depthBiasClamp;
- rs.SlopeScaledDepthBias = desc.graphics.rasterizer.slopeScaledDepthBias;
- rs.DepthClipEnable = desc.graphics.rasterizer.depthClipEnable ? TRUE : FALSE;
- rs.MultisampleEnable = desc.graphics.rasterizer.multisampleEnable ? TRUE : FALSE;
- rs.AntialiasedLineEnable =
- desc.graphics.rasterizer.antialiasedLineEnable ? TRUE : FALSE;
- rs.ForcedSampleCount = desc.graphics.rasterizer.forcedSampleCount;
- rs.ConservativeRaster = desc.graphics.rasterizer.enableConservativeRasterization
- ? D3D12_CONSERVATIVE_RASTERIZATION_MODE_ON
- : D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
- }
+ };
+ if(m_program->isMeshShaderProgram())
{
- D3D12_BLEND_DESC& blend = psoDesc.BlendState;
- blend.IndependentBlendEnable = FALSE;
- blend.AlphaToCoverageEnable = desc.graphics.blend.alphaToCoverageEnable ? TRUE : FALSE;
- blend.RenderTarget[0].RenderTargetWriteMask = (uint8_t)RenderTargetWriteMask::EnableAll;
- for (GfxIndex i = 0; i < desc.graphics.blend.targetCount; i++)
+ D3DX12_MESH_SHADER_PIPELINE_STATE_DESC meshDesc = {};
+ for (auto& shaderBin : programImpl->m_shaders)
{
- auto& d3dDesc = blend.RenderTarget[i];
- d3dDesc.BlendEnable = desc.graphics.blend.targets[i].enableBlend ? TRUE : FALSE;
- d3dDesc.BlendOp = D3DUtil::getBlendOp(desc.graphics.blend.targets[i].color.op);
- d3dDesc.BlendOpAlpha = D3DUtil::getBlendOp(desc.graphics.blend.targets[i].alpha.op);
- d3dDesc.DestBlend =
- D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].color.dstFactor);
- d3dDesc.DestBlendAlpha =
- D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].alpha.dstFactor);
- d3dDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
- d3dDesc.LogicOpEnable = FALSE;
- d3dDesc.RenderTargetWriteMask = desc.graphics.blend.targets[i].writeMask;
- d3dDesc.SrcBlend =
- D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].color.srcFactor);
- d3dDesc.SrcBlendAlpha =
- D3DUtil::getBlendFactor(desc.graphics.blend.targets[i].alpha.srcFactor);
- }
- for (GfxIndex i = 1; i < desc.graphics.blend.targetCount; i++)
- {
- if (memcmp(
- &desc.graphics.blend.targets[i],
- &desc.graphics.blend.targets[0],
- sizeof(desc.graphics.blend.targets[0])) != 0)
+ switch (shaderBin.stage)
{
- blend.IndependentBlendEnable = TRUE;
+ case SLANG_STAGE_FRAGMENT:
+ meshDesc.PS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
+ break;
+ case SLANG_STAGE_AMPLIFICATION:
+ meshDesc.AS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
+ break;
+ case SLANG_STAGE_MESH:
+ meshDesc.MS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
break;
+ default:
+ getDebugCallback()->handleMessage(
+ DebugMessageType::Error,
+ DebugMessageSource::Layer,
+ "Unsupported shader stage.");
+ return SLANG_E_NOT_AVAILABLE;
}
}
- for (uint32_t i = (uint32_t)desc.graphics.blend.targetCount;
- i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT;
- ++i)
+ fillCommonGraphicsState(meshDesc);
+ if (m_device->m_pipelineCreationAPIDispatcher)
{
- blend.RenderTarget[i] = blend.RenderTarget[0];
+ SLANG_RETURN_ON_FAIL(
+ m_device->m_pipelineCreationAPIDispatcher->createMeshPipelineState(
+ m_device,
+ programImpl->linkedProgram.get(),
+ &meshDesc,
+ (void**)m_pipelineState.writeRef()));
}
- }
-
- {
- auto& ds = psoDesc.DepthStencilState;
-
- ds.DepthEnable = desc.graphics.depthStencil.depthTestEnable;
- ds.DepthWriteMask = desc.graphics.depthStencil.depthWriteEnable
- ? D3D12_DEPTH_WRITE_MASK_ALL
- : D3D12_DEPTH_WRITE_MASK_ZERO;
- ds.DepthFunc = D3DUtil::getComparisonFunc(desc.graphics.depthStencil.depthFunc);
- ds.StencilEnable = desc.graphics.depthStencil.stencilEnable;
- ds.StencilReadMask = (UINT8)desc.graphics.depthStencil.stencilReadMask;
- ds.StencilWriteMask = (UINT8)desc.graphics.depthStencil.stencilWriteMask;
- ds.FrontFace = D3DUtil::translateStencilOpDesc(desc.graphics.depthStencil.frontFace);
- ds.BackFace = D3DUtil::translateStencilOpDesc(desc.graphics.depthStencil.backFace);
- }
-
- psoDesc.PrimitiveTopologyType = D3DUtil::getPrimitiveType(desc.graphics.primitiveType);
+ else
+ {
+ CD3DX12_PIPELINE_STATE_STREAM2 meshStateStream{meshDesc};
+ D3D12_PIPELINE_STATE_STREAM_DESC streamDesc{sizeof(meshStateStream), &meshStateStream};
- if (m_device->m_pipelineCreationAPIDispatcher)
- {
- SLANG_RETURN_ON_FAIL(
- m_device->m_pipelineCreationAPIDispatcher->createGraphicsPipelineState(
- m_device,
- programImpl->linkedProgram.get(),
- &psoDesc,
- (void**)m_pipelineState.writeRef()));
+ SLANG_RETURN_ON_FAIL(m_device->m_device5->CreatePipelineState(
+ &streamDesc, IID_PPV_ARGS(m_pipelineState.writeRef())));
+ }
}
else
{
- SLANG_RETURN_ON_FAIL(m_device->m_device->CreateGraphicsPipelineState(
- &psoDesc, IID_PPV_ARGS(m_pipelineState.writeRef())));
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicsDesc = {};
+ for (auto& shaderBin : programImpl->m_shaders)
+ {
+ switch (shaderBin.stage)
+ {
+ case SLANG_STAGE_VERTEX:
+ graphicsDesc.VS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
+ break;
+ case SLANG_STAGE_FRAGMENT:
+ graphicsDesc.PS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
+ break;
+ case SLANG_STAGE_DOMAIN:
+ graphicsDesc.DS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
+ break;
+ case SLANG_STAGE_HULL:
+ graphicsDesc.HS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
+ break;
+ case SLANG_STAGE_GEOMETRY:
+ graphicsDesc.GS = { shaderBin.code.getBuffer(), SIZE_T(shaderBin.code.getCount()) };
+ break;
+ default:
+ getDebugCallback()->handleMessage(
+ DebugMessageType::Error,
+ DebugMessageSource::Layer,
+ "Unsupported shader stage.");
+ return SLANG_E_NOT_AVAILABLE;
+ }
+ }
+
+ if (inputLayoutImpl)
+ {
+ graphicsDesc.InputLayout = {
+ inputLayoutImpl->m_elements.getBuffer(),
+ UINT(inputLayoutImpl->m_elements.getCount()) };
+ }
+
+ fillCommonGraphicsState(graphicsDesc);
+
+ if (m_device->m_pipelineCreationAPIDispatcher)
+ {
+ SLANG_RETURN_ON_FAIL(
+ m_device->m_pipelineCreationAPIDispatcher->createGraphicsPipelineState(
+ m_device,
+ programImpl->linkedProgram.get(),
+ &graphicsDesc,
+ (void**)m_pipelineState.writeRef()));
+ }
+ else
+ {
+ SLANG_RETURN_ON_FAIL(m_device->m_device->CreateGraphicsPipelineState(
+ &graphicsDesc, IID_PPV_ARGS(m_pipelineState.writeRef())));
+ }
}
}
else
diff --git a/tools/gfx/d3d12/d3d12-sal-defs.h b/tools/gfx/d3d12/d3d12-sal-defs.h
new file mode 100644
index 000000000..058fbb14c
--- /dev/null
+++ b/tools/gfx/d3d12/d3d12-sal-defs.h
@@ -0,0 +1,199 @@
+#pragma once
+
+//
+// The defines here are to allow compilers without support for SAL to not choke
+// on any MS headers using these annotations
+//
+
+#if !defined(_In_)
+# define _In_
+#endif
+#if !defined(_Out_)
+# define _Out_
+#endif
+#if !defined(_Inout_)
+# define _Inout_
+#endif
+#if !defined(_In_z_)
+# define _In_z_
+#endif
+#if !defined(_Inout_z_)
+# define _Inout_z_
+#endif
+#if !defined(_In_reads_)
+# define _In_reads_(s)
+#endif
+#if !defined(_In_reads_z_)
+# define _In_reads_z_(s)
+#endif
+#if !defined(_In_reads_or_z_)
+# define _In_reads_or_z_(s)
+#endif
+#if !defined(_Out_writes_)
+# define _Out_writes_(s)
+#endif
+#if !defined(_Out_writes_z_)
+# define _Out_writes_z_(s)
+#endif
+#if !defined(_Inout_updates_)
+# define _Inout_updates_(s)
+#endif
+#if !defined(_Inout_updates_z_)
+# define _Inout_updates_z_(s)
+#endif
+#if !defined(_Out_writes_to_)
+# define _Out_writes_to_(s,c)
+#endif
+#if !defined(_Inout_updates_to_)
+# define _Inout_updates_to_(s,c)
+#endif
+#if !defined(_Inout_updates_all_)
+# define _Inout_updates_all_(s)
+#endif
+#if !defined(_In_reads_to_ptr_)
+# define _In_reads_to_ptr_(p)
+#endif
+#if !defined(_In_reads_to_ptr_z_)
+# define _In_reads_to_ptr_z_(p)
+#endif
+#if !defined(_Out_writes_to_ptr_)
+# define _Out_writes_to_ptr_(p)
+#endif
+#if !defined(_Out_writes_to_ptr_z_)
+# define _Out_writes_to_ptr_z_(p)
+#endif
+#if !defined(_Outptr_)
+# define _Outptr_
+#endif
+#if !defined(_Outptr_opt_)
+# define _Outptr_opt_
+#endif
+#if !defined(_Outptr_result_maybenull_)
+# define _Outptr_result_maybenull_
+#endif
+#if !defined(_Outptr_opt_result_maybenull_)
+# define _Outptr_opt_result_maybenull_
+#endif
+#if !defined(_Outptr_result_z_)
+# define _Outptr_result_z_
+#endif
+#if !defined(_COM_Outptr_)
+# define _COM_Outptr_
+#endif
+#if !defined(_Outptr_result_buffer_)
+# define _Outptr_result_buffer_(s)
+#endif
+#if !defined(_Outptr_result_buffer_to_)
+# define _Outptr_result_buffer_to_(s, c)
+#endif
+#if !defined(_Result_nullonfailure_)
+# define _Result_nullonfailure_
+#endif
+#if !defined(_Result_zeroonfailure_)
+# define _Result_zeroonfailure_
+#endif
+#if !defined(_Outptr_result_nullonfailure_)
+# define _Outptr_result_nullonfailure_
+#endif
+#if !defined(_Outptr_opt_result_nullonfailure_)
+# define _Outptr_opt_result_nullonfailure_
+#endif
+#if !defined(_Outref_result_nullonfailure_)
+# define _Outref_result_nullonfailure_
+#endif
+#if !defined(_Outref_)
+# define _Outref_
+#endif
+#if !defined(_Outref_result_maybenull_)
+# define _Outref_result_maybenull_
+#endif
+#if !defined(_Outref_result_buffer_)
+# define _Outref_result_buffer_(s)
+#endif
+#if !defined(_Outref_result_bytebuffer_)
+# define _Outref_result_bytebuffer_(s)
+#endif
+#if !defined(_Outref_result_buffer_to_)
+# define _Outref_result_buffer_to_(s, c)
+#endif
+#if !defined(_Outref_result_bytebuffer_to_)
+# define _Outref_result_bytebuffer_to_(s, c)
+#endif
+#if !defined(_Outref_result_buffer_all_)
+# define _Outref_result_buffer_all_(s)
+#endif
+#if !defined(_Outref_result_bytebuffer_all_)
+# define _Outref_result_bytebuffer_all_(s)
+#endif
+#if !defined(_Outref_result_buffer_maybenull_)
+# define _Outref_result_buffer_maybenull_(s)
+#endif
+#if !defined(_Outref_result_bytebuffer_maybenull_)
+# define _Outref_result_bytebuffer_maybenull_(s)
+#endif
+#if !defined(_Outref_result_buffer_to_maybenull_)
+# define _Outref_result_buffer_to_maybenull_(s, c)
+#endif
+#if !defined(_Outref_result_bytebuffer_to_maybenull_)
+# define _Outref_result_bytebuffer_to_maybenull_(s,c)
+#endif
+#if !defined(_Outref_result_buffer_all_maybenull_)
+# define _Outref_result_buffer_all_maybenull_(s)
+#endif
+#if !defined(_Outref_result_bytebuffer_all_maybenull_)
+# define _Outref_result_bytebuffer_all_maybenull_(s)
+#endif
+#if !defined(_Printf_format_string_)
+# define _Printf_format_string_
+#endif
+#if !defined(_Scanf_format_string_)
+# define _Scanf_format_string_
+#endif
+#if !defined(_Scanf_s_format_string_)
+# define _Scanf_s_format_string_
+#endif
+#if !defined(_In_range_)
+# define _In_range_(low, hi)
+#endif
+#if !defined(_Pre_equal_to_)
+# define _Pre_equal_to_(expr)
+#endif
+#if !defined(_Struct_size_bytes_)
+# define _Struct_size_bytes_(size)
+#endif
+#if !defined(_Called_from_function_class_)
+# define _Called_from_function_class_(name)
+#endif
+#if !defined(_Check_return_)
+# define _Check_return_
+#endif
+#if !defined(_Function_class_)
+# define _Function_class_(name)
+#endif
+#if !defined(_Raises_SEH_exception_)
+# define _Raises_SEH_exception_
+#endif
+#if !defined(_Maybe_raises_SEH_exception_)
+# define _Maybe_raises_SEH_exception_
+#endif
+#if !defined(_Must_inspect_result_)
+# define _Must_inspect_result_
+#endif
+#if !defined(_Use_decl_annotations_)
+# define _Use_decl_annotations_
+#endif
+#if !defined(_Always_)
+# define _Always_(anno_list)
+#endif
+#if !defined(_On_failure_)
+# define _On_failure_(anno_list)
+#endif
+#if !defined(_Return_type_success_)
+# define _Return_type_success_(expr)
+#endif
+#if !defined(_Success_)
+# define _Success_(expr)
+#endif
+#if !defined(__analysis_assume)
+# define __analysis_assume(expr)
+#endif
diff --git a/tools/gfx/debug-layer/debug-command-encoder.cpp b/tools/gfx/debug-layer/debug-command-encoder.cpp
index 3ddd6401f..b7b06c2f4 100644
--- a/tools/gfx/debug-layer/debug-command-encoder.cpp
+++ b/tools/gfx/debug-layer/debug-command-encoder.cpp
@@ -203,6 +203,12 @@ Result DebugRenderCommandEncoder::drawIndexedInstanced(
indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation);
}
+Result DebugRenderCommandEncoder::drawMeshTasks(int x, int y, int z)
+{
+ SLANG_GFX_API_FUNC;
+ return baseObject->drawMeshTasks(x, y, z);
+}
+
void DebugResourceCommandEncoder::endEncoding()
{
SLANG_GFX_API_FUNC;
diff --git a/tools/gfx/debug-layer/debug-command-encoder.h b/tools/gfx/debug-layer/debug-command-encoder.h
index 395db587e..a0c03e84c 100644
--- a/tools/gfx/debug-layer/debug-command-encoder.h
+++ b/tools/gfx/debug-layer/debug-command-encoder.h
@@ -231,6 +231,9 @@ public:
GfxIndex baseVertexLocation,
GfxIndex startInstanceLocation) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ drawMeshTasks(int x, int y, int z) override;
+
public:
DebugCommandBuffer* commandBuffer;
bool isOpen = false;
diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp
index 94898d519..4043512c6 100644
--- a/tools/gfx/immediate-renderer-base.cpp
+++ b/tools/gfx/immediate-renderer-base.cpp
@@ -413,6 +413,11 @@ public:
return SLANG_OK;
}
+ virtual SLANG_NO_THROW Result SLANG_MCALL drawMeshTasks(int, int, int) override
+ {
+ SLANG_UNIMPLEMENTED_X("ImmediateRenderBase::drawMeshTasks");
+ }
+
virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions(
GfxCount samplesPerPixel,
GfxCount pixelCount,
diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp
index 1e4cbb2f4..5111edee5 100644
--- a/tools/gfx/renderer-shared.cpp
+++ b/tools/gfx/renderer-shared.cpp
@@ -1054,6 +1054,26 @@ Result ShaderProgramBase::createShaderModule(
return SLANG_OK;
}
+bool ShaderProgramBase::isMeshShaderProgram() const
+{
+ // Similar to above, interrogate either explicity specified entry point
+ // componenets or the ones in the linked program entry point array
+ if(linkedEntryPoints.getCount())
+ {
+ for(const auto& e : linkedEntryPoints)
+ if(e->getLayout()->getEntryPointByIndex(0)->getStage() == SLANG_STAGE_MESH)
+ return true;
+ }
+ else
+ {
+ const auto programReflection = linkedProgram->getLayout();
+ for(SlangUInt i = 0; i < programReflection->getEntryPointCount(); ++i)
+ if(programReflection->getEntryPointByIndex(i)->getStage() == SLANG_STAGE_MESH)
+ return true;
+ }
+ return false;
+}
+
Result RendererBase::maybeSpecializePipeline(
PipelineStateBase* currentPipeline,
ShaderObjectBase* rootObject,
diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h
index 32aa22b48..f94b909f7 100644
--- a/tools/gfx/renderer-shared.h
+++ b/tools/gfx/renderer-shared.h
@@ -868,6 +868,8 @@ public:
return linkedProgram->getLayout()->findTypeByName(name);
}
+ bool isMeshShaderProgram() const;
+
};
class InputLayoutBase
diff --git a/tools/gfx/vulkan/vk-api.h b/tools/gfx/vulkan/vk-api.h
index 127988946..3df6436d9 100644
--- a/tools/gfx/vulkan/vk-api.h
+++ b/tools/gfx/vulkan/vk-api.h
@@ -204,6 +204,7 @@ namespace gfx {
x(vkCmdDebugMarkerBeginEXT) \
x(vkCmdDebugMarkerEndEXT) \
x(vkDebugMarkerSetObjectNameEXT) \
+ x(vkCmdDrawMeshTasksEXT) \
/* */
#define VK_API_ALL_GLOBAL_PROCS(x) \
@@ -262,6 +263,11 @@ struct VulkanExtendedFeatureProperties
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR
};
+ // Mesh shader features
+ VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT
+ };
+
// Vulkan 1.2 features.
VkPhysicalDeviceVulkan12Features vulkan12Features = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES};
diff --git a/tools/gfx/vulkan/vk-command-encoder.cpp b/tools/gfx/vulkan/vk-command-encoder.cpp
index dcd33fd19..ddb48833f 100644
--- a/tools/gfx/vulkan/vk-command-encoder.cpp
+++ b/tools/gfx/vulkan/vk-command-encoder.cpp
@@ -1214,6 +1214,14 @@ Result RenderCommandEncoder::drawIndexedInstanced(
return SLANG_OK;
}
+Result RenderCommandEncoder::drawMeshTasks(int x, int y, int z)
+{
+ SLANG_RETURN_ON_FAIL(prepareDraw());
+ auto& api = *m_api;
+ api.vkCmdDrawMeshTasksEXT(m_vkCommandBuffer, x, y, z);
+ return SLANG_OK;
+}
+
void ComputeCommandEncoder::endEncoding() { endEncodingImpl(); }
Result ComputeCommandEncoder::bindPipeline(
diff --git a/tools/gfx/vulkan/vk-command-encoder.h b/tools/gfx/vulkan/vk-command-encoder.h
index 11f557433..ddb980d6a 100644
--- a/tools/gfx/vulkan/vk-command-encoder.h
+++ b/tools/gfx/vulkan/vk-command-encoder.h
@@ -252,6 +252,9 @@ public:
GfxIndex startIndexLocation,
GfxIndex baseVertexLocation,
GfxIndex startInstanceLocation) override;
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ drawMeshTasks(int x, int y, int z) override;
};
class ComputeCommandEncoder
diff --git a/tools/gfx/vulkan/vk-device.cpp b/tools/gfx/vulkan/vk-device.cpp
index 015be5f15..e71337ef6 100644
--- a/tools/gfx/vulkan/vk-device.cpp
+++ b/tools/gfx/vulkan/vk-device.cpp
@@ -430,6 +430,10 @@ Result DeviceImpl::initVulkanInstanceAndDevice(
extendedFeatures.atomicFloatFeatures.pNext = deviceFeatures2.pNext;
deviceFeatures2.pNext = &extendedFeatures.atomicFloatFeatures;
+ // mesh shader features
+ extendedFeatures.meshShaderFeatures.pNext = deviceFeatures2.pNext;
+ deviceFeatures2.pNext = &extendedFeatures.meshShaderFeatures;
+
if (VK_MAKE_VERSION(majorVersion, minorVersion, 0) >= VK_API_VERSION_1_2)
{
extendedFeatures.vulkan12Features.pNext = deviceFeatures2.pNext;
@@ -566,6 +570,16 @@ Result DeviceImpl::initVulkanInstanceAndDevice(
m_features.add("realtime-clock");
}
+ if (extendedFeatures.meshShaderFeatures.meshShader)
+ {
+ deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
+
+ extendedFeatures.meshShaderFeatures.pNext = (void*)deviceCreateInfo.pNext;
+ deviceCreateInfo.pNext = &extendedFeatures.meshShaderFeatures;
+
+ m_features.add("mesh-shader");
+ }
+
if (_hasAnySetBits(
extendedFeatures.vulkan12Features,
offsetof(VkPhysicalDeviceVulkan12Features, pNext) + sizeof(void*)))
@@ -578,10 +592,30 @@ Result DeviceImpl::initVulkanInstanceAndDevice(
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 };
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rtProps = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR };
+ VkPhysicalDeviceSubgroupProperties subgroupProps = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES };
+ rtProps.pNext = extendedProps.pNext;
extendedProps.pNext = &rtProps;
+ subgroupProps.pNext = extendedProps.pNext;
+ extendedProps.pNext = &subgroupProps;
m_api.vkGetPhysicalDeviceProperties2(m_api.m_physicalDevice, &extendedProps);
m_api.m_rtProperties = rtProps;
+ // Approximate DX12's WaveOps boolean
+ if(subgroupProps.supportedOperations &
+ ( VK_SUBGROUP_FEATURE_BASIC_BIT
+ | VK_SUBGROUP_FEATURE_VOTE_BIT
+ | VK_SUBGROUP_FEATURE_ARITHMETIC_BIT
+ | VK_SUBGROUP_FEATURE_BALLOT_BIT
+ | VK_SUBGROUP_FEATURE_SHUFFLE_BIT
+ | VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT
+ | VK_SUBGROUP_FEATURE_CLUSTERED_BIT
+ | VK_SUBGROUP_FEATURE_QUAD_BIT
+ | VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV))
+ {
+ m_features.add("wave-ops");
+ }
+
uint32_t extensionCount = 0;
m_api.vkEnumerateDeviceExtensionProperties(
m_api.m_physicalDevice, NULL, &extensionCount, NULL);
diff --git a/tools/gfx/vulkan/vk-pipeline-state.cpp b/tools/gfx/vulkan/vk-pipeline-state.cpp
index 4be9877af..712811f9a 100644
--- a/tools/gfx/vulkan/vk-pipeline-state.cpp
+++ b/tools/gfx/vulkan/vk-pipeline-state.cpp
@@ -220,7 +220,10 @@ Result PipelineStateImpl::createVKGraphicsPipelineState()
dynamicStates.add(VK_DYNAMIC_STATE_SCISSOR);
dynamicStates.add(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
dynamicStates.add(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
- if (m_device->m_api.m_extendedFeatures.extendedDynamicStateFeatures.extendedDynamicState)
+ // It's not valid to specify VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT when
+ // the pipeline contains a mesh shader.
+ if (!m_program->isMeshShaderProgram() && m_device->m_api.m_extendedFeatures.extendedDynamicStateFeatures.extendedDynamicState)
+
{
dynamicStates.add(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
}
diff --git a/tools/gfx/vulkan/vk-util.cpp b/tools/gfx/vulkan/vk-util.cpp
index 3771b5cc3..e8007805a 100644
--- a/tools/gfx/vulkan/vk-util.cpp
+++ b/tools/gfx/vulkan/vk-util.cpp
@@ -192,6 +192,10 @@ VkShaderStageFlags VulkanUtil::getShaderStage(SlangStage stage)
return VK_SHADER_STAGE_RAYGEN_BIT_KHR;
case SLANG_STAGE_VERTEX:
return VK_SHADER_STAGE_VERTEX_BIT;
+ case SLANG_STAGE_MESH:
+ return VK_SHADER_STAGE_MESH_BIT_EXT;
+ case SLANG_STAGE_AMPLIFICATION:
+ return VK_SHADER_STAGE_TASK_BIT_EXT;
default:
assert(!"unsupported stage.");
return VkShaderStageFlags(-1);
diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp
index 2f304b7c0..0266a0c75 100644
--- a/tools/render-test/options.cpp
+++ b/tools/render-test/options.cpp
@@ -137,6 +137,14 @@ static gfx::DeviceType _toRenderType(Slang::RenderApiType apiType)
{
outOptions.shaderType = ShaderProgramType::RayTracing;
}
+ else if (argValue == "-mesh")
+ {
+ outOptions.shaderType = ShaderProgramType::GraphicsMeshCompute;
+ }
+ else if (argValue == "-task")
+ {
+ outOptions.shaderType = ShaderProgramType::GraphicsTaskMeshCompute;
+ }
else if(argValue == "-use-dxil")
{
outOptions.useDXIL = true;
diff --git a/tools/render-test/options.h b/tools/render-test/options.h
index c2466f671..e3b19c272 100644
--- a/tools/render-test/options.h
+++ b/tools/render-test/options.h
@@ -33,10 +33,18 @@ struct Options
enum class ShaderProgramType
{
+ // Vertex and Fragment shader, writing an image out
Graphics,
+ // Compute shader, writing buffer contents out
Compute,
+ // Vertex and Fragment shader, writing buffer contents out
GraphicsCompute,
+ // Ray tracing shaders, writing buffer contents out
RayTracing,
+ // Mesh and Fragment shader, writing buffer contents out
+ GraphicsMeshCompute,
+ // Task, Mesh and Fragment shader, writing buffer contents out
+ GraphicsTaskMeshCompute,
};
Slang::String appName = "render-test";
diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp
index c79f7be24..3bdcdba07 100644
--- a/tools/render-test/render-test-main.cpp
+++ b/tools/render-test/render-test-main.cpp
@@ -100,6 +100,7 @@ public:
const ShaderCompilerUtil::Input& input);
void runCompute(IComputeCommandEncoder* encoder);
void renderFrame(IRenderCommandEncoder* encoder);
+ void renderFrameMesh(IRenderCommandEncoder* encoder);
void finalize();
Result applyBinding(PipelineType pipelineType, ICommandEncoder* encoder);
@@ -582,6 +583,14 @@ SlangResult RenderTestApp::initialize(
m_pipelineState = device->createGraphicsPipelineState(desc);
}
break;
+ case Options::ShaderProgramType::GraphicsMeshCompute:
+ case Options::ShaderProgramType::GraphicsTaskMeshCompute:
+ {
+ GraphicsPipelineStateDesc desc;
+ desc.program = m_shaderProgram;
+ desc.framebufferLayout = m_framebufferLayout;
+ m_pipelineState = device->createGraphicsPipelineState(desc);
+ }
}
}
// If success must have a pipeline state
@@ -876,6 +885,17 @@ void RenderTestApp::setProjectionMatrix(IShaderObject* rootObject)
.setData(info.identityProjectionMatrix, sizeof(float) * 16);
}
+void RenderTestApp::renderFrameMesh(IRenderCommandEncoder* encoder)
+{
+ auto pipelineType = PipelineType::Graphics;
+ applyBinding(pipelineType, encoder);
+ encoder->drawMeshTasks(
+ m_options.computeDispatchSize[0],
+ m_options.computeDispatchSize[1],
+ m_options.computeDispatchSize[2]
+ );
+}
+
void RenderTestApp::renderFrame(IRenderCommandEncoder* encoder)
{
auto pipelineType = PipelineType::Graphics;
@@ -1009,7 +1029,11 @@ Result RenderTestApp::update()
viewport.extentX = (float)gWindowWidth;
viewport.extentY = (float)gWindowHeight;
encoder->setViewportAndScissor(viewport);
- renderFrame(encoder);
+ if(m_options.shaderType == Options::ShaderProgramType::GraphicsMeshCompute
+ || m_options.shaderType == Options::ShaderProgramType::GraphicsTaskMeshCompute)
+ renderFrameMesh(encoder);
+ else
+ renderFrame(encoder);
encoder->endEncoding();
}
commandBuffer->close();
@@ -1060,7 +1084,10 @@ Result RenderTestApp::update()
if (m_options.outputPath.getLength())
{
- if (m_options.shaderType == Options::ShaderProgramType::Compute || m_options.shaderType == Options::ShaderProgramType::GraphicsCompute)
+ if (m_options.shaderType == Options::ShaderProgramType::Compute
+ || m_options.shaderType == Options::ShaderProgramType::GraphicsCompute
+ || m_options.shaderType == Options::ShaderProgramType::GraphicsMeshCompute
+ || m_options.shaderType == Options::ShaderProgramType::GraphicsTaskMeshCompute)
{
auto request = m_compilationOutput.output.getRequestForReflection();
auto slangReflection = (slang::ShaderReflection*) spGetReflection(request);
diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp
index 54f1b94a1..d9d8ddb45 100644
--- a/tools/render-test/slang-support.cpp
+++ b/tools/render-test/slang-support.cpp
@@ -20,6 +20,8 @@ static const char vertexEntryPointName[] = "vertexMain";
static const char fragmentEntryPointName[] = "fragmentMain";
static const char computeEntryPointName[] = "computeMain";
static const char rtEntryPointName[] = "raygenMain";
+static const char taskEntryPointName[] = "taskMain";
+static const char meshEntryPointName[] = "meshMain";
gfx::StageType translateStage(SlangStage slangStage)
{
@@ -421,7 +423,10 @@ void ShaderCompilerUtil::Output::reset()
//
if( !options.dontAddDefaultEntryPoints )
{
- if (shaderType == Options::ShaderProgramType::Graphics || shaderType == Options::ShaderProgramType::GraphicsCompute)
+ switch(shaderType)
+ {
+ case Options::ShaderProgramType::Graphics:
+ case Options::ShaderProgramType::GraphicsCompute:
{
ShaderCompileRequest::EntryPoint vertexEntryPoint;
vertexEntryPoint.name = vertexEntryPointName;
@@ -433,7 +438,29 @@ void ShaderCompilerUtil::Output::reset()
fragmentEntryPoint.slangStage = SLANG_STAGE_FRAGMENT;
compileRequest.entryPoints.add(fragmentEntryPoint);
}
- else if( shaderType == Options::ShaderProgramType::RayTracing )
+ break;
+ case Options::ShaderProgramType::GraphicsTaskMeshCompute:
+ {
+ ShaderCompileRequest::EntryPoint taskEntryPoint;
+ taskEntryPoint.name = taskEntryPointName;
+ taskEntryPoint.slangStage = SLANG_STAGE_AMPLIFICATION;
+ compileRequest.entryPoints.add(taskEntryPoint);
+ }
+ [[fallthrough]];
+ case Options::ShaderProgramType::GraphicsMeshCompute:
+ {
+ ShaderCompileRequest::EntryPoint meshEntryPoint;
+ meshEntryPoint.name = meshEntryPointName;
+ meshEntryPoint.slangStage = SLANG_STAGE_MESH;
+ compileRequest.entryPoints.add(meshEntryPoint);
+
+ ShaderCompileRequest::EntryPoint fragmentEntryPoint;
+ fragmentEntryPoint.name = fragmentEntryPointName;
+ fragmentEntryPoint.slangStage = SLANG_STAGE_FRAGMENT;
+ compileRequest.entryPoints.add(fragmentEntryPoint);
+ }
+ break;
+ case Options::ShaderProgramType::RayTracing:
{
// Note: Current GPU ray tracing pipelines allow for an
// almost arbitrary mix of entry points for different stages
@@ -445,13 +472,15 @@ void ShaderCompilerUtil::Output::reset()
// instead rely on `[shader(...)]` annotations to tell us
// what entry points are present in the input code.
}
- else
+ break;
+ default:
{
ShaderCompileRequest::EntryPoint computeEntryPoint;
computeEntryPoint.name = computeEntryPointName;
computeEntryPoint.slangStage = SLANG_STAGE_COMPUTE;
compileRequest.entryPoints.add(computeEntryPoint);
}
+ }
}
compileRequest.globalSpecializationArgs = layout.globalSpecializationArgs;
compileRequest.entryPointSpecializationArgs = layout.entryPointSpecializationArgs;