OSDN Git Service

VulkanUnitTests: Call vkDestroyDevice()
[android-x86/external-swiftshader.git] / tests / VulkanUnitTests / Device.cpp
1 // Copyright 2019 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 "Device.hpp"
16 #include "Driver.hpp"
17
18 Device::Device()
19                 : driver(nullptr),
20                   device(nullptr),
21                   physicalDevice(nullptr),
22                   queueFamilyIndex(0) {}
23
24 Device::Device(
25                 Driver const *driver, VkDevice device, VkPhysicalDevice physicalDevice,
26                 uint32_t queueFamilyIndex)
27         : driver(driver),
28           device(device),
29           physicalDevice(physicalDevice),
30           queueFamilyIndex(queueFamilyIndex) {}
31
32 Device::~Device()
33 {
34         if (device != nullptr)
35         {
36                 driver->vkDeviceWaitIdle(device);
37                 driver->vkDestroyDevice(device, nullptr);
38         }
39 }
40
41 bool Device::IsValid() const { return device != nullptr; }
42
43 VkResult Device::CreateComputeDevice(
44                 Driver const *driver, VkInstance instance, std::unique_ptr<Device> &out)
45 {
46     VkResult result;
47
48     // Gather all physical devices
49     std::vector<VkPhysicalDevice> physicalDevices;
50     result = GetPhysicalDevices(driver, instance, physicalDevices);
51     if (result != VK_SUCCESS)
52     {
53                 return result;
54     }
55
56     // Inspect each physical device's queue families for compute support.
57     for (auto physicalDevice : physicalDevices)
58     {
59         int queueFamilyIndex = GetComputeQueueFamilyIndex(driver, physicalDevice);
60         if (queueFamilyIndex < 0)
61         {
62             continue;
63         }
64
65         const float queuePrioritory = 1.0f;
66         const VkDeviceQueueCreateInfo deviceQueueCreateInfo = {
67             VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,  // sType
68             nullptr,                                     // pNext
69             0,                                           // flags
70             (uint32_t)queueFamilyIndex,                  // queueFamilyIndex
71             1,                                           // queueCount
72             &queuePrioritory,                            // pQueuePriorities
73         };
74
75         const VkDeviceCreateInfo deviceCreateInfo = {
76             VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,  // sType
77             nullptr,                               // pNext
78             0,                                     // flags
79             1,                                     // queueCreateInfoCount
80             &deviceQueueCreateInfo,                // pQueueCreateInfos
81             0,                                     // enabledLayerCount
82             nullptr,                               // ppEnabledLayerNames
83             0,                                     // enabledExtensionCount
84             nullptr,                               // ppEnabledExtensionNames
85             nullptr,                               // pEnabledFeatures
86         };
87
88         VkDevice device;
89         result = driver->vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device);
90         if (result != VK_SUCCESS)
91         {
92             return result;
93         }
94
95                 out.reset(new Device(driver, device, physicalDevice, static_cast<uint32_t>(queueFamilyIndex)));
96         return VK_SUCCESS;
97     }
98
99     return VK_SUCCESS;
100 }
101
102 int Device::GetComputeQueueFamilyIndex(
103                 Driver const *driver, VkPhysicalDevice device)
104 {
105     auto properties = GetPhysicalDeviceQueueFamilyProperties(driver, device);
106     for (uint32_t i = 0; i < properties.size(); i++)
107     {
108         if ((properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)
109         {
110             return static_cast<int>(i);
111         }
112     }
113     return -1;
114 }
115
116 std::vector<VkQueueFamilyProperties>
117                 Device::GetPhysicalDeviceQueueFamilyProperties(
118                                 Driver const *driver, VkPhysicalDevice device)
119 {
120     std::vector<VkQueueFamilyProperties> out;
121     uint32_t count = 0;
122     driver->vkGetPhysicalDeviceQueueFamilyProperties(device, &count, nullptr);
123     out.resize(count);
124     driver->vkGetPhysicalDeviceQueueFamilyProperties(device, &count, out.data());
125     return out;
126 }
127
128 VkResult Device::GetPhysicalDevices(
129                 const Driver* driver, VkInstance instance,
130                 std::vector<VkPhysicalDevice>& out)
131 {
132     uint32_t count = 0;
133     VkResult result = driver->vkEnumeratePhysicalDevices(instance, &count, 0);
134     if (result != VK_SUCCESS)
135     {
136         return result;
137     }
138     out.resize(count);
139     return driver->vkEnumeratePhysicalDevices(instance, &count, out.data());
140 }
141
142 VkResult Device::CreateStorageBuffer(
143                 VkDeviceMemory memory, VkDeviceSize size,
144                 VkDeviceSize offset, VkBuffer* out) const
145 {
146         const VkBufferCreateInfo info = {
147                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
148                 nullptr,                              // pNext
149                 0,                                    // flags
150                 size,                                 // size
151                 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,   // usage
152                 VK_SHARING_MODE_EXCLUSIVE,            // sharingMode
153                 0,                                    // queueFamilyIndexCount
154                 nullptr,                              // pQueueFamilyIndices
155         };
156
157         VkBuffer buffer;
158         VkResult result = driver->vkCreateBuffer(device, &info, 0, &buffer);
159         if (result != VK_SUCCESS)
160         {
161                 return result;
162         }
163
164         result = driver->vkBindBufferMemory(device, buffer, memory, offset);
165         if (result != VK_SUCCESS)
166         {
167                 return result;
168         }
169
170         *out = buffer;
171         return VK_SUCCESS;
172 }
173
174 VkResult Device::CreateShaderModule(
175                 const std::vector<uint32_t>& spirv, VkShaderModule* out) const
176 {
177         VkShaderModuleCreateInfo info = {
178                 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // sType
179                 nullptr,                                     // pNext
180                 0,                                           // flags
181                 spirv.size() * 4,                            // codeSize
182                 spirv.data(),                                // pCode
183         };
184         return driver->vkCreateShaderModule(device, &info, 0, out);
185 }
186
187 VkResult Device::CreateDescriptorSetLayout(
188                 const std::vector<VkDescriptorSetLayoutBinding>& bindings,
189                 VkDescriptorSetLayout* out) const
190 {
191         VkDescriptorSetLayoutCreateInfo info = {
192                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
193                 nullptr,                                             // pNext
194                 0,                                                   // flags
195                 (uint32_t)bindings.size(),                           // bindingCount
196                 bindings.data(),                                     // pBindings
197         };
198
199         return driver->vkCreateDescriptorSetLayout(device, &info, 0, out);
200 }
201
202 VkResult Device::CreatePipelineLayout(
203                 VkDescriptorSetLayout layout, VkPipelineLayout* out) const
204 {
205         VkPipelineLayoutCreateInfo info = {
206                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
207                 nullptr,                                       // pNext
208                 0,                                             // flags
209                 1,                                             // setLayoutCount
210                 &layout,                                       // pSetLayouts
211                 0,                                             // pushConstantRangeCount
212                 nullptr,                                       // pPushConstantRanges
213         };
214
215         return driver->vkCreatePipelineLayout(device, &info, 0, out);
216 }
217
218 VkResult Device::CreateComputePipeline(
219                 VkShaderModule module, VkPipelineLayout pipelineLayout,
220                 VkPipeline* out) const
221 {
222         VkComputePipelineCreateInfo info = {
223                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
224                 nullptr,                                        // pNext
225                 0,                                              // flags
226                 {
227                         // stage
228                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
229                         nullptr,                                             // pNext
230                         0,                                                   // flags
231                         VK_SHADER_STAGE_COMPUTE_BIT,                         // stage
232                         module,                                              // module
233                         "main",                                              // pName
234                         nullptr,                                             // pSpecializationInfo
235                 },
236                 pipelineLayout, // layout
237                 0,              // basePipelineHandle
238                 0,              // basePipelineIndex
239         };
240
241         return driver->vkCreateComputePipelines(device, 0, 1, &info, 0, out);
242 }
243
244 VkResult Device::CreateStorageBufferDescriptorPool(uint32_t descriptorCount,
245                 VkDescriptorPool* out) const
246 {
247         VkDescriptorPoolSize size = {
248                 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // type
249                 descriptorCount,                   // descriptorCount
250         };
251
252         VkDescriptorPoolCreateInfo info = {
253                 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
254                 nullptr,                                       // pNext
255                 0,                                             // flags
256                 1,                                             // maxSets
257                 1,                                             // poolSizeCount
258                 &size,                                         // pPoolSizes
259         };
260
261         return driver->vkCreateDescriptorPool(device, &info, 0, out);
262 }
263
264 VkResult Device::AllocateDescriptorSet(
265                 VkDescriptorPool pool, VkDescriptorSetLayout layout,
266                 VkDescriptorSet* out) const
267 {
268         VkDescriptorSetAllocateInfo info = {
269                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
270                 nullptr,                                        // pNext
271                 pool,                                           // descriptorPool
272                 1,                                              // descriptorSetCount
273                 &layout,                                        // pSetLayouts
274         };
275
276         return driver->vkAllocateDescriptorSets(device, &info, out);
277 }
278
279 void Device::UpdateStorageBufferDescriptorSets(
280                 VkDescriptorSet descriptorSet,
281                 const std::vector<VkDescriptorBufferInfo>& bufferInfos) const
282 {
283         std::vector<VkWriteDescriptorSet> writes;
284         writes.reserve(bufferInfos.size());
285         for (uint32_t i = 0; i < bufferInfos.size(); i++)
286         {
287                 writes.push_back(VkWriteDescriptorSet{
288                         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
289                         nullptr,                                // pNext
290                         descriptorSet,                          // dstSet
291                         i,                                      // dstBinding
292                         0,                                      // dstArrayElement
293                         1,                                      // descriptorCount
294                         VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,      // descriptorType
295                         nullptr,                                // pImageInfo
296                         &bufferInfos[i],                        // pBufferInfo
297                         nullptr,                                // pTexelBufferView
298                 });
299         }
300
301         driver->vkUpdateDescriptorSets(device, writes.size(), writes.data(), 0, nullptr);
302 }
303
304 VkResult Device::AllocateMemory(size_t size, VkMemoryPropertyFlags flags, VkDeviceMemory* out) const
305 {
306         VkPhysicalDeviceMemoryProperties properties;
307         driver->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &properties);
308
309         for(uint32_t type = 0; type < properties.memoryTypeCount; type++)
310         {
311                 if ((flags & properties.memoryTypes[type].propertyFlags) == 0)
312                 {
313                         continue;  // Type mismatch
314                 }
315
316                 if (size > properties.memoryHeaps[properties.memoryTypes[type].heapIndex].size)
317                 {
318                         continue;  // Too small.
319                 }
320
321                 const VkMemoryAllocateInfo info = {
322                         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,  // sType
323                         nullptr,                                 // pNext
324                         size,                                    // allocationSize
325                         type,                                    // memoryTypeIndex
326                 };
327
328                 return driver->vkAllocateMemory(device, &info, 0, out);
329         }
330
331     return VK_ERROR_OUT_OF_DEVICE_MEMORY; // TODO: Change to something not made up?
332 }
333
334 VkResult Device::MapMemory(VkDeviceMemory memory, VkDeviceSize offset,
335                 VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) const
336 {
337         return driver->vkMapMemory(device, memory, offset, size, flags, ppData);
338 }
339
340 void Device::UnmapMemory(VkDeviceMemory memory) const
341 {
342         driver->vkUnmapMemory(device, memory);
343 }
344
345 VkResult Device::CreateCommandPool(VkCommandPool* out) const
346 {
347     VkCommandPoolCreateInfo info = {
348         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,  // sType
349         nullptr,                                     // pNext
350         0,                                           // flags
351         queueFamilyIndex,                            // queueFamilyIndex
352     };
353     return driver->vkCreateCommandPool(device, &info, 0, out);
354 }
355
356 VkResult Device::AllocateCommandBuffer(
357                 VkCommandPool pool, VkCommandBuffer* out) const
358 {
359     VkCommandBufferAllocateInfo info = {
360         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,  // sType
361         nullptr,                                         // pNext
362         pool,                                            // commandPool
363         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                 // level
364         1,                                               // commandBufferCount
365     };
366     return driver->vkAllocateCommandBuffers(device, &info, out);
367 }
368
369 VkResult Device::BeginCommandBuffer(
370                 VkCommandBufferUsageFlags usage, VkCommandBuffer commandBuffer) const
371 {
372     VkCommandBufferBeginInfo info = {
373         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,  // sType
374         nullptr,                                      // pNext
375         usage,                                        // flags
376         nullptr,                                      // pInheritanceInfo
377     };
378
379     return driver->vkBeginCommandBuffer(commandBuffer, &info);
380 }
381
382 VkResult Device::QueueSubmitAndWait(VkCommandBuffer commandBuffer) const
383 {
384     VkQueue queue;
385     driver->vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue);
386
387     VkSubmitInfo info = {
388         VK_STRUCTURE_TYPE_SUBMIT_INFO,  // sType
389         nullptr,                        // pNext
390         0,                              // waitSemaphoreCount
391         nullptr,                        // pWaitSemaphores
392         nullptr,                        // pWaitDstStageMask
393         1,                              // commandBufferCount
394         &commandBuffer,                 // pCommandBuffers
395         0,                              // signalSemaphoreCount
396         nullptr,                        // pSignalSemaphores
397     };
398
399     VkResult result = driver->vkQueueSubmit(queue, 1, &info, 0);
400     if (result != VK_SUCCESS)
401     {
402         return result;
403     }
404
405     return driver->vkQueueWaitIdle(queue);
406 }