mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-10 15:15:58 +00:00
Expand coverage of NonzeroTextureCreationTests
Expand coverage for these tests by using combinatorial test parameterization. Covers more cases and expands coverage to compressed textures. This caught a bug on Vulkan where only the first region for multi-layer compressed texture copies was cleared. It also caught a driver bug on some Intel platforms, where clearing the non-zero mip of a depth texture does not work. Bug: dawn:780 Change-Id: Ic601bae111c1c2dd150f569d7e02759ca765201e Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/51680 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
88097989d0
commit
ff70f98545
@ -1072,7 +1072,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
device->fn.CmdCopyBufferToImage(
|
device->fn.CmdCopyBufferToImage(
|
||||||
recordingContext->commandBuffer,
|
recordingContext->commandBuffer,
|
||||||
ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle(), GetHandle(),
|
ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle(), GetHandle(),
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, regions.data());
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions.size(), regions.data());
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
|
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
|
||||||
++level) {
|
++level) {
|
||||||
|
@ -39,6 +39,13 @@
|
|||||||
#define EXPECT_BUFFER(buffer, offset, size, expectation) \
|
#define EXPECT_BUFFER(buffer, offset, size, expectation) \
|
||||||
AddBufferExpectation(__FILE__, __LINE__, buffer, offset, size, expectation)
|
AddBufferExpectation(__FILE__, __LINE__, buffer, offset, size, expectation)
|
||||||
|
|
||||||
|
#define EXPECT_BUFFER_U8_EQ(expected, buffer, offset) \
|
||||||
|
EXPECT_BUFFER(buffer, offset, sizeof(uint8_t), new ::detail::ExpectEq<uint8_t>(expected))
|
||||||
|
|
||||||
|
#define EXPECT_BUFFER_U8_RANGE_EQ(expected, buffer, offset, count) \
|
||||||
|
EXPECT_BUFFER(buffer, offset, sizeof(uint8_t) * (count), \
|
||||||
|
new ::detail::ExpectEq<uint8_t>(expected, count))
|
||||||
|
|
||||||
#define EXPECT_BUFFER_U16_EQ(expected, buffer, offset) \
|
#define EXPECT_BUFFER_U16_EQ(expected, buffer, offset) \
|
||||||
EXPECT_BUFFER(buffer, offset, sizeof(uint16_t), new ::detail::ExpectEq<uint16_t>(expected))
|
EXPECT_BUFFER(buffer, offset, sizeof(uint16_t), new ::detail::ExpectEq<uint16_t>(expected))
|
||||||
|
|
||||||
@ -174,6 +181,7 @@ namespace utils {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
class Expectation;
|
class Expectation;
|
||||||
|
class CustomTextureExpectation;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ExpectEq;
|
class ExpectEq;
|
||||||
@ -361,6 +369,22 @@ class DawnTestBase {
|
|||||||
origin, {1, 1}, level, aspect, sizeof(T), bytesPerRow);
|
origin, {1, 1}, level, aspect, sizeof(T), bytesPerRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename E,
|
||||||
|
typename = typename std::enable_if<
|
||||||
|
std::is_base_of<detail::CustomTextureExpectation, E>::value>::type>
|
||||||
|
std::ostringstream& AddTextureExpectation(const char* file,
|
||||||
|
int line,
|
||||||
|
E* expectation,
|
||||||
|
const wgpu::Texture& texture,
|
||||||
|
wgpu::Origin3D origin,
|
||||||
|
wgpu::Extent3D extent,
|
||||||
|
uint32_t level = 0,
|
||||||
|
wgpu::TextureAspect aspect = wgpu::TextureAspect::All,
|
||||||
|
uint32_t bytesPerRow = 0) {
|
||||||
|
return AddTextureExpectationImpl(file, line, expectation, texture, origin, extent, level,
|
||||||
|
aspect, expectation->DataSize(), bytesPerRow);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::ostringstream& AddTextureBetweenColorsExpectation(
|
std::ostringstream& AddTextureBetweenColorsExpectation(
|
||||||
const char* file,
|
const char* file,
|
||||||
@ -634,6 +658,13 @@ namespace detail {
|
|||||||
// each counterparts. It doesn't matter which value is higher or lower. Essentially color =
|
// each counterparts. It doesn't matter which value is higher or lower. Essentially color =
|
||||||
// lerp(color0, color1, t) where t is [0,1]. But I don't want to be too strict here.
|
// lerp(color0, color1, t) where t is [0,1]. But I don't want to be too strict here.
|
||||||
extern template class ExpectBetweenColors<RGBA8>;
|
extern template class ExpectBetweenColors<RGBA8>;
|
||||||
|
|
||||||
|
class CustomTextureExpectation : public Expectation {
|
||||||
|
public:
|
||||||
|
virtual ~CustomTextureExpectation() = default;
|
||||||
|
virtual uint32_t DataSize() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
#endif // TESTS_DAWNTEST_H_
|
#endif // TESTS_DAWNTEST_H_
|
||||||
|
@ -15,257 +15,276 @@
|
|||||||
#include "tests/DawnTest.h"
|
#include "tests/DawnTest.h"
|
||||||
|
|
||||||
#include "common/Constants.h"
|
#include "common/Constants.h"
|
||||||
|
#include "common/Math.h"
|
||||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||||
|
#include "utils/TestUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
class NonzeroTextureCreationTests : public DawnTest {
|
namespace {
|
||||||
protected:
|
|
||||||
constexpr static uint32_t kSize = 128;
|
|
||||||
constexpr static uint32_t kDepthOrArrayLayers = 7;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test that texture clears 0xFF because toggle is enabled.
|
using Format = wgpu::TextureFormat;
|
||||||
|
using Usage = wgpu::TextureUsage;
|
||||||
|
using Dimension = wgpu::TextureDimension;
|
||||||
|
using DepthOrArrayLayers = uint32_t;
|
||||||
|
using Mip = uint32_t;
|
||||||
|
|
||||||
|
DAWN_TEST_PARAM_STRUCT(Params, Format, Usage, Dimension, DepthOrArrayLayers, Mip)
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ExpectNonZero : public detail::CustomTextureExpectation {
|
||||||
|
public:
|
||||||
|
uint32_t DataSize() override {
|
||||||
|
return sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
testing::AssertionResult Check(const void* data, size_t size) override {
|
||||||
|
ASSERT(size % DataSize() == 0 && size > 0);
|
||||||
|
const T* actual = static_cast<const T*>(data);
|
||||||
|
T value = *actual;
|
||||||
|
if (value == T(0)) {
|
||||||
|
return testing::AssertionFailure()
|
||||||
|
<< "Expected data to be non-zero, was " << value << std::endl;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < size / DataSize(); ++i) {
|
||||||
|
if (actual[i] != value) {
|
||||||
|
return testing::AssertionFailure()
|
||||||
|
<< "Expected data[" << i << "] to be " << value << ", actual "
|
||||||
|
<< actual[i] << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return testing::AssertionSuccess();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EXPECT_TEXTURE_NONZERO(T, ...) \
|
||||||
|
AddTextureExpectation(__FILE__, __LINE__, new ExpectNonZero<T>(), __VA_ARGS__)
|
||||||
|
|
||||||
|
class NonzeroTextureCreationTests : public DawnTestWithParams<Params> {
|
||||||
|
protected:
|
||||||
|
constexpr static uint32_t kSize = 128;
|
||||||
|
constexpr static uint32_t kMipLevelCount = 4;
|
||||||
|
|
||||||
|
std::vector<const char*> GetRequiredExtensions() override {
|
||||||
|
if (GetParam().mFormat == wgpu::TextureFormat::BC1RGBAUnorm &&
|
||||||
|
SupportsExtensions({"texture_compression_bc"})) {
|
||||||
|
return {"texture_compression_bc"};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Run() {
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(GetParam().mFormat == wgpu::TextureFormat::BC1RGBAUnorm &&
|
||||||
|
!SupportsExtensions({"texture_compression_bc"}));
|
||||||
|
|
||||||
|
// TODO(crbug.com/dawn/667): Work around the fact that some platforms do not support
|
||||||
|
// reading from Snorm textures.
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(GetParam().mFormat == wgpu::TextureFormat::RGBA8Snorm &&
|
||||||
|
HasToggleEnabled("disable_snorm_read"));
|
||||||
|
|
||||||
|
// TODO(crbug.com/dawn/547): 3D texture copies not fully implemented on D3D12.
|
||||||
|
// TODO(crbug.com/angleproject/5967): This texture readback hits an assert in ANGLE.
|
||||||
|
DAWN_SUPPRESS_TEST_IF(GetParam().mDimension == wgpu::TextureDimension::e3D &&
|
||||||
|
(IsANGLE() || IsD3D12()));
|
||||||
|
|
||||||
|
// TODO(crbug.com/dawn/791): Determine Intel specific platforms this occurs on, and
|
||||||
|
// implement a workaround on all backends (happens on Windows too, but not on our test
|
||||||
|
// machines).
|
||||||
|
DAWN_SUPPRESS_TEST_IF(GetParam().mFormat == wgpu::TextureFormat::Depth32Float &&
|
||||||
|
IsMetal() && IsIntel() && GetParam().mMip != 0);
|
||||||
|
|
||||||
|
// Copies from depth textures not fully supported on the OpenGL backend right now.
|
||||||
|
DAWN_SUPPRESS_TEST_IF(GetParam().mFormat == wgpu::TextureFormat::Depth32Float &&
|
||||||
|
(IsOpenGL() || IsOpenGLES()));
|
||||||
|
|
||||||
|
// GL may support the extension, but reading data back is not implemented.
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(GetParam().mFormat == wgpu::TextureFormat::BC1RGBAUnorm &&
|
||||||
|
(IsOpenGL() || IsOpenGLES()));
|
||||||
|
|
||||||
|
wgpu::TextureDescriptor descriptor;
|
||||||
|
descriptor.dimension = GetParam().mDimension;
|
||||||
|
descriptor.size.width = kSize;
|
||||||
|
descriptor.size.height = kSize;
|
||||||
|
descriptor.size.depthOrArrayLayers = GetParam().mDepthOrArrayLayers;
|
||||||
|
descriptor.sampleCount = 1;
|
||||||
|
descriptor.format = GetParam().mFormat;
|
||||||
|
descriptor.usage = GetParam().mUsage;
|
||||||
|
descriptor.mipLevelCount = kMipLevelCount;
|
||||||
|
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||||
|
|
||||||
|
uint32_t mip = GetParam().mMip;
|
||||||
|
uint32_t mipSize = std::max(kSize >> mip, 1u);
|
||||||
|
uint32_t depthOrArrayLayers = GetParam().mDimension == wgpu::TextureDimension::e3D
|
||||||
|
? std::max(GetParam().mDepthOrArrayLayers >> mip, 1u)
|
||||||
|
: GetParam().mDepthOrArrayLayers;
|
||||||
|
|
||||||
|
switch (GetParam().mFormat) {
|
||||||
|
case wgpu::TextureFormat::R8Unorm: {
|
||||||
|
EXPECT_TEXTURE_EQ(new ExpectNonZero<uint8_t>(), texture, {0, 0, 0},
|
||||||
|
{mipSize, mipSize, depthOrArrayLayers}, mip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case wgpu::TextureFormat::RG8Unorm: {
|
||||||
|
EXPECT_TEXTURE_EQ(new ExpectNonZero<uint16_t>(), texture, {0, 0, 0},
|
||||||
|
{mipSize, mipSize, depthOrArrayLayers}, mip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case wgpu::TextureFormat::RGBA8Unorm:
|
||||||
|
case wgpu::TextureFormat::RGBA8Snorm: {
|
||||||
|
EXPECT_TEXTURE_EQ(new ExpectNonZero<uint32_t>(), texture, {0, 0, 0},
|
||||||
|
{mipSize, mipSize, depthOrArrayLayers}, mip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case wgpu::TextureFormat::Depth32Float: {
|
||||||
|
EXPECT_TEXTURE_EQ(new ExpectNonZero<float>(), texture, {0, 0, 0},
|
||||||
|
{mipSize, mipSize, depthOrArrayLayers}, mip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case wgpu::TextureFormat::BC1RGBAUnorm: {
|
||||||
|
// Set buffer with dirty data so we know it is cleared by the lazy cleared
|
||||||
|
// texture copy
|
||||||
|
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(GetParam().mFormat);
|
||||||
|
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(GetParam().mFormat);
|
||||||
|
wgpu::Extent3D copySize = {Align(mipSize, blockWidth),
|
||||||
|
Align(mipSize, blockHeight), depthOrArrayLayers};
|
||||||
|
|
||||||
|
uint32_t bytesPerRow =
|
||||||
|
utils::GetMinimumBytesPerRow(GetParam().mFormat, copySize.width);
|
||||||
|
uint32_t rowsPerImage = copySize.height / blockHeight;
|
||||||
|
|
||||||
|
uint64_t bufferSize = utils::RequiredBytesInCopy(bytesPerRow, rowsPerImage,
|
||||||
|
copySize, GetParam().mFormat);
|
||||||
|
|
||||||
|
std::vector<uint8_t> data(bufferSize, 100);
|
||||||
|
wgpu::Buffer bufferDst = utils::CreateBufferFromData(
|
||||||
|
device, data.data(), bufferSize, wgpu::BufferUsage::CopySrc);
|
||||||
|
|
||||||
|
wgpu::ImageCopyBuffer imageCopyBuffer =
|
||||||
|
utils::CreateImageCopyBuffer(bufferDst, 0, bytesPerRow, rowsPerImage);
|
||||||
|
wgpu::ImageCopyTexture imageCopyTexture =
|
||||||
|
utils::CreateImageCopyTexture(texture, mip, {0, 0, 0});
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
encoder.CopyTextureToBuffer(&imageCopyTexture, &imageCopyBuffer, ©Size);
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
|
uint32_t copiedWidthInBytes =
|
||||||
|
utils::GetTexelBlockSizeInBytes(GetParam().mFormat) * copySize.width /
|
||||||
|
blockWidth;
|
||||||
|
uint8_t* d = data.data();
|
||||||
|
for (uint32_t z = 0; z < depthOrArrayLayers; ++z) {
|
||||||
|
for (uint32_t row = 0; row < copySize.height / blockHeight; ++row) {
|
||||||
|
std::fill_n(d, copiedWidthInBytes, 1);
|
||||||
|
d += bytesPerRow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_BUFFER_U8_RANGE_EQ(data.data(), bufferDst, 0, bufferSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class NonzeroNonrenderableTextureCreationTests : public NonzeroTextureCreationTests {};
|
||||||
|
class NonzeroCompressedTextureCreationTests : public NonzeroTextureCreationTests {};
|
||||||
|
class NonzeroDepthTextureCreationTests : public NonzeroTextureCreationTests {};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
// Test that texture clears to a non-zero value because toggle is enabled.
|
||||||
TEST_P(NonzeroTextureCreationTests, TextureCreationClears) {
|
TEST_P(NonzeroTextureCreationTests, TextureCreationClears) {
|
||||||
wgpu::TextureDescriptor descriptor;
|
Run();
|
||||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
|
||||||
descriptor.size.width = kSize;
|
|
||||||
descriptor.size.height = kSize;
|
|
||||||
descriptor.size.depthOrArrayLayers = 1;
|
|
||||||
descriptor.sampleCount = 1;
|
|
||||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
|
||||||
descriptor.mipLevelCount = 1;
|
|
||||||
descriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
|
||||||
|
|
||||||
// 2D
|
|
||||||
{
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
|
|
||||||
std::vector<RGBA8> expected(kSize * kSize, RGBA8(255, 255, 255, 255));
|
|
||||||
EXPECT_TEXTURE_EQ(expected.data(), texture, {0, 0}, {kSize, kSize});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2D Array
|
|
||||||
{
|
|
||||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
|
||||||
descriptor.size.depthOrArrayLayers = kDepthOrArrayLayers;
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
|
|
||||||
std::vector<RGBA8> expected(kSize * kSize * kDepthOrArrayLayers, RGBA8(255, 255, 255, 255));
|
|
||||||
EXPECT_TEXTURE_EQ(expected.data(), texture, {0, 0, 0}, {kSize, kSize, kDepthOrArrayLayers});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that 3D texture clears to nonzero because toggle is enabled.
|
// Test that texture clears to a non-zero value because toggle is enabled.
|
||||||
TEST_P(NonzeroTextureCreationTests, Texture3DCreationClears) {
|
TEST_P(NonzeroNonrenderableTextureCreationTests, TextureCreationClears) {
|
||||||
// TODO(crbug.com/dawn/547): 3D texture copies not fully implemented on D3D12.
|
Run();
|
||||||
// TODO(crbug.com/angleproject/5967): This texture readback hits an assert in ANGLE.
|
|
||||||
DAWN_TEST_UNSUPPORTED_IF(IsD3D12());
|
|
||||||
DAWN_SUPPRESS_TEST_IF(IsANGLE());
|
|
||||||
|
|
||||||
wgpu::TextureDescriptor descriptor;
|
|
||||||
descriptor.dimension = wgpu::TextureDimension::e3D;
|
|
||||||
descriptor.size.width = kSize;
|
|
||||||
descriptor.size.height = kSize;
|
|
||||||
descriptor.size.depthOrArrayLayers = kDepthOrArrayLayers;
|
|
||||||
descriptor.sampleCount = 1;
|
|
||||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
|
||||||
descriptor.mipLevelCount = 1;
|
|
||||||
descriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
|
|
||||||
std::vector<RGBA8> expected(kSize * kSize * kDepthOrArrayLayers, RGBA8(255, 255, 255, 255));
|
|
||||||
EXPECT_TEXTURE_EQ(expected.data(), texture, {0, 0, 0}, {kSize, kSize, kDepthOrArrayLayers});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a depth texture clears 0xFF because toggle is enabled.
|
// Test that texture clears to a non-zero value because toggle is enabled.
|
||||||
TEST_P(NonzeroTextureCreationTests, Depth32TextureCreationDepthClears) {
|
TEST_P(NonzeroCompressedTextureCreationTests, TextureCreationClears) {
|
||||||
// Copies from depth textures not fully supported on the OpenGL backend right now.
|
Run();
|
||||||
DAWN_TEST_UNSUPPORTED_IF(IsOpenGL() || IsOpenGLES());
|
|
||||||
|
|
||||||
wgpu::TextureDescriptor descriptor;
|
|
||||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
|
||||||
descriptor.size.width = kSize;
|
|
||||||
descriptor.size.height = kSize;
|
|
||||||
descriptor.size.depthOrArrayLayers = 1;
|
|
||||||
descriptor.sampleCount = 1;
|
|
||||||
descriptor.mipLevelCount = 1;
|
|
||||||
descriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
|
||||||
descriptor.format = wgpu::TextureFormat::Depth32Float;
|
|
||||||
|
|
||||||
// We can only really test Depth32Float here because Depth24Plus(Stencil8)? may be in an unknown
|
|
||||||
// format.
|
|
||||||
// TODO(crbug.com/dawn/145): Test other formats via sampling.
|
|
||||||
|
|
||||||
// 2D
|
|
||||||
{
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
std::vector<float> expected(kSize * kSize, 1.f);
|
|
||||||
EXPECT_TEXTURE_EQ(expected.data(), texture, {0, 0}, {kSize, kSize});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2D Array
|
|
||||||
{
|
|
||||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
|
||||||
descriptor.size.depthOrArrayLayers = kDepthOrArrayLayers;
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
std::vector<float> expected(kSize * kSize * kDepthOrArrayLayers, 1.f);
|
|
||||||
EXPECT_TEXTURE_EQ(expected.data(), texture, {0, 0, 0}, {kSize, kSize, kDepthOrArrayLayers});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that non-zero mip level clears 0xFF because toggle is enabled.
|
// Test that texture clears to a non-zero value because toggle is enabled.
|
||||||
TEST_P(NonzeroTextureCreationTests, MipMapClears) {
|
TEST_P(NonzeroDepthTextureCreationTests, TextureCreationClears) {
|
||||||
constexpr uint32_t mipLevels = 4;
|
Run();
|
||||||
|
|
||||||
wgpu::TextureDescriptor descriptor;
|
|
||||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
|
||||||
descriptor.size.width = kSize;
|
|
||||||
descriptor.size.height = kSize;
|
|
||||||
descriptor.size.depthOrArrayLayers = 1;
|
|
||||||
descriptor.sampleCount = 1;
|
|
||||||
descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
|
|
||||||
descriptor.mipLevelCount = mipLevels;
|
|
||||||
descriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
|
||||||
|
|
||||||
// 2D
|
|
||||||
{
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
uint32_t mipSize = kSize >> 2;
|
|
||||||
std::vector<RGBA8> expected(mipSize * mipSize, RGBA8(255, 255, 255, 255));
|
|
||||||
EXPECT_TEXTURE_EQ(expected.data(), texture, {0, 0}, {mipSize, mipSize}, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2D Array
|
|
||||||
{
|
|
||||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
|
||||||
descriptor.size.depthOrArrayLayers = kDepthOrArrayLayers;
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
uint32_t mipSize = kSize >> 2;
|
|
||||||
std::vector<RGBA8> expected(mipSize * mipSize * kDepthOrArrayLayers,
|
|
||||||
RGBA8(255, 255, 255, 255));
|
|
||||||
EXPECT_TEXTURE_EQ(expected.data(), texture, {0, 0, 0},
|
|
||||||
{mipSize, mipSize, kDepthOrArrayLayers}, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3D
|
|
||||||
{
|
|
||||||
descriptor.dimension = wgpu::TextureDimension::e3D;
|
|
||||||
descriptor.size.depthOrArrayLayers = kDepthOrArrayLayers;
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
uint32_t mipSize = kSize >> 2;
|
|
||||||
uint32_t mipDepth = kDepthOrArrayLayers >> 2;
|
|
||||||
std::vector<RGBA8> expected(mipSize * mipSize * mipDepth, RGBA8(255, 255, 255, 255));
|
|
||||||
EXPECT_TEXTURE_EQ(expected.data(), texture, {0, 0, 0}, {mipSize, mipSize, mipDepth}, 2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that nonrenderable texture formats clear 0x01 because toggle is enabled
|
// TODO(crbug.com/794): Test/implement texture initialization for multisampled textures.
|
||||||
TEST_P(NonzeroTextureCreationTests, NonrenderableTextureFormat) {
|
|
||||||
// TODO(crbug.com/dawn/667): Work around the fact that some platforms do not support reading
|
|
||||||
// from Snorm textures.
|
|
||||||
DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_snorm_read"));
|
|
||||||
|
|
||||||
wgpu::TextureDescriptor descriptor;
|
DAWN_INSTANTIATE_TEST_P(
|
||||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
NonzeroTextureCreationTests,
|
||||||
descriptor.size.width = kSize;
|
{D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
descriptor.size.height = kSize;
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
descriptor.size.depthOrArrayLayers = 1;
|
MetalBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
descriptor.sampleCount = 1;
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
descriptor.format = wgpu::TextureFormat::RGBA8Snorm;
|
OpenGLBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
descriptor.mipLevelCount = 1;
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
descriptor.usage = wgpu::TextureUsage::CopySrc;
|
OpenGLESBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
VulkanBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"})},
|
||||||
|
{wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::RGBA8Unorm},
|
||||||
|
{wgpu::TextureUsage(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc),
|
||||||
|
wgpu::TextureUsage::CopySrc},
|
||||||
|
{wgpu::TextureDimension::e2D, wgpu::TextureDimension::e3D},
|
||||||
|
{1u, 7u},
|
||||||
|
{0u, 1u, 2u, 3u});
|
||||||
|
|
||||||
// 2D
|
DAWN_INSTANTIATE_TEST_P(NonzeroNonrenderableTextureCreationTests,
|
||||||
{
|
{D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
|
|
||||||
// Set buffer with dirty data so we know it is cleared by the lazy cleared texture copy
|
|
||||||
uint32_t bufferSize = kSize * kSize;
|
|
||||||
std::vector<uint8_t> data(sizeof(uint32_t) * bufferSize, 100);
|
|
||||||
wgpu::Buffer bufferDst = utils::CreateBufferFromData(
|
|
||||||
device, data.data(), static_cast<uint32_t>(data.size()), wgpu::BufferUsage::CopySrc);
|
|
||||||
|
|
||||||
wgpu::ImageCopyBuffer imageCopyBuffer =
|
|
||||||
utils::CreateImageCopyBuffer(bufferDst, 0, kSize * 4);
|
|
||||||
wgpu::ImageCopyTexture imageCopyTexture =
|
|
||||||
utils::CreateImageCopyTexture(texture, 0, {0, 0, 0});
|
|
||||||
wgpu::Extent3D copySize = {kSize, kSize, 1};
|
|
||||||
|
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
||||||
encoder.CopyTextureToBuffer(&imageCopyTexture, &imageCopyBuffer, ©Size);
|
|
||||||
wgpu::CommandBuffer commands = encoder.Finish();
|
|
||||||
queue.Submit(1, &commands);
|
|
||||||
|
|
||||||
uint32_t expectedBytes = IsVulkan() ? 0x7F7F7F7F : 0x01010101;
|
|
||||||
std::vector<uint32_t> expected(bufferSize, expectedBytes);
|
|
||||||
EXPECT_BUFFER_U32_RANGE_EQ(expected.data(), bufferDst, 0, expected.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2D Array
|
|
||||||
{
|
|
||||||
descriptor.dimension = wgpu::TextureDimension::e2D;
|
|
||||||
descriptor.size.depthOrArrayLayers = kDepthOrArrayLayers;
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
|
|
||||||
// Set buffer with dirty data so we know it is cleared by the lazy cleared texture copy
|
|
||||||
uint32_t bufferSize = kSize * kSize * kDepthOrArrayLayers;
|
|
||||||
std::vector<uint8_t> data(sizeof(uint32_t) * bufferSize, 100);
|
|
||||||
wgpu::Buffer bufferDst = utils::CreateBufferFromData(
|
|
||||||
device, data.data(), static_cast<uint32_t>(data.size()), wgpu::BufferUsage::CopySrc);
|
|
||||||
|
|
||||||
wgpu::ImageCopyBuffer imageCopyBuffer =
|
|
||||||
utils::CreateImageCopyBuffer(bufferDst, 0, kSize * 4, kSize);
|
|
||||||
wgpu::ImageCopyTexture imageCopyTexture =
|
|
||||||
utils::CreateImageCopyTexture(texture, 0, {0, 0, 0});
|
|
||||||
wgpu::Extent3D copySize = {kSize, kSize, kDepthOrArrayLayers};
|
|
||||||
|
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
||||||
encoder.CopyTextureToBuffer(&imageCopyTexture, &imageCopyBuffer, ©Size);
|
|
||||||
wgpu::CommandBuffer commands = encoder.Finish();
|
|
||||||
queue.Submit(1, &commands);
|
|
||||||
|
|
||||||
uint32_t expectedBytes = IsVulkan() ? 0x7F7F7F7F : 0x01010101;
|
|
||||||
std::vector<uint32_t> expected(bufferSize, expectedBytes);
|
|
||||||
EXPECT_BUFFER_U32_RANGE_EQ(expected.data(), bufferDst, 0, expected.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3D
|
|
||||||
{
|
|
||||||
descriptor.dimension = wgpu::TextureDimension::e3D;
|
|
||||||
descriptor.size.depthOrArrayLayers = kDepthOrArrayLayers;
|
|
||||||
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
|
||||||
|
|
||||||
// Set buffer with dirty data so we know it is cleared by the lazy cleared texture copy
|
|
||||||
uint32_t bufferSize = kSize * kSize * kDepthOrArrayLayers;
|
|
||||||
std::vector<uint8_t> data(sizeof(uint32_t) * bufferSize, 100);
|
|
||||||
wgpu::Buffer bufferDst = utils::CreateBufferFromData(
|
|
||||||
device, data.data(), static_cast<uint32_t>(data.size()), wgpu::BufferUsage::CopySrc);
|
|
||||||
|
|
||||||
wgpu::ImageCopyBuffer imageCopyBuffer =
|
|
||||||
utils::CreateImageCopyBuffer(bufferDst, 0, kSize * 4, kSize);
|
|
||||||
wgpu::ImageCopyTexture imageCopyTexture =
|
|
||||||
utils::CreateImageCopyTexture(texture, 0, {0, 0, 0});
|
|
||||||
wgpu::Extent3D copySize = {kSize, kSize, kDepthOrArrayLayers};
|
|
||||||
|
|
||||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
||||||
encoder.CopyTextureToBuffer(&imageCopyTexture, &imageCopyBuffer, ©Size);
|
|
||||||
wgpu::CommandBuffer commands = encoder.Finish();
|
|
||||||
queue.Submit(1, &commands);
|
|
||||||
|
|
||||||
uint32_t expectedBytes = IsVulkan() ? 0x7F7F7F7F : 0x01010101;
|
|
||||||
std::vector<uint32_t> expected(bufferSize, expectedBytes);
|
|
||||||
EXPECT_BUFFER_U32_RANGE_EQ(expected.data(), bufferDst, 0, expected.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(NonzeroTextureCreationTests,
|
|
||||||
D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"},
|
|
||||||
{"lazy_clear_resource_on_first_use"}),
|
|
||||||
MetalBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
|
||||||
{"lazy_clear_resource_on_first_use"}),
|
|
||||||
OpenGLBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
|
||||||
{"lazy_clear_resource_on_first_use"}),
|
|
||||||
OpenGLESBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
|
||||||
{"lazy_clear_resource_on_first_use"}),
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
VulkanBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
MetalBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
{"lazy_clear_resource_on_first_use"}));
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
OpenGLBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
OpenGLESBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
VulkanBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"})},
|
||||||
|
{wgpu::TextureFormat::RGBA8Snorm},
|
||||||
|
{wgpu::TextureUsage::CopySrc},
|
||||||
|
{wgpu::TextureDimension::e2D, wgpu::TextureDimension::e3D},
|
||||||
|
{1u, 7u},
|
||||||
|
{0u, 1u, 2u, 3u});
|
||||||
|
|
||||||
|
DAWN_INSTANTIATE_TEST_P(NonzeroCompressedTextureCreationTests,
|
||||||
|
{D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
MetalBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
OpenGLBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
OpenGLESBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
VulkanBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"})},
|
||||||
|
{wgpu::TextureFormat::BC1RGBAUnorm},
|
||||||
|
{wgpu::TextureUsage::CopySrc},
|
||||||
|
{wgpu::TextureDimension::e2D},
|
||||||
|
{1u, 7u},
|
||||||
|
{0u, 1u, 2u, 3u});
|
||||||
|
|
||||||
|
DAWN_INSTANTIATE_TEST_P(NonzeroDepthTextureCreationTests,
|
||||||
|
{D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
MetalBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
OpenGLBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
OpenGLESBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"}),
|
||||||
|
VulkanBackend({"nonzero_clear_resources_on_creation_for_testing"},
|
||||||
|
{"lazy_clear_resource_on_first_use"})},
|
||||||
|
{wgpu::TextureFormat::Depth32Float},
|
||||||
|
{wgpu::TextureUsage(wgpu::TextureUsage::RenderAttachment |
|
||||||
|
wgpu::TextureUsage::CopySrc),
|
||||||
|
wgpu::TextureUsage::CopySrc},
|
||||||
|
{wgpu::TextureDimension::e2D},
|
||||||
|
{1u, 7u},
|
||||||
|
{0u, 1u, 2u, 3u});
|
||||||
|
@ -26,7 +26,9 @@ namespace utils {
|
|||||||
|
|
||||||
uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width) {
|
uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width) {
|
||||||
const uint32_t bytesPerBlock = utils::GetTexelBlockSizeInBytes(format);
|
const uint32_t bytesPerBlock = utils::GetTexelBlockSizeInBytes(format);
|
||||||
return Align(bytesPerBlock * width, kTextureBytesPerRowAlignment);
|
const uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
|
||||||
|
ASSERT(width % blockWidth == 0);
|
||||||
|
return Align(bytesPerBlock * (width / blockWidth), kTextureBytesPerRowAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel(
|
TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user