[Wire] Implement InlineSharedMemoryManager This patch implements InlineSharedMemoryManager as a preparation of importing a Transfer Buffer from Dawn wire to Dawn native. `InlineSharedMemoryManager` is used to emulate `MappedMemoryManager` in Chromium to create and manage the `SharedMemory`s that are shared between wire client and wire server. Like `MappedMemoryManager`, both client and server `InlineMemoryTransferService` will share the same `InlineSharedMemoryManager` and query the information about the `SharedMemory` from the `InlineSharedMemoryManager`. Bug: 386255678 Change-Id: I3062de49591966cbdb4532562d5c403549a006e0 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/331375 Reviewed-by: Loko Kung <lokokung@google.com> Commit-Queue: Shao, Jiawei <jiawei.shao@intel.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/SystemEvent.h b/src/dawn/native/SystemEvent.h index 9f52e3f..26ad1bd 100644 --- a/src/dawn/native/SystemEvent.h +++ b/src/dawn/native/SystemEvent.h
@@ -53,7 +53,6 @@ class SystemEventReceiver final : NonCopyable { public: static SystemEventReceiver CreateAlreadySignaled(); - using SystemHandle = SystemHandle; SystemEventReceiver() = default; explicit SystemEventReceiver(SystemHandle primitive);
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn index 814e408..74b8026 100644 --- a/src/dawn/tests/BUILD.gn +++ b/src/dawn/tests/BUILD.gn
@@ -420,7 +420,10 @@ } if (is_win) { - sources += [ "unittests/WindowsUtilsTests.cpp" ] + sources += [ + "unittests/WindowsUtilsTests.cpp", + "unittests/wire/WireInlineSharedMemoryManagerTests.cpp", + ] } if (dawn_enable_d3d12) {
diff --git a/src/dawn/tests/unittests/wire/WireInlineSharedMemoryManagerTests.cpp b/src/dawn/tests/unittests/wire/WireInlineSharedMemoryManagerTests.cpp new file mode 100644 index 0000000..8faf88e --- /dev/null +++ b/src/dawn/tests/unittests/wire/WireInlineSharedMemoryManagerTests.cpp
@@ -0,0 +1,170 @@ +// Copyright 2026 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 <cstddef> +#include <cstdint> +#include <memory> +#include <span> +#include <vector> + +#include "gtest/gtest.h" +#include "src/dawn/common/Ref.h" +#include "src/dawn/wire/InlineSharedMemoryManager.h" +#include "src/utils/platform.h" + +namespace dawn::wire { +namespace { + +class InlineSharedMemoryManagerTest : public testing::Test { + protected: + void SetUp() override { +#if !DAWN_PLATFORM_IS(WINDOWS) + GTEST_SKIP() << "InlineSharedMemoryManager is only implemented on Windows"; +#endif + mManager = CreateInlineSharedMemoryManager(); + } + + std::shared_ptr<InlineSharedMemoryManager> mManager; +}; + +TEST_F(InlineSharedMemoryManagerTest, CreateSharedMemory_ReturnsNonNull) { + Ref<SharedMemory> memory = mManager->CreateSharedMemory(1024); + EXPECT_NE(nullptr, memory.Get()); +} + +TEST_F(InlineSharedMemoryManagerTest, CreateSharedMemory_MultipleBuffersAreDistinct) { + Ref<SharedMemory> memory1 = mManager->CreateSharedMemory(256); + Ref<SharedMemory> memory2 = mManager->CreateSharedMemory(256); + EXPECT_NE(nullptr, memory1.Get()); + EXPECT_NE(nullptr, memory2.Get()); + EXPECT_NE(memory1.Get(), memory2.Get()); +} + +TEST_F(InlineSharedMemoryManagerTest, GetMappedSpan_ReturnsNonEmptySpanWithCorrectSize) { + constexpr size_t kSize = 1024; + Ref<SharedMemory> memory = mManager->CreateSharedMemory(kSize); + std::span<std::byte> span = memory->GetMappedSpan(); + EXPECT_FALSE(span.empty()); + EXPECT_EQ(kSize, span.size()); + EXPECT_NE(nullptr, span.data()); +} + +TEST_F(InlineSharedMemoryManagerTest, GetHandle_ReturnsNonNullHandle) { + Ref<SharedMemory> memory = mManager->CreateSharedMemory(256); + EXPECT_TRUE(memory->GetSystemHandle().IsValid()); +} + +TEST_F(InlineSharedMemoryManagerTest, PutOnWire_ReturnsUniqueIds) { + Ref<SharedMemory> memory1 = mManager->CreateSharedMemory(256); + Ref<SharedMemory> memory2 = mManager->CreateSharedMemory(256); + SharedMemoryID id1 = mManager->PutOnWireAndGetID(memory1.Get()); + SharedMemoryID id2 = mManager->PutOnWireAndGetID(memory2.Get()); + EXPECT_NE(id1, id2); +} + +TEST_F(InlineSharedMemoryManagerTest, AcquireFromWire_ReturnsSameMemory) { + Ref<SharedMemory> memory = mManager->CreateSharedMemory(256); + SharedMemoryID id = mManager->PutOnWireAndGetID(memory.Get()); + Ref<SharedMemory> acquired = mManager->AcquireFromWire(id); + EXPECT_EQ(memory.Get(), acquired.Get()); +} + +TEST_F(InlineSharedMemoryManagerTest, AcquireFromWire_ReturnsNullForUnknownId) { + EXPECT_EQ(nullptr, mManager->AcquireFromWire(SharedMemoryID(0u)).Get()); + EXPECT_EQ(nullptr, mManager->AcquireFromWire(SharedMemoryID(99999u)).Get()); +} + +TEST_F(InlineSharedMemoryManagerTest, AcquireFromWire_RemovesFromWire) { + Ref<SharedMemory> memory = mManager->CreateSharedMemory(256); + SharedMemoryID id = mManager->PutOnWireAndGetID(memory.Get()); + EXPECT_NE(nullptr, mManager->AcquireFromWire(id).Get()); + + // A second acquire finds nothing since the reference was already transferred off the wire. + EXPECT_EQ(nullptr, mManager->AcquireFromWire(id).Get()); +} + +TEST_F(InlineSharedMemoryManagerTest, PutOnWire_KeepsMemoryAliveAfterLocalRefDropped) { + Ref<SharedMemory> memory = mManager->CreateSharedMemory(256); + SharedMemory* rawSharedMemoryPtr = memory.Get(); + SharedMemoryID id = mManager->PutOnWireAndGetID(rawSharedMemoryPtr); + + // Drop the local reference; the wire still holds one so the memory stays alive. + memory = nullptr; + + Ref<SharedMemory> acquired = mManager->AcquireFromWire(id); + EXPECT_EQ(rawSharedMemoryPtr, acquired.Get()); + EXPECT_FALSE(acquired->GetMappedSpan().empty()); +} + +TEST_F(InlineSharedMemoryManagerTest, DataRoundtrip_WriteAndReadBack) { + constexpr size_t kSize = 256; + Ref<SharedMemory> memory = mManager->CreateSharedMemory(kSize); + + std::span<std::byte> span = memory->GetMappedSpan(); + ASSERT_EQ(kSize, span.size()); + + // Write a known pattern. + for (size_t i = 0; i < kSize; ++i) { + span[i] = static_cast<std::byte>(i); + } + + // Put the memory on the wire and retrieve it back. + SharedMemoryID id = mManager->PutOnWireAndGetID(memory.Get()); + Ref<SharedMemory> acquired = mManager->AcquireFromWire(id); + ASSERT_NE(nullptr, acquired.Get()); + + // Read back through the acquired reference and compare the data with the expected values. + std::span<std::byte> readSpan = acquired->GetMappedSpan(); + ASSERT_EQ(kSize, readSpan.size()); + for (size_t i = 0; i < kSize; ++i) { + EXPECT_EQ(static_cast<std::byte>(i), readSpan[i]) << " at index " << i; + } +} + +TEST_F(InlineSharedMemoryManagerTest, MultipleBuffers_DataIsIsolated) { + constexpr size_t kSize = 128; + Ref<SharedMemory> memory1 = mManager->CreateSharedMemory(kSize); + Ref<SharedMemory> memory2 = mManager->CreateSharedMemory(kSize); + + std::span<std::byte> span1 = memory1->GetMappedSpan(); + std::span<std::byte> span2 = memory2->GetMappedSpan(); + + constexpr std::byte kData1 = std::byte{0xAA}; + constexpr std::byte kData2 = std::byte{0xBB}; + std::fill(span1.begin(), span1.end(), kData1); + std::fill(span2.begin(), span2.end(), kData2); + + for (std::byte b : memory1->GetMappedSpan()) { + EXPECT_EQ(kData1, b); + } + for (std::byte b : memory2->GetMappedSpan()) { + EXPECT_EQ(kData2, b); + } +} + +} // namespace +} // namespace dawn::wire
diff --git a/src/dawn/wire/BUILD.gn b/src/dawn/wire/BUILD.gn index 26aae60..d7694ba 100644 --- a/src/dawn/wire/BUILD.gn +++ b/src/dawn/wire/BUILD.gn
@@ -103,6 +103,8 @@ "ChunkedCommandHandler.h", "ChunkedCommandSerializer.cpp", "ChunkedCommandSerializer.h", + "InlineSharedMemoryManager.cpp", + "InlineSharedMemoryManager.h", "ObjectHandle.cpp", "ObjectHandle.h", "SupportedFeatures.cpp", @@ -156,6 +158,10 @@ "server/ServerSurface.cpp", ] + if (is_win) { + sources += [ "InlineSharedMemoryManager_win.cpp" ] + } + public_deps = [ ":headers", "${dawn_abseil_dir}:absl",
diff --git a/src/dawn/wire/CMakeLists.txt b/src/dawn/wire/CMakeLists.txt index 80ae6ed..6056856 100644 --- a/src/dawn/wire/CMakeLists.txt +++ b/src/dawn/wire/CMakeLists.txt
@@ -44,6 +44,7 @@ "BufferConsumer.h" "ChunkedCommandHandler.h" "ChunkedCommandSerializer.h" + "InlineSharedMemoryManager.h" "client/Adapter.h" "client/ApiObjects.h" "client/Buffer.h" @@ -72,6 +73,7 @@ "${DAWN_WIRE_GEN_SOURCES}" "ChunkedCommandHandler.cpp" "ChunkedCommandSerializer.cpp" + "InlineSharedMemoryManager.cpp" "client/Adapter.cpp" "client/Buffer.cpp" "client/Client.cpp" @@ -106,6 +108,10 @@ "WireServer.cpp" ) +if (WIN32) + list(APPEND sources "InlineSharedMemoryManager_win.cpp") +endif () + dawn_add_library( dawn_wire UTILITY_TARGET dawn_internal_config
diff --git a/src/dawn/wire/InlineSharedMemoryManager.cpp b/src/dawn/wire/InlineSharedMemoryManager.cpp new file mode 100644 index 0000000..44caf1f --- /dev/null +++ b/src/dawn/wire/InlineSharedMemoryManager.cpp
@@ -0,0 +1,76 @@ +// Copyright 2026 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 "src/dawn/wire/InlineSharedMemoryManager.h" + +#include <memory> +#include <utility> + +#include "src/dawn/common/Ref.h" +#include "src/utils/platform.h" + +namespace dawn::wire { + +SharedMemory::SharedMemory(SystemHandle handle, Span<std::byte> data) + : mHandle(std::move(handle)), mData(data) {} + +SharedMemory::~SharedMemory() {} + +InlineSharedMemoryManager::InlineSharedMemoryManager() = default; +InlineSharedMemoryManager::~InlineSharedMemoryManager() = default; + +Ref<SharedMemory> InlineSharedMemoryManager::CreateSharedMemory(size_t) { + return nullptr; +} + +SharedMemoryID InlineSharedMemoryManager::PutOnWireAndGetID(SharedMemory* memory) { + return mAllSharedMemoryOnWire.Use([&](auto allSharedMemoryOnWire) { + SharedMemoryID id = allSharedMemoryOnWire->nextId++; + allSharedMemoryOnWire->idToSharedMemory.emplace(id, memory); + return id; + }); +} + +Ref<SharedMemory> InlineSharedMemoryManager::AcquireFromWire(SharedMemoryID id) { + return mAllSharedMemoryOnWire.Use([&](auto allSharedMemoryOnWire) { + auto it = allSharedMemoryOnWire->idToSharedMemory.find(id); + if (it == allSharedMemoryOnWire->idToSharedMemory.end()) { + return Ref<SharedMemory>(); + } + Ref<SharedMemory> memory = std::move(it->second); + allSharedMemoryOnWire->idToSharedMemory.erase(it); + return memory; + }); +} + +#if !DAWN_PLATFORM_IS(WINDOWS) +std::shared_ptr<InlineSharedMemoryManager> CreateInlineSharedMemoryManager() { + return std::make_shared<InlineSharedMemoryManager>(); +} +#endif // !DAWN_PLATFORM_IS(WINDOWS) + +} // namespace dawn::wire
diff --git a/src/dawn/wire/InlineSharedMemoryManager.h b/src/dawn/wire/InlineSharedMemoryManager.h new file mode 100644 index 0000000..68ee8df --- /dev/null +++ b/src/dawn/wire/InlineSharedMemoryManager.h
@@ -0,0 +1,95 @@ +// Copyright 2026 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. + +#ifndef SRC_DAWN_WIRE_INLINESHAREDMEMORYMANAGER_H_ +#define SRC_DAWN_WIRE_INLINESHAREDMEMORYMANAGER_H_ + +#include <cstddef> +#include <cstdint> +#include <memory> + +#include "absl/container/flat_hash_map.h" +#include "dawn/wire/dawn_wire_export.h" +#include "src/dawn/common/MutexProtected.h" +#include "src/dawn/common/Ref.h" +#include "src/dawn/common/RefCounted.h" +#include "src/dawn/common/SystemHandle.h" +#include "src/utils/span.h" +#include "src/utils/typed_integer.h" + +namespace dawn::wire { + +// Identifies a SharedMemory reference in an InlineSharedMemoryManager. +using SharedMemoryID = TypedInteger<struct SharedMemoryIDT, uint64_t>; + +// A ref-counted shared memory allocation. +class SharedMemory : public RefCounted { + public: + SharedMemory(SystemHandle handle, Span<std::byte> data); + ~SharedMemory() override; + + Span<std::byte> GetMappedSpan() const { return mData; } + + // The underlying OS handle of the shared memory. + const SystemHandle& GetSystemHandle() const { return mHandle; } + + private: + SystemHandle mHandle; + Span<std::byte> mData; +}; + +// `InlineSharedMemoryManager` manages all the shared memory allocations for inline memory transfer +// services. +class InlineSharedMemoryManager { + public: + InlineSharedMemoryManager(); + virtual ~InlineSharedMemoryManager(); + + // Creates a new `SharedMemory` of at least `size` bytes. + virtual Ref<SharedMemory> CreateSharedMemory(size_t size); + + // Registers `sharedMemory` for the transfer through dawn wire and returns a unique ID assigned + // to it. The ID can be used by the wire server to retrieve the shared memory from the + // `InlineSharedMemoryManager`. + SharedMemoryID PutOnWireAndGetID(SharedMemory* sharedMemory); + + // Acquires the `SharedMemory` from the wire with the ID returned by `PutOnWireAndGetID`. + Ref<SharedMemory> AcquireFromWire(SharedMemoryID id); + + private: + struct AllSharedMemoryOnWire { + absl::flat_hash_map<SharedMemoryID, Ref<SharedMemory>> idToSharedMemory; + SharedMemoryID nextId{1u}; + }; + MutexProtected<AllSharedMemoryOnWire> mAllSharedMemoryOnWire; +}; + +DAWN_WIRE_EXPORT std::shared_ptr<InlineSharedMemoryManager> CreateInlineSharedMemoryManager(); + +} // namespace dawn::wire + +#endif // SRC_DAWN_WIRE_INLINESHAREDMEMORYMANAGER_H_
diff --git a/src/dawn/wire/InlineSharedMemoryManager_win.cpp b/src/dawn/wire/InlineSharedMemoryManager_win.cpp new file mode 100644 index 0000000..7f1807e --- /dev/null +++ b/src/dawn/wire/InlineSharedMemoryManager_win.cpp
@@ -0,0 +1,91 @@ +// Copyright 2026 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 "src/utils/windows_with_undefs.h" + +#include <cstddef> +#include <cstdint> +#include <memory> +#include <span> +#include <utility> + +#include "src/dawn/common/Constants.h" +#include "src/dawn/common/Math.h" +#include "src/dawn/common/Ref.h" +#include "src/dawn/common/SystemHandle.h" +#include "src/dawn/wire/InlineSharedMemoryManager.h" +#include "src/utils/span.h" + +namespace dawn::wire { + +namespace { + +class SharedMemoryWin : public SharedMemory { + public: + SharedMemoryWin(SystemHandle handle, std::span<std::byte> data) + : SharedMemory(std::move(handle), data) {} + + ~SharedMemoryWin() override { + std::span<std::byte> data = GetMappedSpan(); + if (data.data() != nullptr) { + UnmapViewOfFile(data.data()); + } + } +}; + +class InlineSharedMemoryManagerImpl_Win : public InlineSharedMemoryManager { + public: + Ref<SharedMemory> CreateSharedMemory(size_t size) override { + const uint64_t alignedSize = Align(static_cast<uint64_t>(size), + kD3D12SharedBufferMemoryFileMappingHandleSizeAlignment); + HANDLE rawHandle = CreateFileMappingW( + INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, static_cast<DWORD>(alignedSize >> 32), + static_cast<DWORD>(alignedSize & 0xFFFFFFFF), nullptr); + if (rawHandle == nullptr) { + return nullptr; + } + SystemHandle handle = SystemHandle::Acquire(rawHandle); + + void* pointer = MapViewOfFile(rawHandle, FILE_MAP_ALL_ACCESS, 0, 0, size); + if (pointer == nullptr) { + return nullptr; + } + + // SAFETY: the pointer returned by a successful MapViewOfFile points to at least `size` + // valid bytes. + auto data = DAWN_UNSAFE_BUFFERS(Span<std::byte>{static_cast<std::byte*>(pointer), size}); + return AcquireRef(new SharedMemoryWin(std::move(handle), data)); + } +}; + +} // namespace + +std::shared_ptr<InlineSharedMemoryManager> CreateInlineSharedMemoryManager() { + return std::make_shared<InlineSharedMemoryManagerImpl_Win>(); +} + +} // namespace dawn::wire