• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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/vulkan/BindGroupVk.h"
16 
17 #include "common/BitSetIterator.h"
18 #include "common/ityp_stack_vec.h"
19 #include "dawn_native/ExternalTexture.h"
20 #include "dawn_native/vulkan/BindGroupLayoutVk.h"
21 #include "dawn_native/vulkan/BufferVk.h"
22 #include "dawn_native/vulkan/DeviceVk.h"
23 #include "dawn_native/vulkan/FencedDeleter.h"
24 #include "dawn_native/vulkan/SamplerVk.h"
25 #include "dawn_native/vulkan/TextureVk.h"
26 #include "dawn_native/vulkan/UtilsVulkan.h"
27 #include "dawn_native/vulkan/VulkanError.h"
28 
29 namespace dawn_native { namespace vulkan {
30 
31     // static
Create(Device * device,const BindGroupDescriptor * descriptor)32     ResultOrError<Ref<BindGroup>> BindGroup::Create(Device* device,
33                                                     const BindGroupDescriptor* descriptor) {
34         return ToBackend(descriptor->layout)->AllocateBindGroup(device, descriptor);
35     }
36 
BindGroup(Device * device,const BindGroupDescriptor * descriptor,DescriptorSetAllocation descriptorSetAllocation)37     BindGroup::BindGroup(Device* device,
38                          const BindGroupDescriptor* descriptor,
39                          DescriptorSetAllocation descriptorSetAllocation)
40         : BindGroupBase(this, device, descriptor),
41           mDescriptorSetAllocation(descriptorSetAllocation) {
42         // Now do a write of a single descriptor set with all possible chained data allocated on the
43         // stack.
44         const uint32_t bindingCount = static_cast<uint32_t>((GetLayout()->GetBindingCount()));
45         ityp::stack_vec<uint32_t, VkWriteDescriptorSet, kMaxOptimalBindingsPerGroup> writes(
46             bindingCount);
47         ityp::stack_vec<uint32_t, VkDescriptorBufferInfo, kMaxOptimalBindingsPerGroup>
48             writeBufferInfo(bindingCount);
49         ityp::stack_vec<uint32_t, VkDescriptorImageInfo, kMaxOptimalBindingsPerGroup>
50             writeImageInfo(bindingCount);
51 
52         uint32_t numWrites = 0;
53         for (const auto& it : GetLayout()->GetBindingMap()) {
54             BindingIndex bindingIndex = it.second;
55             const BindingInfo& bindingInfo = GetLayout()->GetBindingInfo(bindingIndex);
56 
57             auto& write = writes[numWrites];
58             write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
59             write.pNext = nullptr;
60             write.dstSet = GetHandle();
61             write.dstBinding = static_cast<uint32_t>(bindingIndex);
62             write.dstArrayElement = 0;
63             write.descriptorCount = 1;
64             write.descriptorType = VulkanDescriptorType(bindingInfo);
65 
66             switch (bindingInfo.bindingType) {
67                 case BindingInfoType::Buffer: {
68                     BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
69 
70                     VkBuffer handle = ToBackend(binding.buffer)->GetHandle();
71                     if (handle == VK_NULL_HANDLE) {
72                         // The Buffer was destroyed. Skip this descriptor write since it would be
73                         // a Vulkan Validation Layers error. This bind group won't be used as it
74                         // is an error to submit a command buffer that references destroyed
75                         // resources.
76                         continue;
77                     }
78                     writeBufferInfo[numWrites].buffer = handle;
79                     writeBufferInfo[numWrites].offset = binding.offset;
80                     writeBufferInfo[numWrites].range = binding.size;
81                     write.pBufferInfo = &writeBufferInfo[numWrites];
82                     break;
83                 }
84 
85                 case BindingInfoType::Sampler: {
86                     Sampler* sampler = ToBackend(GetBindingAsSampler(bindingIndex));
87                     writeImageInfo[numWrites].sampler = sampler->GetHandle();
88                     write.pImageInfo = &writeImageInfo[numWrites];
89                     break;
90                 }
91 
92                 case BindingInfoType::Texture: {
93                     TextureView* view = ToBackend(GetBindingAsTextureView(bindingIndex));
94 
95                     VkImageView handle = view->GetHandle();
96                     if (handle == VK_NULL_HANDLE) {
97                         // The Texture was destroyed before the TextureView was created.
98                         // Skip this descriptor write since it would be
99                         // a Vulkan Validation Layers error. This bind group won't be used as it
100                         // is an error to submit a command buffer that references destroyed
101                         // resources.
102                         continue;
103                     }
104                     writeImageInfo[numWrites].imageView = handle;
105 
106                     // The layout may be GENERAL here because of interactions between the Sampled
107                     // and ReadOnlyStorage usages. See the logic in VulkanImageLayout.
108                     writeImageInfo[numWrites].imageLayout = VulkanImageLayout(
109                         ToBackend(view->GetTexture()), wgpu::TextureUsage::TextureBinding);
110 
111                     write.pImageInfo = &writeImageInfo[numWrites];
112                     break;
113                 }
114 
115                 case BindingInfoType::StorageTexture: {
116                     TextureView* view = ToBackend(GetBindingAsTextureView(bindingIndex));
117 
118                     VkImageView handle = view->GetHandle();
119                     if (handle == VK_NULL_HANDLE) {
120                         // The Texture was destroyed before the TextureView was created.
121                         // Skip this descriptor write since it would be
122                         // a Vulkan Validation Layers error. This bind group won't be used as it
123                         // is an error to submit a command buffer that references destroyed
124                         // resources.
125                         continue;
126                     }
127                     writeImageInfo[numWrites].imageView = handle;
128                     writeImageInfo[numWrites].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
129 
130                     write.pImageInfo = &writeImageInfo[numWrites];
131                     break;
132                 }
133 
134                 case BindingInfoType::ExternalTexture: {
135                     const std::array<Ref<dawn_native::TextureViewBase>, kMaxPlanesPerFormat>&
136                         textureViews = GetBindingAsExternalTexture(bindingIndex)->GetTextureViews();
137 
138                     // Only single-plane formats are supported right now, so ensure only one view
139                     // exists.
140                     ASSERT(textureViews[1].Get() == nullptr);
141                     ASSERT(textureViews[2].Get() == nullptr);
142 
143                     TextureView* view = ToBackend(textureViews[0].Get());
144 
145                     writeImageInfo[numWrites].imageView = view->GetHandle();
146                     writeImageInfo[numWrites].imageLayout = VulkanImageLayout(
147                         ToBackend(view->GetTexture()), wgpu::TextureUsage::TextureBinding);
148 
149                     write.pImageInfo = &writeImageInfo[numWrites];
150                     break;
151                 }
152             }
153 
154             numWrites++;
155         }
156 
157         // TODO(crbug.com/dawn/855): Batch these updates
158         device->fn.UpdateDescriptorSets(device->GetVkDevice(), numWrites, writes.data(), 0,
159                                         nullptr);
160 
161         SetLabelImpl();
162     }
163 
164     BindGroup::~BindGroup() = default;
165 
DestroyImpl()166     void BindGroup::DestroyImpl() {
167         BindGroupBase::DestroyImpl();
168         ToBackend(GetLayout())->DeallocateBindGroup(this, &mDescriptorSetAllocation);
169     }
170 
GetHandle() const171     VkDescriptorSet BindGroup::GetHandle() const {
172         return mDescriptorSetAllocation.set;
173     }
174 
SetLabelImpl()175     void BindGroup::SetLabelImpl() {
176         SetDebugName(ToBackend(GetDevice()), VK_OBJECT_TYPE_DESCRIPTOR_SET,
177                      reinterpret_cast<uint64_t&>(mDescriptorSetAllocation.set), "Dawn_BindGroup",
178                      GetLabel());
179     }
180 
181 }}  // namespace dawn_native::vulkan
182