From bbed4577964d1f3c7ba1412a1515fbc7fa084a4c Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Mon, 29 Apr 2019 09:31:06 +0000 Subject: [PATCH] Texture: Add validation that the mip chain can't be too large BUG=chromium:954769 Change-Id: I07a00230294cb9385b79edb6150d9f0f7b4b7284 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/6760 Commit-Queue: Corentin Wallez Reviewed-by: Austin Eng Reviewed-by: Kai Ninomiya --- src/dawn_native/Texture.cpp | 6 ++ .../validation/TextureValidationTests.cpp | 68 +++++++++++++++++++ .../validation/TextureViewValidationTests.cpp | 4 +- 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp index 22a62e7d39..633b943a53 100644 --- a/src/dawn_native/Texture.cpp +++ b/src/dawn_native/Texture.cpp @@ -15,6 +15,7 @@ #include "dawn_native/Texture.h" #include "common/Assert.h" +#include "common/Math.h" #include "dawn_native/Device.h" #include "dawn_native/ValidationUtils_autogen.h" @@ -173,6 +174,11 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Cannot create an empty texture"); } + if (Log2(descriptor->size.width) + 1 < descriptor->mipLevelCount || + Log2(descriptor->size.height) + 1 < descriptor->mipLevelCount) { + return DAWN_VALIDATION_ERROR("Texture has too many mip levels"); + } + return {}; } diff --git a/src/tests/unittests/validation/TextureValidationTests.cpp b/src/tests/unittests/validation/TextureValidationTests.cpp index a88a7df4ee..4d011829d7 100644 --- a/src/tests/unittests/validation/TextureValidationTests.cpp +++ b/src/tests/unittests/validation/TextureValidationTests.cpp @@ -95,6 +95,74 @@ TEST_F(TextureValidationTest, SampleCount) { } } +// Test the validation of the mip level count +TEST_F(TextureValidationTest, MipLevelCount) { + dawn::TextureDescriptor defaultDescriptor = CreateDefaultTextureDescriptor(); + + // mipLevelCount == 1 is allowed + { + dawn::TextureDescriptor descriptor = defaultDescriptor; + descriptor.size.width = 32; + descriptor.size.height = 32; + descriptor.mipLevelCount = 1; + + device.CreateTexture(&descriptor); + } + + // mipLevelCount == 0 is an error + { + dawn::TextureDescriptor descriptor = defaultDescriptor; + descriptor.size.width = 32; + descriptor.size.height = 32; + descriptor.mipLevelCount = 0; + + ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor)); + } + + // Full mip chains are allowed + { + dawn::TextureDescriptor descriptor = defaultDescriptor; + descriptor.size.width = 32; + descriptor.size.height = 32; + // Mip level sizes: 32, 16, 8, 4, 2, 1 + descriptor.mipLevelCount = 6; + + device.CreateTexture(&descriptor); + } + + // Too big mip chains on width are disallowed + { + dawn::TextureDescriptor descriptor = defaultDescriptor; + descriptor.size.width = 31; + descriptor.size.height = 32; + // Mip level width: 31, 15, 7, 3, 1 + descriptor.mipLevelCount = 6; + + ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor)); + } + + // Too big mip chains on height are disallowed + { + dawn::TextureDescriptor descriptor = defaultDescriptor; + descriptor.size.width = 32; + descriptor.size.height = 31; + // Mip level height: 31, 15, 7, 3, 1 + descriptor.mipLevelCount = 6; + + ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor)); + } + + // Undefined shift check if miplevel is bigger than the integer bit width. + { + dawn::TextureDescriptor descriptor = defaultDescriptor; + descriptor.size.width = 32; + descriptor.size.height = 32; + descriptor.mipLevelCount = 100; + + ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor)); + } +} + // Test that it is valid to destroy a texture TEST_F(TextureValidationTest, DestroyTexture) { dawn::TextureDescriptor descriptor = CreateDefaultTextureDescriptor(); diff --git a/src/tests/unittests/validation/TextureViewValidationTests.cpp b/src/tests/unittests/validation/TextureViewValidationTests.cpp index 707db08f8f..b7ddfc56ee 100644 --- a/src/tests/unittests/validation/TextureViewValidationTests.cpp +++ b/src/tests/unittests/validation/TextureViewValidationTests.cpp @@ -183,7 +183,7 @@ TEST_F(TextureViewValidationTest, CreateCubeMapTextureView) { // It is an error to create a cube map texture view with width != height. { - dawn::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16); + dawn::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16, 5); dawn::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = dawn::TextureViewDimension::Cube; @@ -193,7 +193,7 @@ TEST_F(TextureViewValidationTest, CreateCubeMapTextureView) { // It is an error to create a cube map array texture view with width != height. { - dawn::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16); + dawn::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16, 5); dawn::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = dawn::TextureViewDimension::CubeArray;