• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "dawn_native/BindGroupLayout.h"
16 
17 #include "common/BitSetIterator.h"
18 #include "common/HashUtils.h"
19 #include "dawn_native/Device.h"
20 #include "dawn_native/ValidationUtils_autogen.h"
21 
22 #include <functional>
23 
24 namespace dawn_native {
25 
ValidateBindGroupLayoutDescriptor(DeviceBase *,const BindGroupLayoutDescriptor * descriptor)26     MaybeError ValidateBindGroupLayoutDescriptor(DeviceBase*,
27                                                  const BindGroupLayoutDescriptor* descriptor) {
28         if (descriptor->nextInChain != nullptr) {
29             return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
30         }
31 
32         std::bitset<kMaxBindingsPerGroup> bindingsSet;
33         for (uint32_t i = 0; i < descriptor->bindingCount; ++i) {
34             const BindGroupLayoutBinding& binding = descriptor->bindings[i];
35             DAWN_TRY(ValidateShaderStageBit(binding.visibility));
36             DAWN_TRY(ValidateBindingType(binding.type));
37 
38             if (binding.binding >= kMaxBindingsPerGroup) {
39                 return DAWN_VALIDATION_ERROR("some binding index exceeds the maximum value");
40             }
41             if (bindingsSet[binding.binding]) {
42                 return DAWN_VALIDATION_ERROR("some binding index was specified more than once");
43             }
44 
45             switch (binding.type) {
46                 case dawn::BindingType::UniformBuffer:
47                 case dawn::BindingType::StorageBuffer:
48                     break;
49                 case dawn::BindingType::SampledTexture:
50                 case dawn::BindingType::Sampler:
51                     if (binding.dynamic) {
52                         return DAWN_VALIDATION_ERROR("Samplers and textures cannot be dynamic");
53                     }
54                     break;
55                 case dawn::BindingType::ReadonlyStorageBuffer:
56                     return DAWN_VALIDATION_ERROR("readonly storage buffers aren't supported (yet)");
57                 case dawn::BindingType::StorageTexture:
58                     return DAWN_VALIDATION_ERROR("storage textures aren't supported (yet)");
59             }
60 
61             if (binding.multisampled) {
62                 return DAWN_VALIDATION_ERROR(
63                     "BindGroupLayoutBinding::multisampled must be false (for now)");
64             }
65 
66             bindingsSet.set(binding.binding);
67         }
68         return {};
69     }
70 
71     namespace {
HashBindingInfo(const BindGroupLayoutBase::LayoutBindingInfo & info)72         size_t HashBindingInfo(const BindGroupLayoutBase::LayoutBindingInfo& info) {
73             size_t hash = Hash(info.mask);
74             HashCombine(&hash, info.dynamic, info.multisampled);
75 
76             for (uint32_t binding : IterateBitSet(info.mask)) {
77                 HashCombine(&hash, info.visibilities[binding], info.types[binding]);
78             }
79 
80             return hash;
81         }
82 
operator ==(const BindGroupLayoutBase::LayoutBindingInfo & a,const BindGroupLayoutBase::LayoutBindingInfo & b)83         bool operator==(const BindGroupLayoutBase::LayoutBindingInfo& a,
84                         const BindGroupLayoutBase::LayoutBindingInfo& b) {
85             if (a.mask != b.mask || a.dynamic != b.dynamic || a.multisampled != b.multisampled) {
86                 return false;
87             }
88 
89             for (uint32_t binding : IterateBitSet(a.mask)) {
90                 if ((a.visibilities[binding] != b.visibilities[binding]) ||
91                     (a.types[binding] != b.types[binding])) {
92                     return false;
93                 }
94             }
95 
96             return true;
97         }
98     }  // namespace
99 
100     // BindGroupLayoutBase
101 
BindGroupLayoutBase(DeviceBase * device,const BindGroupLayoutDescriptor * descriptor,bool blueprint)102     BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device,
103                                              const BindGroupLayoutDescriptor* descriptor,
104                                              bool blueprint)
105         : ObjectBase(device), mIsBlueprint(blueprint) {
106         for (uint32_t i = 0; i < descriptor->bindingCount; ++i) {
107             auto& binding = descriptor->bindings[i];
108 
109             uint32_t index = binding.binding;
110             mBindingInfo.visibilities[index] = binding.visibility;
111             mBindingInfo.types[index] = binding.type;
112 
113             if (binding.dynamic) {
114                 mBindingInfo.dynamic.set(index);
115                 mDynamicBufferCount++;
116             }
117 
118             mBindingInfo.multisampled.set(index, binding.multisampled);
119 
120             ASSERT(!mBindingInfo.mask[index]);
121             mBindingInfo.mask.set(index);
122         }
123     }
124 
BindGroupLayoutBase(DeviceBase * device,ObjectBase::ErrorTag tag)125     BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
126         : ObjectBase(device, tag), mIsBlueprint(true) {
127     }
128 
~BindGroupLayoutBase()129     BindGroupLayoutBase::~BindGroupLayoutBase() {
130         // Do not uncache the actual cached object if we are a blueprint
131         if (!mIsBlueprint && !IsError()) {
132             GetDevice()->UncacheBindGroupLayout(this);
133         }
134     }
135 
136     // static
MakeError(DeviceBase * device)137     BindGroupLayoutBase* BindGroupLayoutBase::MakeError(DeviceBase* device) {
138         return new BindGroupLayoutBase(device, ObjectBase::kError);
139     }
140 
GetBindingInfo() const141     const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBase::GetBindingInfo() const {
142         ASSERT(!IsError());
143         return mBindingInfo;
144     }
145 
operator ()(const BindGroupLayoutBase * bgl) const146     size_t BindGroupLayoutBase::HashFunc::operator()(const BindGroupLayoutBase* bgl) const {
147         return HashBindingInfo(bgl->mBindingInfo);
148     }
149 
operator ()(const BindGroupLayoutBase * a,const BindGroupLayoutBase * b) const150     bool BindGroupLayoutBase::EqualityFunc::operator()(const BindGroupLayoutBase* a,
151                                                        const BindGroupLayoutBase* b) const {
152         return a->mBindingInfo == b->mBindingInfo;
153     }
154 
GetDynamicBufferCount() const155     uint32_t BindGroupLayoutBase::GetDynamicBufferCount() const {
156         return mDynamicBufferCount;
157     }
158 
159 }  // namespace dawn_native
160