blob: f6d19170c3d72fb8c7a6ddb6ffde199aebd2845a [file] [log] [blame]
// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// 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.
#include "VkPipelineLayout.hpp"
#include <atomic>
#include <cstring>
namespace vk {
static std::atomic<uint32_t> layoutIdentifierSerial = { 1 }; // Start at 1. 0 is invalid/void layout.
PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, void *mem)
: identifier(layoutIdentifierSerial++)
, descriptorSetCount(pCreateInfo->setLayoutCount)
, pushConstantRangeCount(pCreateInfo->pushConstantRangeCount)
{
Binding *bindingStorage = reinterpret_cast<Binding *>(mem);
uint32_t dynamicOffsetIndex = 0;
descriptorSets[0].bindings = bindingStorage; // Used in destroy() for deallocation.
for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
{
if(pCreateInfo->pSetLayouts[i] == VK_NULL_HANDLE)
{
continue;
}
const vk::DescriptorSetLayout *setLayout = vk::Cast(pCreateInfo->pSetLayouts[i]);
uint32_t bindingsArraySize = setLayout->getBindingsArraySize();
descriptorSets[i].bindings = bindingStorage;
bindingStorage += bindingsArraySize;
descriptorSets[i].bindingCount = bindingsArraySize;
for(uint32_t j = 0; j < bindingsArraySize; j++)
{
descriptorSets[i].bindings[j].descriptorType = setLayout->getDescriptorType(j);
descriptorSets[i].bindings[j].offset = setLayout->getBindingOffset(j);
descriptorSets[i].bindings[j].dynamicOffsetIndex = dynamicOffsetIndex;
descriptorSets[i].bindings[j].descriptorCount = setLayout->getDescriptorCount(j);
if(DescriptorSetLayout::IsDescriptorDynamic(descriptorSets[i].bindings[j].descriptorType))
{
dynamicOffsetIndex += setLayout->getDescriptorCount(j);
}
}
}
size_t pushConstantRangesSize = pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange);
pushConstantRanges = reinterpret_cast<VkPushConstantRange *>(bindingStorage);
memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize);
incRefCount();
}
void PipelineLayout::destroy(const VkAllocationCallbacks *pAllocator)
{
vk::freeHostMemory(descriptorSets[0].bindings, pAllocator); // pushConstantRanges are in the same allocation
}
bool PipelineLayout::release(const VkAllocationCallbacks *pAllocator)
{
if(decRefCount() == 0)
{
vk::freeHostMemory(descriptorSets[0].bindings, pAllocator); // pushConstantRanges are in the same allocation
return true;
}
return false;
}
size_t PipelineLayout::ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo)
{
uint32_t bindingsCount = 0;
for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
{
if(pCreateInfo->pSetLayouts[i] == VK_NULL_HANDLE)
{
continue;
}
bindingsCount += vk::Cast(pCreateInfo->pSetLayouts[i])->getBindingsArraySize();
}
return bindingsCount * sizeof(Binding) + // descriptorSets[]
pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange); // pushConstantRanges[]
}
size_t PipelineLayout::getDescriptorSetCount() const
{
return descriptorSetCount;
}
uint32_t PipelineLayout::getBindingCount(uint32_t setNumber) const
{
return descriptorSets[setNumber].bindingCount;
}
uint32_t PipelineLayout::getDynamicOffsetIndex(uint32_t setNumber, uint32_t bindingNumber) const
{
ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
return descriptorSets[setNumber].bindings[bindingNumber].dynamicOffsetIndex;
}
uint32_t PipelineLayout::getDescriptorCount(uint32_t setNumber, uint32_t bindingNumber) const
{
ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
return descriptorSets[setNumber].bindings[bindingNumber].descriptorCount;
}
uint32_t PipelineLayout::getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const
{
ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
return descriptorSets[setNumber].bindings[bindingNumber].offset;
}
VkDescriptorType PipelineLayout::getDescriptorType(uint32_t setNumber, uint32_t bindingNumber) const
{
ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
return descriptorSets[setNumber].bindings[bindingNumber].descriptorType;
}
uint32_t PipelineLayout::getDescriptorSize(uint32_t setNumber, uint32_t bindingNumber) const
{
return DescriptorSetLayout::GetDescriptorSize(getDescriptorType(setNumber, bindingNumber));
}
bool PipelineLayout::isDescriptorDynamic(uint32_t setNumber, uint32_t bindingNumber) const
{
return DescriptorSetLayout::IsDescriptorDynamic(getDescriptorType(setNumber, bindingNumber));
}
uint32_t PipelineLayout::incRefCount()
{
return ++refCount;
}
uint32_t PipelineLayout::decRefCount()
{
return --refCount;
}
} // namespace vk