blob: 098e736af3e0d2369f039879771cefc31d7a51bc [file] [log] [blame]
Ben Claytonabb57852019-03-01 14:33:35 +00001// 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
18Device::Device()
19 : driver(nullptr),
20 device(nullptr),
21 physicalDevice(nullptr),
22 queueFamilyIndex(0) {}
23
24Device::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
Ben Clayton40f3d982019-03-21 18:26:46 +000032Device::~Device()
33{
34 if (device != nullptr)
35 {
36 driver->vkDeviceWaitIdle(device);
37 driver->vkDestroyDevice(device, nullptr);
38 }
39}
40
Ben Claytonabb57852019-03-01 14:33:35 +000041bool Device::IsValid() const { return device != nullptr; }
42
43VkResult Device::CreateComputeDevice(
Ben Clayton40f3d982019-03-21 18:26:46 +000044 Driver const *driver, VkInstance instance, std::unique_ptr<Device> &out)
Ben Claytonabb57852019-03-01 14:33:35 +000045{
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;
Ben Clayton40f3d982019-03-21 18:26:46 +000089 result = driver->vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device);
Ben Claytonabb57852019-03-01 14:33:35 +000090 if (result != VK_SUCCESS)
91 {
92 return result;
93 }
94
Ben Clayton40f3d982019-03-21 18:26:46 +000095 out.reset(new Device(driver, device, physicalDevice, static_cast<uint32_t>(queueFamilyIndex)));
Ben Claytonabb57852019-03-01 14:33:35 +000096 return VK_SUCCESS;
97 }
98
99 return VK_SUCCESS;
100}
101
102int 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
116std::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
128VkResult 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
142VkResult 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
174VkResult 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
187VkResult 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
202VkResult 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
218VkResult 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
244VkResult 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
264VkResult 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
279void 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
304VkResult 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
334VkResult 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
340void Device::UnmapMemory(VkDeviceMemory memory) const
341{
342 driver->vkUnmapMemory(device, memory);
343}
344
345VkResult 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
356VkResult 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
369VkResult Device::BeginCommandBuffer(
Nicolas Capensda1ed062019-03-12 11:23:28 -0400370 VkCommandBufferUsageFlags usage, VkCommandBuffer commandBuffer) const
Ben Claytonabb57852019-03-01 14:33:35 +0000371{
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
382VkResult 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}