// Copyright 2023 The Dawn & Tint Authors // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <atomic> #include <condition_variable> #include <functional> #include <limits> #include <memory> #include <mutex> #include <sstream> #include <string> #include <thread> #include <utility> #include <vector> #include "dawn/common/Constants.h" #include "dawn/common/Math.h" #include "dawn/tests/DawnTest.h" #include "dawn/utils/ComboRenderPipelineDescriptor.h" #include "dawn/utils/TestUtils.h" #include "dawn/utils/TextureUtils.h" #include "dawn/utils/WGPUHelpers.h" namespace dawn { namespace { template <typename Step> class LockStep { … }; class MultithreadTests : public DawnTest { … }; // Test that dropping a device's last ref on another thread won't crash Instance::ProcessEvents. TEST_P(MultithreadTests, Device_DroppedOnAnotherThread) { … } // Test that dropping a device's last ref inside a callback on another thread won't crash // Instance::ProcessEvents. TEST_P(MultithreadTests, Device_DroppedInCallback_OnAnotherThread) { … } // Test that multiple buffers being created and mapped on multiple threads won't interfere with // each other. TEST_P(MultithreadTests, Buffers_MapInParallel) { … } // Test CreateShaderModule on multiple threads. Cache hits should share compilation warnings. TEST_P(MultithreadTests, CreateShaderModuleInParallel) { … } // Test CreateComputePipelineAsync on multiple threads. TEST_P(MultithreadTests, CreateComputePipelineAsyncInParallel) { … } // Test CreateComputePipeline on multiple threads. TEST_P(MultithreadTests, CreateComputePipelineInParallel) { … } // Test CreateRenderPipelineAsync on multiple threads. TEST_P(MultithreadTests, CreateRenderPipelineAsyncInParallel) { … } // Test CreateRenderPipeline on multiple threads. TEST_P(MultithreadTests, CreateRenderPipelineInParallel) { … } class MultithreadCachingTests : public MultithreadTests { … }; // Test that creating a same shader module (which will return the cached shader module) and release // it on multiple threads won't race. TEST_P(MultithreadCachingTests, RefAndReleaseCachedShaderModulesInParallel) { … } // Test that creating a same compute pipeline (which will return the cached pipeline) and release it // on multiple threads won't race. TEST_P(MultithreadCachingTests, RefAndReleaseCachedComputePipelinesInParallel) { … } // Test that creating a same bind group layout (which will return the cached layout) and // release it on multiple threads won't race. TEST_P(MultithreadCachingTests, RefAndReleaseCachedBindGroupLayoutsInParallel) { … } // Test that creating a same pipeline layout (which will return the cached layout) and // release it on multiple threads won't race. TEST_P(MultithreadCachingTests, RefAndReleaseCachedPipelineLayoutsInParallel) { … } // Test that creating a same render pipeline (which will return the cached pipeline) and release it // on multiple threads won't race. TEST_P(MultithreadCachingTests, RefAndReleaseCachedRenderPipelinesInParallel) { … } // Test that creating a same sampler pipeline (which will return the cached sampler) and release it // on multiple threads won't race. TEST_P(MultithreadCachingTests, RefAndReleaseCachedSamplersInParallel) { … } class MultithreadEncodingTests : public MultithreadTests { … }; // Test that encoding render passes in parallel should work TEST_P(MultithreadEncodingTests, RenderPassEncodersInParallel) { … } // Test that encoding render passes that resolve to a mip level in parallel should work TEST_P(MultithreadEncodingTests, RenderPassEncoders_ResolveToMipLevelOne_InParallel) { … } // Test that encoding compute passes in parallel should work TEST_P(MultithreadEncodingTests, ComputePassEncodersInParallel) { … } class MultithreadTextureCopyTests : public MultithreadTests { … }; // Test that depth texture's CopyTextureToTexture() can work in parallel with other commands (such // resources creation and texture to buffer copy for texture expectations). // This test is needed since most of command encoder's commands are not synchronized, but // CopyTextureToTexture() command might internally allocate resources and we need to make sure that // it won't race with other threads' works. TEST_P(MultithreadTextureCopyTests, CopyDepthToDepthNoRace) { … } // Test that depth texture's CopyBufferToTexture() can work in parallel with other commands (such // resources creation and texture to buffer copy for texture expectations). // This test is needed since most of command encoder's commands are not synchronized, but // CopyBufferToTexture() command might internally allocate resources and we need to make sure that // it won't race with other threads' works. TEST_P(MultithreadTextureCopyTests, CopyBufferToDepthNoRace) { … } // Test that stencil texture's CopyTextureToTexture() can work in parallel with other commands (such // resources creation and texture to buffer copy for texture expectations). // This test is needed since most of command encoder's commands are not synchronized, but // CopyTextureToTexture() command might internally allocate resources and we need to make sure that // it won't race with other threads' works. TEST_P(MultithreadTextureCopyTests, CopyStencilToStencilNoRace) { … } // Test that stencil texture's CopyBufferToTexture() can work in parallel with other commands (such // resources creation and texture to buffer copy for texture expectations). // This test is needed since most of command encoder's commands are not synchronized, but // CopyBufferToTexture() command might internally allocate resources and we need to make sure that // it won't race with other threads' works. TEST_P(MultithreadTextureCopyTests, CopyBufferToStencilNoRace) { … } // Test that color texture's CopyTextureForBrowser() can work in parallel with other commands (such // resources creation and texture to buffer copy for texture expectations). // This test is needed since CopyTextureForBrowser() command might internally allocate resources and // we need to make sure that it won't race with other threads' works. TEST_P(MultithreadTextureCopyTests, CopyTextureForBrowserNoRace) { … } // Test that error from CopyTextureForBrowser() won't cause deadlock. TEST_P(MultithreadTextureCopyTests, CopyTextureForBrowserErrorNoDeadLock) { … } class MultithreadDrawIndexedIndirectTests : public MultithreadTests { … }; // Test indirect draws with offsets on multiple threads. TEST_P(MultithreadDrawIndexedIndirectTests, IndirectOffsetInParallel) { … } class TimestampExpectation : public detail::Expectation { … }; class MultithreadTimestampQueryTests : public MultithreadTests { … }; // Test resolving timestamp queries on multiple threads. ResolveQuerySet() will create temp // resources internally so we need to make sure they are thread safe. TEST_P(MultithreadTimestampQueryTests, ResolveQuerySets_InParallel) { … } DAWN_INSTANTIATE_TEST(MultithreadTests, D3D11Backend(), D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()); DAWN_INSTANTIATE_TEST(MultithreadCachingTests, D3D11Backend(), D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()); DAWN_INSTANTIATE_TEST(MultithreadEncodingTests, D3D11Backend(), D3D12Backend(), D3D12Backend({ … }; DAWN_INSTANTIATE_TEST( MultithreadTextureCopyTests, D3D11Backend(), D3D12Backend(), MetalBackend(), MetalBackend({ … }; DAWN_INSTANTIATE_TEST(MultithreadDrawIndexedIndirectTests, D3D11Backend(), D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()); DAWN_INSTANTIATE_TEST(MultithreadTimestampQueryTests, D3D11Backend(), D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()); } // anonymous namespace } // namespace dawn