Implement "rg11b10ufloat-renderable" feature

Implement "rg11b10ufloat-renderable" feature that allows
the RENDER_ATTACHMENT usage on textures with format
"rg11b10ufloat", and also allows textures of that format
to be multisampled.

Bug: dawn:1518
Change-Id: I4109dc0e9d90f4c0803219292edea554927a187a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/102000
Commit-Queue: Takahiro <hogehoge@gachapin.jp>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Takahiro 2022-09-22 16:38:06 +00:00 committed by Dawn LUCI CQ
parent 00093a35b7
commit d4dd547bae
10 changed files with 156 additions and 3 deletions

View File

@ -1386,6 +1386,7 @@
{"value": 7, "name": "texture compression ASTC"},
{"value": 8, "name": "indirect first instance"},
{"value": 9, "name": "shader f16"},
{"value": 10, "name": "RG11B10 ufloat renderable"},
{"value": 1001, "name": "dawn shader float 16", "tags": ["dawn"]},
{"value": 1002, "name": "dawn internal usages", "tags": ["dawn"]},
{"value": 1003, "name": "dawn multi planar formats", "tags": ["dawn"]},

View File

@ -68,6 +68,11 @@ static constexpr FeatureEnumAndInfoList kFeatureNameAndInfoList = {{
{"shader-f16", "Supports the \"enable f16;\" directive in WGSL",
"https://bugs.chromium.org/p/dawn/issues/detail?id=1510",
FeatureInfo::FeatureState::Experimental}},
{Feature::RG11B10UfloatRenderable,
{"rg11b10ufloat-renderable",
"Allows the RENDER_ATTACHMENT usage on textures with format \"rg11b10ufloat\", and also "
"allows textures of that format to be multisampled.",
"https://bugs.chromium.org/p/dawn/issues/detail?id=1518", FeatureInfo::FeatureState::Stable}},
{Feature::DawnInternalUsages,
{"dawn-internal-usages",
"Add internal usages to resources to affect how the texture is allocated, but not "
@ -119,6 +124,8 @@ Feature FromAPIFeature(wgpu::FeatureName feature) {
return Feature::ChromiumExperimentalDp4a;
case wgpu::FeatureName::ShaderF16:
return Feature::ShaderF16;
case wgpu::FeatureName::RG11B10UfloatRenderable:
return Feature::RG11B10UfloatRenderable;
}
return Feature::InvalidEnum;
}
@ -151,6 +158,8 @@ wgpu::FeatureName ToAPIFeature(Feature feature) {
return wgpu::FeatureName::ChromiumExperimentalDp4a;
case Feature::ShaderF16:
return wgpu::FeatureName::ShaderF16;
case Feature::RG11B10UfloatRenderable:
return wgpu::FeatureName::RG11B10UfloatRenderable;
case Feature::EnumCount:
break;

View File

@ -37,6 +37,7 @@ enum class Feature {
ChromiumExperimentalDp4a,
IndirectFirstInstance,
ShaderF16,
RG11B10UfloatRenderable,
// Dawn-specific
DawnInternalUsages,

View File

@ -363,7 +363,8 @@ FormatTable BuildFormatTable(const DeviceBase* device) {
AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, true, true, 4, kAnyFloat, 4, wgpu::TextureFormat::BGRA8Unorm);
AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, true, true, 4, kAnyFloat, 4);
AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, false, false, false, false, 4, kAnyFloat, 3);
bool isRG11B10UfloatRenderable = device->HasFeature(Feature::RG11B10UfloatRenderable);
AddColorFormat(wgpu::TextureFormat::RG11B10Ufloat, isRG11B10UfloatRenderable, false, isRG11B10UfloatRenderable, false, 4, kAnyFloat, 3);
AddColorFormat(wgpu::TextureFormat::RGB9E5Ufloat, false, false, false, false, 4, kAnyFloat, 3);
// 8 bytes color formats

View File

@ -137,6 +137,7 @@ MaybeError Adapter::InitializeSupportedFeaturesImpl() {
mSupportedFeatures.EnableFeature(Feature::MultiPlanarFormats);
mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8);
mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance);
mSupportedFeatures.EnableFeature(Feature::RG11B10UfloatRenderable);
if (GetBackend()->GetFunctions()->IsDXCAvailable()) {
uint64_t dxcVersion = 0;

View File

@ -370,8 +370,8 @@ class Adapter : public AdapterBase {
}
mSupportedFeatures.EnableFeature(Feature::IndirectFirstInstance);
mSupportedFeatures.EnableFeature(Feature::ShaderF16);
mSupportedFeatures.EnableFeature(Feature::RG11B10UfloatRenderable);
return {};
}

View File

@ -181,6 +181,16 @@ MaybeError Adapter::InitializeSupportedFeaturesImpl() {
mSupportedFeatures.EnableFeature(Feature::DepthClipControl);
}
VkFormatProperties properties;
mVulkanInstance->GetFunctions().GetPhysicalDeviceFormatProperties(
mPhysicalDevice, VK_FORMAT_B10G11R11_UFLOAT_PACK32, &properties);
if (IsSubset(static_cast<VkFormatFeatureFlags>(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT),
properties.optimalTilingFeatures)) {
mSupportedFeatures.EnableFeature(Feature::RG11B10UfloatRenderable);
}
#if defined(DAWN_USE_SYNC_FDS)
// TODO(chromium:1258986): Precisely enable the feature by querying the device's format
// features.

View File

@ -111,6 +111,83 @@ class ExpectFloat16 : public detail::Expectation {
std::vector<uint16_t> mExpected;
};
// An expectation for RG11B10Ufloat buffer content that can correctly compare different NaN values
class ExpectRG11B10Ufloat : public detail::Expectation {
public:
explicit ExpectRG11B10Ufloat(std::vector<uint32_t> expected) : mExpected(std::move(expected)) {}
testing::AssertionResult Check(const void* data, size_t size) override {
ASSERT(size == sizeof(uint32_t) * mExpected.size());
const uint32_t* actual = static_cast<const uint32_t*>(data);
for (size_t i = 0; i < mExpected.size(); ++i) {
uint32_t expectedValue = mExpected[i];
uint32_t actualValue = actual[i];
if (!RG11B10UfloatMatch(expectedValue, actualValue)) {
testing::AssertionResult result = testing::AssertionFailure()
<< "Expected data[" << i << "] to be "
<< expectedValue << ", actual " << actualValue
<< std::endl;
return result;
}
}
return testing::AssertionSuccess();
}
private:
bool RG11B10UfloatMatch(uint32_t expected, uint32_t actual) {
const uint32_t expectedR = expected & 0x7FF;
const uint32_t expectedG = (expected >> 11) & 0x7FF;
const uint32_t expectedB = (expected >> 22) & 0x3FF;
const uint32_t actualR = actual & 0x7FF;
const uint32_t actualG = (actual >> 11) & 0x7FF;
const uint32_t actualB = (actual >> 22) & 0x3FF;
return Float11Match(expectedR, actualR) && Float11Match(expectedG, actualG) &&
Float10Match(expectedB, actualB);
}
bool Float11Match(uint32_t expected, uint32_t actual) {
ASSERT((expected & ~0x7FF) == 0);
ASSERT((actual & ~0x7FF) == 0);
if (IsFloat11NaN(expected)) {
return IsFloat11NaN(actual);
}
return expected == actual;
}
bool Float10Match(uint32_t expected, uint32_t actual) {
ASSERT((expected & ~0x3FF) == 0);
ASSERT((actual & ~0x3FF) == 0);
if (IsFloat10NaN(expected)) {
return IsFloat10NaN(actual);
}
return expected == actual;
}
// The number is NaN if exponent bits are all 1 and mantissa is non-zero
bool IsFloat11NaN(uint32_t value) {
ASSERT((value & ~0x7FF) == 0);
return ((value & 0x7C0) == 0x7C0) && ((value & 0x3F) != 0);
}
bool IsFloat10NaN(uint32_t value) {
ASSERT((value & ~0x3FF) == 0);
return ((value & 0x3E0) == 0x3E0) && ((value & 0x1F) != 0);
}
std::vector<uint32_t> mExpected;
};
class TextureFormatTest : public DawnTest {
protected:
// Structure containing all the information that tests need to know about the format.
@ -436,6 +513,22 @@ class TextureFormatTest : public DawnTest {
DoFormatRenderingTest(formatInfo, uncompressedData, textureData,
new ExpectFloat16(textureData));
}
// For "rg11b10ufloat-renderable" feature test
std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
if (SupportsFeatures({wgpu::FeatureName::RG11B10UfloatRenderable})) {
mIsRG11B10UfloatRenderableSupported = true;
return {wgpu::FeatureName::RG11B10UfloatRenderable};
} else {
mIsRG11B10UfloatRenderableSupported = false;
return {};
}
}
bool IsRG11B10UfloatRenderableSupported() { return mIsRG11B10UfloatRenderableSupported; }
private:
bool mIsRG11B10UfloatRenderableSupported = false;
};
// Test the R8Unorm format
@ -740,7 +833,20 @@ TEST_P(TextureFormatTest, RG11B10Ufloat) {
DoFloatFormatSamplingTest(
{wgpu::TextureFormat::RG11B10Ufloat, 4, wgpu::TextureComponentType::Float, 4}, textureData,
uncompressedData);
// This format is not renderable.
// This format is renderable if "rg11b10ufloat-renderable" feature is enabled
if (IsRG11B10UfloatRenderableSupported()) {
// TODO(https://crbug.com/swiftshader/147) Rendering INFINITY and NaN isn't handled
// correctly by swiftshader
if ((IsVulkan() && IsSwiftshader()) || IsANGLE()) {
dawn::WarningLog() << "Skip Rendering test because Swiftshader doesn't render INFINITY "
"and NaN correctly for RG11B10Ufloat texture format.";
} else {
DoFormatRenderingTest(
{wgpu::TextureFormat::RG11B10Ufloat, 4, wgpu::TextureComponentType::Float, 4},
uncompressedData, textureData, new ExpectRG11B10Ufloat(textureData));
}
}
}
// Test the RGB9E5Ufloat format

