blob: ccbaa950783d04f78b81be182db2f397fc368df2 [file] [log] [blame]
Po-Hsien Wang42e116c2020-06-09 16:10:27 -07001// Copyright 2020 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <unistd.h>
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +08006#include <algorithm>
Po-Hsien Wang42e116c2020-06-09 16:10:27 -07007#include <limits>
8#include <vulkan/vulkan.hpp>
9
10#include "constant.h"
11#include "utils.h"
12#include "vkBase.h"
13
14extern int g_vlayer;
15
16namespace vkbench {
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080017bool IsLayerSupported(const char* layer) {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070018 std::vector<vk::LayerProperties> availLayers =
19 vk::enumerateInstanceLayerProperties();
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080020 for (const auto& availLayer : availLayers) {
21 if (!strcmp(layer, availLayer.layerName)) {
22 return true;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070023 }
24 }
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080025 LOG("Layer %s is not support.", layer);
26 return false;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070027}
28
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080029bool IsExtensionSupported(const char* ext) {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070030 std::vector<vk::ExtensionProperties> availExtensions =
31 vk::enumerateInstanceExtensionProperties();
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080032 for (const auto& availExtension : availExtensions) {
33 if (!strcmp(ext, availExtension.extensionName)) {
34 return true;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070035 }
36 }
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080037 DEBUG("Extension %s is not supported.", ext);
38 return false;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070039}
40
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080041vkImage::vkImage(vkBase* vkbase,
42 vk::Extent2D img_size,
43 vk::Format img_format,
44 vk::ImageUsageFlags usage,
45 vk::MemoryPropertyFlags memory_properties,
46 vk::ImageTiling tiling) {
47 vkbase_ = vkbase;
48
49 vk::ImageCreateInfo img_create_info;
50 img_create_info.setFormat(img_format)
51 .setImageType(vk::ImageType::e2D)
52 .setSamples(vk::SampleCountFlagBits::e1)
53 .setUsage(usage)
54 .setMipLevels(1)
55 .setArrayLayers(1)
56 .setExtent(vk::Extent3D(img_size, 1))
57 .setQueueFamilyIndexCount(1)
58 .setPQueueFamilyIndices(&vkbase_->GetGFXQueueFamilyIndex())
59 .setInitialLayout(vk::ImageLayout::eUndefined)
60 .setTiling(tiling);
61 img_ = vkbase_->GetDevice().createImage(img_create_info);
62 vk::MemoryRequirements mem_req =
63 vkbase_->GetDevice().getImageMemoryRequirements(img_);
64 memory_ = vkbase_->GetDevice().allocateMemory(
65 {mem_req.size,
66 vkbase_->GetMemoryType(mem_req.memoryTypeBits, memory_properties)});
67 vkbase_->GetDevice().bindImageMemory(img_, memory_, 0);
68}
69
70vkImage::~vkImage() {
71 vkbase_->GetDevice().freeMemory(memory_);
72 vkbase_->GetDevice().destroyImage(img_);
73}
74
75void CreateDebugUtilsMessengerEXT(
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070076 vk::Instance instance,
77 const vk::DebugUtilsMessengerCreateInfoEXT* kPcreateInfo,
78 const vk::AllocationCallbacks* kPallocator,
79 vk::DebugUtilsMessengerEXT* pdebug_messengeer) {
80 auto func = (PFN_vkCreateDebugUtilsMessengerEXT)instance.getProcAddr(
81 "vkCreateDebugUtilsMessengerEXT");
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080082 if (func == nullptr)
Po-Hsien Wang53230a22020-11-12 18:03:18 -080083 RUNTIME_ERROR("can't locate vkCreateDebugUtilsMessengerEXT");
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080084 VkCheck(static_cast<vk::Result>(func(
85 (VkInstance)instance,
86 reinterpret_cast<const VkDebugUtilsMessengerCreateInfoEXT*>(
87 kPcreateInfo),
88 reinterpret_cast<const VkAllocationCallbacks*>(kPallocator),
89 reinterpret_cast<VkDebugUtilsMessengerEXT*>(pdebug_messengeer))),
90 "vkCreateDebugUtilsMessengerEXT");
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070091}
92
93void DestroyDebugUtilsMessengerEXT(vk::Instance instance,
94 vk::DebugUtilsMessengerEXT debug_messengeer,
95 const vk::AllocationCallbacks* kPAllocator) {
96 auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)instance.getProcAddr(
97 "vkDestroyDebugUtilsMessengerEXT");
98 if (func != nullptr) {
99 func((VkInstance)instance,
100 static_cast<VkDebugUtilsMessengerEXT>(debug_messengeer),
101 reinterpret_cast<const VkAllocationCallbacks*>(
102 static_cast<const vk::AllocationCallbacks*>(kPAllocator)));
103 }
104}
105
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800106uint32_t ChooseGFXQueueFamilies(const vk::PhysicalDevice& physical_device) {
107 uint32_t gfx_queue_idx = UINT32_MAX;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700108 std::vector<vk::QueueFamilyProperties> props =
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800109 physical_device.getQueueFamilyProperties();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700110 for (uint32_t i = 0; i < props.size(); i++) {
111 if (props[i].queueCount <= 0)
112 continue;
113 if (props[i].queueFlags & vk::QueueFlagBits::eGraphics) {
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800114 gfx_queue_idx = i;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700115 break;
116 }
117 }
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800118 return gfx_queue_idx;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700119}
120
121VKAPI_ATTR VkBool32 VKAPI_CALL
122ValidationCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
123 VkDebugUtilsMessageTypeFlagsEXT messageType,
124 const VkDebugUtilsMessengerCallbackDataEXT* kPcallbackData,
125 void* pUserData) {
126 UNUSED(messageType);
127 UNUSED(pUserData);
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +0800128 switch (messageSeverity) {
129 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
130 DEBUG("%s", kPcallbackData->pMessage);
131 break;
132 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
133 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
134 LOG("%s", kPcallbackData->pMessage);
135 break;
136 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
137 ERROR("%s", kPcallbackData->pMessage);
138 break;
139 default:
Po-Hsien Wang53230a22020-11-12 18:03:18 -0800140 RUNTIME_ERROR("%s", kPcallbackData->pMessage);
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700141 }
142 return VK_FALSE;
143}
144
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800145void vkBase::Initialize() {
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800146 CreateInstance();
147 ChoosePhysicalDevice();
148 CreateLogicalDevice();
149 CreateCommandPool();
150 initialized_ = true;
151}
152
Po-Hsien Wang513fe192020-10-02 11:40:07 +0800153bool vkBase::IsInitialized() const {
154 return initialized_;
155}
156
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700157void vkBase::CreateInstance() {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700158 vk::ApplicationInfo appInfo("vkbench", 1, "Vulkan.hpp", 1,
159 VK_API_VERSION_1_1);
160 vk::InstanceCreateInfo createInfo({}, &appInfo);
161
162 if (g_vlayer) {
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +0800163 validation_layers_.erase(
164 std::remove_if(
165 validation_layers_.begin(), validation_layers_.end(),
166 [](const char* layer) { return !IsLayerSupported(layer); }),
167 validation_layers_.end());
168 debug_extension_.erase(
169 std::remove_if(
170 debug_extension_.begin(), debug_extension_.end(),
171 [](const char* ext) { return !IsExtensionSupported(ext); }),
172 debug_extension_.end());
173 if (validation_layers_.size() == 0 || debug_extension_.size() == 0) {
174 LOG("Validation layer is not supported. Less log will be printed.")
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700175 enable_validation_layer_ = false;
176 } else {
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +0800177 createInfo.setEnabledExtensionCount(debug_extension_.size())
178 .setPpEnabledExtensionNames(debug_extension_.data())
179 .setEnabledLayerCount(validation_layers_.size())
180 .setPpEnabledLayerNames(validation_layers_.data());
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700181 enable_validation_layer_ = true;
182 }
183 }
184 instance_ = vk::createInstance(createInfo);
185 if (enable_validation_layer_) {
186 vk::DebugUtilsMessengerCreateInfoEXT debugCreateInfo;
187 debugCreateInfo
188 .setMessageSeverity(vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
189 vk::DebugUtilsMessageSeverityFlagBitsEXT::eError)
190 .setMessageType(vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
191 vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation)
192 .setPfnUserCallback(ValidationCallback);
193 CreateDebugUtilsMessengerEXT(instance_, &debugCreateInfo, nullptr,
194 &debug_messenger_);
195 }
196}
197
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800198void vkBase::ChoosePhysicalDevice() {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700199 std::vector<vk::PhysicalDevice> physical_devices =
200 instance_.enumeratePhysicalDevices();
201 if (physical_devices.size() == 0) {
Po-Hsien Wang53230a22020-11-12 18:03:18 -0800202 RUNTIME_ERROR("enumeratePhysicalDevices returns 0 devices.");
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700203 }
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800204
205 auto isSuitable = [&physical_devices](vk::MemoryPropertyFlags flags) -> int {
206 int target = -1;
207 for (auto index = 0; index < physical_devices.size(); index++) {
208 vk::PhysicalDeviceMemoryProperties mem_properties =
209 physical_devices[index].getMemoryProperties();
210
211 for (uint32_t i = 0; i < mem_properties.memoryTypeCount; i++) {
212 if ((mem_properties.memoryTypes[i].propertyFlags & flags) == flags) {
213 target = index;
214 }
215 }
216 }
217 return target;
218 };
219 int index = isSuitable(vk::MemoryPropertyFlagBits::eDeviceLocal |
220 vk::MemoryPropertyFlagBits::eHostVisible |
221 vk::MemoryPropertyFlagBits::eHostCoherent);
222 if (index == -1) {
223 index = isSuitable(vk::MemoryPropertyFlagBits::eDeviceLocal);
224 }
225 physical_device_ = physical_devices[index];
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700226 gfx_queue_idx_ = ChooseGFXQueueFamilies(physical_device_);
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800227 mem_properties_ = physical_device_.getMemoryProperties();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700228}
229
230void vkBase::CreateLogicalDevice() {
231 float tmp = 1.0f;
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800232 vk::DeviceQueueCreateInfo queue_create_info;
233 queue_create_info.setQueueCount(1)
234 .setQueueFamilyIndex(gfx_queue_idx_)
235 .setPQueuePriorities(&tmp);
236 vk::DeviceCreateInfo device_create_info;
237 device_create_info.setQueueCreateInfoCount(1).setPQueueCreateInfos(
238 &queue_create_info);
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700239 if (enable_validation_layer_) {
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800240 device_create_info.setEnabledLayerCount(validation_layers_.size())
241 .setPpEnabledLayerNames(validation_layers_.data());
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700242 }
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800243 device_ = physical_device_.createDevice(device_create_info);
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700244 gfx_queue_ = device_.getQueue(gfx_queue_idx_, /* Queue Index */ 0);
245}
246
247void vkBase::CreateCommandPool() {
248 cmd_pool_ =
249 device_.createCommandPool({vk::CommandPoolCreateFlags(), gfx_queue_idx_});
250}
251
252void vkBase::Destroy() {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700253 if (cmd_pool_)
254 device_.destroy(cmd_pool_, nullptr);
255 device_.destroy();
256 if (enable_validation_layer_) {
257 DestroyDebugUtilsMessengerEXT(instance_, debug_messenger_, nullptr);
258 }
259 instance_.destroy();
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800260 initialized_ = false;
261}
262
263// AllocateImage allocates an VkImage and returns its handle.
264vkImage* vkBase::AllocateImage(
265 vk::Extent2D img_size,
266 vk::Format img_format,
267 vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eColorAttachment,
268 vk::MemoryPropertyFlags memory_properties,
269 vk::ImageTiling tiling) {
270 return new vkImage(this, img_size, img_format, usage, memory_properties,
271 tiling);
272}
273
274// GetReadableImage copys a image created with eTransferSrc to a readable
275// vkImage and returns it.
276vkImage* vkBase::GetReadableImage(vkImage* src,
277 vk::Extent2D size,
278 vk::Format format) {
279 std::vector<vk::CommandBuffer> cmds = device_.allocateCommandBuffers(
280 {cmd_pool_, vk::CommandBufferLevel::ePrimary, 1});
281 DEFER(device_.freeCommandBuffers(cmd_pool_, cmds));
282
283 vk::CommandBuffer command = cmds[0];
284
285 vkImage* dest =
286 AllocateImage(size, format, vk::ImageUsageFlagBits::eTransferDst,
287 vk::MemoryPropertyFlagBits::eHostCoherent |
288 vk::MemoryPropertyFlagBits::eHostVisible,
289 vk::ImageTiling::eLinear);
Po-Hsien Wang41024f42020-10-28 17:52:56 -0700290 command.begin(vk::CommandBufferBeginInfo());
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800291 vk::ImageMemoryBarrier img_memory_barrier[4];
292 // Transition dest image to transfer destination layout.
293 img_memory_barrier[0]
294 .setDstAccessMask(vk::AccessFlagBits::eTransferWrite)
295 .setOldLayout(vk::ImageLayout::eUndefined)
296 .setNewLayout(vk::ImageLayout::eTransferDstOptimal)
297 .setImage(dest->GetImage())
298 .setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
299 // Transition src image to transfer source layout.
300 img_memory_barrier[1]
301 .setSrcAccessMask(vk::AccessFlagBits::eMemoryRead)
302 .setDstAccessMask(vk::AccessFlagBits::eTransferRead)
303 .setOldLayout(vk::ImageLayout::eGeneral)
304 .setNewLayout(vk::ImageLayout::eTransferSrcOptimal)
305 .setImage(src->GetImage())
306 .setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
307 // Transition dst image to general layout.
308 img_memory_barrier[2]
309 .setSrcAccessMask(vk::AccessFlagBits::eTransferWrite)
310 .setDstAccessMask(vk::AccessFlagBits::eMemoryRead)
311 .setOldLayout(vk::ImageLayout::eTransferDstOptimal)
312 .setNewLayout(vk::ImageLayout::eGeneral)
313 .setImage(dest->GetImage())
314 .setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
315 // Transition src image to transfer source layout.
316 img_memory_barrier[3]
317 .setSrcAccessMask(vk::AccessFlagBits::eTransferRead)
318 .setDstAccessMask(vk::AccessFlagBits::eMemoryRead)
319 .setOldLayout(vk::ImageLayout::eTransferSrcOptimal)
320 .setNewLayout(vk::ImageLayout::eGeneral)
321 .setImage(src->GetImage())
322 .setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
323
324 command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
325 vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr,
326 0, nullptr, 1, &img_memory_barrier[0]);
327 command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
328 vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr,
329 0, nullptr, 1, &img_memory_barrier[1]);
330 // Copy the image
331 vk::ImageCopy img_copy_region;
332 img_copy_region.srcSubresource.setAspectMask(vk::ImageAspectFlagBits::eColor)
333 .setLayerCount(1);
334 img_copy_region.dstSubresource.setAspectMask(vk::ImageAspectFlagBits::eColor)
335 .setLayerCount(1);
336 img_copy_region.extent.setWidth(size.width)
337 .setHeight(size.height)
338 .setDepth(1);
339 command.copyImage(src->GetImage(), vk::ImageLayout::eTransferSrcOptimal,
340 dest->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1,
341 &img_copy_region);
342 command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
343 vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr,
344 0, nullptr, 1, &img_memory_barrier[2]);
345 command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
346 vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr,
347 0, nullptr, 1, &img_memory_barrier[3]);
348
349 // Finish command buffer recording and submit.
350 command.end();
351
352 std::vector<vk::SubmitInfo> submit_infos(1);
353 submit_infos[0].setCommandBufferCount(1).setPCommandBuffers(cmds.data());
354 gfx_queue_.submit(submit_infos, {});
355 gfx_queue_.waitIdle();
356 return dest;
357}
358
359// Get the index of a memory type that has all the requested property bits set
360uint32_t vkBase::GetMemoryType(uint32_t bits,
361 vk::MemoryPropertyFlags properties) {
362 for (uint32_t i = 0; i < mem_properties_.memoryTypeCount; i++) {
363 if ((bits & 1) == 1) {
364 if (!properties)
365 return i;
366 if ((mem_properties_.memoryTypes[i].propertyFlags & properties) ==
367 properties) {
368 return i;
369 }
370 }
371 bits >>= 1;
372 }
Po-Hsien Wang53230a22020-11-12 18:03:18 -0800373 RUNTIME_ERROR("could not find a matching memory type");
374 return 0;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700375}
376
377} // namespace vkbench