1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "rsovContext.h"
18
19#include <vector>
20
21#include "rsUtils.h"
22
23namespace android {
24namespace renderscript {
25namespace rsov {
26
27RSoVContext* RSoVContext::mContext = nullptr;
28std::once_flag RSoVContext::mInitFlag;
29
30bool RSoVContext::Initialize(char const* const name) {
31  // Initialize instance
32  VkApplicationInfo appInfo = {
33      .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
34      .pNext = nullptr,
35      .pApplicationName = name,  // TODO: set to app name
36      .applicationVersion = 1,
37      .pEngineName = name,
38      .engineVersion = 1,
39      .apiVersion = VK_API_VERSION_1_0};
40
41  VkInstanceCreateInfo instInfo = {
42      .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
43      .pNext = nullptr,
44      .flags = 0,
45      .pApplicationInfo = &appInfo,
46  };
47
48  VkResult res;
49  res = vkCreateInstance(&instInfo, nullptr, &mInstance);
50  if (res != VK_SUCCESS) {
51    return false;
52  }
53
54  // Enumerate devices
55  uint32_t gpu_count;
56
57  res = vkEnumeratePhysicalDevices(mInstance, &gpu_count, nullptr);
58  if (gpu_count == 0) {
59    return false;
60  }
61
62  std::vector<VkPhysicalDevice> GPUs(gpu_count);
63
64  res = vkEnumeratePhysicalDevices(mInstance, &gpu_count, GPUs.data());
65  if (!(res == VK_SUCCESS && gpu_count > 0)) {
66    return false;
67  }
68
69  mGPU = GPUs[0];
70
71  // Get device memory properties
72  vkGetPhysicalDeviceMemoryProperties(mGPU, &mMemoryProperties);
73
74  // Initialize device
75
76  float queuePriorities[] = {0.0};
77
78  VkDeviceQueueCreateInfo queueInfo = {
79      .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
80      .pNext = nullptr,
81      .queueCount = 1,
82      .pQueuePriorities = queuePriorities,
83  };
84
85  VkDeviceCreateInfo deviceInfo = {
86      .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
87      .pNext = nullptr,
88      .queueCreateInfoCount = 1,
89      .pQueueCreateInfos = &queueInfo,
90      .pEnabledFeatures = nullptr,
91  };
92
93  res = vkCreateDevice(mGPU, &deviceInfo, nullptr, &mDevice);
94  if (res != VK_SUCCESS) {
95    return false;
96  }
97
98  // Initialize queue family index
99  uint32_t queueCount;
100
101  vkGetPhysicalDeviceQueueFamilyProperties(mGPU, &queueCount, nullptr);
102  if (queueCount == 0) {
103    return false;
104  }
105
106  std::vector<VkQueueFamilyProperties> queueProps(queueCount);
107
108  vkGetPhysicalDeviceQueueFamilyProperties(mGPU, &queueCount,
109                                           queueProps.data());
110  if (queueCount == 0) {
111    return false;
112  }
113
114  uint32_t queueFamilyIndex = UINT_MAX;
115  bool found = false;
116  for (unsigned int i = 0; i < queueCount; i++) {
117    if (queueProps[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
118      queueFamilyIndex = i;
119      found = true;
120      break;
121    }
122  }
123
124  if (!found) {
125    return false;
126  }
127
128  // Create a device queue
129
130  vkGetDeviceQueue(mDevice, queueFamilyIndex, 0, &mQueue);
131
132  // Create command pool
133
134  VkCommandPoolCreateInfo cmd_pool_info = {
135      .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
136      .pNext = nullptr,
137      .queueFamilyIndex = queueFamilyIndex,
138      .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
139  };
140
141  res = vkCreateCommandPool(mDevice, &cmd_pool_info, nullptr, &mCmdPool);
142  if (res != VK_SUCCESS) {
143    return false;
144  }
145
146  return true;
147}
148
149bool RSoVContext::MemoryTypeFromProperties(uint32_t typeBits,
150                                           VkFlags requirements_mask,
151                                           uint32_t* typeIndex) {
152  for (uint32_t i = 0; i < 32; i++) {
153    if ((typeBits & 1) == 1) {
154      const uint32_t prop = mMemoryProperties.memoryTypes[i].propertyFlags;
155      if ((prop & requirements_mask) == requirements_mask) {
156        *typeIndex = i;
157        return true;
158      }
159    }
160    typeBits >>= 1;
161  }
162
163  return false;
164}
165
166RSoVContext::RSoVContext() {}
167
168RSoVContext::~RSoVContext() {}
169
170RSoVContext* RSoVContext::create() {
171  std::call_once(mInitFlag, []() {
172    std::unique_ptr<RSoVContext> context(new RSoVContext());
173    char engineName[] = "RSoV";
174
175    if (context && context->Initialize(engineName)) {
176      mContext = context.release();
177    }
178  });
179  return mContext;
180}
181
182}  // namespace rsov
183}  // namespace renderscript
184}  // namespace android
185