View File

@ -885,6 +885,29 @@ TEST_F(CompressedTextureFormatsValidationTests, TextureSize) {
}
}
class RG11B10UfloatTextureFormatsValidationTests : public TextureValidationTest {
protected:
WGPUDevice CreateTestDevice(dawn::native::Adapter dawnAdapter) override {
wgpu::DeviceDescriptor descriptor;
wgpu::FeatureName requiredFeatures[1] = {wgpu::FeatureName::RG11B10UfloatRenderable};
descriptor.requiredFeatures = requiredFeatures;
descriptor.requiredFeaturesCount = 1;
return dawnAdapter.CreateDevice(&descriptor);
}
};
// Test that RG11B10Ufloat format is valid as render attachment and also it allows
// multisampling if "rg11b10ufloat-renderable" feature is enabled
TEST_F(RG11B10UfloatTextureFormatsValidationTests, RenderableFeature) {
wgpu::TextureDescriptor descriptor;
descriptor.size = {1, 1, 1};
descriptor.usage = wgpu::TextureUsage::RenderAttachment;
descriptor.format = wgpu::TextureFormat::RG11B10Ufloat;
descriptor.sampleCount = 4;
device.CreateTexture(&descriptor);
}
static void CheckTextureMatchesDescriptor(const wgpu::Texture& tex,
const wgpu::TextureDescriptor& desc) {
EXPECT_EQ(desc.size.width, tex.GetWidth());

View File

@ -37,6 +37,7 @@ bool IsFeatureSupported(WGPUFeatureName feature) {
case WGPUFeatureName_DawnMultiPlanarFormats:
case WGPUFeatureName_ChromiumExperimentalDp4a:
case WGPUFeatureName_ShaderF16:
case WGPUFeatureName_RG11B10UfloatRenderable:
return true;
}