From 1ee244b3d3cd23962c9b1292cff4f80fa7dc358b Mon Sep 17 00:00:00 2001 From: Enrico Galli Date: Wed, 1 Jun 2022 06:14:07 +0000 Subject: [PATCH] dawn/native: Add support for feature "indirect-first-instance" Bug: dawn:1197 Change-Id: I9042b2dc178dfc01201bff55a2f5e43de28d335e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/90526 Kokoro: Kokoro Reviewed-by: Austin Eng Commit-Queue: Enrico Galli --- dawn.json | 1 + src/dawn/native/Features.cpp | 11 ++++++++--- src/dawn/native/Features.h | 1 + .../native/IndirectDrawValidationEncoder.cpp | 17 ++++++++++++----- src/dawn/native/d3d12/AdapterD3D12.cpp | 1 + src/dawn/native/metal/BackendMTL.mm | 2 ++ src/dawn/native/opengl/BackendGL.cpp | 9 +++++++++ src/dawn/native/vulkan/AdapterVk.cpp | 4 ++++ .../tests/end2end/FirstIndexOffsetTests.cpp | 7 +++++++ 9 files changed, 45 insertions(+), 8 deletions(-) diff --git a/dawn.json b/dawn.json index 051d468108..745167e1e3 100644 --- a/dawn.json +++ b/dawn.json @@ -1214,6 +1214,7 @@ {"name": "depth24 unorm stencil8", "type": "bool", "default": "false"}, {"name": "depth32 float stencil8", "type": "bool", "default": "false"}, {"name": "chromium experimental dp4a", "type": "bool", "default": "false"}, + {"name": "indirect first instance", "type": "bool", "default": "false"}, {"name": "invalid feature", "type": "bool", "default": "false"}, {"name": "dawn internal usages", "type": "bool", "default": "false"}, {"name": "dawn native", "type": "bool", "default": "false"}, diff --git a/src/dawn/native/Features.cpp b/src/dawn/native/Features.cpp index e2b82eed71..a813c6871d 100644 --- a/src/dawn/native/Features.cpp +++ b/src/dawn/native/Features.cpp @@ -78,6 +78,10 @@ static constexpr FeatureEnumAndInfoList kFeatureNameAndInfoList = {{ {"chromium-experimental-dp4a", "Support experimental DP4a instructions in WGSL", "https://bugs.chromium.org/p/tint/issues/detail?id=1497"}, &WGPUDeviceProperties::chromiumExperimentalDp4a}, + {Feature::IndirectFirstInstance, + {"indirect-first-instance", "Support non-zero first instance values on indirect draw calls", + "https://bugs.chromium.org/p/dawn/issues/detail?id=1197"}, + &WGPUDeviceProperties::indirectFirstInstance}, {Feature::DawnInternalUsages, {"dawn-internal-usages", "Add internal usages to resources to affect how the texture is allocated, but not " @@ -117,6 +121,8 @@ Feature FromAPIFeature(wgpu::FeatureName feature) { return Feature::Depth24UnormStencil8; case wgpu::FeatureName::Depth32FloatStencil8: return Feature::Depth32FloatStencil8; + case wgpu::FeatureName::IndirectFirstInstance: + return Feature::IndirectFirstInstance; case wgpu::FeatureName::DawnShaderFloat16: return Feature::ShaderFloat16; case wgpu::FeatureName::DawnInternalUsages: @@ -127,9 +133,6 @@ Feature FromAPIFeature(wgpu::FeatureName feature) { return Feature::DawnNative; case wgpu::FeatureName::ChromiumExperimentalDp4a: return Feature::ChromiumExperimentalDp4a; - - case wgpu::FeatureName::IndirectFirstInstance: - return Feature::InvalidEnum; } return Feature::InvalidEnum; } @@ -152,6 +155,8 @@ wgpu::FeatureName ToAPIFeature(Feature feature) { return wgpu::FeatureName::Depth24UnormStencil8; case Feature::Depth32FloatStencil8: return wgpu::FeatureName::Depth32FloatStencil8; + case Feature::IndirectFirstInstance: + return wgpu::FeatureName::IndirectFirstInstance; case Feature::ShaderFloat16: return wgpu::FeatureName::DawnShaderFloat16; case Feature::DawnInternalUsages: diff --git a/src/dawn/native/Features.h b/src/dawn/native/Features.h index a87eaea27c..ebf804e5ca 100644 --- a/src/dawn/native/Features.h +++ b/src/dawn/native/Features.h @@ -37,6 +37,7 @@ enum class Feature { Depth24UnormStencil8, Depth32FloatStencil8, ChromiumExperimentalDp4a, + IndirectFirstInstance, // Dawn-specific DawnInternalUsages, diff --git a/src/dawn/native/IndirectDrawValidationEncoder.cpp b/src/dawn/native/IndirectDrawValidationEncoder.cpp index 2c20820ad3..0f131829ff 100644 --- a/src/dawn/native/IndirectDrawValidationEncoder.cpp +++ b/src/dawn/native/IndirectDrawValidationEncoder.cpp @@ -43,6 +43,7 @@ constexpr uint64_t kWorkgroupSize = 64; constexpr uint32_t kDuplicateBaseVertexInstance = 1; constexpr uint32_t kIndexedDraw = 2; constexpr uint32_t kValidationEnabled = 4; +constexpr uint32_t kIndirectFirstInstanceEnabled = 8; // Equivalent to the BatchInfo struct defined in the shader below. struct BatchInfo { @@ -64,6 +65,7 @@ static const char sRenderValidationShaderSource[] = R"( let kDuplicateBaseVertexInstance = 1u; let kIndexedDraw = 2u; let kValidationEnabled = 4u; + let kIndirectFirstInstanceEnabled = 8u; struct BatchInfo { numIndexBufferElementsLow: u32, @@ -140,11 +142,13 @@ static const char sRenderValidationShaderSource[] = R"( } let inputIndex = batch.indirectOffsets[id.x]; - // firstInstance is always the last parameter - let firstInstance = inputParams.data[inputIndex + numIndirectParamsPerDrawCallInput() - 1u]; - if (firstInstance != 0u) { - fail(id.x); - return; + if(!bool(batch.flags & kIndirectFirstInstanceEnabled)) { + // firstInstance is always the last parameter + let firstInstance = inputParams.data[inputIndex + numIndirectParamsPerDrawCallInput() - 1u]; + if (firstInstance != 0u) { + fail(id.x); + return; + } } if (!bool(batch.flags & kIndexedDraw)) { @@ -334,6 +338,9 @@ MaybeError EncodeIndirectDrawValidationCommands(DeviceBase* device, if (device->IsValidationEnabled()) { newPass.flags |= kValidationEnabled; } + if (device->IsFeatureEnabled(Feature::IndirectFirstInstance)) { + newPass.flags |= kIndirectFirstInstanceEnabled; + } passes.push_back(std::move(newPass)); } } diff --git a/src/dawn/native/d3d12/AdapterD3D12.cpp b/src/dawn/native/d3d12/AdapterD3D12.cpp index 4ac41348ff..f9a8a93caa 100644 --- a/src/dawn/native/d3d12/AdapterD3D12.cpp +++ b/src/dawn/native/d3d12/AdapterD3D12.cpp @@ -137,6 +137,7 @@ MaybeError Adapter::InitializeSupportedFeaturesImpl() { mSupportedFeatures.EnableFeature(Feature::MultiPlanarFormats); mSupportedFeatures.EnableFeature(Feature::Depth24UnormStencil8); mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8); + mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance); if (GetBackend()->GetFunctions()->IsDXCAvailable()) { uint64_t dxcVersion = 0; diff --git a/src/dawn/native/metal/BackendMTL.mm b/src/dawn/native/metal/BackendMTL.mm index 11430de9ec..63d21b16e4 100644 --- a/src/dawn/native/metal/BackendMTL.mm +++ b/src/dawn/native/metal/BackendMTL.mm @@ -386,6 +386,8 @@ class Adapter : public AdapterBase { } #endif + mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance); + return {}; } diff --git a/src/dawn/native/opengl/BackendGL.cpp b/src/dawn/native/opengl/BackendGL.cpp index 3164edab3d..8143eda8fd 100644 --- a/src/dawn/native/opengl/BackendGL.cpp +++ b/src/dawn/native/opengl/BackendGL.cpp @@ -247,6 +247,15 @@ class Adapter : public AdapterBase { mSupportedFeatures.EnableFeature(Feature::Depth24UnormStencil8); } + // Non-zero baseInstance requires at least desktop OpenGL 4.2, and it is not supported in + // OpenGL ES OpenGL: + // https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsIndirect.xhtml + // OpenGL ES: + // https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glDrawElementsIndirect.xhtml + if (mFunctions.IsAtLeastGL(4, 2)) { + mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance); + } + return {}; } diff --git a/src/dawn/native/vulkan/AdapterVk.cpp b/src/dawn/native/vulkan/AdapterVk.cpp index eae25ad0aa..fbdb709d1a 100644 --- a/src/dawn/native/vulkan/AdapterVk.cpp +++ b/src/dawn/native/vulkan/AdapterVk.cpp @@ -163,6 +163,10 @@ MaybeError Adapter::InitializeSupportedFeaturesImpl() { mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8); } + if (mDeviceInfo.features.drawIndirectFirstInstance == VK_TRUE) { + mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance); + } + if (mDeviceInfo.HasExt(DeviceExt::ShaderIntegerDotProduct) && mDeviceInfo.shaderIntegerDotProductProperties .integerDotProduct4x8BitPackedSignedAccelerated == VK_TRUE && diff --git a/src/dawn/tests/end2end/FirstIndexOffsetTests.cpp b/src/dawn/tests/end2end/FirstIndexOffsetTests.cpp index c06416f19a..6eb45c8712 100644 --- a/src/dawn/tests/end2end/FirstIndexOffsetTests.cpp +++ b/src/dawn/tests/end2end/FirstIndexOffsetTests.cpp @@ -63,6 +63,13 @@ class FirstIndexOffsetTests : public DawnTest { DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES()); } + std::vector GetRequiredFeatures() override { + if (!SupportsFeatures({wgpu::FeatureName::IndirectFirstInstance})) { + return {}; + } + return {wgpu::FeatureName::IndirectFirstInstance}; + } + private: void TestImpl(DrawMode mode, CheckIndex checkIndex,