mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-15 11:51:22 +00:00
Fix computation of mipmap sizes used in validation
The width and height of the mipmaps level > 0 weren't computed correctly. Size of mip level of a texture should be greater than 0. BUG=dawn:176 TEST=dawn_unittests --gtest_filter=CopyCommandTest*.CopyNonSquareTexture Change-Id: I730aef3fd8c036567f824cd707d1ea1a69b132c0 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8242 Commit-Queue: Yizhou Jiang <yizhou.jiang@intel.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
6fa398e682
commit
41c24ee4eb
@ -39,9 +39,10 @@ namespace dawn_native {
|
|||||||
bool IsCompleteSubresourceCopiedTo(const TextureBase* texture,
|
bool IsCompleteSubresourceCopiedTo(const TextureBase* texture,
|
||||||
const Extent3D copySize,
|
const Extent3D copySize,
|
||||||
const uint32_t mipLevel) {
|
const uint32_t mipLevel) {
|
||||||
if (texture->GetSize().depth == copySize.depth &&
|
Extent3D extent = texture->GetMipLevelSize(mipLevel);
|
||||||
(texture->GetSize().width >> mipLevel) == copySize.width &&
|
|
||||||
(texture->GetSize().height >> mipLevel) == copySize.height) {
|
if (extent.depth == copySize.depth && extent.width == copySize.width &&
|
||||||
|
extent.height == copySize.height) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -47,24 +47,12 @@ namespace dawn_native {
|
|||||||
// overflows.
|
// overflows.
|
||||||
uint64_t level = textureCopy.level;
|
uint64_t level = textureCopy.level;
|
||||||
|
|
||||||
uint32_t widthAtLevel = texture->GetSize().width >> level;
|
Extent3D extent = texture->GetMipLevelSize(level);
|
||||||
uint32_t heightAtLevel = texture->GetSize().height >> level;
|
|
||||||
|
|
||||||
// Compressed Textures will have paddings if their width or height is not a multiple of
|
|
||||||
// 4 at non-zero mipmap levels.
|
|
||||||
const Format& textureFormat = texture->GetFormat();
|
|
||||||
if (textureFormat.isCompressed) {
|
|
||||||
// TODO(jiawei.shao@intel.com): check if there are any overflows.
|
|
||||||
uint32_t blockWidth = textureFormat.blockWidth;
|
|
||||||
uint32_t blockHeight = textureFormat.blockHeight;
|
|
||||||
widthAtLevel = (widthAtLevel + blockWidth - 1) / blockWidth * blockWidth;
|
|
||||||
heightAtLevel = (heightAtLevel + blockHeight - 1) / blockHeight * blockHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uint64_t(textureCopy.origin.x) + uint64_t(copySize.width) >
|
if (uint64_t(textureCopy.origin.x) + uint64_t(copySize.width) >
|
||||||
static_cast<uint64_t>(widthAtLevel) ||
|
static_cast<uint64_t>(extent.width) ||
|
||||||
uint64_t(textureCopy.origin.y) + uint64_t(copySize.height) >
|
uint64_t(textureCopy.origin.y) + uint64_t(copySize.height) >
|
||||||
static_cast<uint64_t>(heightAtLevel)) {
|
static_cast<uint64_t>(extent.height)) {
|
||||||
return DAWN_VALIDATION_ERROR("Copy would touch outside of the texture");
|
return DAWN_VALIDATION_ERROR("Copy would touch outside of the texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,6 +497,25 @@ namespace dawn_native {
|
|||||||
return mSampleCount > 1;
|
return mSampleCount > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Extent3D TextureBase::GetMipLevelSize(uint64_t level) const {
|
||||||
|
Extent3D extent;
|
||||||
|
extent.width = std::max(mSize.width >> level, 1u);
|
||||||
|
extent.height = std::max(mSize.height >> level, 1u);
|
||||||
|
extent.depth = std::max(mSize.depth >> level, 1u);
|
||||||
|
|
||||||
|
// Compressed Textures will have paddings if their width or height is not a multiple of
|
||||||
|
// 4 at non-zero mipmap levels.
|
||||||
|
if (mFormat.isCompressed) {
|
||||||
|
// TODO(jiawei.shao@intel.com): check if there are any overflows.
|
||||||
|
uint32_t blockWidth = mFormat.blockWidth;
|
||||||
|
uint32_t blockHeight = mFormat.blockHeight;
|
||||||
|
extent.width = (extent.width + blockWidth - 1) / blockWidth * blockWidth;
|
||||||
|
extent.height = (extent.height + blockHeight - 1) / blockHeight * blockHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return extent;
|
||||||
|
}
|
||||||
|
|
||||||
TextureViewBase* TextureBase::CreateDefaultView() {
|
TextureViewBase* TextureBase::CreateDefaultView() {
|
||||||
TextureViewDescriptor descriptor = {};
|
TextureViewDescriptor descriptor = {};
|
||||||
|
|
||||||
|
@ -99,6 +99,8 @@ namespace dawn_native {
|
|||||||
|
|
||||||
bool IsMultisampledTexture() const;
|
bool IsMultisampledTexture() const;
|
||||||
|
|
||||||
|
Extent3D GetMipLevelSize(uint64_t level) const;
|
||||||
|
|
||||||
// Dawn API
|
// Dawn API
|
||||||
TextureViewBase* CreateDefaultView();
|
TextureViewBase* CreateDefaultView();
|
||||||
TextureViewBase* CreateView(const TextureViewDescriptor* descriptor);
|
TextureViewBase* CreateView(const TextureViewDescriptor* descriptor);
|
||||||
|
@ -28,9 +28,13 @@ class CopyCommandTest : public ValidationTest {
|
|||||||
return device.CreateBuffer(&descriptor);
|
return device.CreateBuffer(&descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
dawn::Texture Create2DTexture(uint32_t width, uint32_t height, uint32_t mipLevelCount,
|
dawn::Texture Create2DTexture(uint32_t width,
|
||||||
uint32_t arrayLayerCount, dawn::TextureFormat format,
|
uint32_t height,
|
||||||
dawn::TextureUsageBit usage, uint32_t sampleCount = 1) {
|
uint32_t mipLevelCount,
|
||||||
|
uint32_t arrayLayerCount,
|
||||||
|
dawn::TextureFormat format,
|
||||||
|
dawn::TextureUsageBit usage,
|
||||||
|
uint32_t sampleCount = 1) {
|
||||||
dawn::TextureDescriptor descriptor;
|
dawn::TextureDescriptor descriptor;
|
||||||
descriptor.dimension = dawn::TextureDimension::e2D;
|
descriptor.dimension = dawn::TextureDimension::e2D;
|
||||||
descriptor.size.width = width;
|
descriptor.size.width = width;
|
||||||
@ -140,8 +144,7 @@ class CopyCommandTest : public ValidationTest {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CopyCommandTest_B2B : public CopyCommandTest {
|
class CopyCommandTest_B2B : public CopyCommandTest {};
|
||||||
};
|
|
||||||
|
|
||||||
// TODO(cwallez@chromium.org): Test that copies are forbidden inside renderpasses
|
// TODO(cwallez@chromium.org): Test that copies are forbidden inside renderpasses
|
||||||
|
|
||||||
@ -263,8 +266,7 @@ TEST_F(CopyCommandTest_B2B, BuffersInErrorState) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CopyCommandTest_B2T : public CopyCommandTest {
|
class CopyCommandTest_B2T : public CopyCommandTest {};
|
||||||
};
|
|
||||||
|
|
||||||
// Test a successfull B2T copy
|
// Test a successfull B2T copy
|
||||||
TEST_F(CopyCommandTest_B2T, Success) {
|
TEST_F(CopyCommandTest_B2T, Success) {
|
||||||
@ -344,7 +346,8 @@ TEST_F(CopyCommandTest_B2T, OutOfBoundsOnBuffer) {
|
|||||||
{
|
{
|
||||||
uint32_t sourceBufferSize = BufferSizeForTextureCopy(7, 3, 1);
|
uint32_t sourceBufferSize = BufferSizeForTextureCopy(7, 3, 1);
|
||||||
ASSERT_TRUE(256 * 3 > sourceBufferSize) << "row pitch * height should overflow buffer";
|
ASSERT_TRUE(256 * 3 > sourceBufferSize) << "row pitch * height should overflow buffer";
|
||||||
dawn::Buffer sourceBuffer = CreateBuffer(sourceBufferSize, dawn::BufferUsageBit::TransferSrc);
|
dawn::Buffer sourceBuffer =
|
||||||
|
CreateBuffer(sourceBufferSize, dawn::BufferUsageBit::TransferSrc);
|
||||||
|
|
||||||
TestB2TCopy(utils::Expectation::Success, source, 0, 256, 0, destination, 0, 0, {0, 0, 0},
|
TestB2TCopy(utils::Expectation::Success, source, 0, 256, 0, destination, 0, 0, {0, 0, 0},
|
||||||
{7, 3, 1});
|
{7, 3, 1});
|
||||||
@ -577,8 +580,33 @@ TEST_F(CopyCommandTest_B2T, TextureCopyBufferSizeLastRowComputation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CopyCommandTest_T2B : public CopyCommandTest {
|
// Test copy from buffer to mip map of non square texture
|
||||||
};
|
TEST_F(CopyCommandTest_B2T, CopyToMipmapOfNonSquareTexture) {
|
||||||
|
uint64_t bufferSize = BufferSizeForTextureCopy(4, 2, 1);
|
||||||
|
dawn::Buffer source = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
|
||||||
|
uint32_t maxMipmapLevel = 3;
|
||||||
|
dawn::Texture destination =
|
||||||
|
Create2DTexture(4, 2, maxMipmapLevel, 1, dawn::TextureFormat::RGBA8Unorm,
|
||||||
|
dawn::TextureUsageBit::TransferDst);
|
||||||
|
|
||||||
|
// Copy to top level mip map
|
||||||
|
TestB2TCopy(utils::Expectation::Success, source, 0, 256, 0, destination, maxMipmapLevel - 1, 0,
|
||||||
|
{0, 0, 0}, {1, 1, 1});
|
||||||
|
// Copy to high level mip map
|
||||||
|
TestB2TCopy(utils::Expectation::Success, source, 0, 256, 0, destination, maxMipmapLevel - 2, 0,
|
||||||
|
{0, 0, 0}, {2, 1, 1});
|
||||||
|
// Mip level out of range
|
||||||
|
TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 0, destination, maxMipmapLevel, 0,
|
||||||
|
{0, 0, 0}, {1, 1, 1});
|
||||||
|
// Copy origin out of range
|
||||||
|
TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 0, destination, maxMipmapLevel - 2, 0,
|
||||||
|
{1, 0, 0}, {2, 1, 1});
|
||||||
|
// Copy size out of range
|
||||||
|
TestB2TCopy(utils::Expectation::Failure, source, 0, 256, 0, destination, maxMipmapLevel - 2, 0,
|
||||||
|
{0, 0, 0}, {2, 2, 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
class CopyCommandTest_T2B : public CopyCommandTest {};
|
||||||
|
|
||||||
// Test a successfull T2B copy
|
// Test a successfull T2B copy
|
||||||
TEST_F(CopyCommandTest_T2B, Success) {
|
TEST_F(CopyCommandTest_T2B, Success) {
|
||||||
@ -682,7 +710,8 @@ TEST_F(CopyCommandTest_T2B, OutOfBoundsOnBuffer) {
|
|||||||
{
|
{
|
||||||
uint32_t destinationBufferSize = BufferSizeForTextureCopy(7, 3, 1);
|
uint32_t destinationBufferSize = BufferSizeForTextureCopy(7, 3, 1);
|
||||||
ASSERT_TRUE(256 * 3 > destinationBufferSize) << "row pitch * height should overflow buffer";
|
ASSERT_TRUE(256 * 3 > destinationBufferSize) << "row pitch * height should overflow buffer";
|
||||||
dawn::Buffer destinationBuffer = CreateBuffer(destinationBufferSize, dawn::BufferUsageBit::TransferDst);
|
dawn::Buffer destinationBuffer =
|
||||||
|
CreateBuffer(destinationBufferSize, dawn::BufferUsageBit::TransferDst);
|
||||||
TestT2BCopy(utils::Expectation::Success, source, 0, 0, {0, 0, 0}, destinationBuffer, 0, 256,
|
TestT2BCopy(utils::Expectation::Success, source, 0, 0, {0, 0, 0}, destinationBuffer, 0, 256,
|
||||||
0, {7, 3, 1});
|
0, {7, 3, 1});
|
||||||
}
|
}
|
||||||
@ -886,6 +915,31 @@ TEST_F(CopyCommandTest_T2B, TextureCopyBufferSizeLastRowComputation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test copy from mip map of non square texture to buffer
|
||||||
|
TEST_F(CopyCommandTest_T2B, CopyFromMipmapOfNonSquareTexture) {
|
||||||
|
uint32_t maxMipmapLevel = 3;
|
||||||
|
dawn::Texture source = Create2DTexture(4, 2, maxMipmapLevel, 1, dawn::TextureFormat::RGBA8Unorm,
|
||||||
|
dawn::TextureUsageBit::TransferSrc);
|
||||||
|
uint64_t bufferSize = BufferSizeForTextureCopy(4, 2, 1);
|
||||||
|
dawn::Buffer destination = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
|
||||||
|
|
||||||
|
// Copy from top level mip map
|
||||||
|
TestT2BCopy(utils::Expectation::Success, source, maxMipmapLevel - 1, 0, {0, 0, 0}, destination,
|
||||||
|
0, 256, 0, {1, 1, 1});
|
||||||
|
// Copy from high level mip map
|
||||||
|
TestT2BCopy(utils::Expectation::Success, source, maxMipmapLevel - 2, 0, {0, 0, 0}, destination,
|
||||||
|
0, 256, 0, {2, 1, 1});
|
||||||
|
// Mip level out of range
|
||||||
|
TestT2BCopy(utils::Expectation::Failure, source, maxMipmapLevel, 0, {0, 0, 0}, destination, 0,
|
||||||
|
256, 0, {2, 1, 1});
|
||||||
|
// Copy origin out of range
|
||||||
|
TestT2BCopy(utils::Expectation::Failure, source, maxMipmapLevel - 2, 0, {2, 0, 0}, destination,
|
||||||
|
0, 256, 0, {2, 1, 1});
|
||||||
|
// Copy size out of range
|
||||||
|
TestT2BCopy(utils::Expectation::Failure, source, maxMipmapLevel - 2, 0, {1, 0, 0}, destination,
|
||||||
|
0, 256, 0, {2, 1, 1});
|
||||||
|
}
|
||||||
|
|
||||||
class CopyCommandTest_T2T : public CopyCommandTest {};
|
class CopyCommandTest_T2T : public CopyCommandTest {};
|
||||||
|
|
||||||
TEST_F(CopyCommandTest_T2T, Success) {
|
TEST_F(CopyCommandTest_T2T, Success) {
|
||||||
@ -1080,6 +1134,31 @@ TEST_F(CopyCommandTest_T2T, MultisampledCopies) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test copy to mip map of non square textures
|
||||||
|
TEST_F(CopyCommandTest_T2T, CopyToMipmapOfNonSquareTexture) {
|
||||||
|
uint32_t maxMipmapLevel = 3;
|
||||||
|
dawn::Texture source = Create2DTexture(4, 2, maxMipmapLevel, 1, dawn::TextureFormat::RGBA8Unorm,
|
||||||
|
dawn::TextureUsageBit::TransferSrc);
|
||||||
|
dawn::Texture destination =
|
||||||
|
Create2DTexture(4, 2, maxMipmapLevel, 1, dawn::TextureFormat::RGBA8Unorm,
|
||||||
|
dawn::TextureUsageBit::TransferDst);
|
||||||
|
// Copy to top level mip map
|
||||||
|
TestT2TCopy(utils::Expectation::Success, source, maxMipmapLevel - 1, 0, {0, 0, 0}, destination,
|
||||||
|
maxMipmapLevel - 1, 0, {0, 0, 0}, {1, 1, 1});
|
||||||
|
// Copy to high level mip map
|
||||||
|
TestT2TCopy(utils::Expectation::Success, source, maxMipmapLevel - 2, 0, {0, 0, 0}, destination,
|
||||||
|
maxMipmapLevel - 2, 0, {0, 0, 0}, {2, 1, 1});
|
||||||
|
// Mip level out of range
|
||||||
|
TestT2TCopy(utils::Expectation::Failure, source, maxMipmapLevel, 0, {0, 0, 0}, destination,
|
||||||
|
maxMipmapLevel, 0, {0, 0, 0}, {2, 1, 1});
|
||||||
|
// Copy origin out of range
|
||||||
|
TestT2TCopy(utils::Expectation::Failure, source, maxMipmapLevel - 2, 0, {2, 0, 0}, destination,
|
||||||
|
maxMipmapLevel - 2, 0, {2, 0, 0}, {2, 1, 1});
|
||||||
|
// Copy size out of range
|
||||||
|
TestT2TCopy(utils::Expectation::Failure, source, maxMipmapLevel - 2, 0, {1, 0, 0}, destination,
|
||||||
|
maxMipmapLevel - 2, 0, {0, 0, 0}, {2, 1, 1});
|
||||||
|
}
|
||||||
|
|
||||||
class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest {
|
class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest {
|
||||||
protected:
|
protected:
|
||||||
dawn::Texture Create2DTexture(dawn::TextureFormat format,
|
dawn::Texture Create2DTexture(dawn::TextureFormat format,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user