• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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