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