1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
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 "VkPipelineLayout.hpp"
16 
17 #include <atomic>
18 #include <cstring>
19 
20 namespace vk {
21 
22 static std::atomic<uint32_t> layoutIdentifierSerial = { 1 };  // Start at 1. 0 is invalid/void layout.
23 
PipelineLayout(const VkPipelineLayoutCreateInfo * pCreateInfo,void * mem)24 PipelineLayout::PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, void *mem)
25     : identifier(layoutIdentifierSerial++)
26     , descriptorSetCount(pCreateInfo->setLayoutCount)
27     , pushConstantRangeCount(pCreateInfo->pushConstantRangeCount)
28 {
29 	Binding *bindingStorage = reinterpret_cast<Binding *>(mem);
30 	uint32_t dynamicOffsetIndex = 0;
31 
32 	descriptorSets[0].bindings = bindingStorage;  // Used in destroy() for deallocation.
33 
34 	for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
35 	{
36 		const vk::DescriptorSetLayout *setLayout = vk::Cast(pCreateInfo->pSetLayouts[i]);
37 		uint32_t bindingsArraySize = setLayout->getBindingsArraySize();
38 		descriptorSets[i].bindings = bindingStorage;
39 		bindingStorage += bindingsArraySize;
40 		descriptorSets[i].bindingCount = bindingsArraySize;
41 
42 		for(uint32_t j = 0; j < bindingsArraySize; j++)
43 		{
44 			descriptorSets[i].bindings[j].descriptorType = setLayout->getDescriptorType(j);
45 			descriptorSets[i].bindings[j].offset = setLayout->getBindingOffset(j);
46 			descriptorSets[i].bindings[j].dynamicOffsetIndex = dynamicOffsetIndex;
47 			descriptorSets[i].bindings[j].descriptorCount = setLayout->getDescriptorCount(j);
48 
49 			if(DescriptorSetLayout::IsDescriptorDynamic(descriptorSets[i].bindings[j].descriptorType))
50 			{
51 				dynamicOffsetIndex += setLayout->getDescriptorCount(j);
52 			}
53 		}
54 	}
55 
56 	size_t pushConstantRangesSize = pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange);
57 	pushConstantRanges = reinterpret_cast<VkPushConstantRange *>(bindingStorage);
58 	memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize);
59 
60 	incRefCount();
61 }
62 
destroy(const VkAllocationCallbacks * pAllocator)63 void PipelineLayout::destroy(const VkAllocationCallbacks *pAllocator)
64 {
65 	vk::deallocate(descriptorSets[0].bindings, pAllocator);  // pushConstantRanges are in the same allocation
66 }
67 
release(const VkAllocationCallbacks * pAllocator)68 bool PipelineLayout::release(const VkAllocationCallbacks *pAllocator)
69 {
70 	if(decRefCount() == 0)
71 	{
72 		vk::deallocate(descriptorSets[0].bindings, pAllocator);  // pushConstantRanges are in the same allocation
73 		return true;
74 	}
75 	return false;
76 }
77 
ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo * pCreateInfo)78 size_t PipelineLayout::ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo)
79 {
80 	uint32_t bindingsCount = 0;
81 	for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
82 	{
83 		bindingsCount += vk::Cast(pCreateInfo->pSetLayouts[i])->getBindingsArraySize();
84 	}
85 
86 	return bindingsCount * sizeof(Binding) +                                   // descriptorSets[]
87 	       pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange);  // pushConstantRanges[]
88 }
89 
getDescriptorSetCount() const90 size_t PipelineLayout::getDescriptorSetCount() const
91 {
92 	return descriptorSetCount;
93 }
94 
getBindingCount(uint32_t setNumber) const95 uint32_t PipelineLayout::getBindingCount(uint32_t setNumber) const
96 {
97 	return descriptorSets[setNumber].bindingCount;
98 }
99 
getDynamicOffsetIndex(uint32_t setNumber,uint32_t bindingNumber) const100 uint32_t PipelineLayout::getDynamicOffsetIndex(uint32_t setNumber, uint32_t bindingNumber) const
101 {
102 	ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
103 	return descriptorSets[setNumber].bindings[bindingNumber].dynamicOffsetIndex;
104 }
105 
getDescriptorCount(uint32_t setNumber,uint32_t bindingNumber) const106 uint32_t PipelineLayout::getDescriptorCount(uint32_t setNumber, uint32_t bindingNumber) const
107 {
108 	ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
109 	return descriptorSets[setNumber].bindings[bindingNumber].descriptorCount;
110 }
111 
getBindingOffset(uint32_t setNumber,uint32_t bindingNumber) const112 uint32_t PipelineLayout::getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const
113 {
114 	ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
115 	return descriptorSets[setNumber].bindings[bindingNumber].offset;
116 }
117 
getDescriptorType(uint32_t setNumber,uint32_t bindingNumber) const118 VkDescriptorType PipelineLayout::getDescriptorType(uint32_t setNumber, uint32_t bindingNumber) const
119 {
120 	ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
121 	return descriptorSets[setNumber].bindings[bindingNumber].descriptorType;
122 }
123 
getDescriptorSize(uint32_t setNumber,uint32_t bindingNumber) const124 uint32_t PipelineLayout::getDescriptorSize(uint32_t setNumber, uint32_t bindingNumber) const
125 {
126 	return DescriptorSetLayout::GetDescriptorSize(getDescriptorType(setNumber, bindingNumber));
127 }
128 
isDescriptorDynamic(uint32_t setNumber,uint32_t bindingNumber) const129 bool PipelineLayout::isDescriptorDynamic(uint32_t setNumber, uint32_t bindingNumber) const
130 {
131 	return DescriptorSetLayout::IsDescriptorDynamic(getDescriptorType(setNumber, bindingNumber));
132 }
133 
incRefCount()134 uint32_t PipelineLayout::incRefCount()
135 {
136 	return ++refCount;
137 }
138 
decRefCount()139 uint32_t PipelineLayout::decRefCount()
140 {
141 	return --refCount;
142 }
143 
144 }  // namespace vk
145