diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp index a97536ade4..5d21ad6b2d 100644 --- a/src/dawn_native/Texture.cpp +++ b/src/dawn_native/Texture.cpp @@ -47,6 +47,22 @@ namespace dawn_native { } } + 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 @@ namespace dawn_native { } } - // 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 @@ namespace dawn_native { "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 @@ namespace dawn_native { 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 @@ namespace dawn_native { mSize(descriptor->size), mArrayLayerCount(descriptor->arrayLayerCount), mMipLevelCount(descriptor->mipLevelCount), + mSampleCount(descriptor->sampleCount), mUsage(descriptor->usage) { } @@ -322,6 +356,10 @@ namespace dawn_native { 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 @@ namespace dawn_native { 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 d7dd6d3f53..0c0222a9b7 100644 --- a/src/dawn_native/Texture.h +++ b/src/dawn_native/Texture.h @@ -54,10 +54,13 @@ namespace dawn_native { 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 @@ namespace dawn_native { 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 28743c37bd..dce5af18bb 100644 --- a/src/tests/unittests/validation/TextureValidationTests.cpp +++ b/src/tests/unittests/validation/TextureValidationTests.cpp @@ -56,6 +56,14 @@ TEST_F(TextureValidationTest, SampleCount) { 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 @@ TEST_F(TextureValidationTest, SampleCount) { 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 9d8c31a5b8..b33060064c 100644 --- a/src/tests/unittests/validation/TextureViewValidationTests.cpp +++ b/src/tests/unittests/validation/TextureViewValidationTests.cpp @@ -28,16 +28,18 @@ constexpr dawn::TextureFormat kDefaultTextureFormat = dawn::TextureFormat::R8G8B 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 @@ TEST_F(TextureViewValidationTest, CreateCubeMapTextureView) { 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.