blob: 9aedfaf42c1d1029ced362a4fd6502d5e115708c [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
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070010#include "utils.h"
11#include "vkBase.h"
12
13extern int g_vlayer;
14
15namespace vkbench {
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080016bool IsLayerSupported(const char* layer) {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070017 std::vector<vk::LayerProperties> availLayers =
18 vk::enumerateInstanceLayerProperties();
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080019 for (const auto& availLayer : availLayers) {
20 if (!strcmp(layer, availLayer.layerName)) {
21 return true;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070022 }
23 }
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080024 LOG("Layer %s is not support.", layer);
25 return false;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070026}
27
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080028bool IsExtensionSupported(const char* ext) {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070029 std::vector<vk::ExtensionProperties> availExtensions =
30 vk::enumerateInstanceExtensionProperties();
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080031 for (const auto& availExtension : availExtensions) {
32 if (!strcmp(ext, availExtension.extensionName)) {
33 return true;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070034 }
35 }
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +080036 DEBUG("Extension %s is not supported.", ext);
37 return false;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070038}
39
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080040vkImage::vkImage(vkBase* vkbase,
41 vk::Extent2D img_size,
42 vk::Format img_format,
43 vk::ImageUsageFlags usage,
44 vk::MemoryPropertyFlags memory_properties,
45 vk::ImageTiling tiling) {
46 vkbase_ = vkbase;
47
48 vk::ImageCreateInfo img_create_info;
49 img_create_info.setFormat(img_format)
50 .setImageType(vk::ImageType::e2D)
51 .setSamples(vk::SampleCountFlagBits::e1)
52 .setUsage(usage)
53 .setMipLevels(1)
54 .setArrayLayers(1)
55 .setExtent(vk::Extent3D(img_size, 1))
56 .setQueueFamilyIndexCount(1)
57 .setPQueueFamilyIndices(&vkbase_->GetGFXQueueFamilyIndex())
58 .setInitialLayout(vk::ImageLayout::eUndefined)
59 .setTiling(tiling);
60 img_ = vkbase_->GetDevice().createImage(img_create_info);
61 vk::MemoryRequirements mem_req =
62 vkbase_->GetDevice().getImageMemoryRequirements(img_);
63 memory_ = vkbase_->GetDevice().allocateMemory(
64 {mem_req.size,
65 vkbase_->GetMemoryType(mem_req.memoryTypeBits, memory_properties)});
66 vkbase_->GetDevice().bindImageMemory(img_, memory_, 0);
67}
68
69vkImage::~vkImage() {
70 vkbase_->GetDevice().freeMemory(memory_);
71 vkbase_->GetDevice().destroyImage(img_);
72}
73
74void CreateDebugUtilsMessengerEXT(
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070075 vk::Instance instance,
76 const vk::DebugUtilsMessengerCreateInfoEXT* kPcreateInfo,
77 const vk::AllocationCallbacks* kPallocator,
78 vk::DebugUtilsMessengerEXT* pdebug_messengeer) {
79 auto func = (PFN_vkCreateDebugUtilsMessengerEXT)instance.getProcAddr(
80 "vkCreateDebugUtilsMessengerEXT");
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080081 if (func == nullptr)
Po-Hsien Wang53230a22020-11-12 18:03:18 -080082 RUNTIME_ERROR("can't locate vkCreateDebugUtilsMessengerEXT");
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +080083 VkCheck(static_cast<vk::Result>(func(
84 (VkInstance)instance,
85 reinterpret_cast<const VkDebugUtilsMessengerCreateInfoEXT*>(
86 kPcreateInfo),
87 reinterpret_cast<const VkAllocationCallbacks*>(kPallocator),
88 reinterpret_cast<VkDebugUtilsMessengerEXT*>(pdebug_messengeer))),
89 "vkCreateDebugUtilsMessengerEXT");
Po-Hsien Wang42e116c2020-06-09 16:10:27 -070090}
91
92void DestroyDebugUtilsMessengerEXT(vk::Instance instance,
93 vk::DebugUtilsMessengerEXT debug_messengeer,
94 const vk::AllocationCallbacks* kPAllocator) {
95 auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)instance.getProcAddr(
96 "vkDestroyDebugUtilsMessengerEXT");
97 if (func != nullptr) {
98 func((VkInstance)instance,
99 static_cast<VkDebugUtilsMessengerEXT>(debug_messengeer),
100 reinterpret_cast<const VkAllocationCallbacks*>(
101 static_cast<const vk::AllocationCallbacks*>(kPAllocator)));
102 }
103}
104
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800105uint32_t ChooseGFXQueueFamilies(const vk::PhysicalDevice& physical_device) {
106 uint32_t gfx_queue_idx = UINT32_MAX;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700107 std::vector<vk::QueueFamilyProperties> props =
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800108 physical_device.getQueueFamilyProperties();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700109 for (uint32_t i = 0; i < props.size(); i++) {
110 if (props[i].queueCount <= 0)
111 continue;
112 if (props[i].queueFlags & vk::QueueFlagBits::eGraphics) {
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800113 gfx_queue_idx = i;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700114 break;
115 }
116 }
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800117 return gfx_queue_idx;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700118}
119
120VKAPI_ATTR VkBool32 VKAPI_CALL
121ValidationCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
122 VkDebugUtilsMessageTypeFlagsEXT messageType,
123 const VkDebugUtilsMessengerCallbackDataEXT* kPcallbackData,
124 void* pUserData) {
125 UNUSED(messageType);
126 UNUSED(pUserData);
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +0800127 switch (messageSeverity) {
128 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
129 DEBUG("%s", kPcallbackData->pMessage);
130 break;
131 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
132 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
133 LOG("%s", kPcallbackData->pMessage);
134 break;
135 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
136 ERROR("%s", kPcallbackData->pMessage);
137 break;
138 default:
Po-Hsien Wang53230a22020-11-12 18:03:18 -0800139 RUNTIME_ERROR("%s", kPcallbackData->pMessage);
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700140 }
141 return VK_FALSE;
142}
143
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800144void vkBase::Initialize() {
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800145 CreateInstance();
146 ChoosePhysicalDevice();
147 CreateLogicalDevice();
148 CreateCommandPool();
149 initialized_ = true;
150}
151
Po-Hsien Wang513fe192020-10-02 11:40:07 +0800152bool vkBase::IsInitialized() const {
153 return initialized_;
154}
155
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700156void vkBase::CreateInstance() {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700157 vk::ApplicationInfo appInfo("vkbench", 1, "Vulkan.hpp", 1,
158 VK_API_VERSION_1_1);
159 vk::InstanceCreateInfo createInfo({}, &appInfo);
160
161 if (g_vlayer) {
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +0800162 validation_layers_.erase(
163 std::remove_if(
164 validation_layers_.begin(), validation_layers_.end(),
165 [](const char* layer) { return !IsLayerSupported(layer); }),
166 validation_layers_.end());
167 debug_extension_.erase(
168 std::remove_if(
169 debug_extension_.begin(), debug_extension_.end(),
170 [](const char* ext) { return !IsExtensionSupported(ext); }),
171 debug_extension_.end());
172 if (validation_layers_.size() == 0 || debug_extension_.size() == 0) {
173 LOG("Validation layer is not supported. Less log will be printed.")
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700174 enable_validation_layer_ = false;
175 } else {
Po-Hsien Wangaafe13e2020-09-24 14:29:58 +0800176 createInfo.setEnabledExtensionCount(debug_extension_.size())
177 .setPpEnabledExtensionNames(debug_extension_.data())
178 .setEnabledLayerCount(validation_layers_.size())
179 .setPpEnabledLayerNames(validation_layers_.data());
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700180 enable_validation_layer_ = true;
181 }
182 }
183 instance_ = vk::createInstance(createInfo);
184 if (enable_validation_layer_) {
185 vk::DebugUtilsMessengerCreateInfoEXT debugCreateInfo;
186 debugCreateInfo
187 .setMessageSeverity(vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
188 vk::DebugUtilsMessageSeverityFlagBitsEXT::eError)
189 .setMessageType(vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
190 vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation)
191 .setPfnUserCallback(ValidationCallback);
192 CreateDebugUtilsMessengerEXT(instance_, &debugCreateInfo, nullptr,
193 &debug_messenger_);
194 }
195}
196
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800197void vkBase::ChoosePhysicalDevice() {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700198 std::vector<vk::PhysicalDevice> physical_devices =
199 instance_.enumeratePhysicalDevices();
200 if (physical_devices.size() == 0) {
Po-Hsien Wang53230a22020-11-12 18:03:18 -0800201 RUNTIME_ERROR("enumeratePhysicalDevices returns 0 devices.");
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700202 }
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800203
204 auto isSuitable = [&physical_devices](vk::MemoryPropertyFlags flags) -> int {
205 int target = -1;
206 for (auto index = 0; index < physical_devices.size(); index++) {
207 vk::PhysicalDeviceMemoryProperties mem_properties =
208 physical_devices[index].getMemoryProperties();
209
210 for (uint32_t i = 0; i < mem_properties.memoryTypeCount; i++) {
211 if ((mem_properties.memoryTypes[i].propertyFlags & flags) == flags) {
212 target = index;
213 }
214 }
215 }
216 return target;
217 };
218 int index = isSuitable(vk::MemoryPropertyFlagBits::eDeviceLocal |
219 vk::MemoryPropertyFlagBits::eHostVisible |
220 vk::MemoryPropertyFlagBits::eHostCoherent);
221 if (index == -1) {
222 index = isSuitable(vk::MemoryPropertyFlagBits::eDeviceLocal);
223 }
224 physical_device_ = physical_devices[index];
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700225 gfx_queue_idx_ = ChooseGFXQueueFamilies(physical_device_);
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800226 mem_properties_ = physical_device_.getMemoryProperties();
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700227}
228
229void vkBase::CreateLogicalDevice() {
230 float tmp = 1.0f;
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800231 vk::DeviceQueueCreateInfo queue_create_info;
232 queue_create_info.setQueueCount(1)
233 .setQueueFamilyIndex(gfx_queue_idx_)
234 .setPQueuePriorities(&tmp);
235 vk::DeviceCreateInfo device_create_info;
236 device_create_info.setQueueCreateInfoCount(1).setPQueueCreateInfos(
237 &queue_create_info);
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700238 if (enable_validation_layer_) {
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800239 device_create_info.setEnabledLayerCount(validation_layers_.size())
240 .setPpEnabledLayerNames(validation_layers_.data());
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700241 }
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800242 device_ = physical_device_.createDevice(device_create_info);
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700243 gfx_queue_ = device_.getQueue(gfx_queue_idx_, /* Queue Index */ 0);
244}
245
246void vkBase::CreateCommandPool() {
247 cmd_pool_ =
248 device_.createCommandPool({vk::CommandPoolCreateFlags(), gfx_queue_idx_});
249}
250
251void vkBase::Destroy() {
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700252 if (cmd_pool_)
253 device_.destroy(cmd_pool_, nullptr);
254 device_.destroy();
255 if (enable_validation_layer_) {
256 DestroyDebugUtilsMessengerEXT(instance_, debug_messenger_, nullptr);
257 }
258 instance_.destroy();
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800259 initialized_ = false;
260}
261
262// AllocateImage allocates an VkImage and returns its handle.
263vkImage* vkBase::AllocateImage(
264 vk::Extent2D img_size,
265 vk::Format img_format,
266 vk::ImageUsageFlags usage = vk::ImageUsageFlagBits::eColorAttachment,
267 vk::MemoryPropertyFlags memory_properties,
268 vk::ImageTiling tiling) {
269 return new vkImage(this, img_size, img_format, usage, memory_properties,
270 tiling);
271}
272
273// GetReadableImage copys a image created with eTransferSrc to a readable
274// vkImage and returns it.
275vkImage* vkBase::GetReadableImage(vkImage* src,
276 vk::Extent2D size,
277 vk::Format format) {
278 std::vector<vk::CommandBuffer> cmds = device_.allocateCommandBuffers(
279 {cmd_pool_, vk::CommandBufferLevel::ePrimary, 1});
280 DEFER(device_.freeCommandBuffers(cmd_pool_, cmds));
281
282 vk::CommandBuffer command = cmds[0];
283
284 vkImage* dest =
285 AllocateImage(size, format, vk::ImageUsageFlagBits::eTransferDst,
286 vk::MemoryPropertyFlagBits::eHostCoherent |
287 vk::MemoryPropertyFlagBits::eHostVisible,
288 vk::ImageTiling::eLinear);
Po-Hsien Wang41024f42020-10-28 17:52:56 -0700289 command.begin(vk::CommandBufferBeginInfo());
Po-Hsien Wanga0e1c312020-09-24 22:06:52 +0800290 vk::ImageMemoryBarrier img_memory_barrier[4];
291 // Transition dest image to transfer destination layout.
292 img_memory_barrier[0]
293 .setDstAccessMask(vk::AccessFlagBits::eTransferWrite)
294 .setOldLayout(vk::ImageLayout::eUndefined)
295 .setNewLayout(vk::ImageLayout::eTransferDstOptimal)
296 .setImage(dest->GetImage())
297 .setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
298 // Transition src image to transfer source layout.
299 img_memory_barrier[1]
300 .setSrcAccessMask(vk::AccessFlagBits::eMemoryRead)
301 .setDstAccessMask(vk::AccessFlagBits::eTransferRead)
302 .setOldLayout(vk::ImageLayout::eGeneral)
303 .setNewLayout(vk::ImageLayout::eTransferSrcOptimal)
304 .setImage(src->GetImage())
305 .setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
306 // Transition dst image to general layout.
307 img_memory_barrier[2]
308 .setSrcAccessMask(vk::AccessFlagBits::eTransferWrite)
309 .setDstAccessMask(vk::AccessFlagBits::eMemoryRead)
310 .setOldLayout(vk::ImageLayout::eTransferDstOptimal)
311 .setNewLayout(vk::ImageLayout::eGeneral)
312 .setImage(dest->GetImage())
313 .setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
314 // Transition src image to transfer source layout.
315 img_memory_barrier[3]
316 .setSrcAccessMask(vk::AccessFlagBits::eTransferRead)
317 .setDstAccessMask(vk::AccessFlagBits::eMemoryRead)
318 .setOldLayout(vk::ImageLayout::eTransferSrcOptimal)
319 .setNewLayout(vk::ImageLayout::eGeneral)
320 .setImage(src->GetImage())
321 .setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
322
323 command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
324 vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr,
325 0, nullptr, 1, &img_memory_barrier[0]);
326 command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
327 vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr,
328 0, nullptr, 1, &img_memory_barrier[1]);
329 // Copy the image
330 vk::ImageCopy img_copy_region;
331 img_copy_region.srcSubresource.setAspectMask(vk::ImageAspectFlagBits::eColor)
332 .setLayerCount(1);
333 img_copy_region.dstSubresource.setAspectMask(vk::ImageAspectFlagBits::eColor)
334 .setLayerCount(1);
335 img_copy_region.extent.setWidth(size.width)
336 .setHeight(size.height)
337 .setDepth(1);
338 command.copyImage(src->GetImage(), vk::ImageLayout::eTransferSrcOptimal,
339 dest->GetImage(), vk::ImageLayout::eTransferDstOptimal, 1,
340 &img_copy_region);
341 command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
342 vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr,
343 0, nullptr, 1, &img_memory_barrier[2]);
344 command.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
345 vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr,
346 0, nullptr, 1, &img_memory_barrier[3]);
347
348 // Finish command buffer recording and submit.
349 command.end();
350
351 std::vector<vk::SubmitInfo> submit_infos(1);
352 submit_infos[0].setCommandBufferCount(1).setPCommandBuffers(cmds.data());
353 gfx_queue_.submit(submit_infos, {});
354 gfx_queue_.waitIdle();
355 return dest;
356}
357
358// Get the index of a memory type that has all the requested property bits set
359uint32_t vkBase::GetMemoryType(uint32_t bits,
360 vk::MemoryPropertyFlags properties) {
361 for (uint32_t i = 0; i < mem_properties_.memoryTypeCount; i++) {
362 if ((bits & 1) == 1) {
363 if (!properties)
364 return i;
365 if ((mem_properties_.memoryTypes[i].propertyFlags & properties) ==
366 properties) {
367 return i;
368 }
369 }
370 bits >>= 1;
371 }
Po-Hsien Wang53230a22020-11-12 18:03:18 -0800372 RUNTIME_ERROR("could not find a matching memory type");
373 return 0;
Po-Hsien Wang42e116c2020-06-09 16:10:27 -0700374}
375
376} // namespace vkbench