From 6d9b3229587fb99365ebd6eba730877cca48a1ec Mon Sep 17 00:00:00 2001 From: Loko Kung Date: Wed, 20 Apr 2022 23:56:25 +0000 Subject: [PATCH] Adds new BlobCache "re-declaration" of PersistentCache. - Note: goal is to merge the two into the same class, but to avoid breaking/fixing the current D3D12 shader caching, introducing a new one, and will merge the old one later on. - Adds instance of BlobCache to the Instance, and passthrough for the Device to get to it. (We want the cache to be at the Instance so that eventually different devices can still use the cache (assuming same isolation key)). Bug: dawn:549 Change-Id: Ib7c82a439f32b306f0cccd3db424fb0e427a90a1 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/86400 Reviewed-by: Austin Eng Kokoro: Kokoro Commit-Queue: Loko Kung --- src/dawn/native/BUILD.gn | 2 + src/dawn/native/BlobCache.cpp | 93 ++++++++++++++++++++++++++++++++++ src/dawn/native/BlobCache.h | 80 +++++++++++++++++++++++++++++ src/dawn/native/CMakeLists.txt | 2 + src/dawn/native/Device.cpp | 5 ++ src/dawn/native/Device.h | 8 +-- src/dawn/native/Instance.cpp | 24 ++++++++- src/dawn/native/Instance.h | 5 ++ 8 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 src/dawn/native/BlobCache.cpp create mode 100644 src/dawn/native/BlobCache.h diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn index 7fa3fb417a..a82dc546bd 100644 --- a/src/dawn/native/BUILD.gn +++ b/src/dawn/native/BUILD.gn @@ -202,6 +202,8 @@ source_set("sources") { "BindGroupTracker.h", "BindingInfo.cpp", "BindingInfo.h", + "BlobCache.cpp", + "BlobCache.h", "BuddyAllocator.cpp", "BuddyAllocator.h", "BuddyMemoryAllocator.cpp", diff --git a/src/dawn/native/BlobCache.cpp b/src/dawn/native/BlobCache.cpp new file mode 100644 index 0000000000..c566695ecc --- /dev/null +++ b/src/dawn/native/BlobCache.cpp @@ -0,0 +1,93 @@ +// Copyright 2022 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 "dawn/native/BlobCache.h" + +#include "dawn/common/Assert.h" +#include "dawn/native/CacheKey.h" +#include "dawn/native/Instance.h" +#include "dawn/platform/DawnPlatform.h" + +namespace dawn::native { + + CachedBlob::CachedBlob(size_t size) { + if (size != 0) { + Reset(size); + } + } + + bool CachedBlob::Empty() const { + return mSize == 0; + } + + const uint8_t* CachedBlob::Data() const { + return mData.get(); + } + + uint8_t* CachedBlob::Data() { + return mData.get(); + } + + size_t CachedBlob::Size() const { + return mSize; + } + + void CachedBlob::Reset(size_t size) { + mSize = size; + mData = std::make_unique(size); + } + + BlobCache::BlobCache(dawn::platform::CachingInterface* cachingInterface) + : mCache(cachingInterface) { + } + + CachedBlob BlobCache::Load(const CacheKey& key) { + std::lock_guard lock(mMutex); + return LoadInternal(key); + } + + void BlobCache::Store(const CacheKey& key, size_t valueSize, const void* value) { + std::lock_guard lock(mMutex); + StoreInternal(key, valueSize, value); + } + + void BlobCache::Store(const CacheKey& key, const CachedBlob& value) { + Store(key, value.Size(), value.Data()); + } + + CachedBlob BlobCache::LoadInternal(const CacheKey& key) { + CachedBlob result; + if (mCache == nullptr) { + return result; + } + const size_t expectedSize = mCache->LoadData(nullptr, key.data(), key.size(), nullptr, 0); + if (expectedSize > 0) { + result.Reset(expectedSize); + const size_t actualSize = + mCache->LoadData(nullptr, key.data(), key.size(), result.Data(), expectedSize); + ASSERT(expectedSize == actualSize); + } + return result; + } + + void BlobCache::StoreInternal(const CacheKey& key, size_t valueSize, const void* value) { + ASSERT(value != nullptr); + ASSERT(valueSize > 0); + if (mCache == nullptr) { + return; + } + mCache->StoreData(nullptr, key.data(), key.size(), value, valueSize); + } + +} // namespace dawn::native diff --git a/src/dawn/native/BlobCache.h b/src/dawn/native/BlobCache.h new file mode 100644 index 0000000000..2e31261caf --- /dev/null +++ b/src/dawn/native/BlobCache.h @@ -0,0 +1,80 @@ +// Copyright 2022 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. + +#ifndef SRC_DAWN_NATIVE_BLOBCACHE_H_ +#define SRC_DAWN_NATIVE_BLOBCACHE_H_ + +#include +#include + +namespace dawn::platform { + class CachingInterface; +} + +namespace dawn::native { + + class BlobCache; + class CacheKey; + class InstanceBase; + + class CachedBlob { + public: + explicit CachedBlob(size_t size = 0); + + bool Empty() const; + const uint8_t* Data() const; + uint8_t* Data(); + size_t Size() const; + void Reset(size_t size); + + private: + std::unique_ptr mData = nullptr; + size_t mSize = 0; + }; + + // This class should always be thread-safe because it may be called asynchronously. Its purpose + // is to wrap the CachingInterface provided via a platform. + // TODO(dawn:549): This is a "re-declaration" of the current PersistentCache since there are + // some dependencies on that one for the semi-implemented D3D12 shader cache and some changes + // introduced here are breaking. Eventually the goal is to unify the two, but for development + // purposes, we are splitting these for now and will re-merge them in a later change. + class BlobCache { + public: + explicit BlobCache(dawn::platform::CachingInterface* cachingInterface = nullptr); + + // Returns empty blob if the key is not found in the cache. + CachedBlob Load(const CacheKey& key); + + // Value to store must be non-empty/non-null. + void Store(const CacheKey& key, size_t valueSize, const void* value); + void Store(const CacheKey& key, const CachedBlob& value); + + private: + // Non-thread safe internal implementations of load and store. Exposed callers that use + // these helpers need to make sure that these are entered with `mMutex` held. + CachedBlob LoadInternal(const CacheKey& key); + void StoreInternal(const CacheKey& key, size_t valueSize, const void* value); + + // Protects thread safety of access to mCache. + std::mutex mMutex; + + // TODO(dawn:549): Current CachingInterface declaration requires passing a device to each + // call, but this might be unnecessary. This class just passes nullptr for those calls + // right now. Eventually we can just change the interface to be more generic. + dawn::platform::CachingInterface* mCache; + }; + +} // namespace dawn::native + +#endif // SRC_DAWN_NATIVE_BLOBCACHE_H_ diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt index edeff36399..3ef0fa01d0 100644 --- a/src/dawn/native/CMakeLists.txt +++ b/src/dawn/native/CMakeLists.txt @@ -45,6 +45,8 @@ target_sources(dawn_native PRIVATE "BindGroupTracker.h" "BindingInfo.cpp" "BindingInfo.h" + "BlobCache.cpp" + "BlobCache.h" "BuddyAllocator.cpp" "BuddyAllocator.h" "BuddyMemoryAllocator.cpp" diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp index 947d078a75..f48efc6a05 100644 --- a/src/dawn/native/Device.cpp +++ b/src/dawn/native/Device.cpp @@ -25,6 +25,7 @@ #include "dawn/native/AttachmentState.h" #include "dawn/native/BindGroup.h" #include "dawn/native/BindGroupLayout.h" +#include "dawn/native/BlobCache.h" #include "dawn/native/Buffer.h" #include "dawn/native/ChainUtils_autogen.h" #include "dawn/native/CommandBuffer.h" @@ -578,6 +579,10 @@ namespace dawn::native { return mPersistentCache.get(); } + BlobCache* DeviceBase::GetBlobCache() { + return mInstance->GetBlobCache(); + } + MaybeError DeviceBase::ValidateObject(const ApiObjectBase* object) const { ASSERT(object != nullptr); DAWN_INVALID_IF(object->GetDevice() != this, diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h index 604961f90a..6bfb5ff8f5 100644 --- a/src/dawn/native/Device.h +++ b/src/dawn/native/Device.h @@ -42,18 +42,15 @@ namespace dawn::platform { } // namespace dawn::platform namespace dawn::native { - class AdapterBase; class AsyncTaskManager; class AttachmentState; class AttachmentStateBlueprint; - class BindGroupLayoutBase; + class BlobCache; class CallbackTaskManager; class DynamicUploader; class ErrorScopeStack; - class ExternalTextureBase; class OwnedCompilationMessages; class PersistentCache; - class StagingBufferBase; struct CallbackTask; struct InternalPipelineStore; struct ShaderModuleParseResult; @@ -279,7 +276,9 @@ namespace dawn::native { MaybeError ValidateIsAlive() const; + // TODO(dawn:549): Deprecate PersistentCache, once it's usage in D3D12 shaders is removed. PersistentCache* GetPersistentCache(); + BlobCache* GetBlobCache(); virtual ResultOrError> CreateStagingBuffer( size_t size) = 0; @@ -546,6 +545,7 @@ namespace dawn::native { std::unique_ptr mInternalPipelineStore; + // TODO(dawn:549): Deprecate PersistentCache, once it's usage in D3D12 shaders is removed. std::unique_ptr mPersistentCache; std::unique_ptr mCallbackTaskManager; diff --git a/src/dawn/native/Instance.cpp b/src/dawn/native/Instance.cpp index fba8c2b50d..3a27b1bbf0 100644 --- a/src/dawn/native/Instance.cpp +++ b/src/dawn/native/Instance.cpp @@ -93,6 +93,14 @@ namespace dawn::native { return enabledBackends; } + dawn::platform::CachingInterface* GetCachingInterface(dawn::platform::Platform* platform) { + if (platform != nullptr) { + return platform->GetCachingInterface(/*fingerprint*/ nullptr, + /*fingerprintSize*/ 0); + } + return nullptr; + } + } // anonymous namespace InstanceBase* APICreateInstance(const InstanceDescriptor* descriptor) { @@ -133,6 +141,11 @@ namespace dawn::native { mRuntimeSearchPaths.push_back(std::move(*p)); } mRuntimeSearchPaths.push_back(""); + + // Initialize the platform to the default for now. + mDefaultPlatform = std::make_unique(); + SetPlatform(mDefaultPlatform.get()); + return {}; } @@ -401,7 +414,12 @@ namespace dawn::native { } void InstanceBase::SetPlatform(dawn::platform::Platform* platform) { - mPlatform = platform; + if (platform == nullptr) { + mPlatform = mDefaultPlatform.get(); + } else { + mPlatform = platform; + } + mBlobCache = std::make_unique(GetCachingInterface(platform)); } dawn::platform::Platform* InstanceBase::GetPlatform() { @@ -415,6 +433,10 @@ namespace dawn::native { return mDefaultPlatform.get(); } + BlobCache* InstanceBase::GetBlobCache() { + return mBlobCache.get(); + } + const std::vector& InstanceBase::GetRuntimeSearchPaths() const { return mRuntimeSearchPaths; } diff --git a/src/dawn/native/Instance.h b/src/dawn/native/Instance.h index 82d7bacbe0..13aa74e8fc 100644 --- a/src/dawn/native/Instance.h +++ b/src/dawn/native/Instance.h @@ -25,6 +25,7 @@ #include "dawn/common/ityp_bitset.h" #include "dawn/native/Adapter.h" #include "dawn/native/BackendConnection.h" +#include "dawn/native/BlobCache.h" #include "dawn/native/Features.h" #include "dawn/native/Toggles.h" #include "dawn/native/dawn_platform.h" @@ -76,8 +77,11 @@ namespace dawn::native { void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup); bool IsBeginCaptureOnStartupEnabled() const; + // TODO(dawn:1374): SetPlatform should become a private helper, and a NOT thread-safe + // testing version exposed for special testing cases. void SetPlatform(dawn::platform::Platform* platform); dawn::platform::Platform* GetPlatform(); + BlobCache* GetBlobCache(); const std::vector& GetRuntimeSearchPaths() const; @@ -115,6 +119,7 @@ namespace dawn::native { dawn::platform::Platform* mPlatform = nullptr; std::unique_ptr mDefaultPlatform; + std::unique_ptr mBlobCache; std::vector> mBackends; std::vector> mAdapters;