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 
23 namespace android {
24 namespace renderscript {
25 namespace rsov {
26 
27 RSoVContext* RSoVContext::mContext = nullptr;
28 std::once_flag RSoVContext::mInitFlag;
29 
Initialize(char const * const name)30 bool 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 
MemoryTypeFromProperties(uint32_t typeBits,VkFlags requirements_mask,uint32_t * typeIndex)149 bool 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 
RSoVContext()166 RSoVContext::RSoVContext() {}
167 
~RSoVContext()168 RSoVContext::~RSoVContext() {}
169 
create()170 RSoVContext* 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