Add float32-blendable feature
This CL adds the float32-blendable feature which allows textures with
formats "r32float", "rg32float", and "rgba32float" to be blendable.
Spec PR: https://github.com/gpuweb/gpuweb/pull/4896
Bug: 364987733
Change-Id: Iae3efd9d504c8c4800a8e622c1b82c4b3a25f755
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/210754
Commit-Queue: Fr <beaufort.francois@gmail.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/DEPS b/DEPS
index ffc07a7..cdabe2e 100644
--- a/DEPS
+++ b/DEPS
@@ -375,7 +375,7 @@
'condition': 'dawn_node',
},
'third_party/gpuweb': {
- 'url': '{github_git}/gpuweb/gpuweb.git@010f5c9ddfd21bc963025979d08eb7489058c1c7',
+ 'url': '{github_git}/gpuweb/gpuweb.git@75702cb31c03bc90d34dc87676d1ab0cc131b53a',
'condition': 'dawn_node',
},
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index c9caf55..346941a 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -2574,8 +2574,9 @@
{"value": 9, "name": "RG11B10 ufloat renderable"},
{"value": 10, "name": "BGRA8 unorm storage"},
{"value": 11, "name": "float32 filterable", "jsrepr": "'float32-filterable'"},
- {"value": 12, "name": "subgroups"},
- {"value": 13, "name": "subgroups f16"},
+ {"value": 12, "name": "float32 blendable", "jsrepr": "'float32-blendable'"},
+ {"value": 13, "name": "subgroups"},
+ {"value": 14, "name": "subgroups f16"},
{"value": 0, "name": "dawn internal usages", "tags": ["dawn"]},
{"value": 1, "name": "dawn multi planar formats", "tags": ["dawn"]},
diff --git a/src/dawn/native/Features.cpp b/src/dawn/native/Features.cpp
index 2db7675..703fd90 100644
--- a/src/dawn/native/Features.cpp
+++ b/src/dawn/native/Features.cpp
@@ -94,6 +94,10 @@
{Feature::Float32Filterable,
{"Allows textures with formats \"r32float\" \"rg32float\" and \"rgba32float\" to be filtered.",
"https://gpuweb.github.io/gpuweb/#float32-filterable", FeatureInfo::FeatureState::Stable}},
+ {Feature::Float32Blendable,
+ {"Allows textures with formats \"r32float\" \"rg32float\" and \"rgba32float\" to be "
+ "blendable.",
+ "https://gpuweb.github.io/gpuweb/#float32-blendable", FeatureInfo::FeatureState::Stable}},
{Feature::ChromiumExperimentalSubgroups,
{"DEPRECATED, use subgroups and subgroups-f16 features instead. "
"Experimental, allows using subgroup and supports the \"enable "
diff --git a/src/dawn/native/Format.cpp b/src/dawn/native/Format.cpp
index 7a2492b..a0f98c0 100644
--- a/src/dawn/native/Format.cpp
+++ b/src/dawn/native/Format.cpp
@@ -46,6 +46,7 @@
StorageROrW = 0x8, // Read Or Write, but not ReadWrite in the shader.
StorageRW = 0x10, // Implies StorageROrW
PLS = 0x20,
+ Blendable = 0x40,
};
} // namespace dawn
@@ -243,6 +244,7 @@
internalFormat.format = format;
bool renderable = capabilities & Cap::Renderable;
internalFormat.isRenderable = renderable;
+ internalFormat.isBlendable = capabilities & Cap::Blendable;
internalFormat.isCompressed = false;
internalFormat.unsupportedReason = unsupportedReason;
internalFormat.supportsStorageUsage =
@@ -324,6 +326,7 @@
internalFormat.format = format;
internalFormat.baseFormat = format;
internalFormat.isRenderable = true;
+ internalFormat.isBlendable = false;
internalFormat.isCompressed = false;
internalFormat.unsupportedReason = unsupportedReason;
internalFormat.supportsStorageUsage = false;
@@ -348,6 +351,7 @@
internalFormat.format = format;
internalFormat.baseFormat = format;
internalFormat.isRenderable = true;
+ internalFormat.isBlendable = false;
internalFormat.isCompressed = false;
internalFormat.unsupportedReason = unsupportedReason;
internalFormat.supportsStorageUsage = false;
@@ -382,6 +386,7 @@
Format internalFormat;
internalFormat.format = format;
internalFormat.isRenderable = false;
+ internalFormat.isBlendable = false;
internalFormat.isCompressed = true;
internalFormat.unsupportedReason = unsupportedReason;
internalFormat.supportsStorageUsage = false;
@@ -418,6 +423,7 @@
internalFormat.baseFormat = format;
internalFormat.subSampling = subSampling;
internalFormat.isRenderable = capabilites & Cap::Renderable;
+ internalFormat.isBlendable = false;
internalFormat.isCompressed = false;
internalFormat.unsupportedReason = unsupportedReason;
internalFormat.supportsStorageUsage = false;
@@ -450,7 +456,7 @@
// clang-format off
// 1 byte color formats
auto r8unormSupportsStorage = device->HasFeature(Feature::R8UnormStorage) ? Cap::StorageROrW : Cap::None;
- AddColorFormat(wgpu::TextureFormat::R8Unorm, Cap::Renderable | Cap::Multisample | Cap::Resolve | r8unormSupportsStorage, ByteSize(1), kAnyFloat, ComponentCount(1), RenderTargetPixelByteCost(1), RenderTargetComponentAlignment(1));
+ AddColorFormat(wgpu::TextureFormat::R8Unorm, Cap::Renderable | Cap::Multisample | Cap::Resolve | r8unormSupportsStorage | Cap::Blendable, ByteSize(1), kAnyFloat, ComponentCount(1), RenderTargetPixelByteCost(1), RenderTargetComponentAlignment(1));
AddColorFormat(wgpu::TextureFormat::R8Snorm, Cap::None, ByteSize(1), kAnyFloat, ComponentCount(1));
AddColorFormat(wgpu::TextureFormat::R8Uint, Cap::Renderable | Cap::Multisample, ByteSize(1), SampleTypeBit::Uint, ComponentCount(1), RenderTargetPixelByteCost(1), RenderTargetComponentAlignment(1));
AddColorFormat(wgpu::TextureFormat::R8Sint, Cap::Renderable | Cap::Multisample, ByteSize(1), SampleTypeBit::Sint, ComponentCount(1), RenderTargetPixelByteCost(1), RenderTargetComponentAlignment(1));
@@ -458,8 +464,8 @@
// 2 bytes color formats
AddColorFormat(wgpu::TextureFormat::R16Uint, Cap::Renderable | Cap::Multisample, ByteSize(2), SampleTypeBit::Uint, ComponentCount(1), RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(2));
AddColorFormat(wgpu::TextureFormat::R16Sint, Cap::Renderable | Cap::Multisample, ByteSize(2), SampleTypeBit::Sint, ComponentCount(1), RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(2));
- AddColorFormat(wgpu::TextureFormat::R16Float, Cap::Renderable | Cap::Multisample | Cap::Resolve, ByteSize(2), kAnyFloat, ComponentCount(1), RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(2));
- AddColorFormat(wgpu::TextureFormat::RG8Unorm, Cap::Renderable | Cap::Multisample | Cap::Resolve, ByteSize(2), kAnyFloat, ComponentCount(2), RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(1));
+ AddColorFormat(wgpu::TextureFormat::R16Float, Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable, ByteSize(2), kAnyFloat, ComponentCount(1), RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(2));
+ AddColorFormat(wgpu::TextureFormat::RG8Unorm, Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable, ByteSize(2), kAnyFloat, ComponentCount(2), RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(1));
AddColorFormat(wgpu::TextureFormat::RG8Snorm, Cap::None, ByteSize(2), kAnyFloat, ComponentCount(2));
AddColorFormat(wgpu::TextureFormat::RG8Uint, Cap::Renderable | Cap::Multisample, ByteSize(2), SampleTypeBit::Uint, ComponentCount(2), RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(1));
AddColorFormat(wgpu::TextureFormat::RG8Sint, Cap::Renderable | Cap::Multisample, ByteSize(2), SampleTypeBit::Sint, ComponentCount(2), RenderTargetPixelByteCost(2), RenderTargetComponentAlignment(1));
@@ -467,15 +473,16 @@
// 4 bytes color formats
SampleTypeBit sampleTypeFor32BitFloatFormats = device->HasFeature(Feature::Float32Filterable) ? kAnyFloat : SampleTypeBit::UnfilterableFloat;
auto supportsPLS = device->HasFeature(Feature::PixelLocalStorageCoherent) || device->HasFeature(Feature::PixelLocalStorageNonCoherent) ? Cap::PLS : Cap::None;
+ auto float32BlendableCaps = device->HasFeature(Feature::Float32Blendable) ? Cap::Blendable : Cap::None;
AddColorFormat(wgpu::TextureFormat::R32Uint, Cap::Renderable | Cap::StorageROrW | Cap::StorageRW | supportsPLS, ByteSize(4), SampleTypeBit::Uint, ComponentCount(1), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(4));
AddColorFormat(wgpu::TextureFormat::R32Sint, Cap::Renderable | Cap::StorageROrW | Cap::StorageRW | supportsPLS, ByteSize(4), SampleTypeBit::Sint, ComponentCount(1), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(4));
- AddColorFormat(wgpu::TextureFormat::R32Float, Cap::Renderable | Cap::Multisample | Cap::StorageROrW | Cap::StorageRW | supportsPLS, ByteSize(4), sampleTypeFor32BitFloatFormats, ComponentCount(1), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(4));
+ AddColorFormat(wgpu::TextureFormat::R32Float, Cap::Renderable | Cap::Multisample | Cap::StorageROrW | Cap::StorageRW | supportsPLS | float32BlendableCaps, ByteSize(4), sampleTypeFor32BitFloatFormats, ComponentCount(1), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(4));
AddColorFormat(wgpu::TextureFormat::RG16Uint, Cap::Renderable | Cap::Multisample, ByteSize(4), SampleTypeBit::Uint, ComponentCount(2), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(2));
AddColorFormat(wgpu::TextureFormat::RG16Sint, Cap::Renderable | Cap::Multisample, ByteSize(4), SampleTypeBit::Sint, ComponentCount(2), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(2));
- AddColorFormat(wgpu::TextureFormat::RG16Float, Cap::Renderable | Cap::Multisample | Cap::Resolve, ByteSize(4), kAnyFloat, ComponentCount(2), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(2));
- AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, Cap::Renderable | Cap::StorageROrW | Cap::Multisample | Cap::Resolve, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1));
- AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, Cap::Renderable | Cap::Multisample | Cap::Resolve, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1), wgpu::TextureFormat::RGBA8Unorm);
+ AddColorFormat(wgpu::TextureFormat::RG16Float, Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable, ByteSize(4), kAnyFloat, ComponentCount(2), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(2));
+ AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, Cap::Renderable | Cap::StorageROrW | Cap::Multisample | Cap::Resolve | Cap::Blendable, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1));
+ AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1), wgpu::TextureFormat::RGBA8Unorm);
AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, Cap::StorageROrW, ByteSize(4), kAnyFloat, ComponentCount(4));
AddColorFormat(wgpu::TextureFormat::RGBA8Uint, Cap::Renderable | Cap::StorageROrW | Cap::Multisample, ByteSize(4), SampleTypeBit::Uint, ComponentCount(4), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(1));
AddColorFormat(wgpu::TextureFormat::RGBA8Sint, Cap::Renderable | Cap::StorageROrW | Cap::Multisample, ByteSize(4), SampleTypeBit::Sint, ComponentCount(4), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(1));
@@ -484,12 +491,12 @@
AddConditionalColorFormat(wgpu::TextureFormat::External, externalUnsupportedReason, Cap::None, ByteSize(1), SampleTypeBit::External, ComponentCount(0));
auto BGRA8UnormSupportsStorageUsage = device->HasFeature(Feature::BGRA8UnormStorage) ? Cap::StorageROrW : Cap::None;
- AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, Cap::Renderable | BGRA8UnormSupportsStorageUsage | Cap::Multisample | Cap::Resolve, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1));
- AddConditionalColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, device->IsCompatibilityMode() ? UnsupportedReason(CompatibilityMode{}) : Format::supported, Cap::Renderable | Cap::Multisample | Cap::Resolve, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1), wgpu::TextureFormat::BGRA8Unorm);
+ AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, Cap::Renderable | BGRA8UnormSupportsStorageUsage | Cap::Multisample | Cap::Resolve | Cap::Blendable, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1));
+ AddConditionalColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, device->IsCompatibilityMode() ? UnsupportedReason(CompatibilityMode{}) : Format::supported, Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(1), wgpu::TextureFormat::BGRA8Unorm);
AddColorFormat(wgpu::TextureFormat::RGB10A2Uint, Cap::Renderable | Cap::Multisample, ByteSize(4), SampleTypeBit::Uint, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
- AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, Cap::Renderable | Cap::Multisample | Cap::Resolve, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
+ AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable, ByteSize(4), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
- auto isRG11B10UfloatCapabilities = device->HasFeature(Feature::RG11B10UfloatRenderable) ? Cap::Renderable | Cap::Multisample | Cap::Resolve : Cap::None;
+ auto isRG11B10UfloatCapabilities = device->HasFeature(Feature::RG11B10UfloatRenderable) ? Cap::Renderable | Cap::Multisample | Cap::Resolve | Cap::Blendable : Cap::None;
AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, isRG11B10UfloatCapabilities, ByteSize(4), kAnyFloat, ComponentCount(3), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
AddColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, Cap::None, ByteSize(4), kAnyFloat, ComponentCount(3));
@@ -498,15 +505,15 @@
AddColorFormat(wgpu::TextureFormat::RG32Uint, Cap::Renderable | rg32StorageCaps, ByteSize(8), SampleTypeBit::Uint, ComponentCount(2), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
AddColorFormat(wgpu::TextureFormat::RG32Sint, Cap::Renderable | rg32StorageCaps, ByteSize(8), SampleTypeBit::Sint, ComponentCount(2), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
- AddColorFormat(wgpu::TextureFormat::RG32Float, Cap::Renderable | rg32StorageCaps, ByteSize(8), sampleTypeFor32BitFloatFormats, ComponentCount(2), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
+ AddColorFormat(wgpu::TextureFormat::RG32Float, Cap::Renderable | rg32StorageCaps | float32BlendableCaps, ByteSize(8), sampleTypeFor32BitFloatFormats, ComponentCount(2), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(4));
AddColorFormat(wgpu::TextureFormat::RGBA16Uint, Cap::Renderable | Cap::StorageROrW | Cap::Multisample, ByteSize(8), SampleTypeBit::Uint, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(2));
AddColorFormat(wgpu::TextureFormat::RGBA16Sint, Cap::Renderable | Cap::StorageROrW | Cap::Multisample, ByteSize(8), SampleTypeBit::Sint, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(2));
- AddColorFormat(wgpu::TextureFormat::RGBA16Float, Cap::Renderable | Cap::StorageROrW | Cap::Multisample | Cap::Resolve, ByteSize(8), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(2));
+ AddColorFormat(wgpu::TextureFormat::RGBA16Float, Cap::Renderable | Cap::StorageROrW | Cap::Multisample | Cap::Resolve | Cap::Blendable, ByteSize(8), kAnyFloat, ComponentCount(4), RenderTargetPixelByteCost(8), RenderTargetComponentAlignment(2));
// 16 bytes color formats
AddColorFormat(wgpu::TextureFormat::RGBA32Uint, Cap::Renderable | Cap::StorageROrW, ByteSize(16), SampleTypeBit::Uint, ComponentCount(4), RenderTargetPixelByteCost(16), RenderTargetComponentAlignment(4));
AddColorFormat(wgpu::TextureFormat::RGBA32Sint, Cap::Renderable | Cap::StorageROrW, ByteSize(16), SampleTypeBit::Sint, ComponentCount(4), RenderTargetPixelByteCost(16), RenderTargetComponentAlignment(4));
- AddColorFormat(wgpu::TextureFormat::RGBA32Float, Cap::Renderable | Cap::StorageROrW, ByteSize(16), sampleTypeFor32BitFloatFormats, ComponentCount(4), RenderTargetPixelByteCost(16), RenderTargetComponentAlignment(4));
+ AddColorFormat(wgpu::TextureFormat::RGBA32Float, Cap::Renderable | Cap::StorageROrW | float32BlendableCaps, ByteSize(16), sampleTypeFor32BitFloatFormats, ComponentCount(4), RenderTargetPixelByteCost(16), RenderTargetComponentAlignment(4));
bool norm16TextureFormats = device->HasFeature(Feature::Norm16TextureFormats);
// Unorm16 color formats
diff --git a/src/dawn/native/Format.h b/src/dawn/native/Format.h
index 32218998..1a27417 100644
--- a/src/dawn/native/Format.h
+++ b/src/dawn/native/Format.h
@@ -136,6 +136,7 @@
// TODO(crbug.com/dawn/1332): These members could be stored in a Format capability matrix.
bool isRenderable = false;
bool isCompressed = false;
+ bool isBlendable = false;
// A format can be known but not supported because it is part of a disabled extension.
UnsupportedReason unsupportedReason;
bool supportsStorageUsage = false;
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp
index df7f01e..d7827aa 100644
--- a/src/dawn/native/RenderPipeline.cpp
+++ b/src/dawn/native/RenderPipeline.cpp
@@ -30,6 +30,7 @@
#include <algorithm>
#include <cmath>
+#include "absl/strings/str_format.h"
#include "dawn/common/BitSetIterator.h"
#include "dawn/common/Enumerator.h"
#include "dawn/common/ityp_array.h"
@@ -38,6 +39,7 @@
#include "dawn/native/CommandValidation.h"
#include "dawn/native/Commands.h"
#include "dawn/native/Device.h"
+#include "dawn/native/Instance.h"
#include "dawn/native/InternalPipelineStore.h"
#include "dawn/native/ObjectContentHasher.h"
#include "dawn/native/ObjectType_autogen.h"
@@ -509,10 +511,16 @@
DAWN_INVALID_IF(!format->IsColor() || !format->isRenderable,
"Color format (%s) is not color renderable.", format->format);
- DAWN_INVALID_IF(
- descriptor.blend &&
+ if (descriptor.blend && !format->isBlendable) {
+ DAWN_INVALID_IF(
!(format->GetAspectInfo(Aspect::Color).supportedSampleTypes & SampleTypeBit::Float),
- "Blending is enabled but color format (%s) is not blendable.", format->format);
+ "Blending is enabled but color format (%s) is not blendable.", format->format);
+
+ device->GetInstance()->EmitDeprecationWarning(absl::StrFormat(
+ "Blending for color format (%s) requires the %s feature. Enabling "
+ "blendability with %s was an implementation bug and is deprecated.",
+ format->format, ToAPI(Feature::Float32Blendable), ToAPI(Feature::Float32Filterable)));
+ }
if (!fragmentWritten) {
DAWN_INVALID_IF(
diff --git a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
index 3c02a53..d576730 100644
--- a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
+++ b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
@@ -142,6 +142,7 @@
EnableFeature(Feature::TextureCompressionBC);
EnableFeature(Feature::D3D11MultithreadProtected);
EnableFeature(Feature::Float32Filterable);
+ EnableFeature(Feature::Float32Blendable);
EnableFeature(Feature::DualSourceBlending);
EnableFeature(Feature::ClipDistances);
EnableFeature(Feature::Unorm16TextureFormats);
diff --git a/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp b/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp
index f205387..85b3a0e 100644
--- a/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp
@@ -134,6 +134,7 @@
EnableFeature(Feature::RG11B10UfloatRenderable);
EnableFeature(Feature::DepthClipControl);
EnableFeature(Feature::Float32Filterable);
+ EnableFeature(Feature::Float32Blendable);
EnableFeature(Feature::DualSourceBlending);
EnableFeature(Feature::Unorm16TextureFormats);
EnableFeature(Feature::Snorm16TextureFormats);
diff --git a/src/dawn/native/metal/PhysicalDeviceMTL.mm b/src/dawn/native/metal/PhysicalDeviceMTL.mm
index 75bf0f9..5934e65 100644
--- a/src/dawn/native/metal/PhysicalDeviceMTL.mm
+++ b/src/dawn/native/metal/PhysicalDeviceMTL.mm
@@ -721,6 +721,7 @@
EnableFeature(Feature::ShaderModuleCompilationOptions);
EnableFeature(Feature::DawnLoadResolveTexture);
EnableFeature(Feature::ClipDistances);
+ EnableFeature(Feature::Float32Blendable);
// SIMD-scoped permute operations is supported by GPU family Metal3, Apple6, Apple7, Apple8,
// and Mac2.
diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.cpp b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
index 4de25b2..1755178 100644
--- a/src/dawn/native/opengl/PhysicalDeviceGL.cpp
+++ b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
@@ -278,6 +278,11 @@
EnableFeature(Feature::Snorm16TextureFormats);
EnableFeature(Feature::Norm16TextureFormats);
}
+
+ // Float32Blendable
+ if (mFunctions.IsGLExtensionSupported("GL_EXT_float_blend")) {
+ EnableFeature(Feature::Float32Blendable);
+ }
}
namespace {
diff --git a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
index 7e4d673..05fecd3 100644
--- a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
+++ b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
@@ -351,6 +351,11 @@
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
EnableFeature(Feature::Float32Filterable);
}
+ if ((r32Properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) &&
+ (rg32Properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) &&
+ (rgba32Properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)) {
+ EnableFeature(Feature::Float32Blendable);
+ }
// Multiplanar formats.
constexpr VkFormat multiplanarFormats[] = {
diff --git a/src/dawn/node/binding/Converter.cpp b/src/dawn/node/binding/Converter.cpp
index 88fc4e0..7eca5f1 100644
--- a/src/dawn/node/binding/Converter.cpp
+++ b/src/dawn/node/binding/Converter.cpp
@@ -1481,6 +1481,9 @@
case interop::GPUFeatureName::kFloat32Filterable:
out = wgpu::FeatureName::Float32Filterable;
return true;
+ case interop::GPUFeatureName::kFloat32Blendable:
+ out = wgpu::FeatureName::Float32Blendable;
+ return true;
case interop::GPUFeatureName::kSubgroups:
out = wgpu::FeatureName::Subgroups;
return true;
@@ -1505,6 +1508,7 @@
case interop::GPUFeatureName::kClipDistances:
out = wgpu::FeatureName::ClipDistances;
return true;
+ case interop::GPUFeatureName::kTextureCompressionAstcSliced3D:
case interop::GPUFeatureName::kTextureCompressionBcSliced3D:
return false;
}
@@ -1525,6 +1529,7 @@
CASE(Depth32FloatStencil8, kDepth32FloatStencil8);
CASE(DepthClipControl, kDepthClipControl);
CASE(Float32Filterable, kFloat32Filterable);
+ CASE(Float32Blendable, kFloat32Blendable);
CASE(IndirectFirstInstance, kIndirectFirstInstance);
CASE(RG11B10UfloatRenderable, kRg11B10UfloatRenderable);
CASE(ShaderF16, kShaderF16);
diff --git a/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp b/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
index cad56a4..9e8531b 100644
--- a/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/RenderPipelineValidationTests.cpp
@@ -477,28 +477,6 @@
}
{
- // Fails because RGBA32Float is not blendable
- utils::ComboRenderPipelineDescriptor descriptor;
- descriptor.vertex.module = vsModule;
- descriptor.cFragment.module = fsModule;
- descriptor.cTargets[0].blend = &descriptor.cBlends[0];
- descriptor.cTargets[0].format = wgpu::TextureFormat::RGBA32Float;
-
- ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
- }
-
- {
- // Succeeds because RGBA32Float is not blendable but blending is disabled
- utils::ComboRenderPipelineDescriptor descriptor;
- descriptor.vertex.module = vsModule;
- descriptor.cFragment.module = fsModule;
- descriptor.cTargets[0].blend = nullptr;
- descriptor.cTargets[0].format = wgpu::TextureFormat::RGBA32Float;
-
- device.CreateRenderPipeline(&descriptor);
- }
-
- {
// Fails because RGBA8Uint is not blendable
utils::ComboRenderPipelineDescriptor descriptor;
descriptor.vertex.module = vsModule;
@@ -506,7 +484,8 @@
descriptor.cTargets[0].blend = &descriptor.cBlends[0];
descriptor.cTargets[0].format = wgpu::TextureFormat::RGBA8Uint;
- ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor));
+ ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor),
+ testing::HasSubstr("Blending is enabled but color format"));
}
{
@@ -521,6 +500,77 @@
}
}
+// Tests that the float32 color formats are not blendable without the float32-blendable feature.
+TEST_F(RenderPipelineValidationTest, Float32NonBlendableFormats) {
+ for (const auto f32Format : {wgpu::TextureFormat::R32Float, wgpu::TextureFormat::RG32Float,
+ wgpu::TextureFormat::RGBA32Float}) {
+ {
+ // Control case: Succeeds because blending is disabled
+ utils::ComboRenderPipelineDescriptor descriptor;
+ descriptor.vertex.module = vsModule;
+ descriptor.cFragment.module = fsModule;
+ descriptor.cTargets[0].blend = nullptr;
+ descriptor.cTargets[0].format = f32Format;
+
+ device.CreateRenderPipeline(&descriptor);
+ }
+ {
+ // Fails because float32 color format blending requires the float32-blendable feature.
+ utils::ComboRenderPipelineDescriptor descriptor;
+ descriptor.vertex.module = vsModule;
+ descriptor.cFragment.module = fsModule;
+ descriptor.cTargets[0].blend = &descriptor.cBlends[0];
+ descriptor.cTargets[0].format = f32Format;
+
+ ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor),
+ testing::HasSubstr("Blending is enabled but color format"));
+ }
+ }
+}
+
+class Float32BlendableValidationTest : public RenderPipelineValidationTest {
+ protected:
+ std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
+ return {wgpu::FeatureName::Float32Blendable};
+ }
+};
+
+// Tests that the float32 color formats are blendable only with the float32-blendable feature.
+TEST_F(Float32BlendableValidationTest, Float32BlendableFormatsWithFeatureEnabled) {
+ for (const auto f32Format : {wgpu::TextureFormat::R32Float, wgpu::TextureFormat::RG32Float,
+ wgpu::TextureFormat::RGBA32Float}) {
+ utils::ComboRenderPipelineDescriptor descriptor;
+ descriptor.vertex.module = vsModule;
+ descriptor.cFragment.module = fsModule;
+ descriptor.cTargets[0].blend = &descriptor.cBlends[0];
+ descriptor.cTargets[0].format = f32Format;
+
+ device.CreateRenderPipeline(&descriptor);
+ }
+}
+
+class Float32FilterableValidationTest : public RenderPipelineValidationTest {
+ protected:
+ std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
+ return {wgpu::FeatureName::Float32Filterable};
+ }
+};
+
+// Tests that blending a float32 color formats without the float32-blendable feature emits a
+// deprecation warning with the float32-filterable feature.
+TEST_F(Float32FilterableValidationTest, Float32BlendableFormatsWithoutFeature) {
+ for (const auto f32Format : {wgpu::TextureFormat::R32Float, wgpu::TextureFormat::RG32Float,
+ wgpu::TextureFormat::RGBA32Float}) {
+ utils::ComboRenderPipelineDescriptor descriptor;
+ descriptor.vertex.module = vsModule;
+ descriptor.cFragment.module = fsModule;
+ descriptor.cTargets[0].blend = &descriptor.cBlends[0];
+ descriptor.cTargets[0].format = f32Format;
+
+ EXPECT_DEPRECATION_WARNING(device.CreateRenderPipeline(&descriptor));
+ }
+}
+
// Tests that the format of the color state descriptor must match the output of the fragment shader.
TEST_F(RenderPipelineValidationTest, FragmentOutputFormatCompatibility) {
std::vector<std::vector<std::string>> kScalarTypeLists = {// Float scalar types
diff --git a/src/dawn/wire/SupportedFeatures.cpp b/src/dawn/wire/SupportedFeatures.cpp
index a0a23ab..5176a39 100644
--- a/src/dawn/wire/SupportedFeatures.cpp
+++ b/src/dawn/wire/SupportedFeatures.cpp
@@ -89,6 +89,7 @@
case WGPUFeatureName_BGRA8UnormStorage:
case WGPUFeatureName_TransientAttachments:
case WGPUFeatureName_Float32Filterable:
+ case WGPUFeatureName_Float32Blendable:
case WGPUFeatureName_MSAARenderToSingleSampled:
case WGPUFeatureName_DualSourceBlending:
case WGPUFeatureName_ANGLETextureSharing:
diff --git a/third_party/gpuweb b/third_party/gpuweb
index 010f5c9..75702cb 160000
--- a/third_party/gpuweb
+++ b/third_party/gpuweb
@@ -1 +1 @@
-Subproject commit 010f5c9ddfd21bc963025979d08eb7489058c1c7
+Subproject commit 75702cb31c03bc90d34dc87676d1ab0cc131b53a