diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp index 1248a6568a..6c5a5dd693 100644 --- a/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/src/dawn_native/d3d12/TextureD3D12.cpp @@ -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 { diff --git a/src/dawn_native/d3d12/TextureD3D12.h b/src/dawn_native/d3d12/TextureD3D12.h index d760c1e2ea..635680053a 100644 --- a/src/dawn_native/d3d12/TextureD3D12.h +++ b/src/dawn_native/d3d12/TextureD3D12.h @@ -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); diff --git a/src/dawn_native/metal/TextureMTL.h b/src/dawn_native/metal/TextureMTL.h index 9c0f4b396f..c03adbf6f9 100644 --- a/src/dawn_native/metal/TextureMTL.h +++ b/src/dawn_native/metal/TextureMTL.h @@ -63,6 +63,7 @@ namespace dawn_native { namespace metal { TextureBase::ClearValue clearValue); NSPRef> mMtlTexture; + MTLTextureUsage mMtlUsage; }; class TextureView final : public TextureViewBase { diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm index cd0cbb09ec..8cc642e351 100644 --- a/src/dawn_native/metal/TextureMTL.mm +++ b/src/dawn_native/metal/TextureMTL.mm @@ -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 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> mtlTexture) : TextureBase(device, descriptor, TextureState::OwnedInternal), mMtlTexture(std::move(mtlTexture)) { + NSRef 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. diff --git a/src/tests/DawnTest.cpp b/src/tests/DawnTest.cpp index 3b9b5a92ad..b35bf7bf42 100644 --- a/src/tests/DawnTest.cpp +++ b/src/tests/DawnTest.cpp @@ -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& 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; }; - - [[group(0), binding(0)]] var tex : texture_depth_2d; [[group(0), binding(1)]] var result : Result; + )"; + shaderSource << "let componentCount : u32 = " << componentCount << "u;\n"; + shaderSource << "let sampleCount : u32 = " << sampleCount << "u;\n"; + shaderSource << "fn doTextureLoad(t: " << wgslTextureType + << ", coord: vec2, 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 ) { - result.values[GlobalInvocationId.y * width + GlobalInvocationId.x] = textureLoad( - tex, vec2(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(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 initialBufferData(width * height, 0.f); + const std::vector 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", 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", + 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( diff --git a/src/tests/DawnTest.h b/src/tests/DawnTest.h index b3afb7d21b..c59f7f5cbe 100644 --- a/src/tests/DawnTest.h +++ b/src/tests/DawnTest.h @@ -74,10 +74,6 @@ EXPECT_BUFFER(buffer, offset, sizeof(float) * (count), \ new ::detail::ExpectEq(expected, count)) -#define EXPECT_BUFFER_FLOAT_RANGE_ABOUT_EQ(expected, buffer, offset, count, tolerance) \ - EXPECT_BUFFER(buffer, offset, sizeof(float) * (count), \ - new ::detail::ExpectEq(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& 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; diff --git a/src/tests/end2end/DepthStencilLoadOpTests.cpp b/src/tests/end2end/DepthStencilLoadOpTests.cpp index 173e353f99..3a3981f96b 100644 --- a/src/tests/end2end/DepthStencilLoadOpTests.cpp +++ b/src/tests/end2end/DepthStencilLoadOpTests.cpp @@ -100,7 +100,9 @@ namespace { switch (GetParam().mCheck) { case Check::SampleDepth: { std::vector expectedDepth(mipSize * mipSize, kDepthValues[mipLevel]); - ExpectSampledDepthData(texture, mipSize, mipSize, 0, mipLevel, expectedDepth) + ExpectSampledDepthData(texture, mipSize, mipSize, 0, mipLevel, + new detail::ExpectEq( + expectedDepth.data(), expectedDepth.size(), 0.0001)) << "sample depth mip " << mipLevel; break; } diff --git a/src/tests/end2end/NonzeroTextureCreationTests.cpp b/src/tests/end2end/NonzeroTextureCreationTests.cpp index 42ab21238a..5db236e768 100644 --- a/src/tests/end2end/NonzeroTextureCreationTests.cpp +++ b/src/tests/end2end/NonzeroTextureCreationTests.cpp @@ -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 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 { protected: constexpr static uint32_t kSize = 128; - constexpr static uint32_t kMipLevelCount = 4; std::vector 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(), texture, {0, 0, 0}, - {mipSize, mipSize, depthOrArrayLayers}, mip); + if (GetParam().mSampleCount > 1) { + ExpectMultisampledFloatData(texture, mipSize, mipSize, 1, + GetParam().mSampleCount, 0, mip, + new ExpectNonZero()); + } else { + EXPECT_TEXTURE_EQ(new ExpectNonZero(), texture, {0, 0, 0}, + {mipSize, mipSize, depthOrArrayLayers}, mip); + } break; } case wgpu::TextureFormat::RG8Unorm: { - EXPECT_TEXTURE_EQ(new ExpectNonZero(), texture, {0, 0, 0}, - {mipSize, mipSize, depthOrArrayLayers}, mip); + if (GetParam().mSampleCount > 1) { + ExpectMultisampledFloatData(texture, mipSize, mipSize, 2, + GetParam().mSampleCount, 0, mip, + new ExpectNonZero()); + } else { + EXPECT_TEXTURE_EQ(new ExpectNonZero(), texture, {0, 0, 0}, + {mipSize, mipSize, depthOrArrayLayers}, mip); + } break; } case wgpu::TextureFormat::RGBA8Unorm: case wgpu::TextureFormat::RGBA8Snorm: { - EXPECT_TEXTURE_EQ(new ExpectNonZero(), texture, {0, 0, 0}, - {mipSize, mipSize, depthOrArrayLayers}, mip); + if (GetParam().mSampleCount > 1) { + ExpectMultisampledFloatData(texture, mipSize, mipSize, 4, + GetParam().mSampleCount, 0, mip, + new ExpectNonZero()); + } else { + EXPECT_TEXTURE_EQ(new ExpectNonZero(), 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(&value); - std::vector 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()) << "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 +);