diff --git a/BUILD.gn b/BUILD.gn index 44709b1e83..36e63015a1 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -643,6 +643,7 @@ test("dawn_end2end_tests") { "src/tests/end2end/IndexFormatTests.cpp", "src/tests/end2end/InputStateTests.cpp", "src/tests/end2end/MultisampledRenderingTests.cpp", + "src/tests/end2end/NonzeroTextureCreationTests.cpp", "src/tests/end2end/ObjectCachingTests.cpp", "src/tests/end2end/PrimitiveTopologyTests.cpp", "src/tests/end2end/PushConstantTests.cpp", diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp index 0eedeaa387..865d15cc2b 100644 --- a/src/dawn_native/Instance.cpp +++ b/src/dawn_native/Instance.cpp @@ -67,7 +67,13 @@ namespace dawn_native { "not support MTLStoreActionStoreAndMultisampleResolve. To support StoreOp::Store on " "those platforms, we should do MSAA resolve in another render pass after ending the " "previous one.", - "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}}}}; + "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}}, + {Toggle::NonzeroClearResourcesOnCreationForTesting, + {"nonzero_clear_resources_on_creation_for_testing", + "Clears texture to full 1 bits as soon as they are created, but doesn't update " + "the tracking state of the texture. This way we can test the logic of clearing " + "textures that use recycled memory.", + "https://bugs.chromium.org/p/dawn/issues/detail?id=145"}}}}; } // anonymous namespace diff --git a/src/dawn_native/Toggles.h b/src/dawn_native/Toggles.h index 5bcda4d568..c60f5f95e3 100644 --- a/src/dawn_native/Toggles.h +++ b/src/dawn_native/Toggles.h @@ -22,9 +22,10 @@ namespace dawn_native { enum class Toggle { - EmulateStoreAndMSAAResolve = 0, + EmulateStoreAndMSAAResolve, + NonzeroClearResourcesOnCreationForTesting, - EnumCount = 1, + EnumCount, InvalidEnum = EnumCount, }; diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp index 7b91f59d68..629d8f9f08 100644 --- a/src/dawn_native/vulkan/DeviceVk.cpp +++ b/src/dawn_native/vulkan/DeviceVk.cpp @@ -42,6 +42,9 @@ namespace dawn_native { namespace vulkan { Device::Device(Adapter* adapter, const DeviceDescriptor* descriptor) : DeviceBase(adapter, descriptor) { + if (descriptor != nullptr) { + ApplyToggleOverrides(descriptor); + } } MaybeError Device::Initialize() { diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp index 70064ec1e9..cfc27a67d1 100644 --- a/src/dawn_native/vulkan/TextureVk.cpp +++ b/src/dawn_native/vulkan/TextureVk.cpp @@ -319,6 +319,24 @@ namespace dawn_native { namespace vulkan { mMemoryAllocation.GetMemoryOffset()) != VK_SUCCESS) { ASSERT(false); } + if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) { + VkImageSubresourceRange range = {}; + range.aspectMask = GetVkAspectMask(); + range.baseMipLevel = 0; + range.levelCount = GetNumMipLevels(); + range.baseArrayLayer = 0; + range.layerCount = GetArrayLayers(); + + // TODO(natlee@microsoft.com): use correct union member depending on the texture format + VkClearColorValue clear_color = {{1.0, 1.0, 1.0, 1.0}}; + + TransitionUsageNow(ToBackend(GetDevice())->GetPendingCommandBuffer(), + dawn::TextureUsageBit::TransferDst); + ToBackend(GetDevice()) + ->fn.CmdClearColorImage(ToBackend(GetDevice())->GetPendingCommandBuffer(), + GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &clear_color, 1, &range); + } } // With this constructor, the lifetime of the resource is externally managed. diff --git a/src/tests/DawnTest.cpp b/src/tests/DawnTest.cpp index b0f423b9cd..4546e366db 100644 --- a/src/tests/DawnTest.cpp +++ b/src/tests/DawnTest.cpp @@ -293,6 +293,7 @@ void DawnTest::SetUp() { DawnDevice backendDevice; const char* forceEnabledWorkaround = GetParam().forceEnabledWorkaround; if (forceEnabledWorkaround != nullptr) { + ASSERT(gTestEnv->GetInstance()->GetToggleInfo(forceEnabledWorkaround) != nullptr); dawn_native::DeviceDescriptor deviceDescriptor = InitWorkaround(forceEnabledWorkaround); backendDevice = backendAdapter.CreateDevice(&deviceDescriptor); } else { diff --git a/src/tests/end2end/NonzeroTextureCreationTests.cpp b/src/tests/end2end/NonzeroTextureCreationTests.cpp new file mode 100644 index 0000000000..28a9b4d992 --- /dev/null +++ b/src/tests/end2end/NonzeroTextureCreationTests.cpp @@ -0,0 +1,99 @@ +// Copyright 2019 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "tests/DawnTest.h" + +#include "utils/ComboRenderPipelineDescriptor.h" +#include "utils/DawnHelpers.h" + +class NonzeroTextureCreationTests : public DawnTest { + protected: + void SetUp() override { + DawnTest::SetUp(); + } + + constexpr static uint32_t kSize = 128; +}; + +// Test that texture clears to 1's because toggle is enabled. +TEST_P(NonzeroTextureCreationTests, TextureCreationClearsOneBits) { + dawn::TextureDescriptor descriptor; + descriptor.dimension = dawn::TextureDimension::e2D; + descriptor.size.width = kSize; + descriptor.size.height = kSize; + descriptor.size.depth = 1; + descriptor.arrayLayerCount = 1; + descriptor.sampleCount = 1; + descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm; + descriptor.mipLevelCount = 1; + descriptor.usage = dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc; + dawn::Texture texture = device.CreateTexture(&descriptor); + + RGBA8 filledWithOnes(255, 255, 255, 255); + EXPECT_PIXEL_RGBA8_EQ(filledWithOnes, texture, 0, 0); +} + +// Test that non-zero mip level clears to 1's because toggle is enabled. +TEST_P(NonzeroTextureCreationTests, MipMapClears) { + constexpr uint32_t mipLevels = 4; + + dawn::TextureDescriptor descriptor; + descriptor.dimension = dawn::TextureDimension::e2D; + descriptor.size.width = kSize; + descriptor.size.height = kSize; + descriptor.size.depth = 1; + descriptor.arrayLayerCount = 1; + descriptor.sampleCount = 1; + descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm; + descriptor.mipLevelCount = mipLevels; + descriptor.usage = dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc; + dawn::Texture texture = device.CreateTexture(&descriptor); + + std::vector expected; + RGBA8 filledWithOnes(255, 255, 255, 255); + for (uint32_t i = 0; i < kSize * kSize; ++i) { + expected.push_back(filledWithOnes); + } + uint32_t mipSize = kSize >> 2; + EXPECT_TEXTURE_RGBA8_EQ(expected.data(), texture, 0, 0, mipSize, mipSize, 2, 0); +} + +// Test that non-zero array layers clears to 1's because toggle is enabled. +TEST_P(NonzeroTextureCreationTests, ArrayLayerClears) { + constexpr uint32_t arrayLayers = 4; + + dawn::TextureDescriptor descriptor; + descriptor.dimension = dawn::TextureDimension::e2D; + descriptor.size.width = kSize; + descriptor.size.height = kSize; + descriptor.size.depth = 1; + descriptor.arrayLayerCount = arrayLayers; + descriptor.sampleCount = 1; + descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm; + descriptor.mipLevelCount = 1; + descriptor.usage = dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc; + dawn::Texture texture = device.CreateTexture(&descriptor); + + std::vector expected; + RGBA8 filledWithOnes(255, 255, 255, 255); + for (uint32_t i = 0; i < kSize * kSize; ++i) { + expected.push_back(filledWithOnes); + } + + EXPECT_TEXTURE_RGBA8_EQ(expected.data(), texture, 0, 0, kSize, kSize, 0, 2); +} + +DAWN_INSTANTIATE_TEST(NonzeroTextureCreationTests, + ForceWorkaround(VulkanBackend, + "nonzero_clear_resources_on_creation_for_testing"));