Pipeline caching: refactor object hashing
Dawn's object-based cache creates keys from memory addresses. These keys cannot be used in a persistent cache. This change modifies the keys to only use hashes so they can be re-used for caching pipelines. BUG=dawn:549 Change-Id: Ica64d58ae6a3c6266435cfc3f776c820190f7895 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/30740 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Bryan Bernhart <bryan.bernhart@intel.com>
This commit is contained in:
parent
fe129405cf
commit
24bf7a4fbb
|
@ -15,8 +15,8 @@
|
|||
#include "dawn_native/AttachmentState.h"
|
||||
|
||||
#include "common/BitSetIterator.h"
|
||||
#include "common/HashUtils.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/ObjectContentHasher.h"
|
||||
#include "dawn_native/Texture.h"
|
||||
|
||||
namespace dawn_native {
|
||||
|
@ -130,6 +130,11 @@ namespace dawn_native {
|
|||
GetDevice()->UncacheAttachmentState(this);
|
||||
}
|
||||
|
||||
size_t AttachmentState::ComputeContentHash() {
|
||||
// TODO(dawn:549): skip this traversal and reuse the blueprint.
|
||||
return AttachmentStateBlueprint::HashFunc()(this);
|
||||
}
|
||||
|
||||
ityp::bitset<ColorAttachmentIndex, kMaxColorAttachments>
|
||||
AttachmentState::GetColorAttachmentsMask() const {
|
||||
return mColorAttachmentsSet;
|
||||
|
|
|
@ -69,6 +69,8 @@ namespace dawn_native {
|
|||
wgpu::TextureFormat GetDepthStencilFormat() const;
|
||||
uint32_t GetSampleCount() const;
|
||||
|
||||
size_t ComputeContentHash() override;
|
||||
|
||||
private:
|
||||
~AttachmentState() override;
|
||||
};
|
||||
|
|
|
@ -218,6 +218,8 @@ source_set("dawn_native_sources") {
|
|||
"InternalPipelineStore.h",
|
||||
"ObjectBase.cpp",
|
||||
"ObjectBase.h",
|
||||
"ObjectContentHasher.cpp",
|
||||
"ObjectContentHasher.h",
|
||||
"PassResourceUsage.h",
|
||||
"PassResourceUsageTracker.cpp",
|
||||
"PassResourceUsageTracker.h",
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
#include "dawn_native/BindGroupLayout.h"
|
||||
|
||||
#include "common/BitSetIterator.h"
|
||||
#include "common/HashUtils.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/ObjectContentHasher.h"
|
||||
#include "dawn_native/PerStage.h"
|
||||
#include "dawn_native/ValidationUtils_autogen.h"
|
||||
|
||||
|
@ -152,11 +152,6 @@ namespace dawn_native {
|
|||
|
||||
namespace {
|
||||
|
||||
void HashCombineBindingInfo(size_t* hash, const BindingInfo& info) {
|
||||
HashCombine(hash, info.hasDynamicOffset, info.visibility, info.type,
|
||||
info.textureComponentType, info.viewDimension, info.storageTextureFormat,
|
||||
info.minBufferBindingSize);
|
||||
}
|
||||
|
||||
bool operator!=(const BindingInfo& a, const BindingInfo& b) {
|
||||
return a.hasDynamicOffset != b.hasDynamicOffset || //
|
||||
|
@ -319,15 +314,20 @@ namespace dawn_native {
|
|||
return it->second;
|
||||
}
|
||||
|
||||
size_t BindGroupLayoutBase::HashFunc::operator()(const BindGroupLayoutBase* bgl) const {
|
||||
size_t hash = 0;
|
||||
size_t BindGroupLayoutBase::ComputeContentHash() {
|
||||
ObjectContentHasher recorder;
|
||||
// std::map is sorted by key, so two BGLs constructed in different orders
|
||||
// will still hash the same.
|
||||
for (const auto& it : bgl->mBindingMap) {
|
||||
HashCombine(&hash, it.first, it.second);
|
||||
HashCombineBindingInfo(&hash, bgl->mBindingInfo[it.second]);
|
||||
// will still record the same.
|
||||
for (const auto& it : mBindingMap) {
|
||||
recorder.Record(it.first, it.second);
|
||||
|
||||
const BindingInfo& info = mBindingInfo[it.second];
|
||||
recorder.Record(info.hasDynamicOffset, info.visibility, info.type,
|
||||
info.textureComponentType, info.viewDimension,
|
||||
info.storageTextureFormat, info.minBufferBindingSize);
|
||||
}
|
||||
return hash;
|
||||
|
||||
return recorder.GetContentHash();
|
||||
}
|
||||
|
||||
bool BindGroupLayoutBase::EqualityFunc::operator()(const BindGroupLayoutBase* a,
|
||||
|
|
|
@ -56,10 +56,9 @@ namespace dawn_native {
|
|||
const BindingMap& GetBindingMap() const;
|
||||
BindingIndex GetBindingIndex(BindingNumber bindingNumber) const;
|
||||
|
||||
// Functors necessary for the unordered_set<BGLBase*>-based cache.
|
||||
struct HashFunc {
|
||||
size_t operator()(const BindGroupLayoutBase* bgl) const;
|
||||
};
|
||||
// Functions necessary for the unordered_set<BGLBase*>-based cache.
|
||||
size_t ComputeContentHash() override;
|
||||
|
||||
struct EqualityFunc {
|
||||
bool operator()(const BindGroupLayoutBase* a, const BindGroupLayoutBase* b) const;
|
||||
};
|
||||
|
|
|
@ -94,6 +94,8 @@ target_sources(dawn_native PRIVATE
|
|||
"ErrorScopeTracker.h"
|
||||
"Extensions.cpp"
|
||||
"Extensions.h"
|
||||
"ObjectContentHasher.cpp"
|
||||
"ObjectContentHasher.h"
|
||||
"Fence.cpp"
|
||||
"Fence.h"
|
||||
"Format.cpp"
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "dawn_native/CachedObject.h"
|
||||
|
||||
#include "common/Assert.h"
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
bool CachedObject::IsCachedReference() const {
|
||||
|
@ -24,4 +26,19 @@ namespace dawn_native {
|
|||
mIsCachedReference = true;
|
||||
}
|
||||
|
||||
size_t CachedObject::HashFunc::operator()(const CachedObject* obj) const {
|
||||
return obj->GetContentHash();
|
||||
}
|
||||
|
||||
size_t CachedObject::GetContentHash() const {
|
||||
ASSERT(mIsContentHashInitialized);
|
||||
return mContentHash;
|
||||
}
|
||||
|
||||
void CachedObject::SetContentHash(size_t contentHash) {
|
||||
ASSERT(!mIsContentHashInitialized);
|
||||
mContentHash = contentHash;
|
||||
mIsContentHashInitialized = true;
|
||||
}
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -29,11 +29,25 @@ namespace dawn_native {
|
|||
|
||||
bool IsCachedReference() const;
|
||||
|
||||
// Functor necessary for the unordered_set<CachedObject*>-based cache.
|
||||
struct HashFunc {
|
||||
size_t operator()(const CachedObject* obj) const;
|
||||
};
|
||||
|
||||
size_t GetContentHash() const;
|
||||
void SetContentHash(size_t contentHash);
|
||||
|
||||
private:
|
||||
friend class DeviceBase;
|
||||
void SetIsCachedReference();
|
||||
|
||||
bool mIsCachedReference = false;
|
||||
|
||||
// Called by ObjectContentHasher upon creation to record the object.
|
||||
virtual size_t ComputeContentHash() = 0;
|
||||
|
||||
size_t mContentHash = 0;
|
||||
bool mIsContentHashInitialized = false;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
#include "dawn_native/ComputePipeline.h"
|
||||
|
||||
#include "common/HashUtils.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/ObjectContentHasher.h"
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
|
@ -59,10 +59,6 @@ namespace dawn_native {
|
|||
return new ComputePipelineBase(device, ObjectBase::kError);
|
||||
}
|
||||
|
||||
size_t ComputePipelineBase::HashFunc::operator()(const ComputePipelineBase* pipeline) const {
|
||||
return PipelineBase::HashForCache(pipeline);
|
||||
}
|
||||
|
||||
bool ComputePipelineBase::EqualityFunc::operator()(const ComputePipelineBase* a,
|
||||
const ComputePipelineBase* b) const {
|
||||
return PipelineBase::EqualForCache(a, b);
|
||||
|
|
|
@ -35,9 +35,6 @@ namespace dawn_native {
|
|||
const EntryPointMetadata& GetMetadata() const;
|
||||
|
||||
// Functors necessary for the unordered_set<ComputePipelineBase*>-based cache.
|
||||
struct HashFunc {
|
||||
size_t operator()(const ComputePipelineBase* pipeline) const;
|
||||
};
|
||||
struct EqualityFunc {
|
||||
bool operator()(const ComputePipelineBase* a, const ComputePipelineBase* b) const;
|
||||
};
|
||||
|
|
|
@ -437,6 +437,9 @@ namespace dawn_native {
|
|||
const BindGroupLayoutDescriptor* descriptor) {
|
||||
BindGroupLayoutBase blueprint(this, descriptor);
|
||||
|
||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||
blueprint.SetContentHash(blueprintHash);
|
||||
|
||||
Ref<BindGroupLayoutBase> result = nullptr;
|
||||
auto iter = mCaches->bindGroupLayouts.find(&blueprint);
|
||||
if (iter != mCaches->bindGroupLayouts.end()) {
|
||||
|
@ -445,6 +448,7 @@ namespace dawn_native {
|
|||
BindGroupLayoutBase* backendObj;
|
||||
DAWN_TRY_ASSIGN(backendObj, CreateBindGroupLayoutImpl(descriptor));
|
||||
backendObj->SetIsCachedReference();
|
||||
backendObj->SetContentHash(blueprintHash);
|
||||
mCaches->bindGroupLayouts.insert(backendObj);
|
||||
result = AcquireRef(backendObj);
|
||||
}
|
||||
|
@ -475,6 +479,9 @@ namespace dawn_native {
|
|||
const ComputePipelineDescriptor* descriptor) {
|
||||
ComputePipelineBase blueprint(this, descriptor);
|
||||
|
||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||
blueprint.SetContentHash(blueprintHash);
|
||||
|
||||
auto iter = mCaches->computePipelines.find(&blueprint);
|
||||
if (iter != mCaches->computePipelines.end()) {
|
||||
(*iter)->Reference();
|
||||
|
@ -484,6 +491,7 @@ namespace dawn_native {
|
|||
ComputePipelineBase* backendObj;
|
||||
DAWN_TRY_ASSIGN(backendObj, CreateComputePipelineImpl(descriptor));
|
||||
backendObj->SetIsCachedReference();
|
||||
backendObj->SetContentHash(blueprintHash);
|
||||
mCaches->computePipelines.insert(backendObj);
|
||||
return backendObj;
|
||||
}
|
||||
|
@ -498,6 +506,9 @@ namespace dawn_native {
|
|||
const PipelineLayoutDescriptor* descriptor) {
|
||||
PipelineLayoutBase blueprint(this, descriptor);
|
||||
|
||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||
blueprint.SetContentHash(blueprintHash);
|
||||
|
||||
auto iter = mCaches->pipelineLayouts.find(&blueprint);
|
||||
if (iter != mCaches->pipelineLayouts.end()) {
|
||||
(*iter)->Reference();
|
||||
|
@ -507,6 +518,7 @@ namespace dawn_native {
|
|||
PipelineLayoutBase* backendObj;
|
||||
DAWN_TRY_ASSIGN(backendObj, CreatePipelineLayoutImpl(descriptor));
|
||||
backendObj->SetIsCachedReference();
|
||||
backendObj->SetContentHash(blueprintHash);
|
||||
mCaches->pipelineLayouts.insert(backendObj);
|
||||
return backendObj;
|
||||
}
|
||||
|
@ -521,6 +533,9 @@ namespace dawn_native {
|
|||
const RenderPipelineDescriptor* descriptor) {
|
||||
RenderPipelineBase blueprint(this, descriptor);
|
||||
|
||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||
blueprint.SetContentHash(blueprintHash);
|
||||
|
||||
auto iter = mCaches->renderPipelines.find(&blueprint);
|
||||
if (iter != mCaches->renderPipelines.end()) {
|
||||
(*iter)->Reference();
|
||||
|
@ -530,6 +545,7 @@ namespace dawn_native {
|
|||
RenderPipelineBase* backendObj;
|
||||
DAWN_TRY_ASSIGN(backendObj, CreateRenderPipelineImpl(descriptor));
|
||||
backendObj->SetIsCachedReference();
|
||||
backendObj->SetContentHash(blueprintHash);
|
||||
mCaches->renderPipelines.insert(backendObj);
|
||||
return backendObj;
|
||||
}
|
||||
|
@ -544,6 +560,9 @@ namespace dawn_native {
|
|||
const SamplerDescriptor* descriptor) {
|
||||
SamplerBase blueprint(this, descriptor);
|
||||
|
||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||
blueprint.SetContentHash(blueprintHash);
|
||||
|
||||
auto iter = mCaches->samplers.find(&blueprint);
|
||||
if (iter != mCaches->samplers.end()) {
|
||||
(*iter)->Reference();
|
||||
|
@ -553,6 +572,7 @@ namespace dawn_native {
|
|||
SamplerBase* backendObj;
|
||||
DAWN_TRY_ASSIGN(backendObj, CreateSamplerImpl(descriptor));
|
||||
backendObj->SetIsCachedReference();
|
||||
backendObj->SetContentHash(blueprintHash);
|
||||
mCaches->samplers.insert(backendObj);
|
||||
return backendObj;
|
||||
}
|
||||
|
@ -567,6 +587,9 @@ namespace dawn_native {
|
|||
const ShaderModuleDescriptor* descriptor) {
|
||||
ShaderModuleBase blueprint(this, descriptor);
|
||||
|
||||
const size_t blueprintHash = blueprint.ComputeContentHash();
|
||||
blueprint.SetContentHash(blueprintHash);
|
||||
|
||||
auto iter = mCaches->shaderModules.find(&blueprint);
|
||||
if (iter != mCaches->shaderModules.end()) {
|
||||
(*iter)->Reference();
|
||||
|
@ -576,6 +599,7 @@ namespace dawn_native {
|
|||
ShaderModuleBase* backendObj;
|
||||
DAWN_TRY_ASSIGN(backendObj, CreateShaderModuleImpl(descriptor));
|
||||
backendObj->SetIsCachedReference();
|
||||
backendObj->SetContentHash(blueprintHash);
|
||||
mCaches->shaderModules.insert(backendObj);
|
||||
return backendObj;
|
||||
}
|
||||
|
@ -595,6 +619,7 @@ namespace dawn_native {
|
|||
|
||||
Ref<AttachmentState> attachmentState = AcquireRef(new AttachmentState(this, *blueprint));
|
||||
attachmentState->SetIsCachedReference();
|
||||
attachmentState->SetContentHash(attachmentState->ComputeContentHash());
|
||||
mCaches->attachmentStates.insert(attachmentState.Get());
|
||||
return attachmentState;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2020 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/ObjectContentHasher.h"
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
size_t ObjectContentHasher::GetContentHash() const {
|
||||
return mContentHash;
|
||||
}
|
||||
} // namespace dawn_native
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2020 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 DAWNNATIVE_OBJECT_CONTENT_HASHER_H_
|
||||
#define DAWNNATIVE_OBJECT_CONTENT_HASHER_H_
|
||||
|
||||
#include "common/HashUtils.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
// ObjectContentHasher records a hash that can be used as a key to lookup a cached object in a
|
||||
// cache.
|
||||
class ObjectContentHasher {
|
||||
public:
|
||||
// Record calls the appropriate record function based on the type.
|
||||
template <typename T, typename... Args>
|
||||
void Record(const T& value, const Args&... args) {
|
||||
RecordImpl<T, Args...>::Call(this, value, args...);
|
||||
}
|
||||
|
||||
size_t GetContentHash() const;
|
||||
|
||||
private:
|
||||
template <typename T, typename... Args>
|
||||
struct RecordImpl {
|
||||
static constexpr void Call(ObjectContentHasher* recorder,
|
||||
const T& value,
|
||||
const Args&... args) {
|
||||
HashCombine(&recorder->mContentHash, value, args...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RecordImpl<T*> {
|
||||
static constexpr void Call(ObjectContentHasher* recorder, T* obj) {
|
||||
// Calling Record(objPtr) is not allowed. This check exists to only prevent such
|
||||
// mistakes.
|
||||
static_assert(obj == nullptr, "");
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct RecordImpl<std::string> {
|
||||
static constexpr void Call(ObjectContentHasher* recorder, const std::string& str) {
|
||||
recorder->RecordIterable<std::string>(str);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RecordImpl<std::vector<T>> {
|
||||
static constexpr void Call(ObjectContentHasher* recorder, const std::vector<T>& vec) {
|
||||
recorder->RecordIterable<std::vector<T>>(vec);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename IteratorT>
|
||||
void RecordIterable(const IteratorT& iterable) {
|
||||
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
||||
Record(*it);
|
||||
}
|
||||
}
|
||||
|
||||
size_t mContentHash = 0;
|
||||
};
|
||||
} // namespace dawn_native
|
||||
|
||||
#endif // DAWNNATIVE_OBJECT_CONTENT_HASHER_H_
|
|
@ -14,9 +14,9 @@
|
|||
|
||||
#include "dawn_native/Pipeline.h"
|
||||
|
||||
#include "common/HashUtils.h"
|
||||
#include "dawn_native/BindGroupLayout.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/ObjectContentHasher.h"
|
||||
#include "dawn_native/PipelineLayout.h"
|
||||
#include "dawn_native/ShaderModule.h"
|
||||
|
||||
|
@ -142,21 +142,17 @@ namespace dawn_native {
|
|||
return bgl;
|
||||
}
|
||||
|
||||
// static
|
||||
size_t PipelineBase::HashForCache(const PipelineBase* pipeline) {
|
||||
size_t hash = 0;
|
||||
size_t PipelineBase::ComputeContentHash() {
|
||||
ObjectContentHasher recorder;
|
||||
recorder.Record(mLayout->GetContentHash());
|
||||
|
||||
// The layout is deduplicated so it can be hashed by pointer.
|
||||
HashCombine(&hash, pipeline->mLayout.Get());
|
||||
|
||||
HashCombine(&hash, pipeline->mStageMask);
|
||||
for (SingleShaderStage stage : IterateStages(pipeline->mStageMask)) {
|
||||
// The module is deduplicated so it can be hashed by pointer.
|
||||
HashCombine(&hash, pipeline->mStages[stage].module.Get());
|
||||
HashCombine(&hash, pipeline->mStages[stage].entryPoint);
|
||||
recorder.Record(mStageMask);
|
||||
for (SingleShaderStage stage : IterateStages(mStageMask)) {
|
||||
recorder.Record(mStages[stage].module->GetContentHash());
|
||||
recorder.Record(mStages[stage].entryPoint);
|
||||
}
|
||||
|
||||
return hash;
|
||||
return recorder.GetContentHash();
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -51,8 +51,8 @@ namespace dawn_native {
|
|||
|
||||
BindGroupLayoutBase* GetBindGroupLayout(uint32_t groupIndex);
|
||||
|
||||
// Helper function for the functors for std::unordered_map-based pipeline caches.
|
||||
static size_t HashForCache(const PipelineBase* pipeline);
|
||||
// Helper functions for std::unordered_map-based pipeline caches.
|
||||
size_t ComputeContentHash() override;
|
||||
static bool EqualForCache(const PipelineBase* a, const PipelineBase* b);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
|
||||
#include "common/Assert.h"
|
||||
#include "common/BitSetIterator.h"
|
||||
#include "common/HashUtils.h"
|
||||
#include "common/ityp_stack_vec.h"
|
||||
#include "dawn_native/BindGroupLayout.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/ObjectContentHasher.h"
|
||||
#include "dawn_native/ShaderModule.h"
|
||||
|
||||
namespace dawn_native {
|
||||
|
@ -253,14 +253,15 @@ namespace dawn_native {
|
|||
return kMaxBindGroupsTyped;
|
||||
}
|
||||
|
||||
size_t PipelineLayoutBase::HashFunc::operator()(const PipelineLayoutBase* pl) const {
|
||||
size_t hash = Hash(pl->mMask);
|
||||
size_t PipelineLayoutBase::ComputeContentHash() {
|
||||
ObjectContentHasher recorder;
|
||||
recorder.Record(mMask);
|
||||
|
||||
for (BindGroupIndex group : IterateBitSet(pl->mMask)) {
|
||||
HashCombine(&hash, pl->GetBindGroupLayout(group));
|
||||
for (BindGroupIndex group : IterateBitSet(mMask)) {
|
||||
recorder.Record(GetBindGroupLayout(group)->GetContentHash());
|
||||
}
|
||||
|
||||
return hash;
|
||||
return recorder.GetContentHash();
|
||||
}
|
||||
|
||||
bool PipelineLayoutBase::EqualityFunc::operator()(const PipelineLayoutBase* a,
|
||||
|
|
|
@ -61,10 +61,9 @@ namespace dawn_native {
|
|||
// [0, kMaxBindGroups]
|
||||
BindGroupIndex GroupsInheritUpTo(const PipelineLayoutBase* other) const;
|
||||
|
||||
// Functors necessary for the unordered_set<PipelineLayoutBase*>-based cache.
|
||||
struct HashFunc {
|
||||
size_t operator()(const PipelineLayoutBase* pl) const;
|
||||
};
|
||||
// Functions necessary for the unordered_set<PipelineLayoutBase*>-based cache.
|
||||
size_t ComputeContentHash() override;
|
||||
|
||||
struct EqualityFunc {
|
||||
bool operator()(const PipelineLayoutBase* a, const PipelineLayoutBase* b) const;
|
||||
};
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#include "dawn_native/RenderPipeline.h"
|
||||
|
||||
#include "common/BitSetIterator.h"
|
||||
#include "common/HashUtils.h"
|
||||
#include "dawn_native/Commands.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/ObjectContentHasher.h"
|
||||
#include "dawn_native/ValidationUtils_autogen.h"
|
||||
|
||||
#include <cmath>
|
||||
|
@ -607,63 +607,62 @@ namespace dawn_native {
|
|||
return mAttachmentState.Get();
|
||||
}
|
||||
|
||||
size_t RenderPipelineBase::HashFunc::operator()(const RenderPipelineBase* pipeline) const {
|
||||
// Hash modules and layout
|
||||
size_t hash = PipelineBase::HashForCache(pipeline);
|
||||
size_t RenderPipelineBase::ComputeContentHash() {
|
||||
ObjectContentHasher recorder;
|
||||
|
||||
// Hierarchically hash the attachment state.
|
||||
// Record modules and layout
|
||||
recorder.Record(PipelineBase::ComputeContentHash());
|
||||
|
||||
// Hierarchically record the attachment state.
|
||||
// It contains the attachments set, texture formats, and sample count.
|
||||
HashCombine(&hash, pipeline->mAttachmentState.Get());
|
||||
recorder.Record(mAttachmentState->GetContentHash());
|
||||
|
||||
// Hash attachments
|
||||
for (ColorAttachmentIndex i :
|
||||
IterateBitSet(pipeline->mAttachmentState->GetColorAttachmentsMask())) {
|
||||
const ColorStateDescriptor& desc = *pipeline->GetColorStateDescriptor(i);
|
||||
HashCombine(&hash, desc.writeMask);
|
||||
HashCombine(&hash, desc.colorBlend.operation, desc.colorBlend.srcFactor,
|
||||
desc.colorBlend.dstFactor);
|
||||
HashCombine(&hash, desc.alphaBlend.operation, desc.alphaBlend.srcFactor,
|
||||
desc.alphaBlend.dstFactor);
|
||||
// Record attachments
|
||||
for (ColorAttachmentIndex i : IterateBitSet(mAttachmentState->GetColorAttachmentsMask())) {
|
||||
const ColorStateDescriptor& desc = *GetColorStateDescriptor(i);
|
||||
recorder.Record(desc.writeMask);
|
||||
recorder.Record(desc.colorBlend.operation, desc.colorBlend.srcFactor,
|
||||
desc.colorBlend.dstFactor);
|
||||
recorder.Record(desc.alphaBlend.operation, desc.alphaBlend.srcFactor,
|
||||
desc.alphaBlend.dstFactor);
|
||||
}
|
||||
|
||||
if (pipeline->mAttachmentState->HasDepthStencilAttachment()) {
|
||||
const DepthStencilStateDescriptor& desc = pipeline->mDepthStencilState;
|
||||
HashCombine(&hash, desc.depthWriteEnabled, desc.depthCompare);
|
||||
HashCombine(&hash, desc.stencilReadMask, desc.stencilWriteMask);
|
||||
HashCombine(&hash, desc.stencilFront.compare, desc.stencilFront.failOp,
|
||||
desc.stencilFront.depthFailOp, desc.stencilFront.passOp);
|
||||
HashCombine(&hash, desc.stencilBack.compare, desc.stencilBack.failOp,
|
||||
desc.stencilBack.depthFailOp, desc.stencilBack.passOp);
|
||||
if (mAttachmentState->HasDepthStencilAttachment()) {
|
||||
const DepthStencilStateDescriptor& desc = mDepthStencilState;
|
||||
recorder.Record(desc.depthWriteEnabled, desc.depthCompare);
|
||||
recorder.Record(desc.stencilReadMask, desc.stencilWriteMask);
|
||||
recorder.Record(desc.stencilFront.compare, desc.stencilFront.failOp,
|
||||
desc.stencilFront.depthFailOp, desc.stencilFront.passOp);
|
||||
recorder.Record(desc.stencilBack.compare, desc.stencilBack.failOp,
|
||||
desc.stencilBack.depthFailOp, desc.stencilBack.passOp);
|
||||
}
|
||||
|
||||
// Hash vertex state
|
||||
HashCombine(&hash, pipeline->mAttributeLocationsUsed);
|
||||
for (VertexAttributeLocation location : IterateBitSet(pipeline->mAttributeLocationsUsed)) {
|
||||
const VertexAttributeInfo& desc = pipeline->GetAttribute(location);
|
||||
HashCombine(&hash, desc.shaderLocation, desc.vertexBufferSlot, desc.offset,
|
||||
desc.format);
|
||||
// Record vertex state
|
||||
recorder.Record(mAttributeLocationsUsed);
|
||||
for (VertexAttributeLocation location : IterateBitSet(mAttributeLocationsUsed)) {
|
||||
const VertexAttributeInfo& desc = GetAttribute(location);
|
||||
recorder.Record(desc.shaderLocation, desc.vertexBufferSlot, desc.offset, desc.format);
|
||||
}
|
||||
|
||||
HashCombine(&hash, pipeline->mVertexBufferSlotsUsed);
|
||||
for (VertexBufferSlot slot : IterateBitSet(pipeline->mVertexBufferSlotsUsed)) {
|
||||
const VertexBufferInfo& desc = pipeline->GetVertexBuffer(slot);
|
||||
HashCombine(&hash, desc.arrayStride, desc.stepMode);
|
||||
recorder.Record(mVertexBufferSlotsUsed);
|
||||
for (VertexBufferSlot slot : IterateBitSet(mVertexBufferSlotsUsed)) {
|
||||
const VertexBufferInfo& desc = GetVertexBuffer(slot);
|
||||
recorder.Record(desc.arrayStride, desc.stepMode);
|
||||
}
|
||||
|
||||
HashCombine(&hash, pipeline->mVertexState.indexFormat);
|
||||
recorder.Record(mVertexState.indexFormat);
|
||||
|
||||
// Hash rasterization state
|
||||
// Record rasterization state
|
||||
{
|
||||
const RasterizationStateDescriptor& desc = pipeline->mRasterizationState;
|
||||
HashCombine(&hash, desc.frontFace, desc.cullMode);
|
||||
HashCombine(&hash, desc.depthBias, desc.depthBiasSlopeScale, desc.depthBiasClamp);
|
||||
const RasterizationStateDescriptor& desc = mRasterizationState;
|
||||
recorder.Record(desc.frontFace, desc.cullMode);
|
||||
recorder.Record(desc.depthBias, desc.depthBiasSlopeScale, desc.depthBiasClamp);
|
||||
}
|
||||
|
||||
// Hash other state
|
||||
HashCombine(&hash, pipeline->mPrimitiveTopology, pipeline->mSampleMask,
|
||||
pipeline->mAlphaToCoverageEnabled);
|
||||
// Record other state
|
||||
recorder.Record(mPrimitiveTopology, mSampleMask, mAlphaToCoverageEnabled);
|
||||
|
||||
return hash;
|
||||
return recorder.GetContentHash();
|
||||
}
|
||||
|
||||
bool RenderPipelineBase::EqualityFunc::operator()(const RenderPipelineBase* a,
|
||||
|
|
|
@ -91,10 +91,9 @@ namespace dawn_native {
|
|||
|
||||
const AttachmentState* GetAttachmentState() const;
|
||||
|
||||
// Functors necessary for the unordered_set<RenderPipelineBase*>-based cache.
|
||||
struct HashFunc {
|
||||
size_t operator()(const RenderPipelineBase* pipeline) const;
|
||||
};
|
||||
// Functions necessary for the unordered_set<RenderPipelineBase*>-based cache.
|
||||
size_t ComputeContentHash() override;
|
||||
|
||||
struct EqualityFunc {
|
||||
bool operator()(const RenderPipelineBase* a, const RenderPipelineBase* b) const;
|
||||
};
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
#include "dawn_native/Sampler.h"
|
||||
|
||||
#include "common/HashUtils.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/ObjectContentHasher.h"
|
||||
#include "dawn_native/ValidationUtils_autogen.h"
|
||||
|
||||
#include <cmath>
|
||||
|
@ -84,20 +84,11 @@ namespace dawn_native {
|
|||
return mCompareFunction != wgpu::CompareFunction::Undefined;
|
||||
}
|
||||
|
||||
size_t SamplerBase::HashFunc::operator()(const SamplerBase* module) const {
|
||||
size_t hash = 0;
|
||||
|
||||
HashCombine(&hash, module->mAddressModeU);
|
||||
HashCombine(&hash, module->mAddressModeV);
|
||||
HashCombine(&hash, module->mAddressModeW);
|
||||
HashCombine(&hash, module->mMagFilter);
|
||||
HashCombine(&hash, module->mMinFilter);
|
||||
HashCombine(&hash, module->mMipmapFilter);
|
||||
HashCombine(&hash, module->mLodMinClamp);
|
||||
HashCombine(&hash, module->mLodMaxClamp);
|
||||
HashCombine(&hash, module->mCompareFunction);
|
||||
|
||||
return hash;
|
||||
size_t SamplerBase::ComputeContentHash() {
|
||||
ObjectContentHasher recorder;
|
||||
recorder.Record(mAddressModeU, mAddressModeV, mAddressModeW, mMagFilter, mMinFilter,
|
||||
mMipmapFilter, mLodMinClamp, mLodMaxClamp, mCompareFunction);
|
||||
return recorder.GetContentHash();
|
||||
}
|
||||
|
||||
bool SamplerBase::EqualityFunc::operator()(const SamplerBase* a, const SamplerBase* b) const {
|
||||
|
|
|
@ -35,10 +35,9 @@ namespace dawn_native {
|
|||
|
||||
bool HasCompareFunction() const;
|
||||
|
||||
// Functors necessary for the unordered_set<SamplerBase*>-based cache.
|
||||
struct HashFunc {
|
||||
size_t operator()(const SamplerBase* module) const;
|
||||
};
|
||||
// Functions necessary for the unordered_set<SamplerBase*>-based cache.
|
||||
size_t ComputeContentHash() override;
|
||||
|
||||
struct EqualityFunc {
|
||||
bool operator()(const SamplerBase* a, const SamplerBase* b) const;
|
||||
};
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
|
||||
#include "dawn_native/ShaderModule.h"
|
||||
|
||||
#include "common/HashUtils.h"
|
||||
#include "dawn_native/BindGroupLayout.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/ObjectContentHasher.h"
|
||||
#include "dawn_native/Pipeline.h"
|
||||
#include "dawn_native/PipelineLayout.h"
|
||||
#include "dawn_native/SpirvUtils.h"
|
||||
|
@ -975,20 +975,12 @@ namespace dawn_native {
|
|||
return *mEntryPoints.at(entryPoint);
|
||||
}
|
||||
|
||||
size_t ShaderModuleBase::HashFunc::operator()(const ShaderModuleBase* module) const {
|
||||
size_t hash = 0;
|
||||
|
||||
HashCombine(&hash, module->mType);
|
||||
|
||||
for (uint32_t word : module->mOriginalSpirv) {
|
||||
HashCombine(&hash, word);
|
||||
}
|
||||
|
||||
for (char c : module->mWgsl) {
|
||||
HashCombine(&hash, c);
|
||||
}
|
||||
|
||||
return hash;
|
||||
size_t ShaderModuleBase::ComputeContentHash() {
|
||||
ObjectContentHasher recorder;
|
||||
recorder.Record(mType);
|
||||
recorder.Record(mOriginalSpirv);
|
||||
recorder.Record(mWgsl);
|
||||
return recorder.GetContentHash();
|
||||
}
|
||||
|
||||
bool ShaderModuleBase::EqualityFunc::operator()(const ShaderModuleBase* a,
|
||||
|
|
|
@ -105,10 +105,9 @@ namespace dawn_native {
|
|||
// must be true.
|
||||
const EntryPointMetadata& GetEntryPoint(const std::string& entryPoint) const;
|
||||
|
||||
// Functors necessary for the unordered_set<ShaderModuleBase*>-based cache.
|
||||
struct HashFunc {
|
||||
size_t operator()(const ShaderModuleBase* module) const;
|
||||
};
|
||||
// Functions necessary for the unordered_set<ShaderModuleBase*>-based cache.
|
||||
size_t ComputeContentHash() override;
|
||||
|
||||
struct EqualityFunc {
|
||||
bool operator()(const ShaderModuleBase* a, const ShaderModuleBase* b) const;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue