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