1 /*------------------------------------------------------------------------- 2 * Vulkan CTS Framework 3 * -------------------- 4 * 5 * Copyright (c) 2015 Google Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Vulkan object builder utilities. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vkBuilderUtil.hpp" 25 26 #include "vkRefUtil.hpp" 27 28 namespace vk 29 { 30 31 // DescriptorSetLayoutBuilder 32 33 DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder (void) 34 { 35 } 36 37 DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::addBinding (VkDescriptorType descriptorType, 38 deUint32 descriptorCount, 39 VkShaderStageFlags stageFlags, 40 const VkSampler* pImmutableSamplers) 41 { 42 if (pImmutableSamplers) 43 { 44 const ImmutableSamplerInfo immutableSamplerInfo = 45 { 46 (deUint32)m_bindings.size(), 47 (deUint32)m_immutableSamplers.size() 48 }; 49 50 m_immutableSamplerInfos.push_back(immutableSamplerInfo); 51 52 for (size_t descriptorNdx = 0; descriptorNdx < descriptorCount; descriptorNdx++) 53 m_immutableSamplers.push_back(pImmutableSamplers[descriptorNdx]); 54 } 55 56 // pImmutableSamplers will be updated at build time 57 const VkDescriptorSetLayoutBinding binding = 58 { 59 (deUint32)m_bindings.size(), // binding 60 descriptorType, // descriptorType 61 descriptorCount, // descriptorCount 62 stageFlags, // stageFlags 63 DE_NULL, // pImmutableSamplers 64 }; 65 m_bindings.push_back(binding); 66 return *this; 67 } 68 69 DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::addIndexedBinding (VkDescriptorType descriptorType, 70 deUint32 descriptorCount, 71 VkShaderStageFlags stageFlags, 72 deUint32 dstBinding, 73 const VkSampler* pImmutableSamplers) 74 { 75 if (pImmutableSamplers) 76 { 77 const ImmutableSamplerInfo immutableSamplerInfo = 78 { 79 (deUint32)dstBinding, 80 (deUint32)m_immutableSamplers.size() 81 }; 82 83 m_immutableSamplerInfos.push_back(immutableSamplerInfo); 84 85 for (size_t descriptorNdx = 0; descriptorNdx < descriptorCount; descriptorNdx++) 86 m_immutableSamplers.push_back(pImmutableSamplers[descriptorNdx]); 87 } 88 89 // pImmutableSamplers will be updated at build time 90 const VkDescriptorSetLayoutBinding binding = 91 { 92 dstBinding, // binding 93 descriptorType, // descriptorType 94 descriptorCount, // descriptorCount 95 stageFlags, // stageFlags 96 DE_NULL, // pImmutableSamplers 97 }; 98 m_bindings.push_back(binding); 99 return *this; 100 } 101 102 Move<VkDescriptorSetLayout> DescriptorSetLayoutBuilder::build (const DeviceInterface& vk, VkDevice device, VkDescriptorSetLayoutCreateFlags extraFlags) const 103 { 104 // Create new layout bindings with pImmutableSamplers updated 105 std::vector<VkDescriptorSetLayoutBinding> bindings = m_bindings; 106 107 for (size_t samplerInfoNdx = 0; samplerInfoNdx < m_immutableSamplerInfos.size(); samplerInfoNdx++) 108 { 109 const ImmutableSamplerInfo& samplerInfo = m_immutableSamplerInfos[samplerInfoNdx]; 110 deUint32 bindingNdx = 0; 111 112 while (bindings[bindingNdx].binding != samplerInfo.bindingIndex) 113 { 114 bindingNdx++; 115 116 if (bindingNdx >= (deUint32)bindings.size()) 117 DE_FATAL("Immutable sampler not found"); 118 } 119 120 bindings[bindingNdx].pImmutableSamplers = &m_immutableSamplers[samplerInfo.samplerBaseIndex]; 121 } 122 123 const VkDescriptorSetLayoutCreateInfo createInfo = 124 { 125 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 126 DE_NULL, 127 (VkDescriptorSetLayoutCreateFlags)extraFlags, // flags 128 (deUint32)bindings.size(), // bindingCount 129 (bindings.empty()) ? (DE_NULL) : (&bindings.front()), // pBinding 130 }; 131 132 return createDescriptorSetLayout(vk, device, &createInfo); 133 } 134 135 // DescriptorPoolBuilder 136 137 DescriptorPoolBuilder::DescriptorPoolBuilder (void) 138 { 139 } 140 141 DescriptorPoolBuilder& DescriptorPoolBuilder::addType (VkDescriptorType type, deUint32 numDescriptors) 142 { 143 if (numDescriptors == 0u) 144 { 145 // nothing to do 146 return *this; 147 } 148 else 149 { 150 for (size_t ndx = 0; ndx < m_counts.size(); ++ndx) 151 { 152 if (m_counts[ndx].type == type) 153 { 154 // augment existing requirement 155 m_counts[ndx].descriptorCount += numDescriptors; 156 return *this; 157 } 158 } 159 160 { 161 // new requirement 162 const VkDescriptorPoolSize typeCount = 163 { 164 type, // type 165 numDescriptors, // numDescriptors 166 }; 167 168 m_counts.push_back(typeCount); 169 return *this; 170 } 171 } 172 } 173 174 Move<VkDescriptorPool> DescriptorPoolBuilder::build (const DeviceInterface& vk, VkDevice device, VkDescriptorPoolCreateFlags flags, deUint32 maxSets, const void *pNext) const 175 { 176 const VkDescriptorPoolSize* const typeCountPtr = (m_counts.empty()) ? (DE_NULL) : (&m_counts[0]); 177 const VkDescriptorPoolCreateInfo createInfo = 178 { 179 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 180 pNext, 181 flags, 182 maxSets, 183 (deUint32)m_counts.size(), // poolSizeCount 184 typeCountPtr, // pPoolSizes 185 }; 186 187 return createDescriptorPool(vk, device, &createInfo); 188 } 189 190 // DescriptorSetUpdateBuilder 191 192 DescriptorSetUpdateBuilder::DescriptorSetUpdateBuilder (void) 193 { 194 } 195 196 DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::write (VkDescriptorSet destSet, 197 deUint32 destBinding, 198 deUint32 destArrayElement, 199 deUint32 count, 200 VkDescriptorType descriptorType, 201 const VkDescriptorImageInfo* pImageInfo, 202 const VkDescriptorBufferInfo* pBufferInfo, 203 const VkBufferView* pTexelBufferView) 204 { 205 // pImageInfo, pBufferInfo and pTexelBufferView will be updated when calling update() 206 const VkWriteDescriptorSet writeParams = 207 { 208 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 209 DE_NULL, 210 destSet, //!< destSet 211 destBinding, //!< destBinding 212 destArrayElement, //!< destArrayElement 213 count, //!< count 214 descriptorType, //!< descriptorType 215 DE_NULL, 216 DE_NULL, 217 DE_NULL 218 }; 219 220 m_writes.push_back(writeParams); 221 222 // Store a copy of pImageInfo, pBufferInfo and pTexelBufferView 223 WriteDescriptorInfo writeInfo; 224 225 if (pImageInfo) 226 writeInfo.imageInfos.insert(writeInfo.imageInfos.end(), pImageInfo, pImageInfo + count); 227 228 if (pBufferInfo) 229 writeInfo.bufferInfos.insert(writeInfo.bufferInfos.end(), pBufferInfo, pBufferInfo + count); 230 231 if (pTexelBufferView) 232 writeInfo.texelBufferViews.insert(writeInfo.texelBufferViews.end(), pTexelBufferView, pTexelBufferView + count); 233 234 m_writeDescriptorInfos.push_back(writeInfo); 235 236 return *this; 237 } 238 239 DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::copy (VkDescriptorSet srcSet, 240 deUint32 srcBinding, 241 deUint32 srcArrayElement, 242 VkDescriptorSet destSet, 243 deUint32 destBinding, 244 deUint32 destArrayElement, 245 deUint32 count) 246 { 247 const VkCopyDescriptorSet copyParams = 248 { 249 VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, 250 DE_NULL, 251 srcSet, //!< srcSet 252 srcBinding, //!< srcBinding 253 srcArrayElement, //!< srcArrayElement 254 destSet, //!< destSet 255 destBinding, //!< destBinding 256 destArrayElement, //!< destArrayElement 257 count, //!< count 258 }; 259 m_copies.push_back(copyParams); 260 return *this; 261 } 262 263 void DescriptorSetUpdateBuilder::update (const DeviceInterface& vk, VkDevice device) const 264 { 265 // Update VkWriteDescriptorSet structures with stored info 266 std::vector<VkWriteDescriptorSet> writes = m_writes; 267 268 for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++) 269 { 270 const WriteDescriptorInfo& writeInfo = m_writeDescriptorInfos[writeNdx]; 271 272 if (!writeInfo.imageInfos.empty()) 273 writes[writeNdx].pImageInfo = &writeInfo.imageInfos[0]; 274 275 if (!writeInfo.bufferInfos.empty()) 276 writes[writeNdx].pBufferInfo = &writeInfo.bufferInfos[0]; 277 278 if (!writeInfo.texelBufferViews.empty()) 279 writes[writeNdx].pTexelBufferView = &writeInfo.texelBufferViews[0]; 280 } 281 282 const VkWriteDescriptorSet* const writePtr = (m_writes.empty()) ? (DE_NULL) : (&writes[0]); 283 const VkCopyDescriptorSet* const copyPtr = (m_copies.empty()) ? (DE_NULL) : (&m_copies[0]); 284 285 vk.updateDescriptorSets(device, (deUint32)writes.size(), writePtr, (deUint32)m_copies.size(), copyPtr); 286 } 287 288 void DescriptorSetUpdateBuilder::updateWithPush (const DeviceInterface& vk, VkCommandBuffer cmd, VkPipelineBindPoint bindPoint, VkPipelineLayout pipelineLayout, deUint32 setIdx, deUint32 descriptorIdx, deUint32 numDescriptors) const 289 { 290 // Write all descriptors or just a subset? 291 deUint32 count = (numDescriptors) ? numDescriptors : (deUint32)m_writes.size(); 292 293 // Update VkWriteDescriptorSet structures with stored info 294 std::vector<VkWriteDescriptorSet> writes = m_writes; 295 296 for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++) 297 { 298 const WriteDescriptorInfo& writeInfo = m_writeDescriptorInfos[writeNdx]; 299 300 if (!writeInfo.imageInfos.empty()) 301 writes[writeNdx].pImageInfo = &writeInfo.imageInfos[0]; 302 303 if (!writeInfo.bufferInfos.empty()) 304 writes[writeNdx].pBufferInfo = &writeInfo.bufferInfos[0]; 305 306 if (!writeInfo.texelBufferViews.empty()) 307 writes[writeNdx].pTexelBufferView = &writeInfo.texelBufferViews[0]; 308 } 309 310 const VkWriteDescriptorSet* const writePtr = (m_writes.empty()) ? (DE_NULL) : (&writes[descriptorIdx]); 311 312 vk.cmdPushDescriptorSetKHR(cmd, bindPoint, pipelineLayout, setIdx, count, writePtr); 313 } 314 315 void DescriptorSetUpdateBuilder::clear(void) 316 { 317 m_writeDescriptorInfos.clear(); 318 m_writes.clear(); 319 m_copies.clear(); 320 } 321 322 } // vk 323