| /*------------------------------------------------------------------------- |
| * Vulkan CTS Framework |
| * -------------------- |
| * |
| * Copyright (c) 2015 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Vulkan object builder utilities. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vkBuilderUtil.hpp" |
| |
| #include "vkRefUtil.hpp" |
| |
| namespace vk |
| { |
| |
| // DescriptorSetLayoutBuilder |
| |
| DescriptorSetLayoutBuilder::DescriptorSetLayoutBuilder (void) |
| { |
| } |
| |
| DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::addBinding (VkDescriptorType descriptorType, |
| deUint32 descriptorCount, |
| VkShaderStageFlags stageFlags, |
| const VkSampler* pImmutableSamplers) |
| { |
| if (pImmutableSamplers) |
| { |
| const ImmutableSamplerInfo immutableSamplerInfo = |
| { |
| (deUint32)m_bindings.size(), |
| (deUint32)m_immutableSamplers.size() |
| }; |
| |
| m_immutableSamplerInfos.push_back(immutableSamplerInfo); |
| |
| for (size_t descriptorNdx = 0; descriptorNdx < descriptorCount; descriptorNdx++) |
| m_immutableSamplers.push_back(pImmutableSamplers[descriptorNdx]); |
| } |
| |
| // pImmutableSamplers will be updated at build time |
| const VkDescriptorSetLayoutBinding binding = |
| { |
| (deUint32)m_bindings.size(), // binding |
| descriptorType, // descriptorType |
| descriptorCount, // descriptorCount |
| stageFlags, // stageFlags |
| DE_NULL, // pImmutableSamplers |
| }; |
| m_bindings.push_back(binding); |
| return *this; |
| } |
| |
| DescriptorSetLayoutBuilder& DescriptorSetLayoutBuilder::addIndexedBinding (VkDescriptorType descriptorType, |
| deUint32 descriptorCount, |
| VkShaderStageFlags stageFlags, |
| deUint32 dstBinding, |
| const VkSampler* pImmutableSamplers) |
| { |
| if (pImmutableSamplers) |
| { |
| const ImmutableSamplerInfo immutableSamplerInfo = |
| { |
| (deUint32)dstBinding, |
| (deUint32)m_immutableSamplers.size() |
| }; |
| |
| m_immutableSamplerInfos.push_back(immutableSamplerInfo); |
| |
| for (size_t descriptorNdx = 0; descriptorNdx < descriptorCount; descriptorNdx++) |
| m_immutableSamplers.push_back(pImmutableSamplers[descriptorNdx]); |
| } |
| |
| // pImmutableSamplers will be updated at build time |
| const VkDescriptorSetLayoutBinding binding = |
| { |
| dstBinding, // binding |
| descriptorType, // descriptorType |
| descriptorCount, // descriptorCount |
| stageFlags, // stageFlags |
| DE_NULL, // pImmutableSamplers |
| }; |
| m_bindings.push_back(binding); |
| return *this; |
| } |
| |
| Move<VkDescriptorSetLayout> DescriptorSetLayoutBuilder::build (const DeviceInterface& vk, VkDevice device, VkDescriptorSetLayoutCreateFlags extraFlags) const |
| { |
| // Create new layout bindings with pImmutableSamplers updated |
| std::vector<VkDescriptorSetLayoutBinding> bindings = m_bindings; |
| |
| for (size_t samplerInfoNdx = 0; samplerInfoNdx < m_immutableSamplerInfos.size(); samplerInfoNdx++) |
| { |
| const ImmutableSamplerInfo& samplerInfo = m_immutableSamplerInfos[samplerInfoNdx]; |
| deUint32 bindingNdx = 0; |
| |
| while (bindings[bindingNdx].binding != samplerInfo.bindingIndex) |
| { |
| bindingNdx++; |
| |
| if (bindingNdx >= (deUint32)bindings.size()) |
| DE_FATAL("Immutable sampler not found"); |
| } |
| |
| bindings[bindingNdx].pImmutableSamplers = &m_immutableSamplers[samplerInfo.samplerBaseIndex]; |
| } |
| |
| const VkDescriptorSetLayoutCreateInfo createInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, |
| DE_NULL, |
| (VkDescriptorSetLayoutCreateFlags)extraFlags, // flags |
| (deUint32)bindings.size(), // bindingCount |
| (bindings.empty()) ? (DE_NULL) : (&bindings.front()), // pBinding |
| }; |
| |
| return createDescriptorSetLayout(vk, device, &createInfo); |
| } |
| |
| // DescriptorPoolBuilder |
| |
| DescriptorPoolBuilder::DescriptorPoolBuilder (void) |
| { |
| } |
| |
| DescriptorPoolBuilder& DescriptorPoolBuilder::addType (VkDescriptorType type, deUint32 numDescriptors) |
| { |
| if (numDescriptors == 0u) |
| { |
| // nothing to do |
| return *this; |
| } |
| else |
| { |
| for (size_t ndx = 0; ndx < m_counts.size(); ++ndx) |
| { |
| if (m_counts[ndx].type == type) |
| { |
| // augment existing requirement |
| m_counts[ndx].descriptorCount += numDescriptors; |
| return *this; |
| } |
| } |
| |
| { |
| // new requirement |
| const VkDescriptorPoolSize typeCount = |
| { |
| type, // type |
| numDescriptors, // numDescriptors |
| }; |
| |
| m_counts.push_back(typeCount); |
| return *this; |
| } |
| } |
| } |
| |
| Move<VkDescriptorPool> DescriptorPoolBuilder::build (const DeviceInterface& vk, VkDevice device, VkDescriptorPoolCreateFlags flags, deUint32 maxSets, const void *pNext) const |
| { |
| const VkDescriptorPoolSize* const typeCountPtr = (m_counts.empty()) ? (DE_NULL) : (&m_counts[0]); |
| const VkDescriptorPoolCreateInfo createInfo = |
| { |
| VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, |
| pNext, |
| flags, |
| maxSets, |
| (deUint32)m_counts.size(), // poolSizeCount |
| typeCountPtr, // pPoolSizes |
| }; |
| |
| return createDescriptorPool(vk, device, &createInfo); |
| } |
| |
| // DescriptorSetUpdateBuilder |
| |
| DescriptorSetUpdateBuilder::DescriptorSetUpdateBuilder (void) |
| { |
| } |
| |
| DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::write (VkDescriptorSet destSet, |
| deUint32 destBinding, |
| deUint32 destArrayElement, |
| deUint32 count, |
| VkDescriptorType descriptorType, |
| const VkDescriptorImageInfo* pImageInfo, |
| const VkDescriptorBufferInfo* pBufferInfo, |
| const VkBufferView* pTexelBufferView) |
| { |
| // pImageInfo, pBufferInfo and pTexelBufferView will be updated when calling update() |
| const VkWriteDescriptorSet writeParams = |
| { |
| VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, |
| DE_NULL, |
| destSet, //!< destSet |
| destBinding, //!< destBinding |
| destArrayElement, //!< destArrayElement |
| count, //!< count |
| descriptorType, //!< descriptorType |
| DE_NULL, |
| DE_NULL, |
| DE_NULL |
| }; |
| |
| m_writes.push_back(writeParams); |
| |
| // Store a copy of pImageInfo, pBufferInfo and pTexelBufferView |
| WriteDescriptorInfo writeInfo; |
| |
| if (pImageInfo) |
| writeInfo.imageInfos.insert(writeInfo.imageInfos.end(), pImageInfo, pImageInfo + count); |
| |
| if (pBufferInfo) |
| writeInfo.bufferInfos.insert(writeInfo.bufferInfos.end(), pBufferInfo, pBufferInfo + count); |
| |
| if (pTexelBufferView) |
| writeInfo.texelBufferViews.insert(writeInfo.texelBufferViews.end(), pTexelBufferView, pTexelBufferView + count); |
| |
| m_writeDescriptorInfos.push_back(writeInfo); |
| |
| return *this; |
| } |
| |
| DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::copy (VkDescriptorSet srcSet, |
| deUint32 srcBinding, |
| deUint32 srcArrayElement, |
| VkDescriptorSet destSet, |
| deUint32 destBinding, |
| deUint32 destArrayElement, |
| deUint32 count) |
| { |
| const VkCopyDescriptorSet copyParams = |
| { |
| VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, |
| DE_NULL, |
| srcSet, //!< srcSet |
| srcBinding, //!< srcBinding |
| srcArrayElement, //!< srcArrayElement |
| destSet, //!< destSet |
| destBinding, //!< destBinding |
| destArrayElement, //!< destArrayElement |
| count, //!< count |
| }; |
| m_copies.push_back(copyParams); |
| return *this; |
| } |
| |
| void DescriptorSetUpdateBuilder::update (const DeviceInterface& vk, VkDevice device) const |
| { |
| // Update VkWriteDescriptorSet structures with stored info |
| std::vector<VkWriteDescriptorSet> writes = m_writes; |
| |
| for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++) |
| { |
| const WriteDescriptorInfo& writeInfo = m_writeDescriptorInfos[writeNdx]; |
| |
| if (!writeInfo.imageInfos.empty()) |
| writes[writeNdx].pImageInfo = &writeInfo.imageInfos[0]; |
| |
| if (!writeInfo.bufferInfos.empty()) |
| writes[writeNdx].pBufferInfo = &writeInfo.bufferInfos[0]; |
| |
| if (!writeInfo.texelBufferViews.empty()) |
| writes[writeNdx].pTexelBufferView = &writeInfo.texelBufferViews[0]; |
| } |
| |
| const VkWriteDescriptorSet* const writePtr = (m_writes.empty()) ? (DE_NULL) : (&writes[0]); |
| const VkCopyDescriptorSet* const copyPtr = (m_copies.empty()) ? (DE_NULL) : (&m_copies[0]); |
| |
| vk.updateDescriptorSets(device, (deUint32)writes.size(), writePtr, (deUint32)m_copies.size(), copyPtr); |
| } |
| |
| void DescriptorSetUpdateBuilder::updateWithPush (const DeviceInterface& vk, VkCommandBuffer cmd, VkPipelineBindPoint bindPoint, VkPipelineLayout pipelineLayout, deUint32 setIdx, deUint32 descriptorIdx, deUint32 numDescriptors) const |
| { |
| // Write all descriptors or just a subset? |
| deUint32 count = (numDescriptors) ? numDescriptors : (deUint32)m_writes.size(); |
| |
| // Update VkWriteDescriptorSet structures with stored info |
| std::vector<VkWriteDescriptorSet> writes = m_writes; |
| |
| for (size_t writeNdx = 0; writeNdx < m_writes.size(); writeNdx++) |
| { |
| const WriteDescriptorInfo& writeInfo = m_writeDescriptorInfos[writeNdx]; |
| |
| if (!writeInfo.imageInfos.empty()) |
| writes[writeNdx].pImageInfo = &writeInfo.imageInfos[0]; |
| |
| if (!writeInfo.bufferInfos.empty()) |
| writes[writeNdx].pBufferInfo = &writeInfo.bufferInfos[0]; |
| |
| if (!writeInfo.texelBufferViews.empty()) |
| writes[writeNdx].pTexelBufferView = &writeInfo.texelBufferViews[0]; |
| } |
| |
| const VkWriteDescriptorSet* const writePtr = (m_writes.empty()) ? (DE_NULL) : (&writes[descriptorIdx]); |
| |
| vk.cmdPushDescriptorSetKHR(cmd, bindPoint, pipelineLayout, setIdx, count, writePtr); |
| } |
| |
| void DescriptorSetUpdateBuilder::clear(void) |
| { |
| m_writeDescriptorInfos.clear(); |
| m_writes.clear(); |
| m_copies.clear(); |
| } |
| |
| } // vk |