blob: dde58c6badc9861c383d7ef8fe5c66670129fe96 [file] [log] [blame]
/*-------------------------------------------------------------------------
* 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,
uint32_t descriptorCount,
VkShaderStageFlags stageFlags,
const VkSampler *pImmutableSamplers)
{
if (pImmutableSamplers)
{
const ImmutableSamplerInfo immutableSamplerInfo = {(uint32_t)m_bindings.size(),
(uint32_t)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 = {
(uint32_t)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,
uint32_t descriptorCount,
VkShaderStageFlags stageFlags,
uint32_t dstBinding,
const VkSampler *pImmutableSamplers)
{
if (pImmutableSamplers)
{
const ImmutableSamplerInfo immutableSamplerInfo = {(uint32_t)dstBinding, (uint32_t)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];
uint32_t bindingNdx = 0;
while (bindings[bindingNdx].binding != samplerInfo.bindingIndex)
{
bindingNdx++;
if (bindingNdx >= (uint32_t)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
(uint32_t)bindings.size(), // bindingCount
(bindings.empty()) ? (DE_NULL) : (&bindings.front()), // pBinding
};
return createDescriptorSetLayout(vk, device, &createInfo);
}
// DescriptorPoolBuilder
DescriptorPoolBuilder::DescriptorPoolBuilder(void)
{
}
DescriptorPoolBuilder &DescriptorPoolBuilder::addType(VkDescriptorType type, uint32_t 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, uint32_t 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,
(uint32_t)m_counts.size(), // poolSizeCount
typeCountPtr, // pPoolSizes
};
return createDescriptorPool(vk, device, &createInfo);
}
// DescriptorSetUpdateBuilder
DescriptorSetUpdateBuilder::DescriptorSetUpdateBuilder(void)
{
}
DescriptorSetUpdateBuilder &DescriptorSetUpdateBuilder::write(VkDescriptorSet destSet, uint32_t destBinding,
uint32_t destArrayElement, uint32_t count,
VkDescriptorType descriptorType,
const VkDescriptorImageInfo *pImageInfo,
const VkDescriptorBufferInfo *pBufferInfo,
const VkBufferView *pTexelBufferView, const void *pNext)
{
// pImageInfo, pBufferInfo and pTexelBufferView will be updated when calling update()
const VkWriteDescriptorSet writeParams = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
pNext,
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, uint32_t srcBinding,
uint32_t srcArrayElement, VkDescriptorSet destSet,
uint32_t destBinding, uint32_t destArrayElement,
uint32_t 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, (uint32_t)writes.size(), writePtr, (uint32_t)m_copies.size(), copyPtr);
}
#ifndef CTS_USES_VULKANSC
void DescriptorSetUpdateBuilder::updateWithPush(const DeviceInterface &vk, VkCommandBuffer cmd,
VkPipelineBindPoint bindPoint, VkPipelineLayout pipelineLayout,
uint32_t setIdx, uint32_t descriptorIdx, uint32_t numDescriptors) const
{
// Write all descriptors or just a subset?
uint32_t count = (numDescriptors) ? numDescriptors : (uint32_t)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);
}
#endif // CTS_USES_VULKANSC
void DescriptorSetUpdateBuilder::clear(void)
{
m_writeDescriptorInfos.clear();
m_writes.clear();
m_copies.clear();
}
} // namespace vk