Implement initialization of multisampled textures

Metal needs RenderTarget usage to be added to the texture
allocation so the clear can be done using a render pass.

Already working for GL which does not have usage flags on
creation.
Also working on Vulkan which does not need a render pass.
We use vkCmdClearColorImage.
D3D12 also needs a render pass to clear multisampled textures,
but it already requires multisampled
textures to be created with RenderTarget flags.

To test the behavior, NonzeroTextureCreation tests are
expanded, and the ExpectSampledDepthData helper is factored
into a more general ExpectSampledFloatData helper.

Fixes: dawn:794
Change-Id: If0f9f26f3c58b4292c85265aa7ff330e9931ddae
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/55604
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Austin Eng 2021-06-24 02:01:46 +00:00 committed by Dawn LUCI CQ
parent 2a57db73cb
commit 75c5067ed1
8 changed files with 305 additions and 136 deletions

View File

@ -471,6 +471,9 @@ namespace dawn_native { namespace d3d12 {
mDxgiKeyedMutex = std::move(dxgiKeyedMutex);
mSwapChainTexture = isSwapChainTexture;
D3D12_RESOURCE_DESC desc = d3d12Texture->GetDesc();
mD3D12ResourceFlags = desc.Flags;
AllocationInfo info;
info.mMethod = AllocationMethod::kExternal;
// When creating the ResourceHeapAllocation, the resource heap is set to nullptr because the
@ -507,6 +510,7 @@ namespace dawn_native { namespace d3d12 {
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resourceDescriptor.Flags =
D3D12ResourceFlags(GetUsage(), GetFormat(), IsMultisampledTexture());
mD3D12ResourceFlags = resourceDescriptor.Flags;
DAWN_TRY_ASSIGN(mResourceAllocation,
ToBackend(GetDevice())
@ -879,82 +883,80 @@ namespace dawn_native { namespace d3d12 {
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f;
if ((GetUsage() & wgpu::TextureUsage::RenderAttachment) != 0) {
if (GetFormat().HasDepthOrStencil()) {
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_DEPTH_WRITE, range);
if ((mD3D12ResourceFlags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) != 0) {
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_DEPTH_WRITE, range);
for (uint32_t level = range.baseMipLevel;
level < range.baseMipLevel + range.levelCount; ++level) {
for (uint32_t layer = range.baseArrayLayer;
layer < range.baseArrayLayer + range.layerCount; ++layer) {
// Iterate the aspects individually to determine which clear flags to use.
D3D12_CLEAR_FLAGS clearFlags = {};
for (Aspect aspect : IterateEnumMask(range.aspects)) {
if (clearValue == TextureBase::ClearValue::Zero &&
IsSubresourceContentInitialized(
SubresourceRange::SingleMipAndLayer(level, layer, aspect))) {
// Skip lazy clears if already initialized.
continue;
}
switch (aspect) {
case Aspect::Depth:
clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
break;
case Aspect::Stencil:
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
break;
default:
UNREACHABLE();
}
}
if (clearFlags == 0) {
continue;
}
CPUDescriptorHeapAllocation dsvHandle;
DAWN_TRY_ASSIGN(dsvHandle, device->GetDepthStencilViewAllocator()
->AllocateTransientCPUDescriptors());
const D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor =
dsvHandle.GetBaseDescriptor();
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(level, layer, 1);
device->GetD3D12Device()->CreateDepthStencilView(GetD3D12Resource(),
&dsvDesc, baseDescriptor);
commandList->ClearDepthStencilView(baseDescriptor, clearFlags, fClearColor,
clearColor, 0, nullptr);
}
}
} else {
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_RENDER_TARGET,
range);
const float clearColorRGBA[4] = {fClearColor, fClearColor, fClearColor,
fClearColor};
ASSERT(range.aspects == Aspect::Color);
for (uint32_t level = range.baseMipLevel;
level < range.baseMipLevel + range.levelCount; ++level) {
for (uint32_t layer = range.baseArrayLayer;
layer < range.baseArrayLayer + range.layerCount; ++layer) {
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
++level) {
for (uint32_t layer = range.baseArrayLayer;
layer < range.baseArrayLayer + range.layerCount; ++layer) {
// Iterate the aspects individually to determine which clear flags to use.
D3D12_CLEAR_FLAGS clearFlags = {};
for (Aspect aspect : IterateEnumMask(range.aspects)) {
if (clearValue == TextureBase::ClearValue::Zero &&
IsSubresourceContentInitialized(
SubresourceRange::SingleMipAndLayer(level, layer, Aspect::Color))) {
SubresourceRange::SingleMipAndLayer(level, layer, aspect))) {
// Skip lazy clears if already initialized.
continue;
}
CPUDescriptorHeapAllocation rtvHeap;
DAWN_TRY_ASSIGN(rtvHeap, device->GetRenderTargetViewAllocator()
->AllocateTransientCPUDescriptors());
const D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetBaseDescriptor();
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = GetRTVDescriptor(level, layer, 1);
device->GetD3D12Device()->CreateRenderTargetView(GetD3D12Resource(),
&rtvDesc, rtvHandle);
commandList->ClearRenderTargetView(rtvHandle, clearColorRGBA, 0, nullptr);
switch (aspect) {
case Aspect::Depth:
clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
break;
case Aspect::Stencil:
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
break;
default:
UNREACHABLE();
}
}
if (clearFlags == 0) {
continue;
}
CPUDescriptorHeapAllocation dsvHandle;
DAWN_TRY_ASSIGN(
dsvHandle,
device->GetDepthStencilViewAllocator()->AllocateTransientCPUDescriptors());
const D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor =
dsvHandle.GetBaseDescriptor();
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(level, layer, 1);
device->GetD3D12Device()->CreateDepthStencilView(GetD3D12Resource(), &dsvDesc,
baseDescriptor);
commandList->ClearDepthStencilView(baseDescriptor, clearFlags, fClearColor,
clearColor, 0, nullptr);
}
}
} else if ((mD3D12ResourceFlags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) != 0) {
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_RENDER_TARGET, range);
const float clearColorRGBA[4] = {fClearColor, fClearColor, fClearColor, fClearColor};
ASSERT(range.aspects == Aspect::Color);
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
++level) {
for (uint32_t layer = range.baseArrayLayer;
layer < range.baseArrayLayer + range.layerCount; ++layer) {
if (clearValue == TextureBase::ClearValue::Zero &&
IsSubresourceContentInitialized(
SubresourceRange::SingleMipAndLayer(level, layer, Aspect::Color))) {
// Skip lazy clears if already initialized.
continue;
}
CPUDescriptorHeapAllocation rtvHeap;
DAWN_TRY_ASSIGN(
rtvHeap,
device->GetRenderTargetViewAllocator()->AllocateTransientCPUDescriptors());
const D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetBaseDescriptor();
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = GetRTVDescriptor(level, layer, 1);
device->GetD3D12Device()->CreateRenderTargetView(GetD3D12Resource(), &rtvDesc,
rtvHandle);
commandList->ClearRenderTargetView(rtvHandle, clearColorRGBA, 0, nullptr);
}
}
} else {

View File

@ -123,6 +123,7 @@ namespace dawn_native { namespace d3d12 {
ResourceHeapAllocation mResourceAllocation;
bool mSwapChainTexture = false;
D3D12_RESOURCE_FLAGS mD3D12ResourceFlags;
ExternalMutexSerial mAcquireMutexKey = ExternalMutexSerial(0);
ExternalMutexSerial mReleaseMutexKey = ExternalMutexSerial(0);

View File

@ -63,6 +63,7 @@ namespace dawn_native { namespace metal {
TextureBase::ClearValue clearValue);
NSPRef<id<MTLTexture>> mMtlTexture;
MTLTextureUsage mMtlUsage;
};
class TextureView final : public TextureViewBase {

View File

@ -34,7 +34,9 @@ namespace dawn_native { namespace metal {
return usage & kUsageNeedsTextureView;
}
MTLTextureUsage MetalTextureUsage(const Format& format, wgpu::TextureUsage usage) {
MTLTextureUsage MetalTextureUsage(const Format& format,
wgpu::TextureUsage usage,
uint32_t sampleCount) {
MTLTextureUsage result = MTLTextureUsageUnknown; // This is 0
if (usage & (wgpu::TextureUsage::Storage)) {
@ -53,7 +55,8 @@ namespace dawn_native { namespace metal {
}
}
if (usage & (wgpu::TextureUsage::RenderAttachment)) {
// MTLTextureUsageRenderTarget is needed to clear multisample textures.
if (usage & (wgpu::TextureUsage::RenderAttachment) || sampleCount > 1) {
result |= MTLTextureUsageRenderTarget;
}
@ -310,7 +313,7 @@ namespace dawn_native { namespace metal {
// TODO: add MTLTextureUsagePixelFormatView when needed when we support format
// reinterpretation.
mtlDesc.usage = MetalTextureUsage(device->GetValidInternalFormat(descriptor->format),
descriptor->usage);
descriptor->usage, descriptor->sampleCount);
mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format);
mtlDesc.mipmapLevelCount = descriptor->mipLevelCount;
mtlDesc.storageMode = MTLStorageModePrivate;
@ -357,6 +360,7 @@ namespace dawn_native { namespace metal {
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(device, descriptor);
mMtlTexture =
AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()]);
mMtlUsage = [*mtlDesc usage];
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
device->ConsumedError(ClearTexture(device->GetPendingCommandContext(),
@ -370,6 +374,8 @@ namespace dawn_native { namespace metal {
NSPRef<id<MTLTexture>> mtlTexture)
: TextureBase(device, descriptor, TextureState::OwnedInternal),
mMtlTexture(std::move(mtlTexture)) {
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor(device, descriptor);
mMtlUsage = [*mtlDesc usage];
}
Texture::Texture(Device* device,
@ -386,6 +392,7 @@ namespace dawn_native { namespace metal {
mMtlTexture = AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()
iosurface:ioSurface
plane:plane]);
mMtlUsage = [*mtlDesc usage];
SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
}
@ -410,7 +417,7 @@ namespace dawn_native { namespace metal {
const uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
const double dClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.0 : 1.0;
if ((GetUsage() & wgpu::TextureUsage::RenderAttachment) != 0) {
if ((mMtlUsage & MTLTextureUsageRenderTarget) != 0) {
ASSERT(GetFormat().isRenderable);
// End the blit encoder if it is open.

View File

@ -1088,27 +1088,57 @@ std::ostringstream& DawnTestBase::AddTextureExpectationImpl(const char* file,
return *(mDeferredExpectations.back().message.get());
}
std::ostringstream& DawnTestBase::ExpectSampledDepthData(wgpu::Texture texture,
uint32_t width,
uint32_t height,
uint32_t arrayLayer,
uint32_t mipLevel,
const std::vector<float>& expected) {
std::ostringstream& DawnTestBase::ExpectSampledFloatDataImpl(wgpu::TextureView textureView,
const char* wgslTextureType,
uint32_t width,
uint32_t height,
uint32_t componentCount,
uint32_t sampleCount,
detail::Expectation* expectation) {
std::ostringstream shaderSource;
shaderSource << "let width : u32 = " << width << "u;\n";
shaderSource << "[[group(0), binding(0)]] var tex : " << wgslTextureType << ";\n";
shaderSource << R"(
[[block]] struct Result {
values : array<f32>;
};
[[group(0), binding(0)]] var tex : texture_depth_2d;
[[group(0), binding(1)]] var<storage, read_write> result : Result;
)";
shaderSource << "let componentCount : u32 = " << componentCount << "u;\n";
shaderSource << "let sampleCount : u32 = " << sampleCount << "u;\n";
shaderSource << "fn doTextureLoad(t: " << wgslTextureType
<< ", coord: vec2<i32>, sample: u32, component: u32) -> f32";
if (sampleCount > 1) {
shaderSource << R"({
return textureLoad(tex, coord, i32(sample))[component];
})";
} else {
if (strcmp(wgslTextureType, "texture_depth_2d") == 0) {
ASSERT(componentCount == 1);
shaderSource << R"({
return textureLoad(tex, coord, 0);
})";
} else {
shaderSource << R"({
return textureLoad(tex, coord, 0)[component];
})";
}
}
shaderSource << R"(
[[stage(compute), workgroup_size(1)]] fn main(
[[builtin(global_invocation_id)]] GlobalInvocationId : vec3<u32>
) {
result.values[GlobalInvocationId.y * width + GlobalInvocationId.x] = textureLoad(
tex, vec2<i32>(i32(GlobalInvocationId.x), i32(GlobalInvocationId.y)), 0);
let baseOutIndex = GlobalInvocationId.y * width + GlobalInvocationId.x;
for (var s = 0u; s < sampleCount; s = s + 1u) {
for (var c = 0u; c < componentCount; c = c + 1u) {
result.values[
baseOutIndex * sampleCount * componentCount +
s * componentCount +
c
] = doTextureLoad(tex, vec2<i32>(GlobalInvocationId.xy), s, c);
}
}
}
)";
@ -1122,22 +1152,13 @@ std::ostringstream& DawnTestBase::ExpectSampledDepthData(wgpu::Texture texture,
// Create and initialize the slot buffer so that it won't unexpectedly affect the count of
// resources lazily cleared.
const std::vector<float> initialBufferData(width * height, 0.f);
const std::vector<float> initialBufferData(width * height * componentCount * sampleCount, 0.f);
wgpu::Buffer readbackBuffer = utils::CreateBufferFromData(
device, initialBufferData.data(), sizeof(float) * width * height,
device, initialBufferData.data(), sizeof(float) * initialBufferData.size(),
wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::Storage);
wgpu::TextureViewDescriptor viewDesc = {};
viewDesc.aspect = wgpu::TextureAspect::DepthOnly;
viewDesc.dimension = wgpu::TextureViewDimension::e2D;
viewDesc.baseMipLevel = mipLevel;
viewDesc.mipLevelCount = 1;
viewDesc.baseArrayLayer = arrayLayer;
viewDesc.arrayLayerCount = 1;
wgpu::BindGroup bindGroup =
utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
{{0, texture.CreateView(&viewDesc)}, {1, readbackBuffer}});
wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
{{0, textureView}, {1, readbackBuffer}});
wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
wgpu::ComputePassEncoder pass = commandEncoder.BeginComputePass();
@ -1148,8 +1169,62 @@ std::ostringstream& DawnTestBase::ExpectSampledDepthData(wgpu::Texture texture,
wgpu::CommandBuffer commands = commandEncoder.Finish();
queue.Submit(1, &commands);
return EXPECT_BUFFER_FLOAT_RANGE_ABOUT_EQ(expected.data(), readbackBuffer, 0, expected.size(),
0.00001);
return EXPECT_BUFFER(readbackBuffer, 0, initialBufferData.size() * sizeof(float), expectation);
}
std::ostringstream& DawnTestBase::ExpectSampledFloatData(wgpu::Texture texture,
uint32_t width,
uint32_t height,
uint32_t componentCount,
uint32_t arrayLayer,
uint32_t mipLevel,
detail::Expectation* expectation) {
wgpu::TextureViewDescriptor viewDesc = {};
viewDesc.dimension = wgpu::TextureViewDimension::e2D;
viewDesc.baseMipLevel = mipLevel;
viewDesc.mipLevelCount = 1;
viewDesc.baseArrayLayer = arrayLayer;
viewDesc.arrayLayerCount = 1;
return ExpectSampledFloatDataImpl(texture.CreateView(&viewDesc), "texture_2d<f32>", width,
height, componentCount, 1, expectation);
}
std::ostringstream& DawnTestBase::ExpectMultisampledFloatData(wgpu::Texture texture,
uint32_t width,
uint32_t height,
uint32_t componentCount,
uint32_t sampleCount,
uint32_t arrayLayer,
uint32_t mipLevel,
detail::Expectation* expectation) {
wgpu::TextureViewDescriptor viewDesc = {};
viewDesc.dimension = wgpu::TextureViewDimension::e2D;
viewDesc.baseMipLevel = mipLevel;
viewDesc.mipLevelCount = 1;
viewDesc.baseArrayLayer = arrayLayer;
viewDesc.arrayLayerCount = 1;
return ExpectSampledFloatDataImpl(texture.CreateView(&viewDesc), "texture_multisampled_2d<f32>",
width, height, componentCount, sampleCount, expectation);
}
std::ostringstream& DawnTestBase::ExpectSampledDepthData(wgpu::Texture texture,
uint32_t width,
uint32_t height,
uint32_t arrayLayer,
uint32_t mipLevel,
detail::Expectation* expectation) {
wgpu::TextureViewDescriptor viewDesc = {};
viewDesc.aspect = wgpu::TextureAspect::DepthOnly;
viewDesc.dimension = wgpu::TextureViewDimension::e2D;
viewDesc.baseMipLevel = mipLevel;
viewDesc.mipLevelCount = 1;
viewDesc.baseArrayLayer = arrayLayer;
viewDesc.arrayLayerCount = 1;
return ExpectSampledFloatDataImpl(texture.CreateView(&viewDesc), "texture_depth_2d", width,
height, 1, 1, expectation);
}
std::ostringstream& DawnTestBase::ExpectAttachmentDepthStencilTestData(

View File

@ -74,10 +74,6 @@
EXPECT_BUFFER(buffer, offset, sizeof(float) * (count), \
new ::detail::ExpectEq<float>(expected, count))
#define EXPECT_BUFFER_FLOAT_RANGE_ABOUT_EQ(expected, buffer, offset, count, tolerance) \
EXPECT_BUFFER(buffer, offset, sizeof(float) * (count), \
new ::detail::ExpectEq<float>(expected, count, tolerance))
// Test a pixel of the mip level 0 of a 2D texture.
#define EXPECT_PIXEL_RGBA8_EQ(expected, texture, x, y) \
AddTextureExpectation(__FILE__, __LINE__, expected, texture, {x, y})
@ -407,12 +403,29 @@ class DawnTestBase {
level, aspect, sizeof(T), bytesPerRow);
}
std::ostringstream& ExpectSampledFloatData(wgpu::Texture texture,
uint32_t width,
uint32_t height,
uint32_t componentCount,
uint32_t arrayLayer,
uint32_t mipLevel,
detail::Expectation* expectation);
std::ostringstream& ExpectMultisampledFloatData(wgpu::Texture texture,
uint32_t width,
uint32_t height,
uint32_t componentCount,
uint32_t sampleCount,
uint32_t arrayLayer,
uint32_t mipLevel,
detail::Expectation* expectation);
std::ostringstream& ExpectSampledDepthData(wgpu::Texture depthTexture,
uint32_t width,
uint32_t height,
uint32_t arrayLayer,
uint32_t mipLevel,
const std::vector<float>& expected);
detail::Expectation* expectation);
// Check depth by uploading expected data to a sampled texture, writing it out as a depth
// attachment, and then using the "equals" depth test to check the contents are the same.
@ -485,6 +498,14 @@ class DawnTestBase {
uint32_t dataSize,
uint32_t bytesPerRow);
std::ostringstream& ExpectSampledFloatDataImpl(wgpu::TextureView textureView,
const char* wgslTextureType,
uint32_t width,
uint32_t height,
uint32_t componentCount,
uint32_t sampleCount,
detail::Expectation* expectation);
// MapRead buffers used to get data for the expectations
struct ReadbackSlot {
wgpu::Buffer buffer;

View File

@ -100,7 +100,9 @@ namespace {
switch (GetParam().mCheck) {
case Check::SampleDepth: {
std::vector<float> expectedDepth(mipSize * mipSize, kDepthValues[mipLevel]);
ExpectSampledDepthData(texture, mipSize, mipSize, 0, mipLevel, expectedDepth)
ExpectSampledDepthData(texture, mipSize, mipSize, 0, mipLevel,
new detail::ExpectEq<float>(
expectedDepth.data(), expectedDepth.size(), 0.0001))
<< "sample depth mip " << mipLevel;
break;
}

View File

@ -27,9 +27,19 @@ namespace {
using Usage = wgpu::TextureUsage;
using Dimension = wgpu::TextureDimension;
using DepthOrArrayLayers = uint32_t;
using MipCount = uint32_t;
using Mip = uint32_t;
using SampleCount = uint32_t;
DAWN_TEST_PARAM_STRUCT(Params, Format, Aspect, Usage, Dimension, DepthOrArrayLayers, Mip)
DAWN_TEST_PARAM_STRUCT(Params,
Format,
Aspect,
Usage,
Dimension,
DepthOrArrayLayers,
MipCount,
Mip,
SampleCount)
template <typename T>
class ExpectNonZero : public detail::CustomTextureExpectation {
@ -49,8 +59,8 @@ namespace {
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;
<< "Expected data[" << i << "] to match non-zero value " << value
<< ", actual " << actual[i] << std::endl;
}
}
@ -64,7 +74,6 @@ namespace {
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 &&
@ -130,10 +139,10 @@ namespace {
descriptor.size.width = kSize;
descriptor.size.height = kSize;
descriptor.size.depthOrArrayLayers = GetParam().mDepthOrArrayLayers;
descriptor.sampleCount = 1;
descriptor.sampleCount = GetParam().mSampleCount;
descriptor.format = GetParam().mFormat;
descriptor.usage = GetParam().mUsage;
descriptor.mipLevelCount = kMipLevelCount;
descriptor.mipLevelCount = GetParam().mMipCount;
wgpu::Texture texture = device.CreateTexture(&descriptor);
@ -142,22 +151,39 @@ namespace {
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);
if (GetParam().mSampleCount > 1) {
ExpectMultisampledFloatData(texture, mipSize, mipSize, 1,
GetParam().mSampleCount, 0, mip,
new ExpectNonZero<float>());
} else {
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);
if (GetParam().mSampleCount > 1) {
ExpectMultisampledFloatData(texture, mipSize, mipSize, 2,
GetParam().mSampleCount, 0, mip,
new ExpectNonZero<float>());
} else {
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);
if (GetParam().mSampleCount > 1) {
ExpectMultisampledFloatData(texture, mipSize, mipSize, 4,
GetParam().mSampleCount, 0, mip,
new ExpectNonZero<float>());
} else {
EXPECT_TEXTURE_EQ(new ExpectNonZero<uint32_t>(), texture, {0, 0, 0},
{mipSize, mipSize, depthOrArrayLayers}, mip);
}
break;
}
case wgpu::TextureFormat::Depth32Float: {
@ -168,18 +194,10 @@ namespace {
case wgpu::TextureFormat::Depth24PlusStencil8: {
switch (GetParam().mAspect) {
case wgpu::TextureAspect::DepthOnly: {
uint32_t value = 0x01010101;
float fValue = *reinterpret_cast<float*>(&value);
std::vector<float> expectedDepth(
mipSize * mipSize,
(IsVulkan() || IsOpenGL() ||
(GetParam().mUsage & wgpu::TextureUsage::RenderAttachment) != 0)
? 1.f
: fValue);
for (uint32_t arrayLayer = 0;
arrayLayer < GetParam().mDepthOrArrayLayers; ++arrayLayer) {
ExpectSampledDepthData(texture, mipSize, mipSize, arrayLayer, mip,
expectedDepth)
new ExpectNonZero<float>())
<< "arrayLayer " << arrayLayer;
}
break;
@ -250,6 +268,7 @@ namespace {
class NonzeroCompressedTextureCreationTests : public NonzeroTextureCreationTests {};
class NonzeroDepthTextureCreationTests : public NonzeroTextureCreationTests {};
class NonzeroDepthStencilTextureCreationTests : public NonzeroTextureCreationTests {};
class NonzeroMultisampledTextureCreationTests : public NonzeroTextureCreationTests {};
} // anonymous namespace
@ -278,7 +297,10 @@ TEST_P(NonzeroDepthStencilTextureCreationTests, TextureCreationClears) {
Run();
}
// TODO(crbug.com/794): Test/implement texture initialization for multisampled textures.
// Test that texture clears to a non-zero value because toggle is enabled.
TEST_P(NonzeroMultisampledTextureCreationTests, TextureCreationClears) {
Run();
}
DAWN_INSTANTIATE_TEST_P(
NonzeroTextureCreationTests,
@ -297,8 +319,11 @@ DAWN_INSTANTIATE_TEST_P(
{wgpu::TextureUsage(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc),
wgpu::TextureUsage::CopySrc},
{wgpu::TextureDimension::e2D, wgpu::TextureDimension::e3D},
{1u, 7u},
{0u, 1u, 2u, 3u});
{1u, 7u}, // depth or array layers
{4u}, // mip count
{0u, 1u, 2u, 3u}, // mip
{1u} // sample count
);
DAWN_INSTANTIATE_TEST_P(NonzeroNonrenderableTextureCreationTests,
{D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"},
@ -315,8 +340,11 @@ DAWN_INSTANTIATE_TEST_P(NonzeroNonrenderableTextureCreationTests,
{wgpu::TextureAspect::All},
{wgpu::TextureUsage::CopySrc},
{wgpu::TextureDimension::e2D, wgpu::TextureDimension::e3D},
{1u, 7u},
{0u, 1u, 2u, 3u});
{1u, 7u}, // depth or array layers
{4u}, // mip count
{0u, 1u, 2u, 3u}, // mip
{1u} // sample count
);
DAWN_INSTANTIATE_TEST_P(NonzeroCompressedTextureCreationTests,
{D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"},
@ -333,8 +361,11 @@ DAWN_INSTANTIATE_TEST_P(NonzeroCompressedTextureCreationTests,
{wgpu::TextureAspect::All},
{wgpu::TextureUsage::CopySrc},
{wgpu::TextureDimension::e2D},
{1u, 7u},
{0u, 1u, 2u, 3u});
{1u, 7u}, // depth or array layers
{4u}, // mip count
{0u, 1u, 2u, 3u}, // mip
{1u} // sample count
);
DAWN_INSTANTIATE_TEST_P(NonzeroDepthTextureCreationTests,
{D3D12Backend({"nonzero_clear_resources_on_creation_for_testing"},
@ -353,8 +384,11 @@ DAWN_INSTANTIATE_TEST_P(NonzeroDepthTextureCreationTests,
wgpu::TextureUsage::CopySrc),
wgpu::TextureUsage::CopySrc},
{wgpu::TextureDimension::e2D},
{1u, 7u},
{0u, 1u, 2u, 3u});
{1u, 7u}, // depth or array layers
{4u}, // mip count
{0u, 1u, 2u, 3u}, // mip
{1u} // sample count
);
DAWN_INSTANTIATE_TEST_P(
NonzeroDepthStencilTextureCreationTests,
@ -374,5 +408,31 @@ DAWN_INSTANTIATE_TEST_P(
wgpu::TextureUsage::Sampled),
wgpu::TextureUsage(wgpu::TextureUsage::Sampled | wgpu::TextureUsage::CopySrc)},
{wgpu::TextureDimension::e2D},
{1u, 7u},
{0u, 1u, 2u, 3u});
{1u, 7u}, // depth or array layers
{4u}, // mip count
{0u, 1u, 2u, 3u}, // mip
{1u} // sample count
);
DAWN_INSTANTIATE_TEST_P(
NonzeroMultisampledTextureCreationTests,
{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::R8Unorm, wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::RGBA8Unorm},
{wgpu::TextureAspect::All},
{wgpu::TextureUsage(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::Sampled),
wgpu::TextureUsage::Sampled},
{wgpu::TextureDimension::e2D},
{1u}, // depth or array layers
{1u}, // mip count
{0u}, // mip
{4u} // sample count
);