1 // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
21 physicalDevice(nullptr),
22 queueFamilyIndex(0) {}
25 Driver const *driver, VkDevice device, VkPhysicalDevice physicalDevice,
26 uint32_t queueFamilyIndex)
29 physicalDevice(physicalDevice),
30 queueFamilyIndex(queueFamilyIndex) {}
34 if (device != nullptr)
36 driver->vkDeviceWaitIdle(device);
37 driver->vkDestroyDevice(device, nullptr);
41 bool Device::IsValid() const { return device != nullptr; }
43 VkResult Device::CreateComputeDevice(
44 Driver const *driver, VkInstance instance, std::unique_ptr<Device> &out)
48 // Gather all physical devices
49 std::vector<VkPhysicalDevice> physicalDevices;
50 result = GetPhysicalDevices(driver, instance, physicalDevices);
51 if (result != VK_SUCCESS)
56 // Inspect each physical device's queue families for compute support.
57 for (auto physicalDevice : physicalDevices)
59 int queueFamilyIndex = GetComputeQueueFamilyIndex(driver, physicalDevice);
60 if (queueFamilyIndex < 0)
65 const float queuePrioritory = 1.0f;
66 const VkDeviceQueueCreateInfo deviceQueueCreateInfo = {
67 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
70 (uint32_t)queueFamilyIndex, // queueFamilyIndex
72 &queuePrioritory, // pQueuePriorities
75 const VkDeviceCreateInfo deviceCreateInfo = {
76 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
79 1, // queueCreateInfoCount
80 &deviceQueueCreateInfo, // pQueueCreateInfos
81 0, // enabledLayerCount
82 nullptr, // ppEnabledLayerNames
83 0, // enabledExtensionCount
84 nullptr, // ppEnabledExtensionNames
85 nullptr, // pEnabledFeatures
89 result = driver->vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device);
90 if (result != VK_SUCCESS)
95 out.reset(new Device(driver, device, physicalDevice, static_cast<uint32_t>(queueFamilyIndex)));
102 int Device::GetComputeQueueFamilyIndex(
103 Driver const *driver, VkPhysicalDevice device)
105 auto properties = GetPhysicalDeviceQueueFamilyProperties(driver, device);
106 for (uint32_t i = 0; i < properties.size(); i++)
108 if ((properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)
110 return static_cast<int>(i);
116 std::vector<VkQueueFamilyProperties>
117 Device::GetPhysicalDeviceQueueFamilyProperties(
118 Driver const *driver, VkPhysicalDevice device)
120 std::vector<VkQueueFamilyProperties> out;
122 driver->vkGetPhysicalDeviceQueueFamilyProperties(device, &count, nullptr);
124 driver->vkGetPhysicalDeviceQueueFamilyProperties(device, &count, out.data());
128 VkResult Device::GetPhysicalDevices(
129 const Driver* driver, VkInstance instance,
130 std::vector<VkPhysicalDevice>& out)
133 VkResult result = driver->vkEnumeratePhysicalDevices(instance, &count, 0);
134 if (result != VK_SUCCESS)
139 return driver->vkEnumeratePhysicalDevices(instance, &count, out.data());
142 VkResult Device::CreateStorageBuffer(
143 VkDeviceMemory memory, VkDeviceSize size,
144 VkDeviceSize offset, VkBuffer* out) const
146 const VkBufferCreateInfo info = {
147 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
151 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage
152 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
153 0, // queueFamilyIndexCount
154 nullptr, // pQueueFamilyIndices
158 VkResult result = driver->vkCreateBuffer(device, &info, 0, &buffer);
159 if (result != VK_SUCCESS)
164 result = driver->vkBindBufferMemory(device, buffer, memory, offset);
165 if (result != VK_SUCCESS)
174 VkResult Device::CreateShaderModule(
175 const std::vector<uint32_t>& spirv, VkShaderModule* out) const
177 VkShaderModuleCreateInfo info = {
178 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // sType
181 spirv.size() * 4, // codeSize
182 spirv.data(), // pCode
184 return driver->vkCreateShaderModule(device, &info, 0, out);
187 VkResult Device::CreateDescriptorSetLayout(
188 const std::vector<VkDescriptorSetLayoutBinding>& bindings,
189 VkDescriptorSetLayout* out) const
191 VkDescriptorSetLayoutCreateInfo info = {
192 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
195 (uint32_t)bindings.size(), // bindingCount
196 bindings.data(), // pBindings
199 return driver->vkCreateDescriptorSetLayout(device, &info, 0, out);
202 VkResult Device::CreatePipelineLayout(
203 VkDescriptorSetLayout layout, VkPipelineLayout* out) const
205 VkPipelineLayoutCreateInfo info = {
206 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
210 &layout, // pSetLayouts
211 0, // pushConstantRangeCount
212 nullptr, // pPushConstantRanges
215 return driver->vkCreatePipelineLayout(device, &info, 0, out);
218 VkResult Device::CreateComputePipeline(
219 VkShaderModule module, VkPipelineLayout pipelineLayout,
220 VkPipeline* out) const
222 VkComputePipelineCreateInfo info = {
223 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
228 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType
231 VK_SHADER_STAGE_COMPUTE_BIT, // stage
234 nullptr, // pSpecializationInfo
236 pipelineLayout, // layout
237 0, // basePipelineHandle
238 0, // basePipelineIndex
241 return driver->vkCreateComputePipelines(device, 0, 1, &info, 0, out);
244 VkResult Device::CreateStorageBufferDescriptorPool(uint32_t descriptorCount,
245 VkDescriptorPool* out) const
247 VkDescriptorPoolSize size = {
248 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // type
249 descriptorCount, // descriptorCount
252 VkDescriptorPoolCreateInfo info = {
253 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
261 return driver->vkCreateDescriptorPool(device, &info, 0, out);
264 VkResult Device::AllocateDescriptorSet(
265 VkDescriptorPool pool, VkDescriptorSetLayout layout,
266 VkDescriptorSet* out) const
268 VkDescriptorSetAllocateInfo info = {
269 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
271 pool, // descriptorPool
272 1, // descriptorSetCount
273 &layout, // pSetLayouts
276 return driver->vkAllocateDescriptorSets(device, &info, out);
279 void Device::UpdateStorageBufferDescriptorSets(
280 VkDescriptorSet descriptorSet,
281 const std::vector<VkDescriptorBufferInfo>& bufferInfos) const
283 std::vector<VkWriteDescriptorSet> writes;
284 writes.reserve(bufferInfos.size());
285 for (uint32_t i = 0; i < bufferInfos.size(); i++)
287 writes.push_back(VkWriteDescriptorSet{
288 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
290 descriptorSet, // dstSet
292 0, // dstArrayElement
293 1, // descriptorCount
294 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
295 nullptr, // pImageInfo
296 &bufferInfos[i], // pBufferInfo
297 nullptr, // pTexelBufferView
301 driver->vkUpdateDescriptorSets(device, writes.size(), writes.data(), 0, nullptr);
304 VkResult Device::AllocateMemory(size_t size, VkMemoryPropertyFlags flags, VkDeviceMemory* out) const
306 VkPhysicalDeviceMemoryProperties properties;
307 driver->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &properties);
309 for(uint32_t type = 0; type < properties.memoryTypeCount; type++)
311 if ((flags & properties.memoryTypes[type].propertyFlags) == 0)
313 continue; // Type mismatch
316 if (size > properties.memoryHeaps[properties.memoryTypes[type].heapIndex].size)
318 continue; // Too small.
321 const VkMemoryAllocateInfo info = {
322 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
324 size, // allocationSize
325 type, // memoryTypeIndex
328 return driver->vkAllocateMemory(device, &info, 0, out);
331 return VK_ERROR_OUT_OF_DEVICE_MEMORY; // TODO: Change to something not made up?
334 VkResult Device::MapMemory(VkDeviceMemory memory, VkDeviceSize offset,
335 VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) const
337 return driver->vkMapMemory(device, memory, offset, size, flags, ppData);
340 void Device::UnmapMemory(VkDeviceMemory memory) const
342 driver->vkUnmapMemory(device, memory);
345 VkResult Device::CreateCommandPool(VkCommandPool* out) const
347 VkCommandPoolCreateInfo info = {
348 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
351 queueFamilyIndex, // queueFamilyIndex
353 return driver->vkCreateCommandPool(device, &info, 0, out);
356 VkResult Device::AllocateCommandBuffer(
357 VkCommandPool pool, VkCommandBuffer* out) const
359 VkCommandBufferAllocateInfo info = {
360 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
363 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
364 1, // commandBufferCount
366 return driver->vkAllocateCommandBuffers(device, &info, out);
369 VkResult Device::BeginCommandBuffer(
370 VkCommandBufferUsageFlags usage, VkCommandBuffer commandBuffer) const
372 VkCommandBufferBeginInfo info = {
373 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
376 nullptr, // pInheritanceInfo
379 return driver->vkBeginCommandBuffer(commandBuffer, &info);
382 VkResult Device::QueueSubmitAndWait(VkCommandBuffer commandBuffer) const
385 driver->vkGetDeviceQueue(device, queueFamilyIndex, 0, &queue);
387 VkSubmitInfo info = {
388 VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
390 0, // waitSemaphoreCount
391 nullptr, // pWaitSemaphores
392 nullptr, // pWaitDstStageMask
393 1, // commandBufferCount
394 &commandBuffer, // pCommandBuffers
395 0, // signalSemaphoreCount
396 nullptr, // pSignalSemaphores
399 VkResult result = driver->vkQueueSubmit(queue, 1, &info, 0);
400 if (result != VK_SUCCESS)
405 return driver->vkQueueWaitIdle(queue);