1 // Copyright 2017 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef DAWNNATIVE_BINDGROUPLAYOUT_H_ 16 #define DAWNNATIVE_BINDGROUPLAYOUT_H_ 17 18 #include "common/Constants.h" 19 #include "common/Math.h" 20 #include "common/SlabAllocator.h" 21 #include "common/ityp_span.h" 22 #include "common/ityp_vector.h" 23 #include "dawn_native/BindingInfo.h" 24 #include "dawn_native/CachedObject.h" 25 #include "dawn_native/Error.h" 26 #include "dawn_native/Forward.h" 27 #include "dawn_native/ObjectBase.h" 28 29 #include "dawn_native/dawn_platform.h" 30 31 #include <bitset> 32 #include <map> 33 34 namespace dawn_native { 35 36 MaybeError ValidateBindGroupLayoutDescriptor(DeviceBase* device, 37 const BindGroupLayoutDescriptor* descriptor, 38 bool allowInternalBinding = false); 39 40 // Bindings are specified as a |BindingNumber| in the BindGroupLayoutDescriptor. 41 // These numbers may be arbitrary and sparse. Internally, Dawn packs these numbers 42 // into a packed range of |BindingIndex| integers. 43 class BindGroupLayoutBase : public ApiObjectBase, public CachedObject { 44 public: 45 BindGroupLayoutBase(DeviceBase* device, 46 const BindGroupLayoutDescriptor* descriptor, 47 PipelineCompatibilityToken pipelineCompatibilityToken, 48 ApiObjectBase::UntrackedByDeviceTag tag); 49 BindGroupLayoutBase(DeviceBase* device, 50 const BindGroupLayoutDescriptor* descriptor, 51 PipelineCompatibilityToken pipelineCompatibilityToken); 52 ~BindGroupLayoutBase() override; 53 54 static BindGroupLayoutBase* MakeError(DeviceBase* device); 55 56 ObjectType GetType() const override; 57 58 // A map from the BindingNumber to its packed BindingIndex. 59 using BindingMap = std::map<BindingNumber, BindingIndex>; 60 GetBindingInfo(BindingIndex bindingIndex)61 const BindingInfo& GetBindingInfo(BindingIndex bindingIndex) const { 62 ASSERT(!IsError()); 63 ASSERT(bindingIndex < mBindingInfo.size()); 64 return mBindingInfo[bindingIndex]; 65 } 66 const BindingMap& GetBindingMap() const; 67 bool HasBinding(BindingNumber bindingNumber) const; 68 BindingIndex GetBindingIndex(BindingNumber bindingNumber) const; 69 70 // Functions necessary for the unordered_set<BGLBase*>-based cache. 71 size_t ComputeContentHash() override; 72 73 struct EqualityFunc { 74 bool operator()(const BindGroupLayoutBase* a, const BindGroupLayoutBase* b) const; 75 }; 76 77 BindingIndex GetBindingCount() const; 78 // Returns |BindingIndex| because buffers are packed at the front. 79 BindingIndex GetBufferCount() const; 80 // Returns |BindingIndex| because dynamic buffers are packed at the front. 81 BindingIndex GetDynamicBufferCount() const; 82 uint32_t GetUnverifiedBufferCount() const; 83 84 // Used to get counts and validate them in pipeline layout creation. Other getters 85 // should be used to get typed integer counts. 86 const BindingCounts& GetBindingCountInfo() const; 87 88 // Tests that the BindingInfo of two bind groups are equal, 89 // ignoring their compatibility groups. 90 bool IsLayoutEqual(const BindGroupLayoutBase* other, 91 bool excludePipelineCompatibiltyToken = false) const; 92 PipelineCompatibilityToken GetPipelineCompatibilityToken() const; 93 94 struct BufferBindingData { 95 uint64_t offset; 96 uint64_t size; 97 }; 98 99 struct BindingDataPointers { 100 ityp::span<BindingIndex, BufferBindingData> const bufferData = {}; 101 ityp::span<BindingIndex, Ref<ObjectBase>> const bindings = {}; 102 ityp::span<uint32_t, uint64_t> const unverifiedBufferSizes = {}; 103 }; 104 105 // Compute the amount of space / alignment required to store bindings for a bind group of 106 // this layout. 107 size_t GetBindingDataSize() const; GetBindingDataAlignment()108 static constexpr size_t GetBindingDataAlignment() { 109 static_assert(alignof(Ref<ObjectBase>) <= alignof(BufferBindingData), ""); 110 return alignof(BufferBindingData); 111 } 112 113 BindingDataPointers ComputeBindingDataPointers(void* dataStart) const; 114 115 bool IsStorageBufferBinding(BindingIndex bindingIndex) const; 116 117 protected: 118 // Constructor used only for mocking and testing. 119 BindGroupLayoutBase(DeviceBase* device); 120 void DestroyImpl() override; 121 122 template <typename BindGroup> MakeFrontendBindGroupAllocator(size_t size)123 SlabAllocator<BindGroup> MakeFrontendBindGroupAllocator(size_t size) { 124 return SlabAllocator<BindGroup>( 125 size, // bytes 126 Align(sizeof(BindGroup), GetBindingDataAlignment()) + GetBindingDataSize(), // size 127 std::max(alignof(BindGroup), GetBindingDataAlignment()) // alignment 128 ); 129 } 130 131 private: 132 BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag); 133 134 BindingCounts mBindingCounts = {}; 135 ityp::vector<BindingIndex, BindingInfo> mBindingInfo; 136 137 // Map from BindGroupLayoutEntry.binding to packed indices. 138 BindingMap mBindingMap; 139 140 // Non-0 if this BindGroupLayout was created as part of a default PipelineLayout. 141 const PipelineCompatibilityToken mPipelineCompatibilityToken = 142 PipelineCompatibilityToken(0); 143 }; 144 145 } // namespace dawn_native 146 147 #endif // DAWNNATIVE_BINDGROUPLAYOUT_H_ 148