Add validation on the creation of 4x Multisampled textures
This patch adds validations on the creation of the multisampled textures
with sampleCount == 4. The validations include:
1. Only accept 1 or 4 as valid value of sampleCount.
2. According to Vulkan SPEC, when sampleCount > 1:
- The value of mipLevelCount can only be 1
- We cannot create cube map or cube map array texture views on this
texture.
BUG=dawn:56
TEST=dawn_unittests
Change-Id: Iac7cbe7cd7af16216b9185afd37a80eef0712f6b
Reviewed-on: https://dawn-review.googlesource.com/c/5160
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index a97536a..5d21ad6 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -47,6 +47,22 @@
}
}
+ bool IsTextureViewDimensionCompatibleWithTextureSampleCount(
+ dawn::TextureViewDimension textureViewDimension,
+ const uint32_t sampleCount) {
+ switch (textureViewDimension) {
+ case dawn::TextureViewDimension::Cube:
+ case dawn::TextureViewDimension::CubeArray:
+ return sampleCount == 1;
+ case dawn::TextureViewDimension::e2D:
+ case dawn::TextureViewDimension::e2DArray:
+ return true;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+ }
+
// TODO(jiawei.shao@intel.com): support validation on all texture view dimensions
bool IsArrayLayerValidForTextureViewDimension(
dawn::TextureViewDimension textureViewDimension,
@@ -82,10 +98,20 @@
}
}
- // TODO(jiawei.shao@intel.com): support multisampled textures
- MaybeError ValidateSampleCount(uint32_t sampleCount) {
- if (sampleCount != 1) {
- return DAWN_VALIDATION_ERROR("The sample count of the texture is not supported.");
+ // TODO(jiawei.shao@intel.com): support more sample count.
+ MaybeError ValidateSampleCount(const TextureDescriptor* descriptor) {
+ switch (descriptor->sampleCount) {
+ case 1:
+ break;
+ case 4:
+ if (descriptor->mipLevelCount > 1) {
+ return DAWN_VALIDATION_ERROR(
+ "The mipmap level count of a multisampled texture must be 1.");
+ }
+ break;
+ default:
+ return DAWN_VALIDATION_ERROR(
+ "The sample count of the texture is not supported.");
}
return {};
@@ -107,6 +133,13 @@
"original texture");
}
+ if (!IsTextureViewDimensionCompatibleWithTextureSampleCount(
+ descriptor->dimension, texture->GetSampleCount())) {
+ return DAWN_VALIDATION_ERROR(
+ "The dimension of the texture view is not compatible with the sample count of "
+ "the original texture");
+ }
+
if (!IsTextureSizeValidForTextureViewDimension(descriptor->dimension,
texture->GetSize())) {
return DAWN_VALIDATION_ERROR(
@@ -151,7 +184,7 @@
DAWN_TRY(ValidateTextureUsageBit(descriptor->usage));
DAWN_TRY(ValidateTextureDimension(descriptor->dimension));
DAWN_TRY(ValidateTextureFormat(descriptor->format));
- DAWN_TRY(ValidateSampleCount(descriptor->sampleCount));
+ DAWN_TRY(ValidateSampleCount(descriptor));
// TODO(jiawei.shao@intel.com): check stuff based on the dimension
if (descriptor->size.width == 0 || descriptor->size.height == 0 ||
@@ -290,6 +323,7 @@
mSize(descriptor->size),
mArrayLayerCount(descriptor->arrayLayerCount),
mMipLevelCount(descriptor->mipLevelCount),
+ mSampleCount(descriptor->sampleCount),
mUsage(descriptor->usage) {
}
@@ -322,6 +356,10 @@
ASSERT(!IsError());
return mMipLevelCount;
}
+ uint32_t TextureBase::GetSampleCount() const {
+ ASSERT(!IsError());
+ return mSampleCount;
+ }
dawn::TextureUsageBit TextureBase::GetUsage() const {
ASSERT(!IsError());
return mUsage;
@@ -332,6 +370,11 @@
return {};
}
+ bool TextureBase::IsMultisampledTexture() const {
+ ASSERT(!IsError());
+ return mSampleCount > 1;
+ }
+
TextureViewBase* TextureBase::CreateDefaultTextureView() {
TextureViewDescriptor descriptor = {};
diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h
index d7dd6d3..0c0222a 100644
--- a/src/dawn_native/Texture.h
+++ b/src/dawn_native/Texture.h
@@ -54,10 +54,13 @@
const Extent3D& GetSize() const;
uint32_t GetArrayLayers() const;
uint32_t GetNumMipLevels() const;
+ uint32_t GetSampleCount() const;
dawn::TextureUsageBit GetUsage() const;
MaybeError ValidateCanUseInSubmitNow() const;
+ bool IsMultisampledTexture() const;
+
// Dawn API
TextureViewBase* CreateDefaultTextureView();
TextureViewBase* CreateTextureView(const TextureViewDescriptor* descriptor);
@@ -70,6 +73,7 @@
Extent3D mSize;
uint32_t mArrayLayerCount;
uint32_t mMipLevelCount;
+ uint32_t mSampleCount;
dawn::TextureUsageBit mUsage = dawn::TextureUsageBit::None;
};
diff --git a/src/tests/unittests/validation/TextureValidationTests.cpp b/src/tests/unittests/validation/TextureValidationTests.cpp
index 28743c3..dce5af1 100644
--- a/src/tests/unittests/validation/TextureValidationTests.cpp
+++ b/src/tests/unittests/validation/TextureValidationTests.cpp
@@ -56,6 +56,14 @@
device.CreateTexture(&descriptor);
}
+ // sampleCount == 4 is allowed.
+ {
+ dawn::TextureDescriptor descriptor = defaultDescriptor;
+ descriptor.sampleCount = 4;
+
+ device.CreateTexture(&descriptor);
+ }
+
// It is an error to create a texture with an invalid sampleCount.
{
dawn::TextureDescriptor descriptor = defaultDescriptor;
@@ -63,5 +71,14 @@
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
+
+ // It is an error to create a multisampled texture with mipLevelCount > 1.
+ {
+ dawn::TextureDescriptor descriptor = defaultDescriptor;
+ descriptor.sampleCount = 4;
+ descriptor.mipLevelCount = 2;
+
+ ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
+ }
}
} // namespace
diff --git a/src/tests/unittests/validation/TextureViewValidationTests.cpp b/src/tests/unittests/validation/TextureViewValidationTests.cpp
index 9d8c31a..b330600 100644
--- a/src/tests/unittests/validation/TextureViewValidationTests.cpp
+++ b/src/tests/unittests/validation/TextureViewValidationTests.cpp
@@ -28,16 +28,18 @@
dawn::Texture Create2DArrayTexture(dawn::Device& device,
uint32_t arrayLayerCount,
uint32_t width = kWidth,
- uint32_t height = kHeight) {
+ uint32_t height = kHeight,
+ uint32_t mipLevelCount = kDefaultMipLevels,
+ uint32_t sampleCount = 1) {
dawn::TextureDescriptor descriptor;
descriptor.dimension = dawn::TextureDimension::e2D;
descriptor.size.width = width;
descriptor.size.height = height;
descriptor.size.depth = 1;
descriptor.arrayLayerCount = arrayLayerCount;
- descriptor.sampleCount = 1;
+ descriptor.sampleCount = sampleCount;
descriptor.format = kDefaultTextureFormat;
- descriptor.mipLevelCount = kDefaultMipLevels;
+ descriptor.mipLevelCount = mipLevelCount;
descriptor.usage = dawn::TextureUsageBit::Sampled;
return device.CreateTexture(&descriptor);
}
@@ -198,6 +200,30 @@
descriptor.arrayLayerCount = 12;
ASSERT_DEVICE_ERROR(nonSquareTexture.CreateTextureView(&descriptor));
}
+
+ // It is an error to create a cube map texture view on a multisampled texture.
+ {
+ constexpr uint32_t kSampleCount = 4;
+ dawn::Texture multisampledTexture = Create2DArrayTexture(device, kDefaultArrayLayers,
+ kWidth, kHeight, 1, kSampleCount);
+ dawn::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
+ descriptor.dimension = dawn::TextureViewDimension::Cube;
+ descriptor.arrayLayerCount = 6;
+ descriptor.mipLevelCount = 1;
+ ASSERT_DEVICE_ERROR(multisampledTexture.CreateTextureView(&descriptor));
+ }
+
+ // It is an error to create a cube map array texture view on a multisampled texture.
+ {
+ constexpr uint32_t kSampleCount = 4;
+ dawn::Texture multisampledTexture = Create2DArrayTexture(device, kDefaultArrayLayers,
+ kWidth, kHeight, 1, kSampleCount);
+ dawn::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor;
+ descriptor.dimension = dawn::TextureViewDimension::CubeArray;
+ descriptor.arrayLayerCount = 12;
+ descriptor.mipLevelCount = 1;
+ ASSERT_DEVICE_ERROR(multisampledTexture.CreateTextureView(&descriptor));
+ }
}
// Test the format compatibility rules when creating a texture view.