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 if(pCreateInfo->pSetLayouts[i] == VK_NULL_HANDLE)
37 {
38 continue;
39 }
40 const vk::DescriptorSetLayout *setLayout = vk::Cast(pCreateInfo->pSetLayouts[i]);
41 uint32_t bindingsArraySize = setLayout->getBindingsArraySize();
42 descriptorSets[i].bindings = bindingStorage;
43 bindingStorage += bindingsArraySize;
44 descriptorSets[i].bindingCount = bindingsArraySize;
45
46 for(uint32_t j = 0; j < bindingsArraySize; j++)
47 {
48 descriptorSets[i].bindings[j].descriptorType = setLayout->getDescriptorType(j);
49 descriptorSets[i].bindings[j].offset = setLayout->getBindingOffset(j);
50 descriptorSets[i].bindings[j].dynamicOffsetIndex = dynamicOffsetIndex;
51 descriptorSets[i].bindings[j].descriptorCount = setLayout->getDescriptorCount(j);
52
53 if(DescriptorSetLayout::IsDescriptorDynamic(descriptorSets[i].bindings[j].descriptorType))
54 {
55 dynamicOffsetIndex += setLayout->getDescriptorCount(j);
56 }
57 }
58 }
59
60 size_t pushConstantRangesSize = pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange);
61 pushConstantRanges = reinterpret_cast<VkPushConstantRange *>(bindingStorage);
62 memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize);
63
64 incRefCount();
65 }
66
destroy(const VkAllocationCallbacks * pAllocator)67 void PipelineLayout::destroy(const VkAllocationCallbacks *pAllocator)
68 {
69 vk::freeHostMemory(descriptorSets[0].bindings, pAllocator); // pushConstantRanges are in the same allocation
70 }
71
release(const VkAllocationCallbacks * pAllocator)72 bool PipelineLayout::release(const VkAllocationCallbacks *pAllocator)
73 {
74 if(decRefCount() == 0)
75 {
76 vk::freeHostMemory(descriptorSets[0].bindings, pAllocator); // pushConstantRanges are in the same allocation
77 return true;
78 }
79 return false;
80 }
81
ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo * pCreateInfo)82 size_t PipelineLayout::ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo)
83 {
84 uint32_t bindingsCount = 0;
85 for(uint32_t i = 0; i < pCreateInfo->setLayoutCount; i++)
86 {
87 if(pCreateInfo->pSetLayouts[i] == VK_NULL_HANDLE)
88 {
89 continue;
90 }
91 bindingsCount += vk::Cast(pCreateInfo->pSetLayouts[i])->getBindingsArraySize();
92 }
93
94 return bindingsCount * sizeof(Binding) + // descriptorSets[]
95 pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange); // pushConstantRanges[]
96 }
97
getDescriptorSetCount() const98 size_t PipelineLayout::getDescriptorSetCount() const
99 {
100 return descriptorSetCount;
101 }
102
getBindingCount(uint32_t setNumber) const103 uint32_t PipelineLayout::getBindingCount(uint32_t setNumber) const
104 {
105 return descriptorSets[setNumber].bindingCount;
106 }
107
getDynamicOffsetIndex(uint32_t setNumber,uint32_t bindingNumber) const108 uint32_t PipelineLayout::getDynamicOffsetIndex(uint32_t setNumber, uint32_t bindingNumber) const
109 {
110 ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
111 return descriptorSets[setNumber].bindings[bindingNumber].dynamicOffsetIndex;
112 }
113
getDescriptorCount(uint32_t setNumber,uint32_t bindingNumber) const114 uint32_t PipelineLayout::getDescriptorCount(uint32_t setNumber, uint32_t bindingNumber) const
115 {
116 ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
117 return descriptorSets[setNumber].bindings[bindingNumber].descriptorCount;
118 }
119
getBindingOffset(uint32_t setNumber,uint32_t bindingNumber) const120 uint32_t PipelineLayout::getBindingOffset(uint32_t setNumber, uint32_t bindingNumber) const
121 {
122 ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
123 return descriptorSets[setNumber].bindings[bindingNumber].offset;
124 }
125
getDescriptorType(uint32_t setNumber,uint32_t bindingNumber) const126 VkDescriptorType PipelineLayout::getDescriptorType(uint32_t setNumber, uint32_t bindingNumber) const
127 {
128 ASSERT(setNumber < descriptorSetCount && bindingNumber < descriptorSets[setNumber].bindingCount);
129 return descriptorSets[setNumber].bindings[bindingNumber].descriptorType;
130 }
131
getDescriptorSize(uint32_t setNumber,uint32_t bindingNumber) const132 uint32_t PipelineLayout::getDescriptorSize(uint32_t setNumber, uint32_t bindingNumber) const
133 {
134 return DescriptorSetLayout::GetDescriptorSize(getDescriptorType(setNumber, bindingNumber));
135 }
136
isDescriptorDynamic(uint32_t setNumber,uint32_t bindingNumber) const137 bool PipelineLayout::isDescriptorDynamic(uint32_t setNumber, uint32_t bindingNumber) const
138 {
139 return DescriptorSetLayout::IsDescriptorDynamic(getDescriptorType(setNumber, bindingNumber));
140 }
141
incRefCount()142 uint32_t PipelineLayout::incRefCount()
143 {
144 return ++refCount;
145 }
146
decRefCount()147 uint32_t PipelineLayout::decRefCount()
148 {
149 return --refCount;
150 }
151
152 } // namespace vk
153